summaryrefslogtreecommitdiff
path: root/src/tests/jsonwalker.py
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/tests/jsonwalker.py
Diffstat (limited to 'src/tests/jsonwalker.py')
-rw-r--r--src/tests/jsonwalker.py113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/tests/jsonwalker.py b/src/tests/jsonwalker.py
new file mode 100644
index 000000000000..265c69c703a2
--- /dev/null
+++ b/src/tests/jsonwalker.py
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+
+import sys
+try:
+ import cjson
+except ImportError:
+ print "Warning: skipping audit log verification because the cjson module" \
+ " is unavailable"
+ sys.exit(0)
+from collections import defaultdict
+from optparse import OptionParser
+
+class Parser(object):
+ DEFAULTS = {int:0,
+ str:'',
+ list:[]}
+
+ def __init__(self, defconf=None):
+ self.defaults = None
+ if defconf is not None:
+ self.defaults = self.flatten(defconf)
+
+ def run(self, logs, verbose=None):
+ result = self.parse(logs)
+ if len(result) != len(self.defaults):
+ diff = set(self.defaults.keys()).difference(result.keys())
+ print 'Test failed.'
+ print 'The following attributes were not set:'
+ for it in diff:
+ print it
+ sys.exit(1)
+
+ def flatten(self, defaults):
+ """
+ Flattens pathes to attributes.
+
+ Parameters
+ ----------
+ defaults : a dictionaries populated with default values
+
+ Returns :
+ dict : with flattened attributes
+ """
+ result = dict()
+ for path,value in self._walk(defaults):
+ if path in result:
+ print 'Warning: attribute path %s already exists' % path
+ result[path] = value
+
+ return result
+
+ def parse(self, logs):
+ result = defaultdict(list)
+ for msg in logs:
+ # each message is treated as a dictionary of dictionaries
+ for a,v in self._walk(msg):
+ # see if path is registered in defaults
+ if a in self.defaults:
+ dv = self.defaults.get(a)
+ if dv is None:
+ # determine default value by type
+ if v is not None:
+ dv = self.DEFAULTS[type(v)]
+ else:
+ print 'Warning: attribute %s is set to None' % a
+ continue
+ # by now we have default value
+ if v != dv:
+ # test passed
+ result[a].append(v)
+ return result
+
+ def _walk(self, adict):
+ """
+ Generator that works through dictionary.
+ """
+ for a,v in adict.iteritems():
+ if isinstance(v,dict):
+ for (attrpath,u) in self._walk(v):
+ yield (a+'.'+attrpath,u)
+ else:
+ yield (a,v)
+
+
+if __name__ == '__main__':
+
+ parser = OptionParser()
+ parser.add_option("-i", "--logfile", dest="filename",
+ help="input log file in json fmt", metavar="FILE")
+ parser.add_option("-d", "--defaults", dest="defaults",
+ help="dictionary with defaults", metavar="FILE")
+
+ (options, args) = parser.parse_args()
+ if options.filename is not None:
+ with open(options.filename, 'r') as f:
+ content = list()
+ for l in f:
+ content.append(cjson.decode(l.rstrip()))
+ f.close()
+ else:
+ print 'Input file in jason format is required'
+ exit()
+
+ defaults = None
+ if options.defaults is not None:
+ with open(options.defaults, 'r') as f:
+ defaults = cjson.decode(f.read())
+ f.close()
+
+ # run test
+ p = Parser(defaults)
+ p.run(content)
+ exit()