source: test/pyregfi-smoketest.py @ 225

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

added test case for python callback read/seek
began adding windows support in pyregfi
improved win32 build target

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