Tests: triggers: Add syscall event rule condition filter tests
[lttng-tools.git] / tests / regression / tools / notification / notification.c
CommitLineData
434f8068
JR
1/*
2 * notification.c
3 *
4 * Tests suite for LTTng notification API
5 *
6 * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
7 *
9d16b343 8 * SPDX-License-Identifier: MIT
434f8068 9 *
434f8068
JR
10 */
11
12#include <assert.h>
13#include <math.h>
14#include <stdbool.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19#include <inttypes.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
854382b8 23#include <signal.h>
854382b8 24#include <poll.h>
434f8068 25
edf4b93e 26#include <common/compat/errno.h>
434f8068
JR
27#include <lttng/action/action.h>
28#include <lttng/action/notify.h>
29#include <lttng/condition/buffer-usage.h>
30#include <lttng/condition/condition.h>
31#include <lttng/condition/evaluation.h>
7948461b 32#include <lttng/condition/event-rule.h>
434f8068
JR
33#include <lttng/domain.h>
34#include <lttng/endpoint.h>
51704c8e 35#include <lttng/event-rule/kprobe.h>
aab0598f 36#include <lttng/event-rule/syscall.h>
7948461b 37#include <lttng/event-rule/tracepoint.h>
45294d8a 38#include <lttng/event-rule/uprobe.h>
51704c8e 39#include <lttng/kernel-probe.h>
434f8068 40#include <lttng/lttng-error.h>
7948461b 41#include <lttng/lttng.h>
434f8068
JR
42#include <lttng/notification/channel.h>
43#include <lttng/notification/notification.h>
44#include <lttng/trigger/trigger.h>
45294d8a 45#include <lttng/userspace-probe.h>
434f8068
JR
46
47#include <tap/tap.h>
48
434f8068
JR
49int nb_args = 0;
50int named_pipe_args_start = 0;
7344b6a3 51pid_t app_pid = 0;
854382b8
JR
52const char *app_state_file = NULL;
53
54static
55void wait_on_file(const char *path, bool file_exist)
56{
57 if (!path) {
58 return;
59 }
60 for (;;) {
61 int ret;
62 struct stat buf;
63
64 ret = stat(path, &buf);
65 if (ret == -1 && errno == ENOENT) {
66 if (file_exist) {
f0784451
FD
67 /*
68 * The file does not exist. wait a bit and
69 * continue looping until it does.
70 */
71 (void) poll(NULL, 0, 10);
72 continue;
854382b8 73 }
f0784451
FD
74
75 /*
76 * File does not exist and the exit condition we want.
77 * Break from the loop and return.
78 */
79 break;
854382b8
JR
80 }
81 if (ret) {
82 perror("stat");
83 exit(EXIT_FAILURE);
84 }
f0784451
FD
85 /*
86 * stat() returned 0, so the file exists. break now only if
87 * that's the exit condition we want.
88 */
89 if (file_exist) {
90 break;
91 }
854382b8
JR
92 }
93}
434f8068 94
f12eb9c1 95static
434f8068
JR
96int write_pipe(const char *path, uint8_t data)
97{
98 int ret = 0;
99 int fd = 0;
100
101 fd = open(path, O_WRONLY | O_NONBLOCK);
102 if (fd < 0) {
103 perror("Could not open consumer control named pipe");
104 goto end;
105 }
106
107 ret = write(fd, &data , sizeof(data));
108 if (ret < 1) {
109 perror("Named pipe write failed");
eff748d0
JR
110 if (close(fd)) {
111 perror("Named pipe close failed");
112 }
434f8068
JR
113 ret = -1;
114 goto end;
115 }
116
117 ret = close(fd);
118 if (ret < 0) {
119 perror("Name pipe closing failed");
120 ret = -1;
121 goto end;
122 }
123end:
124 return ret;
125}
126
f12eb9c1 127static
434f8068
JR
128int stop_consumer(const char **argv)
129{
9df6c82a
JG
130 int ret = 0, i;
131
132 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
133 ret = write_pipe(argv[i], 49);
134 }
135 return ret;
136}
137
f12eb9c1 138static
434f8068
JR
139int resume_consumer(const char **argv)
140{
9df6c82a
JG
141 int ret = 0, i;
142
143 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
144 ret = write_pipe(argv[i], 0);
145 }
146 return ret;
147}
148
f12eb9c1
SM
149static
150int suspend_application(void)
854382b8
JR
151{
152 int ret;
153 struct stat buf;
154
155 if (!stat(app_state_file, &buf)) {
156 fail("App is already in a suspended state.");
157 ret = -1;
158 goto error;
159 }
160
161 /*
162 * Send SIGUSR1 to application instructing it to bypass tracepoint.
163 */
7344b6a3
FD
164 assert(app_pid > 1);
165
854382b8
JR
166 ret = kill(app_pid, SIGUSR1);
167 if (ret) {
168 fail("SIGUSR1 failed. errno %d", errno);
169 ret = -1;
170 goto error;
171 }
172
173 wait_on_file(app_state_file, true);
174
175error:
176 return ret;
177
178}
179
f12eb9c1 180static
a3ecaea8 181int resume_application(void)
854382b8
JR
182{
183 int ret;
184 struct stat buf;
185
186 ret = stat(app_state_file, &buf);
187 if (ret == -1 && errno == ENOENT) {
188 fail("State file does not exist");
189 goto error;
190 }
191 if (ret) {
192 perror("stat");
193 goto error;
194 }
195
7344b6a3
FD
196 assert(app_pid > 1);
197
854382b8
JR
198 ret = kill(app_pid, SIGUSR1);
199 if (ret) {
200 fail("SIGUSR1 failed. errno %d", errno);
201 ret = -1;
202 goto error;
203 }
204
205 wait_on_file(app_state_file, false);
206
207error:
208 return ret;
209
210}
211
212
f12eb9c1 213static
434f8068
JR
214void test_triggers_buffer_usage_condition(const char *session_name,
215 const char *channel_name,
216 enum lttng_domain_type domain_type,
217 enum lttng_condition_type condition_type)
218{
9df6c82a 219 unsigned int test_vector_size = 5, i;
434f8068
JR
220 enum lttng_condition_status condition_status;
221 struct lttng_action *action;
222
223 /* Set-up */
224 action = lttng_action_notify_create();
225 if (!action) {
226 fail("Setup error on action creation");
227 goto end;
228 }
229
230 /* Test lttng_register_trigger with null value */
231 ok(lttng_register_trigger(NULL) == -LTTNG_ERR_INVALID, "Registering a NULL trigger fails as expected");
232
233 /* Test: register a trigger */
9df6c82a
JG
234
235 for (i = 0; i < pow(2,test_vector_size); i++) {
434f8068
JR
236 int loop_ret = 0;
237 char *test_tuple_string = NULL;
238 unsigned int mask_position = 0;
239 bool session_name_set = false;
240 bool channel_name_set = false;
241 bool threshold_ratio_set = false;
242 bool threshold_byte_set = false;
243 bool domain_type_set = false;
244
245 struct lttng_trigger *trigger = NULL;
246 struct lttng_condition *condition = NULL;
247
248 /* Create base condition */
249 switch (condition_type) {
250 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
251 condition = lttng_condition_buffer_usage_low_create();
252 break;
253 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
254 condition = lttng_condition_buffer_usage_high_create();
255 break;
256 default:
257 loop_ret = 1;
258 goto loop_end;
259 }
260
261 if (!condition) {
262 loop_ret = 1;
263 goto loop_end;
264
265 }
266
267 /* Prepare the condition for trigger registration test */
268
269 /* Set session name */
270 if ((1 << mask_position) & i) {
271 condition_status = lttng_condition_buffer_usage_set_session_name(
272 condition, session_name);
273 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
274 loop_ret = 1;
275 goto loop_end;
276 }
277 session_name_set = true;
278 }
279 mask_position++;
280
281 /* Set channel name */
282 if ((1 << mask_position) & i) {
283 condition_status = lttng_condition_buffer_usage_set_channel_name(
284 condition, channel_name);
285 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
286 loop_ret = 1;
287 goto loop_end;
288 }
289 channel_name_set = true;
290 }
291 mask_position++;
292
293 /* Set threshold ratio */
294 if ((1 << mask_position) & i) {
295 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
296 condition, 0.0);
297 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
298 loop_ret = 1;
299 goto loop_end;
300 }
301 threshold_ratio_set = true;
302 }
303 mask_position++;
304
305 /* Set threshold byte */
306 if ((1 << mask_position) & i) {
307 condition_status = lttng_condition_buffer_usage_set_threshold(
308 condition, 0);
309 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
310 loop_ret = 1;
311 goto loop_end;
312 }
313 threshold_byte_set = true;
314 }
315 mask_position++;
316
317 /* Set domain type */
318 if ((1 << mask_position) & i) {
319 condition_status = lttng_condition_buffer_usage_set_domain_type(
320 condition, LTTNG_DOMAIN_UST);
321 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
322 loop_ret = 1;
323 goto loop_end;
324 }
325 domain_type_set = true;
326 }
327
328 /* Safety check */
329 if (mask_position != test_vector_size -1) {
330 assert("Logic error for test vector generation");
331 }
332
9479b7a7 333 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
434f8068
JR
334 session_name_set ? "set" : "unset",
335 channel_name_set ? "set" : "unset",
336 threshold_ratio_set ? "set" : "unset",
337 threshold_byte_set ? "set" : "unset",
338 domain_type_set? "set" : "unset");
339 if (!test_tuple_string || loop_ret < 0) {
340 loop_ret = 1;
341 goto loop_end;
342 }
343
344 /* Create trigger */
345 trigger = lttng_trigger_create(condition, action);
346 if (!trigger) {
347 loop_ret = 1;
348 goto loop_end;
349 }
350
351 loop_ret = lttng_register_trigger(trigger);
352
353loop_end:
354 if (loop_ret == 1) {
355 fail("Setup error occurred for tuple: %s", test_tuple_string);
356 goto loop_cleanup;
357 }
358
359 /* This combination happens three times */
360 if (session_name_set && channel_name_set
361 && (threshold_ratio_set || threshold_byte_set)
362 && domain_type_set) {
363 ok(loop_ret == 0, "Trigger is registered: %s", test_tuple_string);
364
365 /*
366 * Test that a trigger cannot be registered
367 * multiple time.
368 */
369 loop_ret = lttng_register_trigger(trigger);
370 ok(loop_ret == -LTTNG_ERR_TRIGGER_EXISTS, "Re-register trigger fails as expected: %s", test_tuple_string);
371
372 /* Test that a trigger can be unregistered */
373 loop_ret = lttng_unregister_trigger(trigger);
374 ok(loop_ret == 0, "Unregister trigger: %s", test_tuple_string);
375
376 /*
377 * Test that unregistration of a non-previously
378 * registered trigger fail.
379 */
380 loop_ret = lttng_unregister_trigger(trigger);
43e0c204 381 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
434f8068
JR
382 } else {
383 ok(loop_ret == -LTTNG_ERR_INVALID_TRIGGER, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string);
384 }
385
386loop_cleanup:
387 free(test_tuple_string);
388 lttng_trigger_destroy(trigger);
389 lttng_condition_destroy(condition);
390 }
391
392end:
393 lttng_action_destroy(action);
394}
395
ff2b03c8
JG
396static
397void wait_data_pending(const char *session_name)
398{
399 int ret;
400
401 do {
402 ret = lttng_data_pending(session_name);
403 assert(ret >= 0);
404 } while (ret != 0);
405}
406
f12eb9c1 407static
17423302
FD
408int setup_buffer_usage_condition(struct lttng_condition *condition,
409 const char *condition_name,
410 const char *session_name,
411 const char *channel_name,
412 const enum lttng_domain_type domain_type)
413{
414 enum lttng_condition_status condition_status;
415 int ret = 0;
416
417 condition_status = lttng_condition_buffer_usage_set_session_name(
418 condition, session_name);
419 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
420 fail("Failed to set session name on creation of condition `%s`",
421 condition_name);
422 ret = -1;
423 goto end;
424 }
425
426 condition_status = lttng_condition_buffer_usage_set_channel_name(
427 condition, channel_name);
428 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
429 fail("Failed to set channel name on creation of condition `%s`",
430 condition_name);
431 ret = -1;
432 goto end;
433 }
434
435 condition_status = lttng_condition_buffer_usage_set_domain_type(
436 condition, domain_type);
437 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
438 fail("Failed to set domain type on creation of condition `%s`",
439 condition_name);
440 ret = -1;
441 goto end;
442 }
443
444end:
445 return ret;
446}
447
448static
90fcb2ec
FD
449void test_invalid_channel_subscription(
450 const enum lttng_domain_type domain_type)
434f8068 451{
434f8068
JR
452 enum lttng_condition_status condition_status;
453 enum lttng_notification_channel_status nc_status;
434f8068 454 struct lttng_condition *dummy_condition = NULL;
90fcb2ec
FD
455 struct lttng_condition *dummy_invalid_condition = NULL;
456 struct lttng_notification_channel *notification_channel = NULL;
457 int ret = 0;
434f8068 458
90fcb2ec
FD
459 notification_channel = lttng_notification_channel_create(
460 lttng_session_daemon_notification_endpoint);
461 ok(notification_channel, "Notification channel object creation");
462 if (!notification_channel) {
434f8068
JR
463 goto end;
464 }
465
90fcb2ec
FD
466 /*
467 * Create a dummy, empty (thus invalid) condition to test error paths.
468 */
434f8068
JR
469 dummy_invalid_condition = lttng_condition_buffer_usage_low_create();
470 if (!dummy_invalid_condition) {
471 fail("Setup error on condition creation");
472 goto end;
473 }
474
90fcb2ec
FD
475 /*
476 * Test subscription and unsubscription of an invalid condition to/from
477 * a channel.
478 */
479 nc_status = lttng_notification_channel_subscribe(
480 notification_channel, dummy_invalid_condition);
481 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
482 "Subscribing to an invalid condition");
483
484 nc_status = lttng_notification_channel_unsubscribe(
485 notification_channel, dummy_invalid_condition);
486 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
487 "Unsubscribing from an invalid condition");
488
434f8068
JR
489 /* Create a valid dummy condition with a ratio of 0.5 */
490 dummy_condition = lttng_condition_buffer_usage_low_create();
491 if (!dummy_condition) {
492 fail("Setup error on dummy_condition creation");
493 goto end;
434f8068 494 }
90fcb2ec 495
434f8068
JR
496 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
497 dummy_condition, 0.5);
498 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
499 fail("Setup error on condition creation");
500 goto end;
501 }
502
17423302 503 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
90fcb2ec 504 "dummy_session", "dummy_channel", domain_type);
17423302
FD
505 if (ret) {
506 fail("Setup error on dummy condition creation");
434f8068
JR
507 goto end;
508 }
509
90fcb2ec
FD
510 /*
511 * Test subscription and unsubscription to/from a channel with invalid
512 * parameters.
513 */
514 nc_status = lttng_notification_channel_subscribe(NULL, NULL);
515 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
516 "Notification channel subscription is invalid: NULL, NULL");
517
518 nc_status = lttng_notification_channel_subscribe(
519 notification_channel, NULL);
520 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
521 "Notification channel subscription is invalid: NON-NULL, NULL");
522
523 nc_status = lttng_notification_channel_subscribe(NULL, dummy_condition);
524 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
525 "Notification channel subscription is invalid: NULL, NON-NULL");
526
527 nc_status = lttng_notification_channel_unsubscribe(
528 notification_channel, dummy_condition);
529 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION,
530 "Unsubscribing from a valid unknown condition");
531
532end:
533 lttng_notification_channel_destroy(notification_channel);
534 lttng_condition_destroy(dummy_invalid_condition);
535 lttng_condition_destroy(dummy_condition);
536 return;
537}
538
3780613c
FD
539enum buffer_usage_type {
540 BUFFER_USAGE_TYPE_LOW,
541 BUFFER_USAGE_TYPE_HIGH,
542};
543
544static int register_buffer_usage_notify_trigger(const char *session_name,
90fcb2ec
FD
545 const char *channel_name,
546 const enum lttng_domain_type domain_type,
3780613c
FD
547 enum buffer_usage_type buffer_usage_type,
548 double ratio,
549 struct lttng_condition **condition,
550 struct lttng_action **action,
551 struct lttng_trigger **trigger)
90fcb2ec 552{
90fcb2ec 553 enum lttng_condition_status condition_status;
3780613c
FD
554 struct lttng_action *tmp_action = NULL;
555 struct lttng_condition *tmp_condition = NULL;
556 struct lttng_trigger *tmp_trigger = NULL;
557 int ret = 0;
90fcb2ec
FD
558
559 /* Set-up */
3780613c 560 tmp_action = lttng_action_notify_create();
90fcb2ec
FD
561 if (!action) {
562 fail("Setup error on action creation");
3780613c
FD
563 ret = -1;
564 goto error;
434f8068
JR
565 }
566
3780613c
FD
567 if (buffer_usage_type == BUFFER_USAGE_TYPE_LOW) {
568 tmp_condition = lttng_condition_buffer_usage_low_create();
569 } else {
570 tmp_condition = lttng_condition_buffer_usage_high_create();
434f8068
JR
571 }
572
3780613c
FD
573 if (!tmp_condition) {
574 fail("Setup error on condition creation");
575 ret = -1;
576 goto error;
434f8068
JR
577 }
578
3780613c 579 /* Set the buffer usage threashold */
434f8068 580 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
3780613c 581 tmp_condition, ratio);
434f8068 582 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
3780613c
FD
583 fail("Setup error on condition creation");
584 ret = -1;
585 goto error;
434f8068
JR
586 }
587
3780613c 588 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
17423302
FD
589 session_name, channel_name, domain_type);
590 if (ret) {
3780613c
FD
591 fail("Setup error on condition creation");
592 ret = -1;
593 goto error;
434f8068
JR
594 }
595
3780613c
FD
596 /* Register the trigger for condition. */
597 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
598 if (!tmp_trigger) {
599 fail("Setup error on trigger creation");
600 ret = -1;
601 goto error;
434f8068
JR
602 }
603
3780613c 604 ret = lttng_register_trigger(tmp_trigger);
434f8068 605 if (ret) {
3780613c
FD
606 fail("Setup error on trigger registration");
607 ret = -1;
608 goto error;
434f8068
JR
609 }
610
3780613c
FD
611 *condition = tmp_condition;
612 *trigger = tmp_trigger;
613 *action = tmp_action;
614 goto end;
434f8068 615
3780613c
FD
616error:
617 lttng_action_destroy(tmp_action);
618 lttng_condition_destroy(tmp_condition);
619 lttng_trigger_destroy(tmp_trigger);
620
621end:
622 return ret;
623}
624
fa448dbe
FD
625static void test_subscription_twice(const char *session_name,
626 const char *channel_name,
627 const enum lttng_domain_type domain_type)
628{
629 int ret = 0;
630 enum lttng_notification_channel_status nc_status;
631
632 struct lttng_action *action = NULL;
633 struct lttng_notification_channel *notification_channel = NULL;
634 struct lttng_trigger *trigger = NULL;
635
636 struct lttng_condition *condition = NULL;
637
638 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
639 domain_type, BUFFER_USAGE_TYPE_LOW, 0.99, &condition,
640 &action, &trigger);
641 if (ret) {
642 fail("Setup error on trigger registration");
643 goto end;
644 }
645
646 /* Begin testing. */
647 notification_channel = lttng_notification_channel_create(
648 lttng_session_daemon_notification_endpoint);
649 ok(notification_channel, "Notification channel object creation");
650 if (!notification_channel) {
651 goto end;
652 }
653
654 /* Subscribe a valid condition. */
655 nc_status = lttng_notification_channel_subscribe(
656 notification_channel, condition);
657 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
658 "Subscribe to condition");
659
660 /* Subscribing again should fail. */
661 nc_status = lttng_notification_channel_subscribe(
662 notification_channel, condition);
663 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED,
664 "Subscribe to a condition for which subscription was already done");
665
666end:
667 lttng_unregister_trigger(trigger);
668 lttng_trigger_destroy(trigger);
669 lttng_notification_channel_destroy(notification_channel);
670 lttng_action_destroy(action);
671 lttng_condition_destroy(condition);
672}
673
40ac6709 674static void test_buffer_usage_notification_channel(const char *session_name,
3780613c
FD
675 const char *channel_name,
676 const enum lttng_domain_type domain_type,
677 const char **argv)
678{
679 int ret = 0;
680 enum lttng_notification_channel_status nc_status;
681
682 struct lttng_action *low_action = NULL;
683 struct lttng_action *high_action = NULL;
684 struct lttng_notification *notification = NULL;
685 struct lttng_notification_channel *notification_channel = NULL;
686 struct lttng_trigger *low_trigger = NULL;
687 struct lttng_trigger *high_trigger = NULL;
688
689 struct lttng_condition *low_condition = NULL;
690 struct lttng_condition *high_condition = NULL;
691
692 const double low_ratio = 0.0;
693 const double high_ratio = 0.90;
694
695 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
696 domain_type, BUFFER_USAGE_TYPE_LOW, low_ratio,
697 &low_condition, &low_action, &low_trigger);
698 if (ret) {
699 fail("Setup error on low trigger registration");
434f8068
JR
700 goto end;
701 }
702
3780613c
FD
703 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
704 domain_type, BUFFER_USAGE_TYPE_HIGH, high_ratio,
705 &high_condition, &high_action, &high_trigger);
434f8068
JR
706 if (ret) {
707 fail("Setup error on high trigger registration");
708 goto end;
709 }
710
711 /* Begin testing */
a6ae2480
FD
712 notification_channel = lttng_notification_channel_create(
713 lttng_session_daemon_notification_endpoint);
434f8068
JR
714 ok(notification_channel, "Notification channel object creation");
715 if (!notification_channel) {
716 goto end;
717 }
718
434f8068 719 /* Subscribe a valid low condition */
a6ae2480
FD
720 nc_status = lttng_notification_channel_subscribe(
721 notification_channel, low_condition);
722 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 723 "Subscribe to low condition");
434f8068
JR
724
725 /* Subscribe a valid high condition */
a6ae2480
FD
726 nc_status = lttng_notification_channel_subscribe(
727 notification_channel, high_condition);
728 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 729 "Subscribe to high condition");
434f8068 730
7676e0d2
FD
731 resume_application();
732
434f8068 733 /* Wait for notification to happen */
434f8068 734 stop_consumer(argv);
ff2b03c8 735 lttng_start_tracing(session_name);
434f8068
JR
736
737 /* Wait for high notification */
67c93c15 738 do {
a6ae2480
FD
739 nc_status = lttng_notification_channel_get_next_notification(
740 notification_channel, &notification);
67c93c15 741 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
742 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
743 lttng_condition_get_type(lttng_notification_get_condition(
744 notification)) ==
745 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
746 "High notification received after intermediary communication");
747 lttng_notification_destroy(notification);
748 notification = NULL;
749
854382b8 750 suspend_application();
ff2b03c8 751 lttng_stop_tracing_no_wait(session_name);
434f8068 752 resume_consumer(argv);
ff2b03c8 753 wait_data_pending(session_name);
434f8068
JR
754
755 /*
756 * Test that communication still work even if there is notification
757 * waiting for consumption.
758 */
759
a6ae2480
FD
760 nc_status = lttng_notification_channel_unsubscribe(
761 notification_channel, low_condition);
762 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
763 "Unsubscribe with pending notification");
434f8068 764
a6ae2480
FD
765 nc_status = lttng_notification_channel_subscribe(
766 notification_channel, low_condition);
767 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
768 "Subscribe with pending notification");
434f8068 769
67c93c15 770 do {
a6ae2480
FD
771 nc_status = lttng_notification_channel_get_next_notification(
772 notification_channel, &notification);
67c93c15 773 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
774 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
775 lttng_condition_get_type(lttng_notification_get_condition(
776 notification)) ==
777 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
778 "Low notification received after intermediary communication");
779 lttng_notification_destroy(notification);
780 notification = NULL;
781
782 /* Stop consumer to force a high notification */
ff2b03c8 783 stop_consumer(argv);
854382b8 784 resume_application();
434f8068 785 lttng_start_tracing(session_name);
434f8068 786
67c93c15 787 do {
a6ae2480
FD
788 nc_status = lttng_notification_channel_get_next_notification(
789 notification_channel, &notification);
67c93c15 790 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 791 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
792 lttng_condition_get_type(lttng_notification_get_condition(
793 notification)) ==
794 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
795 "High notification received after intermediary communication");
796 lttng_notification_destroy(notification);
797 notification = NULL;
798
854382b8 799 suspend_application();
ff2b03c8 800 lttng_stop_tracing_no_wait(session_name);
434f8068 801 resume_consumer(argv);
ff2b03c8 802 wait_data_pending(session_name);
434f8068 803
67c93c15 804 do {
a6ae2480
FD
805 nc_status = lttng_notification_channel_get_next_notification(
806 notification_channel, &notification);
67c93c15 807 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 808 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
809 lttng_condition_get_type(lttng_notification_get_condition(
810 notification)) ==
811 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
812 "Low notification received after re-subscription");
813 lttng_notification_destroy(notification);
814 notification = NULL;
815
ff2b03c8 816 stop_consumer(argv);
854382b8 817 resume_application();
434f8068
JR
818 /* Stop consumer to force a high notification */
819 lttng_start_tracing(session_name);
434f8068 820
67c93c15 821 do {
a6ae2480
FD
822 nc_status = lttng_notification_channel_get_next_notification(
823 notification_channel, &notification);
67c93c15 824 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 825 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
826 lttng_condition_get_type(lttng_notification_get_condition(
827 notification)) ==
828 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
829 "High notification");
830 lttng_notification_destroy(notification);
831 notification = NULL;
832
ff2b03c8 833 suspend_application();
7676e0d2
FD
834
835 /* Resume consumer to allow event consumption */
ff2b03c8 836 lttng_stop_tracing_no_wait(session_name);
434f8068 837 resume_consumer(argv);
ff2b03c8 838 wait_data_pending(session_name);
434f8068 839
a6ae2480
FD
840 nc_status = lttng_notification_channel_unsubscribe(
841 notification_channel, low_condition);
842 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
843 "Unsubscribe low condition with pending notification");
844
845 nc_status = lttng_notification_channel_unsubscribe(
846 notification_channel, high_condition);
847 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
848 "Unsubscribe high condition with pending notification");
434f8068
JR
849
850end:
851 lttng_notification_channel_destroy(notification_channel);
3780613c
FD
852 lttng_trigger_destroy(low_trigger);
853 lttng_trigger_destroy(high_trigger);
854 lttng_action_destroy(low_action);
855 lttng_action_destroy(high_action);
434f8068 856 lttng_condition_destroy(low_condition);
eff748d0 857 lttng_condition_destroy(high_condition);
434f8068
JR
858}
859
7948461b
FD
860static void create_tracepoint_event_rule_trigger(const char *event_pattern,
861 const char *trigger_name,
862 const char *filter,
863 unsigned int exclusion_count,
3e4ee3b3 864 const char * const *exclusions,
7948461b
FD
865 enum lttng_domain_type domain_type,
866 struct lttng_condition **condition,
867 struct lttng_trigger **trigger)
868{
869 enum lttng_event_rule_status event_rule_status;
870 enum lttng_trigger_status trigger_status;
871
872 struct lttng_action *tmp_action = NULL;
873 struct lttng_event_rule *event_rule = NULL;
874 struct lttng_condition *tmp_condition = NULL;
875 struct lttng_trigger *tmp_trigger = NULL;
876 int ret;
877
878 assert(event_pattern);
879 assert(trigger_name);
880 assert(condition);
881 assert(trigger);
882
883 event_rule = lttng_event_rule_tracepoint_create(domain_type);
884 ok(event_rule, "Tracepoint event rule object creation");
885
886 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
887 event_rule, event_pattern);
888 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
889 "Setting tracepoint event rule pattern: '%s'",
890 event_pattern);
891
892 if (filter) {
893 event_rule_status = lttng_event_rule_tracepoint_set_filter(
894 event_rule, filter);
895 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
896 "Setting tracepoint event rule filter: '%s'",
897 filter);
898 }
899
900 if (exclusions) {
901 int i;
902 bool success = true;
903
904 assert(domain_type == LTTNG_DOMAIN_UST);
905 assert(exclusion_count > 0);
906
907 for (i = 0; i < exclusion_count; i++) {
908 event_rule_status =
909 lttng_event_rule_tracepoint_add_exclusion(
910 event_rule,
911 exclusions[i]);
912 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
913 fail("Setting tracepoint event rule exclusion '%s'.",
914 exclusions[i]);
915 success = false;
916 }
917 }
918
919 ok(success, "Setting tracepoint event rule exclusions");
920 }
921
922 tmp_condition = lttng_condition_event_rule_create(event_rule);
923 ok(tmp_condition, "Condition event rule object creation");
924
925 tmp_action = lttng_action_notify_create();
926 ok(tmp_action, "Action event rule object creation");
927
928 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
929 ok(tmp_trigger, "Trigger object creation %s", trigger_name);
930
931 trigger_status = lttng_trigger_set_name(tmp_trigger, trigger_name);
932 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
933 "Setting name to trigger %s", trigger_name);
934
935 ret = lttng_register_trigger(tmp_trigger);
936 ok(ret == 0, "Trigger registration %s", trigger_name);
937
938 lttng_event_rule_destroy(event_rule);
939
940 *condition = tmp_condition;
941 *trigger = tmp_trigger;
942
943 return;
944}
945
946static char *get_next_notification_trigger_name(
947 struct lttng_notification_channel *notification_channel)
948{
949 struct lttng_notification *notification;
950 enum lttng_notification_channel_status status;
951 const struct lttng_evaluation *notification_evaluation;
952 char *trigger_name = NULL;
953 const char *name;
954 enum lttng_condition_type notification_evaluation_type;
955
956 /* Receive the next notification. */
957 status = lttng_notification_channel_get_next_notification(
958 notification_channel, &notification);
959
960 switch (status) {
961 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
962 break;
963 default:
964 /* Unhandled conditions / errors. */
965 fail("Failed to get next notification channel notification: status = %d",
966 status);
967 goto end;
968 }
969
970 notification_evaluation =
971 lttng_notification_get_evaluation(notification);
972
973 notification_evaluation_type =
974 lttng_evaluation_get_type(notification_evaluation);
975 switch (notification_evaluation_type) {
976 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
977 lttng_evaluation_event_rule_get_trigger_name(
978 notification_evaluation, &name);
979
980 trigger_name = strdup(name);
981 break;
982 default:
983 fail("Unexpected notification evaluation type: notification type = %d",
984 notification_evaluation_type);
985 break;
986 }
987
988 lttng_notification_destroy(notification);
989
990end:
991 return trigger_name;
992}
993
994static void test_tracepoint_event_rule_notification(
995 enum lttng_domain_type domain_type)
996{
997 int i;
998 const int notification_count = 3;
999 enum lttng_notification_channel_status nc_status;
1000 struct lttng_action *action = NULL;
1001 struct lttng_condition *condition = NULL;
1002 struct lttng_notification_channel *notification_channel = NULL;
1003 struct lttng_trigger *trigger = NULL;
1004 const char * const trigger_name = "my_precious";
1005 const char *pattern;
1006
1007 if (domain_type == LTTNG_DOMAIN_UST) {
1008 pattern = "tp:tptest";
1009 } else {
1010 pattern = "lttng_test_filter_event";
1011 }
1012
1013 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
1014 NULL, domain_type, &condition, &trigger);
1015
1016 notification_channel = lttng_notification_channel_create(
1017 lttng_session_daemon_notification_endpoint);
1018 ok(notification_channel, "Notification channel object creation");
1019
1020 nc_status = lttng_notification_channel_subscribe(
1021 notification_channel, condition);
1022 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1023 "Subscribe to tracepoint event rule condition");
1024
1025 resume_application();
1026
1027 /* Get 3 notifications. */
1028 for (i = 0; i < notification_count; i++) {
1029 char *name = get_next_notification_trigger_name(
1030 notification_channel);
1031
1032 ok(strcmp(trigger_name, name) == 0,
1033 "Received notification for the expected trigger name: '%s' (%d/%d)",
1034 trigger_name, i + 1, notification_count);
1035 free(name);
1036 }
1037
1038 suspend_application();
1039 lttng_notification_channel_destroy(notification_channel);
1040 lttng_unregister_trigger(trigger);
1041 lttng_trigger_destroy(trigger);
1042 lttng_action_destroy(action);
1043 lttng_condition_destroy(condition);
1044 return;
1045}
1046
a740a242
FD
1047static void test_tracepoint_event_rule_notification_filter(
1048 enum lttng_domain_type domain_type)
1049{
1050 int i;
1051 enum lttng_notification_channel_status nc_status;
1052
1053 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1054 struct lttng_notification_channel *notification_channel = NULL;
1055 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1056 const char * const ctrl_trigger_name = "control_trigger";
1057 const char * const trigger_name = "trigger";
1058 const char *pattern;
1059 int ctrl_count = 0, count = 0;
1060
1061 if (domain_type == LTTNG_DOMAIN_UST) {
1062 pattern = "tp:tptest";
1063 } else {
1064 pattern = "lttng_test_filter_event";
1065 }
1066
1067 notification_channel = lttng_notification_channel_create(
1068 lttng_session_daemon_notification_endpoint);
1069 ok(notification_channel, "Notification channel object creation");
1070
1071 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
1072 0, NULL, domain_type, &ctrl_condition, &ctrl_trigger);
1073
1074 nc_status = lttng_notification_channel_subscribe(
1075 notification_channel, ctrl_condition);
1076 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1077 "Subscribe to tracepoint event rule condition");
1078
1079 /*
1080 * Attach a filter expression to get notification only if the
1081 * `intfield` is even.
1082 */
1083 create_tracepoint_event_rule_trigger(pattern, trigger_name,
1084 "(intfield & 1) == 0", 0, NULL, domain_type, &condition,
1085 &trigger);
1086
1087 nc_status = lttng_notification_channel_subscribe(
1088 notification_channel, condition);
1089 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1090 "Subscribe to tracepoint event rule condition");
1091
1092 /*
1093 * We registered 2 notifications triggers, one with a filter and one
1094 * without (control). The one with a filter will only fired when the
1095 * `intfield` is a multiple of 2. We should get two times as many
1096 * control notifications as filter notifications.
1097 */
1098 resume_application();
1099
1100 /*
1101 * Get 3 notifications. We should get 1 for the regular trigger (with
1102 * the filter) and 2 from the control trigger. This works whatever
1103 * the order we receive the notifications.
1104 */
1105 for (i = 0; i < 3; i++) {
1106 char *name = get_next_notification_trigger_name(
1107 notification_channel);
1108
1109 if (strcmp(ctrl_trigger_name, name) == 0) {
1110 ctrl_count++;
1111 } else if (strcmp(trigger_name, name) == 0) {
1112 count++;
1113 }
1114
1115 free(name);
1116 }
1117
1118 ok(ctrl_count / 2 == count,
1119 "Get twice as many control notif as of regular notif");
1120
1121 suspend_application();
1122
1123 lttng_unregister_trigger(trigger);
1124 lttng_unregister_trigger(ctrl_trigger);
1125 lttng_notification_channel_destroy(notification_channel);
1126 lttng_trigger_destroy(trigger);
1127 lttng_trigger_destroy(ctrl_trigger);
1128 lttng_condition_destroy(condition);
1129 lttng_condition_destroy(ctrl_condition);
1130}
1131
3e4ee3b3
FD
1132static void test_tracepoint_event_rule_notification_exclusion(
1133 enum lttng_domain_type domain_type)
1134{
1135 enum lttng_notification_channel_status nc_status;
1136 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1137 struct lttng_notification_channel *notification_channel = NULL;
1138 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1139 int ctrl_count = 0, count = 0, i;
1140 const char * const ctrl_trigger_name = "control_exclusion_trigger";
1141 const char * const trigger_name = "exclusion_trigger";
1142 const char * const pattern = "tp:tptest*";
1143 const char * const exclusions[] = {
1144 "tp:tptest2",
1145 "tp:tptest3",
1146 "tp:tptest4",
1147 "tp:tptest5"
1148 };
1149
1150 notification_channel = lttng_notification_channel_create(
1151 lttng_session_daemon_notification_endpoint);
1152 ok(notification_channel, "Notification channel object creation");
1153
1154 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
1155 0, NULL, domain_type, &ctrl_condition, &ctrl_trigger);
1156
1157 nc_status = lttng_notification_channel_subscribe(
1158 notification_channel, ctrl_condition);
1159 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1160 "Subscribe to tracepoint event rule condition");
1161
1162 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 4,
1163 exclusions, domain_type, &condition, &trigger);
1164
1165 nc_status = lttng_notification_channel_subscribe(
1166 notification_channel, condition);
1167 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1168 "Subscribe to tracepoint event rule condition");
1169
1170 /*
1171 * We registered 2 notifications triggers, one with an exclusion and
1172 * one without (control).
1173 * - The trigger with an exclusion will fire once every iteration.
1174 * - The trigger without an exclusion will fire 5 times every
1175 * iteration.
1176 *
1177 * We should get 5 times as many notifications from the control
1178 * trigger.
1179 */
1180 resume_application();
1181
1182 /*
1183 * Get 6 notifications. We should get 1 for the regular trigger (with
1184 * the exclusion) and 5 from the control trigger. This works whatever
1185 * the order we receive the notifications.
1186 */
1187 for (i = 0; i < 6; i++) {
1188 char *name = get_next_notification_trigger_name(
1189 notification_channel);
1190
1191 if (strcmp(ctrl_trigger_name, name) == 0) {
1192 ctrl_count++;
1193 } else if (strcmp(trigger_name, name) == 0) {
1194 count++;
1195 }
1196
1197 free(name);
1198 }
1199
1200 ok(ctrl_count / 5 == count,
1201 "Got 5 times as many control notif as of regular notif");
1202
1203 suspend_application();
1204
1205 lttng_unregister_trigger(trigger);
1206 lttng_unregister_trigger(ctrl_trigger);
1207 lttng_notification_channel_destroy(notification_channel);
1208 lttng_trigger_destroy(trigger);
1209 lttng_trigger_destroy(ctrl_trigger);
1210 lttng_condition_destroy(condition);
1211 lttng_condition_destroy(ctrl_condition);
1212 return;
1213}
1214
51704c8e
FD
1215static void test_kprobe_event_rule_notification(
1216 enum lttng_domain_type domain_type)
1217{
1218 int i, ret;
1219 const int notification_count = 3;
1220 enum lttng_notification_channel_status nc_status;
1221 enum lttng_event_rule_status event_rule_status;
1222 enum lttng_trigger_status trigger_status;
1223 struct lttng_notification_channel *notification_channel = NULL;
1224 struct lttng_condition *condition = NULL;
1225 struct lttng_kernel_probe_location *location = NULL;
1226 struct lttng_event_rule *event_rule = NULL;
1227 struct lttng_action *action = NULL;
1228 struct lttng_trigger *trigger = NULL;
1229 const char * const trigger_name = "kprobe_trigger";
1230 const char * const symbol_name = "lttng_test_filter_event_write";
1231
1232 action = lttng_action_notify_create();
1233 if (!action) {
1234 fail("Failed to create notify action");
1235 goto end;
1236 }
1237
1238 location = lttng_kernel_probe_location_symbol_create(symbol_name, 0);
1239 if (!location) {
1240 fail("Failed to create kernel probe location");
1241 goto end;
1242 }
1243
1244 notification_channel = lttng_notification_channel_create(
1245 lttng_session_daemon_notification_endpoint);
1246 ok(notification_channel, "Notification channel object creation");
1247
1248 event_rule = lttng_event_rule_kprobe_create();
1249 ok(event_rule, "kprobe event rule object creation");
1250
1251 event_rule_status = lttng_event_rule_kprobe_set_location(
1252 event_rule, location);
1253 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1254 "Setting kprobe event rule location: '%s'", symbol_name);
1255
1256 event_rule_status = lttng_event_rule_kprobe_set_name(
1257 event_rule, trigger_name);
1258 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1259 "Setting kprobe event rule name: '%s'", trigger_name);
1260
1261 condition = lttng_condition_event_rule_create(event_rule);
1262 ok(condition, "Condition event rule object creation");
1263
1264 /* Register the trigger for condition. */
1265 trigger = lttng_trigger_create(condition, action);
1266 if (!trigger) {
1267 fail("Failed to create trigger with kernel probe event rule condition and notify action");
1268 goto end;
1269 }
1270
1271 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1272 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1273 "Setting trigger name to '%s'", trigger_name);
1274
1275 ret = lttng_register_trigger(trigger);
1276 if (ret) {
1277 fail("Failed to register trigger with kernel probe event rule condition and notify action");
1278 goto end;
1279 }
1280
1281 nc_status = lttng_notification_channel_subscribe(
1282 notification_channel, condition);
1283 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1284 "Subscribe to tracepoint event rule condition");
1285
1286 resume_application();
1287
1288 for (i = 0; i < notification_count; i++) {
1289 char *name = get_next_notification_trigger_name(
1290 notification_channel);
1291
1292 ok(strcmp(trigger_name, name) == 0,
1293 "Received notification for the expected trigger name: '%s' (%d/%d)",
1294 trigger_name, i + 1, notification_count);
1295 free(name);
1296 }
1297
1298end:
1299 suspend_application();
1300 lttng_notification_channel_destroy(notification_channel);
1301 lttng_unregister_trigger(trigger);
1302 lttng_trigger_destroy(trigger);
1303 lttng_action_destroy(action);
aab0598f 1304 lttng_event_rule_destroy(event_rule);
51704c8e
FD
1305 lttng_condition_destroy(condition);
1306 lttng_kernel_probe_location_destroy(location);
1307 return;
1308}
1309
45294d8a
FD
1310static void test_uprobe_event_rule_notification(
1311 enum lttng_domain_type domain_type,
1312 const char *testapp_path,
1313 const char *test_symbol_name)
1314{
1315 int i, ret;
1316 const int notification_count = 3;
1317 enum lttng_notification_channel_status nc_status;
1318 enum lttng_event_rule_status event_rule_status;
1319 enum lttng_trigger_status trigger_status;
1320 struct lttng_notification_channel *notification_channel = NULL;
1321 struct lttng_userspace_probe_location *probe_location = NULL;
1322 struct lttng_userspace_probe_location_lookup_method *lookup_method =
1323 NULL;
1324 struct lttng_condition *condition = NULL;
1325 struct lttng_event_rule *event_rule = NULL;
1326 struct lttng_action *action = NULL;
1327 struct lttng_trigger *trigger = NULL;
1328 const char * const trigger_name = "uprobe_trigger";
1329
1330 action = lttng_action_notify_create();
1331 if (!action) {
1332 fail("Failed to create notify action");
1333 goto end;
1334 }
1335
1336 lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
1337 if (!lookup_method) {
1338 fail("Setup error on userspace probe lookup method creation");
1339 goto end;
1340 }
1341
1342 probe_location = lttng_userspace_probe_location_function_create(
1343 testapp_path, test_symbol_name, lookup_method);
1344 if (!probe_location) {
1345 fail("Failed to create userspace probe location");
1346 goto end;
1347 }
1348
1349 notification_channel = lttng_notification_channel_create(
1350 lttng_session_daemon_notification_endpoint);
1351 ok(notification_channel, "Notification channel object creation");
1352
1353 event_rule = lttng_event_rule_uprobe_create();
1354 ok(event_rule, "kprobe event rule object creation");
1355
1356 event_rule_status = lttng_event_rule_uprobe_set_location(
1357 event_rule, probe_location);
1358 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1359 "Setting uprobe event rule location");
1360
1361 event_rule_status = lttng_event_rule_uprobe_set_name(
1362 event_rule, trigger_name);
1363 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1364 "Setting uprobe event rule name: '%s'", trigger_name);
1365
1366 condition = lttng_condition_event_rule_create(event_rule);
1367 ok(condition, "Condition event rule object creation");
1368
1369 /* Register the trigger for condition. */
1370 trigger = lttng_trigger_create(condition, action);
1371 if (!trigger) {
1372 fail("Failed to create trigger with userspace probe event rule condition and notify action");
1373 goto end;
1374 }
1375
1376 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1377 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1378 "Setting name to trigger '%s'", trigger_name);
1379
1380 ret = lttng_register_trigger(trigger);
1381 if (ret) {
1382 fail("Failed to register trigger with userspace probe event rule condition and notify action");
1383 goto end;
1384 }
1385
1386 nc_status = lttng_notification_channel_subscribe(
1387 notification_channel, condition);
1388 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1389 "Subscribe to tracepoint event rule condition");
1390
1391 resume_application();
1392
1393 for (i = 0; i < notification_count; i++) {
1394 char *name = get_next_notification_trigger_name(
1395 notification_channel);
1396
1397 ok(strcmp(trigger_name, name) == 0,
1398 "Received notification for the expected trigger name: '%s' (%d/%d)",
1399 trigger_name, i + 1, notification_count);
1400 free(name);
1401 }
1402end:
1403 suspend_application();
1404
1405 lttng_notification_channel_destroy(notification_channel);
1406 lttng_unregister_trigger(trigger);
1407 lttng_trigger_destroy(trigger);
1408 lttng_action_destroy(action);
1409 lttng_event_rule_destroy(event_rule);
1410 lttng_condition_destroy(condition);
1411 return;
1412}
1413
aab0598f
FD
1414static void test_syscall_event_rule_notification(
1415 enum lttng_domain_type domain_type)
1416{
1417 int i, ret;
1418 const int notification_count = 3;
1419 enum lttng_notification_channel_status nc_status;
1420 enum lttng_event_rule_status event_rule_status;
1421 enum lttng_trigger_status trigger_status;
1422 struct lttng_notification_channel *notification_channel = NULL;
1423 struct lttng_condition *condition = NULL;
1424 struct lttng_event_rule *event_rule = NULL;
1425 struct lttng_action *action = NULL;
1426 struct lttng_trigger *trigger = NULL;
1427 const char * const trigger_name = "syscall_trigger";
1428 const char * const syscall_name = "openat";
1429
1430 action = lttng_action_notify_create();
1431 if (!action) {
1432 fail("Failed to create notify action");
1433 goto end;
1434 }
1435
1436 notification_channel = lttng_notification_channel_create(
1437 lttng_session_daemon_notification_endpoint);
1438 ok(notification_channel, "Notification channel object creation");
1439
1440 event_rule = lttng_event_rule_syscall_create();
1441 ok(event_rule, "syscall event rule object creation");
1442
1443 event_rule_status = lttng_event_rule_syscall_set_pattern(
1444 event_rule, syscall_name);
1445 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1446 "Setting syscall event rule pattern: '%s'", syscall_name);
1447
1448 condition = lttng_condition_event_rule_create(event_rule);
1449 ok(condition, "Condition syscall event rule object creation");
1450
1451 /* Register the trigger for condition. */
1452 trigger = lttng_trigger_create(condition, action);
1453 if (!trigger) {
1454 fail("Failed to create trigger with syscall event rule condition and notify action");
1455 goto end;
1456 }
1457
1458 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1459 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1460 "Setting name to trigger '%s'", trigger_name);
1461
1462 ret = lttng_register_trigger(trigger);
1463 if (ret) {
1464 fail("Failed to register trigger with syscall event rule condition and notify action");
1465 goto end;
1466 }
1467
1468 nc_status = lttng_notification_channel_subscribe(
1469 notification_channel, condition);
1470 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1471 "Subscribe to tracepoint event rule condition");
1472
1473 resume_application();
1474
1475 for (i = 0; i < notification_count; i++) {
1476 char *name = get_next_notification_trigger_name(
1477 notification_channel);
1478
1479 ok(strcmp(trigger_name, name) == 0,
1480 "Received notification for the expected trigger name: '%s' (%d/%d)",
1481 trigger_name, i + 1, notification_count);
1482 free(name);
1483 }
1484end:
1485 suspend_application();
1486 lttng_notification_channel_destroy(notification_channel);
1487 lttng_unregister_trigger(trigger);
1488 lttng_trigger_destroy(trigger);
1489 lttng_action_destroy(action);
1490 lttng_condition_destroy(condition);
1491 return;
1492}
1493
acb98866
FD
1494static void test_syscall_event_rule_notification_filter(
1495 enum lttng_domain_type domain_type)
1496{
1497 int i, ret;
1498 const int notification_count = 3;
1499 enum lttng_notification_channel_status nc_status;
1500 enum lttng_event_rule_status event_rule_status;
1501 enum lttng_trigger_status trigger_status;
1502 struct lttng_notification_channel *notification_channel = NULL;
1503 struct lttng_condition *condition = NULL;
1504 struct lttng_event_rule *event_rule = NULL;
1505 struct lttng_action *action = NULL;
1506 struct lttng_trigger *trigger = NULL;
1507 const char * const trigger_name = "syscall_trigger";
1508 const char * const syscall_name = "openat";
1509 const char * const filter_pattern = "filename == \"/proc/cpuinfo\"";
1510
1511 action = lttng_action_notify_create();
1512 if (!action) {
1513 fail("Failed to create notify action");
1514 goto end;
1515 }
1516
1517 notification_channel = lttng_notification_channel_create(
1518 lttng_session_daemon_notification_endpoint);
1519 ok(notification_channel, "Notification channel object creation");
1520
1521 event_rule = lttng_event_rule_syscall_create();
1522 ok(event_rule, "syscall event rule object creation");
1523
1524 event_rule_status = lttng_event_rule_syscall_set_pattern(
1525 event_rule, syscall_name);
1526 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1527 "Setting syscall event rule pattern: '%s'", syscall_name);
1528
1529 event_rule_status = lttng_event_rule_syscall_set_filter(
1530 event_rule, filter_pattern);
1531 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1532 "Setting filter: '%s'", filter_pattern);
1533
1534 condition = lttng_condition_event_rule_create(event_rule);
1535 ok(condition, "Condition event rule object creation");
1536
1537 /* Register the triggers for condition */
1538 trigger = lttng_trigger_create(condition, action);
1539 if (!trigger) {
1540 fail("Failed to create trigger with syscall filtering event rule condition and notify action");
1541 goto end;
1542 }
1543
1544 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1545 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1546 "Setting name to trigger '%s'", trigger_name);
1547
1548 ret = lttng_register_trigger(trigger);
1549 if (ret) {
1550 fail("Failed to register trigger with syscall filtering event rule condition and notify action");
1551 goto end;
1552 }
1553
1554 nc_status = lttng_notification_channel_subscribe(
1555 notification_channel, condition);
1556 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1557 "Subscribe to tracepoint event rule condition");
1558
1559 resume_application();
1560
1561 for (i = 0; i < 3; i++) {
1562 char *name = get_next_notification_trigger_name(
1563 notification_channel);
1564
1565 ok(strcmp(trigger_name, name) == 0,
1566 "Received notification for the expected trigger name: '%s' (%d/%d)",
1567 trigger_name, i + 1, notification_count);
1568 free(name);
1569 }
1570
1571end:
1572 suspend_application();
1573
1574 lttng_unregister_trigger(trigger);
1575 lttng_notification_channel_destroy(notification_channel);
1576 lttng_trigger_destroy(trigger);
1577 lttng_event_rule_destroy(event_rule);
1578 lttng_condition_destroy(condition);
1579 return;
1580}
1581
434f8068
JR
1582int main(int argc, const char *argv[])
1583{
069fc1c5 1584 int test_scenario;
434f8068
JR
1585 const char *domain_type_string = NULL;
1586 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
1587
a740a242
FD
1588 if (argc < 5) {
1589 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
434f8068
JR
1590 goto error;
1591 }
1592
069fc1c5
FD
1593 test_scenario = atoi(argv[1]);
1594 domain_type_string = argv[2];
a740a242
FD
1595 app_pid = (pid_t) atoi(argv[3]);
1596 app_state_file = argv[4];
434f8068
JR
1597
1598 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
1599 domain_type = LTTNG_DOMAIN_UST;
1600 }
1601 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
1602 domain_type = LTTNG_DOMAIN_KERNEL;
1603 }
1604 if (domain_type == LTTNG_DOMAIN_NONE) {
1605 fail("Unknown domain type");
1606 goto error;
1607 }
1608
a740a242
FD
1609 /*
1610 * Test cases are responsible for resuming the app when needed
1611 * and making sure it's suspended when returning.
1612 */
1613 suspend_application();
1614
069fc1c5
FD
1615 switch (test_scenario) {
1616 case 1:
1617 {
a740a242 1618 plan_tests(38);
7948461b 1619
069fc1c5 1620 /* Test cases that need gen-ust-event testapp. */
a740a242 1621 diag("Test basic notification error paths for %s domain",
069fc1c5
FD
1622 domain_type_string);
1623 test_invalid_channel_subscription(domain_type);
7948461b
FD
1624
1625 diag("Test tracepoint event rule notifications for domain %s",
1626 domain_type_string);
1627 test_tracepoint_event_rule_notification(domain_type);
1628
a740a242
FD
1629 diag("Test tracepoint event rule notifications with filter for domain %s",
1630 domain_type_string);
1631 test_tracepoint_event_rule_notification_filter(domain_type);
069fc1c5
FD
1632 break;
1633 }
1634 case 2:
1635 {
45294d8a 1636 const char *session_name, *channel_name;
069fc1c5
FD
1637 /* Test cases that need a tracing session enabled. */
1638 plan_tests(99);
7676e0d2 1639
069fc1c5
FD
1640 /*
1641 * Argument 7 and upward are named pipe location for consumerd
1642 * control.
1643 */
1644 named_pipe_args_start = 7;
1645
1646 if (argc < 8) {
1647 fail("Missing parameter for tests to run %d", argc);
1648 goto error;
1649 }
434f8068 1650
069fc1c5
FD
1651 nb_args = argc;
1652
a740a242
FD
1653 session_name = argv[5];
1654 channel_name = argv[6];
069fc1c5
FD
1655
1656 test_subscription_twice(session_name, channel_name,
1657 domain_type);
1658
1659 diag("Test trigger for domain %s with buffer_usage_low condition",
1660 domain_type_string);
1661 test_triggers_buffer_usage_condition(session_name, channel_name,
1662 domain_type,
1663 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
1664
1665 diag("Test trigger for domain %s with buffer_usage_high condition",
1666 domain_type_string);
1667 test_triggers_buffer_usage_condition(session_name, channel_name,
1668 domain_type,
1669 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
1670
1671 diag("Test buffer usage notification channel api for domain %s",
1672 domain_type_string);
1673 test_buffer_usage_notification_channel(session_name, channel_name,
1674 domain_type, argv);
1675 break;
1676 }
3e4ee3b3
FD
1677 case 3:
1678 {
1679 /*
1680 * Test cases that need a test app with more than one event
1681 * type.
1682 */
1683 plan_tests(19);
1684
1685 /*
1686 * At the moment, the only test case of this scenario is
1687 * exclusion which is only supported by UST.
1688 */
1689 assert(domain_type == LTTNG_DOMAIN_UST);
1690 diag("Test tracepoint event rule notifications with exclusion for domain %s",
1691 domain_type_string);
1692 test_tracepoint_event_rule_notification_exclusion(domain_type);
1693
1694 break;
1695 }
51704c8e
FD
1696 case 4:
1697 {
1698 plan_tests(10);
1699
1700 /* Test cases that need the kernel tracer. */
1701 assert(domain_type == LTTNG_DOMAIN_KERNEL);
aab0598f 1702
51704c8e
FD
1703 diag("Test kprobe event rule notifications for domain %s",
1704 domain_type_string);
1705
1706 test_kprobe_event_rule_notification(domain_type);
1707
1708 break;
1709 }
aab0598f
FD
1710 case 5:
1711 {
acb98866 1712 plan_tests(19);
aab0598f
FD
1713 /* Test cases that need the kernel tracer. */
1714 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1715
1716 diag("Test syscall event rule notifications for domain %s",
1717 domain_type_string);
1718
1719 test_syscall_event_rule_notification(domain_type);
1720
acb98866
FD
1721 diag("Test syscall filtering event rule notifications for domain %s",
1722 domain_type_string);
1723
1724 test_syscall_event_rule_notification_filter(domain_type);
1725
aab0598f
FD
1726 break;
1727 }
45294d8a
FD
1728 case 6:
1729 {
1730 const char *testapp_path, *test_symbol_name;
1731
1732 plan_tests(10);
1733
1734 if (argc < 7) {
1735 fail("Missing parameter for tests to run %d", argc);
1736 goto error;
1737 }
1738
1739 testapp_path = argv[5];
1740 test_symbol_name = argv[6];
1741 /* Test cases that need the kernel tracer. */
1742 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1743
1744 diag("Test userspace-probe event rule notifications for domain %s",
1745 domain_type_string);
1746
1747 test_uprobe_event_rule_notification(
1748 domain_type, testapp_path, test_symbol_name);
1749
1750 break;
1751 }
069fc1c5
FD
1752 default:
1753 abort();
1754 }
90fcb2ec 1755
434f8068
JR
1756error:
1757 return exit_status();
1758}
1759
This page took 0.107395 seconds and 4 git commands to generate.