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
RevLine 
[213]1#!/usr/bin/env python3
[197]2
3import sys
[213]4import gc
[225]5import io
[215]6import time
[197]7import pyregfi
8
[225]9
[197]10
[227]11pyregfi.SetLogMask((pyregfi.LOG_TYPES.INFO, pyregfi.LOG_TYPES.WARN, pyregfi.LOG_TYPES.ERROR))
[197]12
[213]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
[225]16def iterTallyNames(hive, fh):
[213]17    key_count = 0
18    key_lens = 0
19    key_rawlens = 0
20    value_count = 0
21    value_lens = 0
22    value_rawlens = 0
[197]23
[213]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)
[199]30
[213]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)
[200]37
[214]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))
[200]41
[209]42
[220]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
[215]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.
[225]61def iterParentWalk(hive, fh):
[215]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)
[209]74
[215]75
[216]76# Uses the HiveIterator to walk all keys
77# Gathers various (meaningless) statistics about data/data_raw attributes
[225]78def iterTallyData(hive, fh):
[216]79    data_stat = 0.0
80    dataraw_stat = 0.0
81   
82    for k in hive:
83        for v in k.values:
[219]84            d = v.fetch_data()
[216]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
[219]92            d = v.fetch_raw_data()
[216]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
[217]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))
[216]114
[217]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.
[225]128def recurseKeyTally(hive, fh):
[218]129    checkValues(hive.root)
130    recurseTree(hive.root, checkValues)
[217]131    print("  Key stat: %f" % recurseKey_stat)
132    print("  Value stat: %f" % recurseValue_stat)
133
134
[219]135# Iterates hive gathering stats about security and classname records
[225]136def iterFetchRelated(hive, fh):
[219]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
[220]156
157
[225]158def iterIterWalk(hive, fh):
[220]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
[225]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
[220]190
[227]191tests = {
192    "iterTallyNames":iterTallyNames,
193    "iterParentWalk":iterParentWalk,
194    "iterTallyData":iterTallyData,
195    "recurseKeyTally":recurseKeyTally,
196    "iterFetchRelated":iterFetchRelated,
197    "iterIterWalk":iterIterWalk,
198    "iterCallbackIO":iterCallbackIO,
199    }
[209]200
[227]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)
[215]206
207
[227]208if len(sys.argv) < 3:
209    usage()
210    sys.exit(1)
[220]211
[227]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)
[220]218
[213]219files = []
[227]220for f in sys.argv[2:]:
[224]221    files.append((f, open(f,"rb")))
[213]222
223
[215]224start_time = time.time()
[213]225for hname,fh in files:
226    hive = pyregfi.Hive(fh)
[227]227    for tname in selected_tests:
228        t = tests[tname]
[215]229        teststart = time.time()
[213]230        tstr = "'%s' on '%s'" % (tname,hname)
231        print("##BEGIN %s:" % tstr)
[225]232        t(hive, fh)
[215]233        print("##END %s; runtime=%f; messages:" % (tstr, time.time() - teststart))
[213]234        print(pyregfi.GetLogMessages())
235        print
[215]236        sys.stdout.flush()
[224]237    fh.close()
[213]238
[215]239hive = None
[213]240files = None
241tests = None
242gc.collect()
[215]243print("### Tests Completed, runtime: %f ###" % (time.time() -  start_time))
[214]244#print(gc.garbage)
Note: See TracBrowser for help on using the repository browser.