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