source: test/pyregfi-smoketest.py @ 227

Last change on this file since 227 was 227, checked in by tim, 13 years ago

added a SetLogMask? function to pyregfi as an interface to regfi_log_set_mask
made pyregfi-smoketest.py easier to use

  • Property svn:executable set to *
File size: 6.9 KB
Line 
1#!/usr/bin/env python3
2
3import sys
4import gc
5import io
6import time
7import pyregfi
8
9
10
11pyregfi.SetLogMask((pyregfi.LOG_TYPES.INFO, pyregfi.LOG_TYPES.WARN, pyregfi.LOG_TYPES.ERROR))
12
13# Uses the HiveIterator to walk all keys
14# Gathers various (meaningless) statistics to exercise simple attribute access
15# and to hopefully smoke out any bugs that can be identified by changing stats
16def iterTallyNames(hive, fh):
17    key_count = 0
18    key_lens = 0
19    key_rawlens = 0
20    value_count = 0
21    value_lens = 0
22    value_rawlens = 0
23
24    for k in hive:
25        key_count += 1
26        if k.name != None:
27            key_lens += len(k.name)
28        if k.name_raw != None:
29            key_rawlens += len(k.name_raw)
30
31        for v in k.values:
32            value_count += 1
33            if v.name != None:
34                value_lens += len(v.name)
35            if v.name_raw != None:
36                value_rawlens += len(v.name_raw)
37
38    print("  Counts: keys=%d, values=%d" % (key_count, value_count))
39    print("  Total name length: keys=%d, values=%d" % (key_lens, value_lens))
40    print("  Total raw name lengths: keys=%d, values=%d" % (key_rawlens, value_rawlens))
41
42
43# helper function
44def getCurrentPath(key):
45    if key == None:
46        return ''
47    path = []
48    p = key
49    while p != None:
50        path.append(p.name)
51        p = p.get_parent()
52    path.reverse()
53    del path[0]
54
55    return path
56
57# For each key in the hive, this traverses the parent links up to the root,
58# recording the path as it goes, and then uses the subtree/descend method
59# to find the same key again, verifying it is the same.  This test is currently
60# very slow because no key caching is used.
61def iterParentWalk(hive, fh):
62    i = 1
63    for k in hive:
64        path = getCurrentPath(k)
65        try:
66            hive_iter = hive.subtree(path)
67            if hive_iter.current_key() != k:
68                print("WARNING: k != current_key for path '%s'." % path)
69            else:
70                i += 1
71        except Exception as e:
72            print("WARNING: Could not decend to path '%s'.\nError:\n %s\n%s" % (path,e.args,e))
73    print("   Successfully tested paths on %d keys." % i)
74
75
76# Uses the HiveIterator to walk all keys
77# Gathers various (meaningless) statistics about data/data_raw attributes
78def iterTallyData(hive, fh):
79    data_stat = 0.0
80    dataraw_stat = 0.0
81   
82    for k in hive:
83        for v in k.values:
84            d = v.fetch_data()
85            if d == None:
86                data_stat += 0.1
87            elif hasattr(d, "__len__"):
88                data_stat += len(d)
89            else:
90                data_stat += d/2.0**64
91
92            d = v.fetch_raw_data()
93            if d == None:
94                dataraw_stat += 0.1
95            else:
96                dataraw_stat += len(d)
97
98    print("  Data stat: %f" % data_stat)
99    print("  Raw data stat: %f" % dataraw_stat)
100
101
102recurseKey_stat = 0.0
103recurseValue_stat = 0.0
104def checkValues(key):
105    global recurseKey_stat
106    global recurseValue_stat
107    recurseKey_stat += (key.mtime.low^key.mtime.high - key.max_bytes_subkeyname) * key.flags
108    for v in key.values:
109        recurseValue_stat += (v.data_off - v.data_size) / (1.0 + v.flags) + v.data_in_offset
110        value = key.values[v.name]
111        if v != value:
112            print("WARNING: iterator value '%s' does not match dictionary value '%s'." 
113                  % (v.name, value.name))
114
115def recurseTree(cur, operation):
116    for k in cur.subkeys:
117        key = cur.subkeys[k.name]
118        if k != key:
119            print("WARNING: iterator subkey '%s' does not match dictionary subkey '%s'." 
120                  % (k.name, key.name))
121        del key
122        operation(k)
123        recurseTree(k, operation)
124
125# Retrieves all keys by recursion, rather than the iterator, and validates
126# list dictionary access.  Also builds nonsensical statistics as an excuse
127# to access various base structure attributes.
128def recurseKeyTally(hive, fh):
129    checkValues(hive.root)
130    recurseTree(hive.root, checkValues)
131    print("  Key stat: %f" % recurseKey_stat)
132    print("  Value stat: %f" % recurseValue_stat)
133
134
135# Iterates hive gathering stats about security and classname records
136def iterFetchRelated(hive, fh):
137    security_stat = 0.0
138    classname_stat = 0.0
139    modified_stat = 0.0
140
141    for k in hive:
142        cn = k.fetch_classname()
143        if cn == None:
144            classname_stat += 0.000001
145        elif type(cn) == bytearray:
146            classname_stat += len(cn)/2**32
147        else:
148            classname_stat += len(cn)
149
150        modified_stat += k.modified
151       
152    print("  Security stat: %f" % security_stat)
153    print("  Classname stat: %f" % classname_stat)
154    print("  Modified stat: %f" % modified_stat)
155
156
157
158def iterIterWalk(hive, fh):
159    sk_stat = 0.0
160    v_stat = 0.0
161    iter = pyregfi.HiveIterator(hive)
162    for k in iter:
163        path = getCurrentPath(k)
164        try:
165            hive_iter = hive.subtree(path)
166            sk = hive_iter.first_subkey()
167            while sk != None:
168                ssk = hive_iter.find_subkey(sk.name)
169                sk_stat += len(ssk.name)
170                sk = hive_iter.next_subkey()
171
172            v = hive_iter.first_value()
173            while v != None:
174                vv = hive_iter.find_value(v.name)
175                v_stat += len(vv.name)
176                v = hive_iter.next_value()
177
178        except Exception as e:
179            print("WARNING: Could not decend to path '%s'.\nError:\n %s\n%s" % (path,e.args,e))
180    print("   Subkey stat: %f" % sk_stat)
181    print("   Value stat: %f" % v_stat)
182
183
184def iterCallbackIO(hive, fh):
185    fh.seek(0)
186    new_fh = io.BytesIO(fh.read())
187    new_hive = pyregfi.Hive(new_fh)
188    for k in new_hive:
189        pass
190
191tests = {
192    "iterTallyNames":iterTallyNames,
193    "iterParentWalk":iterParentWalk,
194    "iterTallyData":iterTallyData,
195    "recurseKeyTally":recurseKeyTally,
196    "iterFetchRelated":iterFetchRelated,
197    "iterIterWalk":iterIterWalk,
198    "iterCallbackIO":iterCallbackIO,
199    }
200
201def usage():
202    sys.stderr.write("USAGE: pyregfi-smoketest.py test1[,test2[,...]] hive1 [hive2 ...]\n")
203    sys.stderr.write("\tAvailable tests:\n")
204    for t in tests.keys():
205        sys.stderr.write("\t\t%s\n" % t)
206
207
208if len(sys.argv) < 3:
209    usage()
210    sys.exit(1)
211
212selected_tests = sys.argv[1].split(',')
213for st in selected_tests:
214    if st not in tests:
215        usage()
216        sys.stderr.write("ERROR: %s not a valid test type" % st)
217        sys.exit(1)
218
219files = []
220for f in sys.argv[2:]:
221    files.append((f, open(f,"rb")))
222
223
224start_time = time.time()
225for hname,fh in files:
226    hive = pyregfi.Hive(fh)
227    for tname in selected_tests:
228        t = tests[tname]
229        teststart = time.time()
230        tstr = "'%s' on '%s'" % (tname,hname)
231        print("##BEGIN %s:" % tstr)
232        t(hive, fh)
233        print("##END %s; runtime=%f; messages:" % (tstr, time.time() - teststart))
234        print(pyregfi.GetLogMessages())
235        print
236        sys.stdout.flush()
237    fh.close()
238
239hive = None
240files = None
241tests = None
242gc.collect()
243print("### Tests Completed, runtime: %f ###" % (time.time() -  start_time))
244#print(gc.garbage)
Note: See TracBrowser for help on using the repository browser.