Tests: triggers: Add userspace-probe event rule condition kernel tests
[lttng-tools.git] / tests / regression / tools / notification / notification.c
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 *
8 * SPDX-License-Identifier: MIT
9 *
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>
23 #include <signal.h>
24 #include <poll.h>
25
26 #include <common/compat/errno.h>
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>
32 #include <lttng/condition/event-rule.h>
33 #include <lttng/domain.h>
34 #include <lttng/endpoint.h>
35 #include <lttng/event-rule/kprobe.h>
36 #include <lttng/event-rule/syscall.h>
37 #include <lttng/event-rule/tracepoint.h>
38 #include <lttng/event-rule/uprobe.h>
39 #include <lttng/kernel-probe.h>
40 #include <lttng/lttng-error.h>
41 #include <lttng/lttng.h>
42 #include <lttng/notification/channel.h>
43 #include <lttng/notification/notification.h>
44 #include <lttng/trigger/trigger.h>
45 #include <lttng/userspace-probe.h>
46
47 #include <tap/tap.h>
48
49 int nb_args = 0;
50 int named_pipe_args_start = 0;
51 pid_t app_pid = 0;
52 const char *app_state_file = NULL;
53
54 static
55 void 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) {
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;
73 }
74
75 /*
76 * File does not exist and the exit condition we want.
77 * Break from the loop and return.
78 */
79 break;
80 }
81 if (ret) {
82 perror("stat");
83 exit(EXIT_FAILURE);
84 }
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 }
92 }
93 }
94
95 static
96 int 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");
110 if (close(fd)) {
111 perror("Named pipe close failed");
112 }
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 }
123 end:
124 return ret;
125 }
126
127 static
128 int stop_consumer(const char **argv)
129 {
130 int ret = 0, i;
131
132 for (i = named_pipe_args_start; i < nb_args; i++) {
133 ret = write_pipe(argv[i], 49);
134 }
135 return ret;
136 }
137
138 static
139 int resume_consumer(const char **argv)
140 {
141 int ret = 0, i;
142
143 for (i = named_pipe_args_start; i < nb_args; i++) {
144 ret = write_pipe(argv[i], 0);
145 }
146 return ret;
147 }
148
149 static
150 int suspend_application(void)
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 */
164 assert(app_pid > 1);
165
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
175 error:
176 return ret;
177
178 }
179
180 static
181 int resume_application(void)
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
196 assert(app_pid > 1);
197
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
207 error:
208 return ret;
209
210 }
211
212
213 static
214 void 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 {
219 unsigned int test_vector_size = 5, i;
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 */
234
235 for (i = 0; i < pow(2,test_vector_size); i++) {
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
333 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
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
353 loop_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);
381 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
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
386 loop_cleanup:
387 free(test_tuple_string);
388 lttng_trigger_destroy(trigger);
389 lttng_condition_destroy(condition);
390 }
391
392 end:
393 lttng_action_destroy(action);
394 }
395
396 static
397 void 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
407 static
408 int 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
444 end:
445 return ret;
446 }
447
448 static
449 void test_invalid_channel_subscription(
450 const enum lttng_domain_type domain_type)
451 {
452 enum lttng_condition_status condition_status;
453 enum lttng_notification_channel_status nc_status;
454 struct lttng_condition *dummy_condition = NULL;
455 struct lttng_condition *dummy_invalid_condition = NULL;
456 struct lttng_notification_channel *notification_channel = NULL;
457 int ret = 0;
458
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) {
463 goto end;
464 }
465
466 /*
467 * Create a dummy, empty (thus invalid) condition to test error paths.
468 */
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
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
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;
494 }
495
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
503 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
504 "dummy_session", "dummy_channel", domain_type);
505 if (ret) {
506 fail("Setup error on dummy condition creation");
507 goto end;
508 }
509
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
532 end:
533 lttng_notification_channel_destroy(notification_channel);
534 lttng_condition_destroy(dummy_invalid_condition);
535 lttng_condition_destroy(dummy_condition);
536 return;
537 }
538
539 enum buffer_usage_type {
540 BUFFER_USAGE_TYPE_LOW,
541 BUFFER_USAGE_TYPE_HIGH,
542 };
543
544 static int register_buffer_usage_notify_trigger(const char *session_name,
545 const char *channel_name,
546 const enum lttng_domain_type domain_type,
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)
552 {
553 enum lttng_condition_status condition_status;
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;
558
559 /* Set-up */
560 tmp_action = lttng_action_notify_create();
561 if (!action) {
562 fail("Setup error on action creation");
563 ret = -1;
564 goto error;
565 }
566
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();
571 }
572
573 if (!tmp_condition) {
574 fail("Setup error on condition creation");
575 ret = -1;
576 goto error;
577 }
578
579 /* Set the buffer usage threashold */
580 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
581 tmp_condition, ratio);
582 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
583 fail("Setup error on condition creation");
584 ret = -1;
585 goto error;
586 }
587
588 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
589 session_name, channel_name, domain_type);
590 if (ret) {
591 fail("Setup error on condition creation");
592 ret = -1;
593 goto error;
594 }
595
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;
602 }
603
604 ret = lttng_register_trigger(tmp_trigger);
605 if (ret) {
606 fail("Setup error on trigger registration");
607 ret = -1;
608 goto error;
609 }
610
611 *condition = tmp_condition;
612 *trigger = tmp_trigger;
613 *action = tmp_action;
614 goto end;
615
616 error:
617 lttng_action_destroy(tmp_action);
618 lttng_condition_destroy(tmp_condition);
619 lttng_trigger_destroy(tmp_trigger);
620
621 end:
622 return ret;
623 }
624
625 static 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
666 end:
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
674 static void test_buffer_usage_notification_channel(const char *session_name,
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");
700 goto end;
701 }
702
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);
706 if (ret) {
707 fail("Setup error on high trigger registration");
708 goto end;
709 }
710
711 /* Begin testing */
712 notification_channel = lttng_notification_channel_create(
713 lttng_session_daemon_notification_endpoint);
714 ok(notification_channel, "Notification channel object creation");
715 if (!notification_channel) {
716 goto end;
717 }
718
719 /* Subscribe a valid low condition */
720 nc_status = lttng_notification_channel_subscribe(
721 notification_channel, low_condition);
722 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
723 "Subscribe to low condition");
724
725 /* Subscribe a valid high condition */
726 nc_status = lttng_notification_channel_subscribe(
727 notification_channel, high_condition);
728 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
729 "Subscribe to high condition");
730
731 resume_application();
732
733 /* Wait for notification to happen */
734 stop_consumer(argv);
735 lttng_start_tracing(session_name);
736
737 /* Wait for high notification */
738 do {
739 nc_status = lttng_notification_channel_get_next_notification(
740 notification_channel, &notification);
741 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
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,
746 "High notification received after intermediary communication");
747 lttng_notification_destroy(notification);
748 notification = NULL;
749
750 suspend_application();
751 lttng_stop_tracing_no_wait(session_name);
752 resume_consumer(argv);
753 wait_data_pending(session_name);
754
755 /*
756 * Test that communication still work even if there is notification
757 * waiting for consumption.
758 */
759
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");
764
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");
769
770 do {
771 nc_status = lttng_notification_channel_get_next_notification(
772 notification_channel, &notification);
773 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
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,
778 "Low notification received after intermediary communication");
779 lttng_notification_destroy(notification);
780 notification = NULL;
781
782 /* Stop consumer to force a high notification */
783 stop_consumer(argv);
784 resume_application();
785 lttng_start_tracing(session_name);
786
787 do {
788 nc_status = lttng_notification_channel_get_next_notification(
789 notification_channel, &notification);
790 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
791 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
792 lttng_condition_get_type(lttng_notification_get_condition(
793 notification)) ==
794 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
795 "High notification received after intermediary communication");
796 lttng_notification_destroy(notification);
797 notification = NULL;
798
799 suspend_application();
800 lttng_stop_tracing_no_wait(session_name);
801 resume_consumer(argv);
802 wait_data_pending(session_name);
803
804 do {
805 nc_status = lttng_notification_channel_get_next_notification(
806 notification_channel, &notification);
807 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
808 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
809 lttng_condition_get_type(lttng_notification_get_condition(
810 notification)) ==
811 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
812 "Low notification received after re-subscription");
813 lttng_notification_destroy(notification);
814 notification = NULL;
815
816 stop_consumer(argv);
817 resume_application();
818 /* Stop consumer to force a high notification */
819 lttng_start_tracing(session_name);
820
821 do {
822 nc_status = lttng_notification_channel_get_next_notification(
823 notification_channel, &notification);
824 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
825 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
826 lttng_condition_get_type(lttng_notification_get_condition(
827 notification)) ==
828 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
829 "High notification");
830 lttng_notification_destroy(notification);
831 notification = NULL;
832
833 suspend_application();
834
835 /* Resume consumer to allow event consumption */
836 lttng_stop_tracing_no_wait(session_name);
837 resume_consumer(argv);
838 wait_data_pending(session_name);
839
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");
849
850 end:
851 lttng_notification_channel_destroy(notification_channel);
852 lttng_trigger_destroy(low_trigger);
853 lttng_trigger_destroy(high_trigger);
854 lttng_action_destroy(low_action);
855 lttng_action_destroy(high_action);
856 lttng_condition_destroy(low_condition);
857 lttng_condition_destroy(high_condition);
858 }
859
860 static void create_tracepoint_event_rule_trigger(const char *event_pattern,
861 const char *trigger_name,
862 const char *filter,
863 unsigned int exclusion_count,
864 const char * const *exclusions,
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
946 static 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
990 end:
991 return trigger_name;
992 }
993
994 static 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
1047 static 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
1132 static 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
1215 static 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
1298 end:
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);
1304 lttng_event_rule_destroy(event_rule);
1305 lttng_condition_destroy(condition);
1306 lttng_kernel_probe_location_destroy(location);
1307 return;
1308 }
1309
1310 static 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 }
1402 end:
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
1414 static 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 }
1484 end:
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
1494 int main(int argc, const char *argv[])
1495 {
1496 int test_scenario;
1497 const char *domain_type_string = NULL;
1498 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
1499
1500 if (argc < 5) {
1501 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
1502 goto error;
1503 }
1504
1505 test_scenario = atoi(argv[1]);
1506 domain_type_string = argv[2];
1507 app_pid = (pid_t) atoi(argv[3]);
1508 app_state_file = argv[4];
1509
1510 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
1511 domain_type = LTTNG_DOMAIN_UST;
1512 }
1513 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
1514 domain_type = LTTNG_DOMAIN_KERNEL;
1515 }
1516 if (domain_type == LTTNG_DOMAIN_NONE) {
1517 fail("Unknown domain type");
1518 goto error;
1519 }
1520
1521 /*
1522 * Test cases are responsible for resuming the app when needed
1523 * and making sure it's suspended when returning.
1524 */
1525 suspend_application();
1526
1527 switch (test_scenario) {
1528 case 1:
1529 {
1530 plan_tests(38);
1531
1532 /* Test cases that need gen-ust-event testapp. */
1533 diag("Test basic notification error paths for %s domain",
1534 domain_type_string);
1535 test_invalid_channel_subscription(domain_type);
1536
1537 diag("Test tracepoint event rule notifications for domain %s",
1538 domain_type_string);
1539 test_tracepoint_event_rule_notification(domain_type);
1540
1541 diag("Test tracepoint event rule notifications with filter for domain %s",
1542 domain_type_string);
1543 test_tracepoint_event_rule_notification_filter(domain_type);
1544 break;
1545 }
1546 case 2:
1547 {
1548 const char *session_name, *channel_name;
1549 /* Test cases that need a tracing session enabled. */
1550 plan_tests(99);
1551
1552 /*
1553 * Argument 7 and upward are named pipe location for consumerd
1554 * control.
1555 */
1556 named_pipe_args_start = 7;
1557
1558 if (argc < 8) {
1559 fail("Missing parameter for tests to run %d", argc);
1560 goto error;
1561 }
1562
1563 nb_args = argc;
1564
1565 session_name = argv[5];
1566 channel_name = argv[6];
1567
1568 test_subscription_twice(session_name, channel_name,
1569 domain_type);
1570
1571 diag("Test trigger for domain %s with buffer_usage_low condition",
1572 domain_type_string);
1573 test_triggers_buffer_usage_condition(session_name, channel_name,
1574 domain_type,
1575 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
1576
1577 diag("Test trigger for domain %s with buffer_usage_high condition",
1578 domain_type_string);
1579 test_triggers_buffer_usage_condition(session_name, channel_name,
1580 domain_type,
1581 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
1582
1583 diag("Test buffer usage notification channel api for domain %s",
1584 domain_type_string);
1585 test_buffer_usage_notification_channel(session_name, channel_name,
1586 domain_type, argv);
1587 break;
1588 }
1589 case 3:
1590 {
1591 /*
1592 * Test cases that need a test app with more than one event
1593 * type.
1594 */
1595 plan_tests(19);
1596
1597 /*
1598 * At the moment, the only test case of this scenario is
1599 * exclusion which is only supported by UST.
1600 */
1601 assert(domain_type == LTTNG_DOMAIN_UST);
1602 diag("Test tracepoint event rule notifications with exclusion for domain %s",
1603 domain_type_string);
1604 test_tracepoint_event_rule_notification_exclusion(domain_type);
1605
1606 break;
1607 }
1608 case 4:
1609 {
1610 plan_tests(10);
1611
1612 /* Test cases that need the kernel tracer. */
1613 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1614
1615 diag("Test kprobe event rule notifications for domain %s",
1616 domain_type_string);
1617
1618 test_kprobe_event_rule_notification(domain_type);
1619
1620 break;
1621 }
1622 case 5:
1623 {
1624 plan_tests(10);
1625 /* Test cases that need the kernel tracer. */
1626 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1627
1628 diag("Test syscall event rule notifications for domain %s",
1629 domain_type_string);
1630
1631 test_syscall_event_rule_notification(domain_type);
1632
1633 break;
1634 }
1635 case 6:
1636 {
1637 const char *testapp_path, *test_symbol_name;
1638
1639 plan_tests(10);
1640
1641 if (argc < 7) {
1642 fail("Missing parameter for tests to run %d", argc);
1643 goto error;
1644 }
1645
1646 testapp_path = argv[5];
1647 test_symbol_name = argv[6];
1648 /* Test cases that need the kernel tracer. */
1649 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1650
1651 diag("Test userspace-probe event rule notifications for domain %s",
1652 domain_type_string);
1653
1654 test_uprobe_event_rule_notification(
1655 domain_type, testapp_path, test_symbol_name);
1656
1657 break;
1658 }
1659 default:
1660 abort();
1661 }
1662
1663 error:
1664 return exit_status();
1665 }
1666
This page took 0.111253 seconds and 4 git commands to generate.