Commit | Line | Data |
---|---|---|
a0b1f42c JD |
1 | #!/usr/bin/env python3 |
2 | ||
4c4634e3 FD |
3 | import argparse |
4 | import pprint | |
a0b1f42c JD |
5 | import sys |
6 | import time | |
4c4634e3 FD |
7 | |
8 | from collections import defaultdict | |
a0b1f42c JD |
9 | |
10 | NSEC_PER_SEC = 1000000000 | |
11 | ||
12 | try: | |
13 | from babeltrace import TraceCollection | |
14 | except ImportError: | |
15 | # quick fix for debian-based distros | |
16 | sys.path.append("/usr/local/lib/python%d.%d/site-packages" % | |
17 | (sys.version_info.major, sys.version_info.minor)) | |
18 | from babeltrace import TraceCollection | |
19 | ||
20 | ||
21 | class TraceParser: | |
22 | def __init__(self, trace, pid): | |
23 | self.trace = trace | |
24 | self.pid = pid | |
4c4634e3 FD |
25 | |
26 | # This dictionnary holds the results of each testcases of a test. | |
27 | # Its layout is the following: | |
28 | # self.expect={ | |
29 | # 'event_name_1': {'check_1': 0, 'check_2: 1}, | |
30 | # 'event_name_2': {'check_1': 1} | |
31 | # } | |
32 | # Each test classes checks the payload of different events. Each of | |
33 | # those checks are stored in a event_name specific dictionnary in this | |
34 | # data structure. | |
35 | self.expect = defaultdict(lambda : defaultdict(int)) | |
36 | ||
37 | # This dictionnary holds the value recorded in the trace that are | |
38 | # tested. Its content is use to print the values that caused a test to | |
39 | # fail. | |
40 | self.recorded_values = {} | |
a0b1f42c JD |
41 | |
42 | def ns_to_hour_nsec(self, ns): | |
43 | d = time.localtime(ns/NSEC_PER_SEC) | |
44 | return "%02d:%02d:%02d.%09d" % (d.tm_hour, d.tm_min, d.tm_sec, | |
45 | ns % NSEC_PER_SEC) | |
46 | ||
47 | def parse(self): | |
48 | # iterate over all the events | |
49 | for event in self.trace.events: | |
50 | if self.pid is not None and event["pid"] != self.pid: | |
51 | continue | |
52 | ||
53 | method_name = "handle_%s" % event.name.replace(":", "_").replace( | |
54 | "+", "_") | |
55 | # call the function to handle each event individually | |
56 | if hasattr(TraceParser, method_name): | |
57 | func = getattr(TraceParser, method_name) | |
58 | func(self, event) | |
59 | ||
60 | ret = 0 | |
4c4634e3 FD |
61 | # For each event of the test case, check all entries for failed |
62 | for event_name, event_results in self.expect.items(): | |
63 | for val in event_results.keys(): | |
64 | if self.expect[event_name][val] == 0: | |
65 | print("%s not validated" % val) | |
66 | print("Values of the local variables of this test:") | |
67 | # using pprint for pretty printing the dictionnary | |
68 | pprint.pprint(self.recorded_values[event_name]) | |
69 | ret = 1 | |
a0b1f42c JD |
70 | |
71 | return ret | |
72 | ||
73 | # epoll_ctl | |
74 | def handle_compat_syscall_entry_epoll_ctl(self, event): | |
75 | self.epoll_ctl_entry(event) | |
76 | ||
77 | def handle_compat_syscall_exit_epoll_ctl(self, event): | |
78 | self.epoll_ctl_exit(event) | |
79 | ||
80 | def handle_syscall_entry_epoll_ctl(self, event): | |
81 | self.epoll_ctl_entry(event) | |
82 | ||
83 | def handle_syscall_exit_epoll_ctl(self, event): | |
84 | self.epoll_ctl_exit(event) | |
85 | ||
86 | def epoll_ctl_entry(self, event): | |
87 | pass | |
88 | ||
89 | def epoll_ctl_exit(self, event): | |
90 | pass | |
91 | ||
92 | # epoll_wait + epoll_pwait | |
93 | def handle_compat_syscall_entry_epoll_wait(self, event): | |
94 | self.epoll_wait_entry(event) | |
95 | ||
96 | def handle_compat_syscall_exit_epoll_wait(self, event): | |
97 | self.epoll_wait_exit(event) | |
98 | ||
99 | def handle_syscall_entry_epoll_wait(self, event): | |
100 | self.epoll_wait_entry(event) | |
101 | ||
102 | def handle_syscall_exit_epoll_wait(self, event): | |
103 | self.epoll_wait_exit(event) | |
104 | ||
105 | def handle_compat_syscall_entry_epoll_pwait(self, event): | |
106 | self.epoll_wait_entry(event) | |
107 | ||
108 | def handle_compat_syscall_exit_epoll_pwait(self, event): | |
109 | self.epoll_wait_exit(event) | |
110 | ||
111 | def handle_syscall_entry_epoll_pwait(self, event): | |
112 | self.epoll_wait_entry(event) | |
113 | ||
114 | def handle_syscall_exit_epoll_pwait(self, event): | |
115 | self.epoll_wait_exit(event) | |
116 | ||
117 | def epoll_wait_entry(self, event): | |
118 | pass | |
119 | ||
120 | def epoll_wait_exit(self, event): | |
121 | pass | |
122 | ||
123 | ## poll + ppoll | |
124 | def handle_compat_syscall_entry_poll(self, event): | |
125 | self.poll_entry(event) | |
126 | ||
127 | def handle_compat_syscall_exit_poll(self, event): | |
128 | self.poll_exit(event) | |
129 | ||
130 | def handle_syscall_entry_poll(self, event): | |
131 | self.poll_entry(event) | |
132 | ||
133 | def handle_syscall_exit_poll(self, event): | |
134 | self.poll_exit(event) | |
135 | ||
136 | def handle_compat_syscall_entry_ppoll(self, event): | |
137 | self.poll_entry(event) | |
138 | ||
139 | def handle_compat_syscall_exit_ppoll(self, event): | |
140 | self.poll_exit(event) | |
141 | ||
142 | def handle_syscall_entry_ppoll(self, event): | |
143 | self.poll_entry(event) | |
144 | ||
145 | def handle_syscall_exit_ppoll(self, event): | |
146 | self.poll_exit(event) | |
147 | ||
148 | def poll_entry(self, event): | |
149 | pass | |
150 | ||
151 | def poll_exit(self, event): | |
152 | pass | |
153 | ||
154 | # epoll_create | |
155 | def handle_compat_syscall_entry_epoll_create1(self, event): | |
156 | self.epoll_create_entry(event) | |
157 | ||
158 | def handle_compat_syscall_exit_epoll_create1(self, event): | |
159 | self.epoll_create_exit(event) | |
160 | ||
161 | def handle_compat_syscall_entry_epoll_create(self, event): | |
162 | self.epoll_create_entry(event) | |
163 | ||
164 | def handle_compat_syscall_exit_epoll_create(self, event): | |
165 | self.epoll_create_exit(event) | |
166 | ||
167 | def handle_syscall_entry_epoll_create1(self, event): | |
168 | self.epoll_create_entry(event) | |
169 | ||
170 | def handle_syscall_exit_epoll_create1(self, event): | |
171 | self.epoll_create_exit(event) | |
172 | ||
173 | def handle_syscall_entry_epoll_create(self, event): | |
174 | self.epoll_create_entry(event) | |
175 | ||
176 | def handle_syscall_exit_epoll_create(self, event): | |
177 | self.epoll_create_exit(event) | |
178 | ||
179 | def epoll_create_entry(self, event): | |
180 | pass | |
181 | ||
182 | def epoll_create_exit(self, event): | |
183 | pass | |
184 | ||
185 | # select + pselect6 | |
186 | def handle_syscall_entry_pselect6(self, event): | |
187 | self.select_entry(event) | |
188 | ||
189 | def handle_syscall_exit_pselect6(self, event): | |
190 | self.select_exit(event) | |
191 | ||
192 | def handle_compat_syscall_entry_pselect6(self, event): | |
193 | self.select_entry(event) | |
194 | ||
195 | def handle_compat_syscall_exit_pselect6(self, event): | |
196 | self.select_exit(event) | |
197 | ||
198 | def handle_syscall_entry_select(self, event): | |
199 | self.select_entry(event) | |
200 | ||
201 | def handle_syscall_exit_select(self, event): | |
202 | self.select_exit(event) | |
203 | ||
204 | def handle_compat_syscall_entry_select(self, event): | |
205 | self.select_entry(event) | |
206 | ||
207 | def handle_compat_syscall_exit_select(self, event): | |
208 | self.select_exit(event) | |
209 | ||
210 | def select_entry(self, event): | |
211 | pass | |
212 | ||
213 | def select_exit(self, event): | |
214 | pass | |
215 | ||
216 | ||
217 | class Test1(TraceParser): | |
218 | def __init__(self, trace, pid): | |
219 | super().__init__(trace, pid) | |
4c4634e3 FD |
220 | self.expect["select_entry"]["select_in_fd0"] = 0 |
221 | self.expect["select_entry"]["select_in_fd1023"] = 0 | |
222 | self.expect["select_exit"]["select_out_fd0"] = 0 | |
223 | self.expect["select_exit"]["select_out_fd1023"] = 0 | |
224 | self.expect["poll_entry"]["poll_in_nfds1"] = 0 | |
225 | self.expect["poll_exit"]["poll_out_nfds1"] = 0 | |
226 | self.expect["epoll_ctl_entry"]["epoll_ctl_in_add"] = 0 | |
227 | self.expect["epoll_ctl_exit"]["epoll_ctl_out_ok"] = 0 | |
228 | self.expect["epoll_wait_entry"]["epoll_wait_in_ok"] = 0 | |
229 | self.expect["epoll_wait_exit"]["epoll_wait_out_fd0"] = 0 | |
a0b1f42c JD |
230 | |
231 | def select_entry(self, event): | |
a0b1f42c JD |
232 | n = event["n"] |
233 | overflow = event["overflow"] | |
4c4634e3 | 234 | readfd_0 = event["readfds"][0] |
a0b1f42c JD |
235 | |
236 | # check that the FD 0 is actually set in the readfds | |
4c4634e3 FD |
237 | if n == 1 and readfd_0 == 1: |
238 | self.expect["select_entry"]["select_in_fd0"] = 1 | |
a0b1f42c | 239 | if n == 1023: |
4c4634e3 FD |
240 | readfd_127 = event["readfds"][127] |
241 | writefd_127 = event["writefds"][127] | |
242 | exceptfd_127 = event["exceptfds"][127] | |
243 | ||
a0b1f42c | 244 | # check that the FD 1023 is actually set in the readfds |
4c4634e3 FD |
245 | if readfd_127 == 0x40 and writefd_127 == 0 and \ |
246 | exceptfd_127 == 0 and overflow == 0: | |
247 | self.expect["select_entry"]["select_in_fd1023"] = 1 | |
248 | ||
249 | # Save values of local variables to print in case of test failure | |
250 | self.recorded_values["select_entry"] = locals() | |
a0b1f42c JD |
251 | |
252 | def select_exit(self, event): | |
a0b1f42c | 253 | ret = event["ret"] |
a0b1f42c | 254 | tvp = event["tvp"] |
4c4634e3 | 255 | overflow = event["overflow"] |
a0b1f42c | 256 | _readfds_length = event["_readfds_length"] |
a0b1f42c JD |
257 | |
258 | if ret == 1: | |
259 | # check that the FD 0 is actually set in the readfds | |
4c4634e3 FD |
260 | readfd_0 = event["readfds"][0] |
261 | ||
262 | if readfd_0 == 1: | |
263 | self.expect["select_exit"]["select_out_fd0"] = 1 | |
a0b1f42c | 264 | # check that the FD 1023 is actually set in the readfds |
4c4634e3 FD |
265 | if _readfds_length == 128: |
266 | readfd_127 = event["readfds"][127] | |
267 | writefd_127 = event["writefds"][127] | |
268 | exceptfd_127 = event["exceptfds"][127] | |
269 | if readfd_127 == 0x40 and writefd_127 == 0 and \ | |
270 | exceptfd_127 == 0 and tvp == 0: | |
271 | self.expect["select_exit"]["select_out_fd1023"] = 1 | |
272 | ||
273 | # Save values of local variables to print in case of test failure | |
274 | self.recorded_values["select_exit"] = locals() | |
a0b1f42c JD |
275 | |
276 | def poll_entry(self, event): | |
a0b1f42c JD |
277 | nfds = event["nfds"] |
278 | fds_length = event["fds_length"] | |
279 | overflow = event["overflow"] | |
a0b1f42c JD |
280 | |
281 | # check that only one FD is set, that it has the POLLIN flag and that | |
282 | # the raw value matches the events bit field. | |
4c4634e3 FD |
283 | if nfds == 1 and fds_length == 1: |
284 | fd_0 = event["fds"][0] | |
285 | if fd_0["raw_events"] == 0x3 and fd_0["events"]["POLLIN"] == 1 and \ | |
286 | fd_0["events"]["padding"] == 0: | |
287 | self.expect["poll_entry"]["poll_in_nfds1"] = 1 | |
288 | ||
289 | # Save values of local variables to print in case of test failure | |
290 | self.recorded_values["poll_entry"] = locals() | |
a0b1f42c JD |
291 | |
292 | def poll_exit(self, event): | |
a0b1f42c | 293 | ret = event["ret"] |
a0b1f42c | 294 | fds_length = event["fds_length"] |
a0b1f42c JD |
295 | |
296 | # check that only one FD is set, that it has the POLLIN flag and that | |
297 | # the raw value matches the events bit field. | |
4c4634e3 FD |
298 | if ret == 1 and fds_length == 1: |
299 | fd_0 = event["fds"][0] | |
300 | if fd_0["raw_events"] == 0x1 and fd_0["events"]["POLLIN"] == 1 and \ | |
301 | fd_0["events"]["padding"] == 0: | |
302 | self.expect["poll_exit"]["poll_out_nfds1"] = 1 | |
303 | ||
304 | # Save values of local variables to print in case of test failure | |
305 | self.recorded_values["poll_exit"] = locals() | |
a0b1f42c JD |
306 | |
307 | def epoll_ctl_entry(self, event): | |
a0b1f42c JD |
308 | epfd = event["epfd"] |
309 | op_enum = event["op_enum"] | |
310 | fd = event["fd"] | |
311 | _event = event["event"] | |
312 | ||
313 | # check that we have FD 0 waiting for EPOLLIN|EPOLLPRI and that | |
314 | # data.fd = 0 | |
315 | if epfd == 3 and op_enum == "EPOLL_CTL_ADD" and fd == 0 and \ | |
316 | _event["data_union"]["fd"] == 0 and \ | |
317 | _event["events"]["EPOLLIN"] == 1 and \ | |
318 | _event["events"]["EPOLLPRI"] == 1: | |
4c4634e3 FD |
319 | self.expect["epoll_ctl_entry"]["epoll_ctl_in_add"] = 1 |
320 | ||
321 | # Save values of local variables to print in case of test failure | |
322 | self.recorded_values["epoll_ctl_entry"] = locals() | |
a0b1f42c JD |
323 | |
324 | def epoll_ctl_exit(self, event): | |
a0b1f42c JD |
325 | ret = event["ret"] |
326 | ||
327 | if ret == 0: | |
4c4634e3 FD |
328 | self.expect["epoll_ctl_exit"]["epoll_ctl_out_ok"] = 1 |
329 | ||
330 | # Save values of local variables to print in case of test failure | |
331 | self.recorded_values["epoll_ctl_exit"] = locals() | |
a0b1f42c JD |
332 | |
333 | def epoll_wait_entry(self, event): | |
a0b1f42c JD |
334 | epfd = event["epfd"] |
335 | maxevents = event["maxevents"] | |
336 | timeout = event["timeout"] | |
337 | ||
338 | if epfd == 3 and maxevents == 1 and timeout == -1: | |
4c4634e3 FD |
339 | self.expect["epoll_wait_entry"]["epoll_wait_in_ok"] = 1 |
340 | ||
341 | # Save values of local variables to print in case of test failure | |
342 | self.recorded_values["epoll_wait_entry"] = locals() | |
a0b1f42c JD |
343 | |
344 | def epoll_wait_exit(self, event): | |
a0b1f42c JD |
345 | ret = event["ret"] |
346 | fds_length = event["fds_length"] | |
347 | overflow = event["overflow"] | |
a0b1f42c JD |
348 | |
349 | # check that FD 0 returned with EPOLLIN and the right data.fd | |
4c4634e3 FD |
350 | if ret == 1 and fds_length == 1: |
351 | fd_0 = event["fds"][0] | |
352 | if overflow == 0 and fd_0["data_union"]["fd"] == 0 and \ | |
353 | fd_0["events"]["EPOLLIN"] == 1: | |
354 | self.expect["epoll_wait_exit"]["epoll_wait_out_fd0"] = 1 | |
355 | ||
356 | # Save values of local variables to print in case of test failure | |
357 | self.recorded_values["epoll_wait_exit"] = locals() | |
a0b1f42c JD |
358 | |
359 | ||
360 | class Test2(TraceParser): | |
361 | def __init__(self, trace, pid): | |
362 | super().__init__(trace, pid) | |
4c4634e3 FD |
363 | self.expect["select_entry"]["select_timeout_in_fd0"] = 0 |
364 | self.expect["select_entry"]["select_timeout_in_fd1023"] = 0 | |
365 | self.expect["select_exit"]["select_timeout_out"] = 0 | |
366 | self.expect["poll_entry"]["poll_timeout_in"] = 0 | |
367 | self.expect["poll_exit"]["poll_timeout_out"] = 0 | |
368 | self.expect["epoll_ctl_entry"]["epoll_ctl_timeout_in_add"] = 0 | |
369 | self.expect["epoll_ctl_exit"]["epoll_ctl_timeout_out_ok"] = 0 | |
370 | self.expect["epoll_wait_entry"]["epoll_wait_timeout_in"] = 0 | |
371 | self.expect["epoll_wait_exit"]["epoll_wait_timeout_out"] = 0 | |
a0b1f42c JD |
372 | |
373 | def select_entry(self, event): | |
a0b1f42c | 374 | n = event["n"] |
a0b1f42c | 375 | tvp = event["tvp"] |
a0b1f42c JD |
376 | |
377 | if n == 1 and tvp != 0: | |
4c4634e3 | 378 | self.expect["select_entry"]["select_timeout_in_fd0"] = 1 |
a0b1f42c | 379 | if n == 1023: |
4c4634e3 FD |
380 | readfd_127 = event["readfds"][127] |
381 | writefd_127 = event["writefds"][127] | |
382 | exceptfd_127 = event["exceptfds"][127] | |
383 | ||
384 | if readfd_127 == 0x40 and writefd_127 == 0 and \ | |
385 | exceptfd_127 == 0 and tvp != 0: | |
386 | self.expect["select_entry"]["select_timeout_in_fd1023"] = 1 | |
387 | ||
388 | # Save values of local variables to print in case of test failure | |
389 | self.recorded_values["select_entry"] = locals() | |
a0b1f42c JD |
390 | |
391 | def select_exit(self, event): | |
a0b1f42c | 392 | ret = event["ret"] |
a0b1f42c | 393 | tvp = event["tvp"] |
a0b1f42c JD |
394 | |
395 | if ret == 0 and tvp != 0: | |
4c4634e3 FD |
396 | self.expect["select_exit"]["select_timeout_out"] = 1 |
397 | ||
398 | # Save values of local variables to print in case of test failure | |
399 | self.recorded_values["select_exit"] = locals() | |
a0b1f42c JD |
400 | |
401 | def poll_entry(self, event): | |
a0b1f42c JD |
402 | nfds = event["nfds"] |
403 | fds_length = event["fds_length"] | |
a0b1f42c JD |
404 | |
405 | # check that we wait on FD 0 for POLLIN and that the raw_events | |
406 | # field matches the value of POLLIN | |
4c4634e3 FD |
407 | if nfds == 1 and fds_length == 1: |
408 | fd_0 = event["fds"][0] | |
409 | if fd_0["raw_events"] == 0x3 and \ | |
410 | fd_0["events"]["POLLIN"] == 1 and \ | |
411 | fd_0["events"]["padding"] == 0: | |
412 | self.expect["poll_entry"]["poll_timeout_in"] = 1 | |
413 | ||
414 | # Save values of local variables to print in case of test failure | |
415 | self.recorded_values["poll_entry"] = locals() | |
a0b1f42c JD |
416 | |
417 | def poll_exit(self, event): | |
a0b1f42c JD |
418 | ret = event["ret"] |
419 | nfds = event["nfds"] | |
420 | fds_length = event["fds_length"] | |
a0b1f42c JD |
421 | |
422 | if ret == 0 and nfds == 1 and fds_length == 0: | |
4c4634e3 FD |
423 | self.expect["poll_exit"]["poll_timeout_out"] = 1 |
424 | ||
425 | # Save values of local variables to print in case of test failure | |
426 | self.recorded_values["poll_exit"] = locals() | |
a0b1f42c JD |
427 | |
428 | def epoll_ctl_entry(self, event): | |
a0b1f42c | 429 | op_enum = event["op_enum"] |
a0b1f42c JD |
430 | _event = event["event"] |
431 | ||
432 | # make sure we see a EPOLLIN|EPOLLPRI | |
433 | if op_enum == "EPOLL_CTL_ADD" and \ | |
434 | _event["events"]["EPOLLIN"] == 1 and \ | |
435 | _event["events"]["EPOLLPRI"] == 1: | |
4c4634e3 FD |
436 | self.expect["epoll_ctl_entry"]["epoll_ctl_timeout_in_add"] = 1 |
437 | ||
438 | # Save values of local variables to print in case of test failure | |
439 | self.recorded_values["epoll_ctl_entry"] = locals() | |
a0b1f42c JD |
440 | |
441 | def epoll_ctl_exit(self, event): | |
a0b1f42c JD |
442 | ret = event["ret"] |
443 | ||
444 | if ret == 0: | |
4c4634e3 FD |
445 | self.expect["epoll_ctl_exit"]["epoll_ctl_timeout_out_ok"] = 1 |
446 | ||
447 | # Save values of local variables to print in case of test failure | |
448 | self.recorded_values["epoll_ctl_exit"] = locals() | |
a0b1f42c JD |
449 | |
450 | def epoll_wait_entry(self, event): | |
a0b1f42c JD |
451 | maxevents = event["maxevents"] |
452 | timeout = event["timeout"] | |
453 | ||
454 | if maxevents == 1 and timeout == 1: | |
4c4634e3 FD |
455 | self.expect["epoll_wait_entry"]["epoll_wait_timeout_in"] = 1 |
456 | ||
457 | # Save values of local variables to print in case of test failure | |
458 | self.recorded_values["epoll_wait_entry"] = locals() | |
a0b1f42c JD |
459 | |
460 | def epoll_wait_exit(self, event): | |
a0b1f42c JD |
461 | ret = event["ret"] |
462 | fds_length = event["fds_length"] | |
463 | overflow = event["overflow"] | |
a0b1f42c JD |
464 | |
465 | if ret == 0 and fds_length == 0 and overflow == 0: | |
4c4634e3 FD |
466 | self.expect["epoll_wait_exit"]["epoll_wait_timeout_out"] = 1 |
467 | ||
468 | # Save values of local variables to print in case of test failure | |
469 | self.recorded_values["epoll_wait_exit"] = locals() | |
a0b1f42c JD |
470 | |
471 | ||
472 | class Test3(TraceParser): | |
473 | def __init__(self, trace, pid): | |
474 | super().__init__(trace, pid) | |
4c4634e3 FD |
475 | self.expect["select_entry"]["select_invalid_fd_in"] = 0 |
476 | self.expect["select_exit"]["select_invalid_fd_out"] = 0 | |
a0b1f42c JD |
477 | |
478 | def select_entry(self, event): | |
a0b1f42c JD |
479 | n = event["n"] |
480 | overflow = event["overflow"] | |
a0b1f42c | 481 | |
8b3b99e2 | 482 | if n > 0 and overflow == 0: |
4c4634e3 FD |
483 | self.expect["select_entry"]["select_invalid_fd_in"] = 1 |
484 | ||
485 | # Save values of local variables to print in case of test failure | |
486 | self.recorded_values["select_entry"] = locals() | |
a0b1f42c JD |
487 | |
488 | def select_exit(self, event): | |
a0b1f42c JD |
489 | ret = event["ret"] |
490 | overflow = event["overflow"] | |
a0b1f42c | 491 | _readfds_length = event["_readfds_length"] |
a0b1f42c | 492 | |
8b3b99e2 | 493 | # make sure the event has a ret field equal to -EBADF |
a0b1f42c | 494 | if ret == -9 and overflow == 0 and _readfds_length == 0: |
4c4634e3 FD |
495 | self.expect["select_exit"]["select_invalid_fd_out"] = 1 |
496 | ||
497 | # Save values of local variables to print in case of test failure | |
498 | self.recorded_values["select_exit"] = locals() | |
a0b1f42c JD |
499 | |
500 | ||
501 | class Test4(TraceParser): | |
502 | def __init__(self, trace, pid): | |
503 | super().__init__(trace, pid) | |
4c4634e3 FD |
504 | self.expect["poll_entry"]["big_poll_in"] = 0 |
505 | self.expect["poll_exit"]["big_poll_out"] = 0 | |
a0b1f42c JD |
506 | |
507 | def poll_entry(self, event): | |
a0b1f42c JD |
508 | nfds = event["nfds"] |
509 | fds_length = event["fds_length"] | |
510 | overflow = event["overflow"] | |
a0b1f42c JD |
511 | |
512 | # test of big list of FDs and the behaviour of the overflow | |
4c4634e3 FD |
513 | if nfds == 2047 and fds_length == 512 and overflow == 1: |
514 | fd_0 = event["fds"][0] | |
515 | fd_511 = event["fds"][511] | |
516 | if fd_0["raw_events"] == 0x3 and fd_0["events"]["POLLIN"] == 1 and \ | |
517 | fd_0["events"]["padding"] == 0 and \ | |
518 | fd_511["events"]["POLLIN"] == 1 and \ | |
519 | fd_511["events"]["POLLPRI"] == 1: | |
520 | self.expect["poll_entry"]["big_poll_in"] = 1 | |
521 | ||
522 | # Save values of local variables to print in case of test failure | |
523 | self.recorded_values["poll_entry"] = locals() | |
a0b1f42c JD |
524 | |
525 | def poll_exit(self, event): | |
a0b1f42c JD |
526 | ret = event["ret"] |
527 | nfds = event["nfds"] | |
528 | fds_length = event["fds_length"] | |
529 | overflow = event["overflow"] | |
a0b1f42c JD |
530 | |
531 | # test of big list of FDs and the behaviour of the overflow | |
4c4634e3 FD |
532 | if ret == 2047 and nfds == 2047 and fds_length == 512 and overflow == 1: |
533 | fd_0 = event["fds"][0] | |
534 | fd_511 = event["fds"][511] | |
535 | if fd_0["events"]["POLLIN"] == 1 and fd_511["events"]["POLLIN"] == 1: | |
536 | self.expect["poll_exit"]["big_poll_out"] = 1 | |
a0b1f42c | 537 | |
4c4634e3 FD |
538 | # Save values of local variables to print in case of test failure |
539 | self.recorded_values["poll_exit"] = locals() | |
a0b1f42c JD |
540 | |
541 | class Test5(TraceParser): | |
542 | def __init__(self, trace, pid): | |
543 | super().__init__(trace, pid) | |
4c4634e3 FD |
544 | self.expect["poll_entry"]["poll_overflow_in"] = 0 |
545 | self.expect["poll_exit"]["poll_overflow_out"] = 0 | |
a0b1f42c JD |
546 | |
547 | def poll_entry(self, event): | |
a0b1f42c JD |
548 | nfds = event["nfds"] |
549 | fds_length = event["fds_length"] | |
550 | overflow = event["overflow"] | |
a0b1f42c JD |
551 | |
552 | # test that event in valid even though the target buffer is too small | |
553 | # and the program segfaults | |
4c4634e3 FD |
554 | if nfds == 100 and fds_length == 100 and overflow == 0: |
555 | fd_0 = event["fds"][0] | |
556 | if fd_0["events"]["POLLIN"] == 1: | |
557 | self.expect["poll_entry"]["poll_overflow_in"] = 1 | |
558 | ||
559 | # Save values of local variables to print in case of test failure | |
560 | self.recorded_values["poll_entry"] = locals() | |
a0b1f42c JD |
561 | |
562 | def poll_exit(self, event): | |
a0b1f42c | 563 | nfds = event["nfds"] |
a0b1f42c | 564 | overflow = event["overflow"] |
a0b1f42c JD |
565 | |
566 | # test that event in valid even though the target buffer is too small | |
567 | # and the program segfaults | |
568 | if nfds == 100 and overflow == 0: | |
4c4634e3 FD |
569 | self.expect["poll_exit"]["poll_overflow_out"] = 1 |
570 | ||
571 | # Save values of local variables to print in case of test failure | |
572 | self.recorded_values["poll_exit"] = locals() | |
a0b1f42c JD |
573 | |
574 | ||
575 | class Test6(TraceParser): | |
576 | def __init__(self, trace, pid): | |
577 | super().__init__(trace, pid) | |
4c4634e3 FD |
578 | self.expect["select_entry"]["pselect_invalid_in"] = 0 |
579 | self.expect["select_exit"]["pselect_invalid_out"] = 0 | |
a0b1f42c JD |
580 | |
581 | def select_entry(self, event): | |
a0b1f42c JD |
582 | n = event["n"] |
583 | overflow = event["overflow"] | |
a0b1f42c | 584 | _readfds_length = event["_readfds_length"] |
a0b1f42c JD |
585 | |
586 | # test that event in valid even though the target buffer pointer is | |
587 | # invalid and the program segfaults | |
588 | if n == 1 and overflow == 0 and _readfds_length == 0: | |
4c4634e3 FD |
589 | self.expect["select_entry"]["pselect_invalid_in"] = 1 |
590 | ||
591 | # Save values of local variables to print in case of test failure | |
592 | self.recorded_values["select_entry"] = locals() | |
a0b1f42c JD |
593 | |
594 | def select_exit(self, event): | |
a0b1f42c JD |
595 | ret = event["ret"] |
596 | overflow = event["overflow"] | |
a0b1f42c | 597 | _readfds_length = event["_readfds_length"] |
a0b1f42c JD |
598 | |
599 | # test that event in valid even though the target buffer pointer is | |
600 | # invalid and the program segfaults | |
601 | if ret == -14 and overflow == 0 and _readfds_length == 0: | |
4c4634e3 FD |
602 | self.expect["select_exit"]["pselect_invalid_out"] = 1 |
603 | ||
604 | # Save values of local variables to print in case of test failure | |
605 | self.recorded_values["select_exit"] = locals() | |
a0b1f42c JD |
606 | |
607 | ||
608 | class Test7(TraceParser): | |
609 | def __init__(self, trace, pid): | |
610 | super().__init__(trace, pid) | |
4c4634e3 FD |
611 | self.expect["poll_entry"]["poll_max_in"] = 0 |
612 | self.expect["poll_exit"]["poll_max_out"] = 0 | |
a0b1f42c JD |
613 | |
614 | def poll_entry(self, event): | |
a0b1f42c | 615 | nfds = event["nfds"] |
a0b1f42c | 616 | overflow = event["overflow"] |
a0b1f42c JD |
617 | |
618 | # check the proper working of INT_MAX maxevent value | |
619 | if nfds == 4294967295 and overflow == 1: | |
4c4634e3 FD |
620 | self.expect["poll_entry"]["poll_max_in"] = 1 |
621 | ||
622 | # Save values of local variables to print in case of test failure | |
623 | self.recorded_values["poll_entry"] = locals() | |
624 | ||
a0b1f42c JD |
625 | |
626 | def poll_exit(self, event): | |
a0b1f42c JD |
627 | ret = event["ret"] |
628 | nfds = event["nfds"] | |
a0b1f42c | 629 | overflow = event["overflow"] |
a0b1f42c JD |
630 | |
631 | # check the proper working of UINT_MAX maxevent value | |
632 | if ret == -22 and nfds == 4294967295 and overflow == 0: | |
4c4634e3 FD |
633 | self.expect["poll_exit"]["poll_max_out"] = 1 |
634 | ||
635 | # Save values of local variables to print in case of test failure | |
636 | self.recorded_values["poll_exit"] = locals() | |
a0b1f42c JD |
637 | |
638 | ||
639 | class Test8(TraceParser): | |
640 | def __init__(self, trace, pid): | |
641 | super().__init__(trace, pid) | |
4c4634e3 FD |
642 | self.expect["epoll_wait_entry"]["epoll_wait_invalid_in"] = 0 |
643 | self.expect["epoll_wait_exit"]["epoll_wait_invalid_out"] = 0 | |
a0b1f42c JD |
644 | |
645 | def epoll_wait_entry(self, event): | |
a0b1f42c JD |
646 | epfd = event["epfd"] |
647 | maxevents = event["maxevents"] | |
648 | timeout = event["timeout"] | |
649 | ||
650 | # test that event in valid even though the target buffer pointer is | |
651 | # invalid and the program segfaults | |
652 | if epfd == 3 and maxevents == 1 and timeout == -1: | |
4c4634e3 FD |
653 | self.expect["epoll_wait_entry"]["epoll_wait_invalid_in"] = 1 |
654 | ||
655 | # Save values of local variables to print in case of test failure | |
656 | self.recorded_values["epoll_wait_entry"] = locals() | |
a0b1f42c JD |
657 | |
658 | def epoll_wait_exit(self, event): | |
a0b1f42c JD |
659 | ret = event["ret"] |
660 | fds_length = event["fds_length"] | |
661 | overflow = event["overflow"] | |
a0b1f42c JD |
662 | |
663 | # test that event in valid even though the target buffer pointer is | |
664 | # invalid and the program segfaults | |
665 | if ret == -14 and fds_length == 0 and overflow == 0: | |
4c4634e3 FD |
666 | self.expect["epoll_wait_exit"]["epoll_wait_invalid_out"] = 1 |
667 | ||
668 | # Save values of local variables to print in case of test failure | |
669 | self.recorded_values["epoll_wait_exit"] = locals() | |
a0b1f42c JD |
670 | |
671 | ||
672 | class Test9(TraceParser): | |
673 | def __init__(self, trace, pid): | |
674 | super().__init__(trace, pid) | |
4c4634e3 FD |
675 | self.expect["epoll_wait_entry"]["epoll_wait_max_in"] = 0 |
676 | self.expect["epoll_wait_exit"]["epoll_wait_max_out"] = 0 | |
a0b1f42c JD |
677 | |
678 | def epoll_wait_entry(self, event): | |
a0b1f42c JD |
679 | epfd = event["epfd"] |
680 | maxevents = event["maxevents"] | |
681 | timeout = event["timeout"] | |
682 | ||
683 | # check the proper working of INT_MAX maxevent value | |
684 | if epfd == 3 and maxevents == 2147483647 and timeout == -1: | |
4c4634e3 FD |
685 | self.expect["epoll_wait_entry"]["epoll_wait_max_in"] = 1 |
686 | ||
687 | # Save values of local variables to print in case of test failure | |
688 | self.recorded_values["epoll_wait_entry"] = locals() | |
a0b1f42c JD |
689 | |
690 | def epoll_wait_exit(self, event): | |
a0b1f42c JD |
691 | ret = event["ret"] |
692 | fds_length = event["fds_length"] | |
693 | overflow = event["overflow"] | |
a0b1f42c JD |
694 | |
695 | # check the proper working of INT_MAX maxevent value | |
696 | if ret == -22 and fds_length == 0 and overflow == 0: | |
4c4634e3 FD |
697 | self.expect["epoll_wait_exit"]["epoll_wait_max_out"] = 1 |
698 | ||
699 | # Save values of local variables to print in case of test failure | |
700 | self.recorded_values["epoll_wait_exit"] = locals() | |
a0b1f42c JD |
701 | |
702 | ||
703 | if __name__ == "__main__": | |
704 | parser = argparse.ArgumentParser(description='Trace parser') | |
705 | parser.add_argument('path', metavar="<path/to/trace>", help='Trace path') | |
706 | parser.add_argument('-t', '--test', type=int, help='Test to validate') | |
707 | parser.add_argument('-p', '--pid', type=int, help='PID of the app') | |
708 | args = parser.parse_args() | |
709 | ||
710 | if not args.test: | |
711 | print("Need to pass a test to validate (-t)") | |
712 | sys.exit(1) | |
713 | ||
714 | if not args.pid: | |
715 | print("Need to pass the PID to check (-p)") | |
716 | sys.exit(1) | |
717 | ||
718 | traces = TraceCollection() | |
719 | handle = traces.add_traces_recursive(args.path, "ctf") | |
720 | if handle is None: | |
721 | sys.exit(1) | |
722 | ||
723 | t = None | |
724 | ||
725 | if args.test == 1: | |
726 | t = Test1(traces, args.pid) | |
727 | elif args.test == 2: | |
728 | t = Test2(traces, args.pid) | |
729 | elif args.test == 3: | |
730 | t = Test3(traces, args.pid) | |
731 | elif args.test == 4: | |
732 | t = Test4(traces, args.pid) | |
733 | elif args.test == 5: | |
734 | t = Test5(traces, args.pid) | |
735 | elif args.test == 6: | |
736 | t = Test6(traces, args.pid) | |
737 | elif args.test == 7: | |
738 | t = Test7(traces, args.pid) | |
739 | elif args.test == 8: | |
740 | t = Test8(traces, args.pid) | |
741 | elif args.test == 9: | |
742 | t = Test9(traces, args.pid) | |
743 | elif args.test == 10: | |
744 | # stress test, nothing reliable to check | |
745 | ret = 0 | |
746 | elif args.test == 11: | |
747 | # stress test, nothing reliable to check | |
748 | ret = 0 | |
749 | else: | |
750 | print("Invalid test case") | |
751 | sys.exit(1) | |
752 | ||
753 | if t is not None: | |
754 | ret = t.parse() | |
755 | ||
756 | for h in handle.values(): | |
757 | traces.remove_trace(h) | |
758 | ||
759 | sys.exit(ret) |