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