vscode: Add configurations to run the executables under the debugger
[lttng-tools.git] / tests / regression / kernel / validate_select_poll_epoll.py
CommitLineData
a0b1f42c 1#!/usr/bin/env python3
9d16b343
MJ
2#
3# Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
a0b1f42c 7
4c4634e3
FD
8import argparse
9import pprint
a0b1f42c
JD
10import sys
11import time
d40c2620 12import json
4c4634e3
FD
13
14from collections import defaultdict
a0b1f42c 15
a0b1f42c 16try:
53f8be7a 17 import bt2
a0b1f42c
JD
18except ImportError:
19 # quick fix for debian-based distros
6a871bbe
KS
20 sys.path.append(
21 "/usr/local/lib/python%d.%d/site-packages"
22 % (sys.version_info.major, sys.version_info.minor)
23 )
53f8be7a 24 import bt2
a0b1f42c 25
53f8be7a 26NSEC_PER_SEC = 1000000000
a0b1f42c 27
6a871bbe 28
a0b1f42c 29class TraceParser:
53f8be7a
FD
30 def __init__(self, trace_msg_iter, pid):
31 self.trace = trace_msg_iter
a0b1f42c 32 self.pid = pid
4c4634e3
FD
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.
6a871bbe 43 self.expect = defaultdict(lambda: defaultdict(int))
4c4634e3
FD
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 = {}
a0b1f42c
JD
49
50 def ns_to_hour_nsec(self, ns):
6a871bbe
KS
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 )
a0b1f42c
JD
58
59 def parse(self):
60 # iterate over all the events
53f8be7a
FD
61 for msg in self.trace:
62 if type(msg) is not bt2._EventMessageConst:
a0b1f42c
JD
63 continue
64
53f8be7a
FD
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(
6a871bbe
KS
69 "+", "_"
70 )
a0b1f42c
JD
71 # call the function to handle each event individually
72 if hasattr(TraceParser, method_name):
73 func = getattr(TraceParser, method_name)
53f8be7a 74 func(self, msg.event)
a0b1f42c
JD
75
76 ret = 0
4c4634e3
FD
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
a0b1f42c
JD
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):
d40c2620 122 self.epoll_pwait_entry(event)
a0b1f42c
JD
123
124 def handle_compat_syscall_exit_epoll_pwait(self, event):
d40c2620 125 self.epoll_pwait_exit(event)
a0b1f42c
JD
126
127 def handle_syscall_entry_epoll_pwait(self, event):
d40c2620 128 self.epoll_pwait_entry(event)
a0b1f42c
JD
129
130 def handle_syscall_exit_epoll_pwait(self, event):
d40c2620 131 self.epoll_pwait_exit(event)
a0b1f42c
JD
132
133 def epoll_wait_entry(self, event):
134 pass
135
136 def epoll_wait_exit(self, event):
137 pass
138
d40c2620
JG
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
a0b1f42c
JD
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
2a2ac572 239class WorkingCases(TraceParser):
d40c2620 240 def __init__(self, trace, validation_args):
6a871bbe 241 super().__init__(trace, validation_args["pid"])
d40c2620
JG
242
243 # Values expected in the trace
6a871bbe
KS
244 self.epoll_wait_fd = validation_args["epoll_wait_fd"]
245 self.epoll_pwait_fd = validation_args["epoll_pwait_fd"]
d40c2620 246
4c4634e3
FD
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
d40c2620
JG
257 self.expect["epoll_pwait_entry"]["epoll_pwait_in_ok"] = 0
258 self.expect["epoll_pwait_exit"]["epoll_pwait_out_fd0"] = 0
a0b1f42c
JD
259
260 def select_entry(self, event):
a0b1f42c
JD
261 n = event["n"]
262 overflow = event["overflow"]
4c4634e3 263 readfd_0 = event["readfds"][0]
a0b1f42c
JD
264
265 # check that the FD 0 is actually set in the readfds
4c4634e3
FD
266 if n == 1 and readfd_0 == 1:
267 self.expect["select_entry"]["select_in_fd0"] = 1
a0b1f42c 268 if n == 1023:
4c4634e3
FD
269 readfd_127 = event["readfds"][127]
270 writefd_127 = event["writefds"][127]
271 exceptfd_127 = event["exceptfds"][127]
272
a0b1f42c 273 # check that the FD 1023 is actually set in the readfds
6a871bbe
KS
274 if (
275 readfd_127 == 0x40
276 and writefd_127 == 0
277 and exceptfd_127 == 0
278 and overflow == 0
279 ):
4c4634e3
FD
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()
a0b1f42c
JD
284
285 def select_exit(self, event):
a0b1f42c 286 ret = event["ret"]
a0b1f42c 287 tvp = event["tvp"]
4c4634e3 288 overflow = event["overflow"]
a0b1f42c 289 _readfds_length = event["_readfds_length"]
a0b1f42c
JD
290
291 if ret == 1:
292 # check that the FD 0 is actually set in the readfds
4c4634e3
FD
293 readfd_0 = event["readfds"][0]
294
295 if readfd_0 == 1:
296 self.expect["select_exit"]["select_out_fd0"] = 1
a0b1f42c 297 # check that the FD 1023 is actually set in the readfds
4c4634e3
FD
298 if _readfds_length == 128:
299 readfd_127 = event["readfds"][127]
300 writefd_127 = event["writefds"][127]
301 exceptfd_127 = event["exceptfds"][127]
6a871bbe
KS
302 if (
303 readfd_127 == 0x40
304 and writefd_127 == 0
305 and exceptfd_127 == 0
306 and tvp == 0
307 ):
4c4634e3
FD
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()
a0b1f42c
JD
312
313 def poll_entry(self, event):
a0b1f42c
JD
314 nfds = event["nfds"]
315 fds_length = event["fds_length"]
316 overflow = event["overflow"]
a0b1f42c
JD
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.
4c4634e3
FD
320 if nfds == 1 and fds_length == 1:
321 fd_0 = event["fds"][0]
6a871bbe
KS
322 if (
323 fd_0["raw_events"] == 0x3
324 and fd_0["events"]["POLLIN"] == 1
325 and fd_0["events"]["padding"] == 0
326 ):
4c4634e3
FD
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()
a0b1f42c
JD
331
332 def poll_exit(self, event):
a0b1f42c 333 ret = event["ret"]
a0b1f42c 334 fds_length = event["fds_length"]
a0b1f42c
JD
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.
4c4634e3
FD
338 if ret == 1 and fds_length == 1:
339 fd_0 = event["fds"][0]
6a871bbe
KS
340 if (
341 fd_0["raw_events"] == 0x1
342 and fd_0["events"]["POLLIN"] == 1
343 and fd_0["events"]["padding"] == 0
344 ):
4c4634e3
FD
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()
a0b1f42c
JD
349
350 def epoll_ctl_entry(self, event):
a0b1f42c
JD
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
6a871bbe
KS
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 ):
4c4634e3
FD
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()
a0b1f42c
JD
370
371 def epoll_ctl_exit(self, event):
a0b1f42c
JD
372 ret = event["ret"]
373
374 if ret == 0:
4c4634e3
FD
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()
a0b1f42c
JD
379
380 def epoll_wait_entry(self, event):
a0b1f42c
JD
381 epfd = event["epfd"]
382 maxevents = event["maxevents"]
383 timeout = event["timeout"]
384
d40c2620 385 if epfd == self.epoll_wait_fd and maxevents == 1 and timeout == -1:
4c4634e3
FD
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()
a0b1f42c
JD
390
391 def epoll_wait_exit(self, event):
a0b1f42c
JD
392 ret = event["ret"]
393 fds_length = event["fds_length"]
394 overflow = event["overflow"]
a0b1f42c
JD
395
396 # check that FD 0 returned with EPOLLIN and the right data.fd
4c4634e3
FD
397 if ret == 1 and fds_length == 1:
398 fd_0 = event["fds"][0]
6a871bbe
KS
399 if (
400 overflow == 0
401 and fd_0["data_union"]["fd"] == 0
402 and fd_0["events"]["EPOLLIN"] == 1
403 ):
4c4634e3
FD
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()
a0b1f42c 408
d40c2620
JG
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]
6a871bbe
KS
428 if (
429 overflow == 0
430 and fd_0["data_union"]["fd"] == 0
431 and fd_0["events"]["EPOLLIN"] == 1
432 ):
d40c2620
JG
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()
a0b1f42c 437
6a871bbe 438
2a2ac572 439class WorkingCasesTimeout(TraceParser):
d40c2620 440 def __init__(self, trace, validation_args):
6a871bbe 441 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
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
a0b1f42c
JD
451
452 def select_entry(self, event):
a0b1f42c 453 n = event["n"]
a0b1f42c 454 tvp = event["tvp"]
a0b1f42c
JD
455
456 if n == 1 and tvp != 0:
4c4634e3 457 self.expect["select_entry"]["select_timeout_in_fd0"] = 1
a0b1f42c 458 if n == 1023:
4c4634e3
FD
459 readfd_127 = event["readfds"][127]
460 writefd_127 = event["writefds"][127]
461 exceptfd_127 = event["exceptfds"][127]
462
6a871bbe
KS
463 if (
464 readfd_127 == 0x40
465 and writefd_127 == 0
466 and exceptfd_127 == 0
467 and tvp != 0
468 ):
4c4634e3
FD
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()
a0b1f42c
JD
473
474 def select_exit(self, event):
a0b1f42c 475 ret = event["ret"]
a0b1f42c 476 tvp = event["tvp"]
a0b1f42c
JD
477
478 if ret == 0 and tvp != 0:
4c4634e3
FD
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()
a0b1f42c
JD
483
484 def poll_entry(self, event):
a0b1f42c
JD
485 nfds = event["nfds"]
486 fds_length = event["fds_length"]
a0b1f42c
JD
487
488 # check that we wait on FD 0 for POLLIN and that the raw_events
489 # field matches the value of POLLIN
4c4634e3
FD
490 if nfds == 1 and fds_length == 1:
491 fd_0 = event["fds"][0]
6a871bbe
KS
492 if (
493 fd_0["raw_events"] == 0x3
494 and fd_0["events"]["POLLIN"] == 1
495 and fd_0["events"]["padding"] == 0
496 ):
4c4634e3
FD
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()
a0b1f42c
JD
501
502 def poll_exit(self, event):
a0b1f42c
JD
503 ret = event["ret"]
504 nfds = event["nfds"]
505 fds_length = event["fds_length"]
a0b1f42c
JD
506
507 if ret == 0 and nfds == 1 and fds_length == 0:
4c4634e3
FD
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()
a0b1f42c
JD
512
513 def epoll_ctl_entry(self, event):
a0b1f42c 514 op_enum = event["op_enum"]
a0b1f42c
JD
515 _event = event["event"]
516
517 # make sure we see a EPOLLIN|EPOLLPRI
6a871bbe
KS
518 if (
519 "EPOLL_CTL_ADD" in op_enum.labels
520 and _event["events"]["EPOLLIN"] == 1
521 and _event["events"]["EPOLLPRI"] == 1
522 ):
4c4634e3
FD
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()
a0b1f42c
JD
527
528 def epoll_ctl_exit(self, event):
a0b1f42c
JD
529 ret = event["ret"]
530
531 if ret == 0:
4c4634e3
FD
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()
a0b1f42c
JD
536
537 def epoll_wait_entry(self, event):
a0b1f42c
JD
538 maxevents = event["maxevents"]
539 timeout = event["timeout"]
540
541 if maxevents == 1 and timeout == 1:
4c4634e3
FD
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()
a0b1f42c
JD
546
547 def epoll_wait_exit(self, event):
a0b1f42c
JD
548 ret = event["ret"]
549 fds_length = event["fds_length"]
550 overflow = event["overflow"]
a0b1f42c
JD
551
552 if ret == 0 and fds_length == 0 and overflow == 0:
4c4634e3
FD
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()
a0b1f42c
JD
557
558
2a2ac572 559class PselectInvalidFd(TraceParser):
d40c2620 560 def __init__(self, trace, validation_args):
6a871bbe 561 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
562 self.expect["select_entry"]["select_invalid_fd_in"] = 0
563 self.expect["select_exit"]["select_invalid_fd_out"] = 0
a0b1f42c
JD
564
565 def select_entry(self, event):
a0b1f42c
JD
566 n = event["n"]
567 overflow = event["overflow"]
a0b1f42c 568
8b3b99e2 569 if n > 0 and overflow == 0:
4c4634e3
FD
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()
a0b1f42c
JD
574
575 def select_exit(self, event):
a0b1f42c
JD
576 ret = event["ret"]
577 overflow = event["overflow"]
a0b1f42c 578 _readfds_length = event["_readfds_length"]
a0b1f42c 579
8b3b99e2 580 # make sure the event has a ret field equal to -EBADF
a0b1f42c 581 if ret == -9 and overflow == 0 and _readfds_length == 0:
4c4634e3
FD
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()
a0b1f42c
JD
586
587
2a2ac572 588class PpollBig(TraceParser):
d40c2620 589 def __init__(self, trace, validation_args):
6a871bbe 590 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
591 self.expect["poll_entry"]["big_poll_in"] = 0
592 self.expect["poll_exit"]["big_poll_out"] = 0
a0b1f42c
JD
593
594 def poll_entry(self, event):
a0b1f42c
JD
595 nfds = event["nfds"]
596 fds_length = event["fds_length"]
597 overflow = event["overflow"]
a0b1f42c
JD
598
599 # test of big list of FDs and the behaviour of the overflow
4c4634e3
FD
600 if nfds == 2047 and fds_length == 512 and overflow == 1:
601 fd_0 = event["fds"][0]
602 fd_511 = event["fds"][511]
6a871bbe
KS
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 ):
4c4634e3
FD
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()
a0b1f42c
JD
614
615 def poll_exit(self, event):
a0b1f42c
JD
616 ret = event["ret"]
617 nfds = event["nfds"]
618 fds_length = event["fds_length"]
619 overflow = event["overflow"]
a0b1f42c
JD
620
621 # test of big list of FDs and the behaviour of the overflow
4c4634e3 622 if ret == 2047 and nfds == 2047 and fds_length == 512 and overflow == 1:
6a871bbe
KS
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
a0b1f42c 627
4c4634e3
FD
628 # Save values of local variables to print in case of test failure
629 self.recorded_values["poll_exit"] = locals()
a0b1f42c 630
6a871bbe 631
2a2ac572 632class PpollFdsBufferOverflow(TraceParser):
d40c2620 633 def __init__(self, trace, validation_args):
6a871bbe 634 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
635 self.expect["poll_entry"]["poll_overflow_in"] = 0
636 self.expect["poll_exit"]["poll_overflow_out"] = 0
a0b1f42c
JD
637
638 def poll_entry(self, event):
a0b1f42c
JD
639 nfds = event["nfds"]
640 fds_length = event["fds_length"]
641 overflow = event["overflow"]
a0b1f42c
JD
642
643 # test that event in valid even though the target buffer is too small
644 # and the program segfaults
4c4634e3
FD
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()
a0b1f42c
JD
652
653 def poll_exit(self, event):
a0b1f42c 654 nfds = event["nfds"]
a0b1f42c 655 overflow = event["overflow"]
a0b1f42c
JD
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:
4c4634e3
FD
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()
a0b1f42c
JD
664
665
2a2ac572 666class PselectInvalidPointer(TraceParser):
d40c2620 667 def __init__(self, trace, validation_args):
6a871bbe 668 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
669 self.expect["select_entry"]["pselect_invalid_in"] = 0
670 self.expect["select_exit"]["pselect_invalid_out"] = 0
a0b1f42c
JD
671
672 def select_entry(self, event):
a0b1f42c
JD
673 n = event["n"]
674 overflow = event["overflow"]
a0b1f42c 675 _readfds_length = event["_readfds_length"]
a0b1f42c
JD
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:
4c4634e3
FD
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()
a0b1f42c
JD
684
685 def select_exit(self, event):
a0b1f42c
JD
686 ret = event["ret"]
687 overflow = event["overflow"]
a0b1f42c 688 _readfds_length = event["_readfds_length"]
a0b1f42c
JD
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:
4c4634e3
FD
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()
a0b1f42c
JD
697
698
2a2ac572 699class PpollFdsULongMax(TraceParser):
d40c2620 700 def __init__(self, trace, validation_args):
6a871bbe 701 super().__init__(trace, validation_args["pid"])
4c4634e3
FD
702 self.expect["poll_entry"]["poll_max_in"] = 0
703 self.expect["poll_exit"]["poll_max_out"] = 0
a0b1f42c
JD
704
705 def poll_entry(self, event):
a0b1f42c 706 nfds = event["nfds"]
a0b1f42c 707 overflow = event["overflow"]
a0b1f42c
JD
708
709 # check the proper working of INT_MAX maxevent value
710 if nfds == 4294967295 and overflow == 1:
4c4634e3
FD
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
a0b1f42c 716 def poll_exit(self, event):
a0b1f42c
JD
717 ret = event["ret"]
718 nfds = event["nfds"]
a0b1f42c 719 overflow = event["overflow"]
a0b1f42c
JD
720
721 # check the proper working of UINT_MAX maxevent value
722 if ret == -22 and nfds == 4294967295 and overflow == 0:
4c4634e3
FD
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()
a0b1f42c
JD
727
728
2a2ac572 729class EpollPwaitInvalidPointer(TraceParser):
d40c2620 730 def __init__(self, trace, validation_args):
6a871bbe 731 super().__init__(trace, validation_args["pid"])
d40c2620
JG
732
733 # Values expected in the trace
6a871bbe 734 self.epoll_fd = validation_args["epollfd"]
d40c2620 735
4c4634e3
FD
736 self.expect["epoll_wait_entry"]["epoll_wait_invalid_in"] = 0
737 self.expect["epoll_wait_exit"]["epoll_wait_invalid_out"] = 0
a0b1f42c
JD
738
739 def epoll_wait_entry(self, event):
a0b1f42c
JD
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
d40c2620 746 if epfd == self.epoll_fd and maxevents == 1 and timeout == -1:
4c4634e3
FD
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()
a0b1f42c
JD
751
752 def epoll_wait_exit(self, event):
a0b1f42c
JD
753 ret = event["ret"]
754 fds_length = event["fds_length"]
755 overflow = event["overflow"]
a0b1f42c
JD
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:
4c4634e3
FD
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()
a0b1f42c
JD
764
765
2a2ac572 766class EpollPwaitIntMax(TraceParser):
d40c2620 767 def __init__(self, trace, validation_args):
6a871bbe 768 super().__init__(trace, validation_args["pid"])
d40c2620
JG
769
770 # Values expected in the trace
6a871bbe 771 self.epoll_fd = validation_args["epollfd"]
d40c2620 772
4c4634e3
FD
773 self.expect["epoll_wait_entry"]["epoll_wait_max_in"] = 0
774 self.expect["epoll_wait_exit"]["epoll_wait_max_out"] = 0
a0b1f42c
JD
775
776 def epoll_wait_entry(self, event):
a0b1f42c
JD
777 epfd = event["epfd"]
778 maxevents = event["maxevents"]
779 timeout = event["timeout"]
780
781 # check the proper working of INT_MAX maxevent value
d40c2620 782 if epfd == self.epoll_fd and maxevents == 2147483647 and timeout == -1:
4c4634e3
FD
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()
a0b1f42c
JD
787
788 def epoll_wait_exit(self, event):
a0b1f42c
JD
789 ret = event["ret"]
790 fds_length = event["fds_length"]
791 overflow = event["overflow"]
a0b1f42c
JD
792
793 # check the proper working of INT_MAX maxevent value
794 if ret == -22 and fds_length == 0 and overflow == 0:
4c4634e3
FD
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()
a0b1f42c
JD
799
800
801if __name__ == "__main__":
6a871bbe
KS
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 )
a0b1f42c
JD
808 args = parser.parse_args()
809
810 if not args.test:
d40c2620 811 print("Need to pass a test to validate (--test/-t)")
a0b1f42c
JD
812 sys.exit(1)
813
d40c2620
JG
814 if not args.validation_file:
815 print("Need to pass the test validation file (--validation-file/-o)")
a0b1f42c
JD
816 sys.exit(1)
817
53f8be7a 818 traces = bt2.TraceCollectionMessageIterator(args.path)
a0b1f42c 819
d40c2620
JG
820 with open(args.validation_file) as f:
821 try:
822 test_validation_args = json.load(f)
823 except Exception as e:
6a871bbe 824 print("Failed to parse validation file: " + str(e))
d40c2620
JG
825 sys.exit(1)
826
a0b1f42c
JD
827 t = None
828
2a2ac572
JG
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":
a0b1f42c
JD
848 # stress test, nothing reliable to check
849 ret = 0
2a2ac572 850 elif args.test == "epoll_pwait_concurrent_munmap":
a0b1f42c
JD
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
a0b1f42c 860 sys.exit(ret)
This page took 0.090587 seconds and 4 git commands to generate.