4 * Tests suite for LTTng notification API
6 * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
8 * SPDX-License-Identifier: MIT
20 #include <sys/types.h>
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/tracepoint.h>
37 #include <lttng/kernel-probe.h>
38 #include <lttng/lttng-error.h>
39 #include <lttng/lttng.h>
40 #include <lttng/notification/channel.h>
41 #include <lttng/notification/notification.h>
42 #include <lttng/trigger/trigger.h>
47 int named_pipe_args_start
= 0;
49 const char *app_state_file
= NULL
;
52 void wait_on_file(const char *path
, bool file_exist
)
61 ret
= stat(path
, &buf
);
62 if (ret
== -1 && errno
== ENOENT
) {
65 * The file does not exist. wait a bit and
66 * continue looping until it does.
68 (void) poll(NULL
, 0, 10);
73 * File does not exist and the exit condition we want.
74 * Break from the loop and return.
83 * stat() returned 0, so the file exists. break now only if
84 * that's the exit condition we want.
93 int write_pipe(const char *path
, uint8_t data
)
98 fd
= open(path
, O_WRONLY
| O_NONBLOCK
);
100 perror("Could not open consumer control named pipe");
104 ret
= write(fd
, &data
, sizeof(data
));
106 perror("Named pipe write failed");
108 perror("Named pipe close failed");
116 perror("Name pipe closing failed");
125 int stop_consumer(const char **argv
)
129 for (i
= named_pipe_args_start
; i
< nb_args
; i
++) {
130 ret
= write_pipe(argv
[i
], 49);
136 int resume_consumer(const char **argv
)
140 for (i
= named_pipe_args_start
; i
< nb_args
; i
++) {
141 ret
= write_pipe(argv
[i
], 0);
147 int suspend_application(void)
152 if (!stat(app_state_file
, &buf
)) {
153 fail("App is already in a suspended state.");
159 * Send SIGUSR1 to application instructing it to bypass tracepoint.
163 ret
= kill(app_pid
, SIGUSR1
);
165 fail("SIGUSR1 failed. errno %d", errno
);
170 wait_on_file(app_state_file
, true);
178 int resume_application(void)
183 ret
= stat(app_state_file
, &buf
);
184 if (ret
== -1 && errno
== ENOENT
) {
185 fail("State file does not exist");
195 ret
= kill(app_pid
, SIGUSR1
);
197 fail("SIGUSR1 failed. errno %d", errno
);
202 wait_on_file(app_state_file
, false);
211 void test_triggers_buffer_usage_condition(const char *session_name
,
212 const char *channel_name
,
213 enum lttng_domain_type domain_type
,
214 enum lttng_condition_type condition_type
)
216 unsigned int test_vector_size
= 5, i
;
217 enum lttng_condition_status condition_status
;
218 struct lttng_action
*action
;
221 action
= lttng_action_notify_create();
223 fail("Setup error on action creation");
227 /* Test lttng_register_trigger with null value */
228 ok(lttng_register_trigger(NULL
) == -LTTNG_ERR_INVALID
, "Registering a NULL trigger fails as expected");
230 /* Test: register a trigger */
232 for (i
= 0; i
< pow(2,test_vector_size
); i
++) {
234 char *test_tuple_string
= NULL
;
235 unsigned int mask_position
= 0;
236 bool session_name_set
= false;
237 bool channel_name_set
= false;
238 bool threshold_ratio_set
= false;
239 bool threshold_byte_set
= false;
240 bool domain_type_set
= false;
242 struct lttng_trigger
*trigger
= NULL
;
243 struct lttng_condition
*condition
= NULL
;
245 /* Create base condition */
246 switch (condition_type
) {
247 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
248 condition
= lttng_condition_buffer_usage_low_create();
250 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
251 condition
= lttng_condition_buffer_usage_high_create();
264 /* Prepare the condition for trigger registration test */
266 /* Set session name */
267 if ((1 << mask_position
) & i
) {
268 condition_status
= lttng_condition_buffer_usage_set_session_name(
269 condition
, session_name
);
270 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
274 session_name_set
= true;
278 /* Set channel name */
279 if ((1 << mask_position
) & i
) {
280 condition_status
= lttng_condition_buffer_usage_set_channel_name(
281 condition
, channel_name
);
282 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
286 channel_name_set
= true;
290 /* Set threshold ratio */
291 if ((1 << mask_position
) & i
) {
292 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
294 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
298 threshold_ratio_set
= true;
302 /* Set threshold byte */
303 if ((1 << mask_position
) & i
) {
304 condition_status
= lttng_condition_buffer_usage_set_threshold(
306 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
310 threshold_byte_set
= true;
314 /* Set domain type */
315 if ((1 << mask_position
) & i
) {
316 condition_status
= lttng_condition_buffer_usage_set_domain_type(
317 condition
, LTTNG_DOMAIN_UST
);
318 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
322 domain_type_set
= true;
326 if (mask_position
!= test_vector_size
-1) {
327 assert("Logic error for test vector generation");
330 loop_ret
= asprintf(&test_tuple_string
, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
331 session_name_set
? "set" : "unset",
332 channel_name_set
? "set" : "unset",
333 threshold_ratio_set
? "set" : "unset",
334 threshold_byte_set
? "set" : "unset",
335 domain_type_set
? "set" : "unset");
336 if (!test_tuple_string
|| loop_ret
< 0) {
342 trigger
= lttng_trigger_create(condition
, action
);
348 loop_ret
= lttng_register_trigger(trigger
);
352 fail("Setup error occurred for tuple: %s", test_tuple_string
);
356 /* This combination happens three times */
357 if (session_name_set
&& channel_name_set
358 && (threshold_ratio_set
|| threshold_byte_set
)
359 && domain_type_set
) {
360 ok(loop_ret
== 0, "Trigger is registered: %s", test_tuple_string
);
363 * Test that a trigger cannot be registered
366 loop_ret
= lttng_register_trigger(trigger
);
367 ok(loop_ret
== -LTTNG_ERR_TRIGGER_EXISTS
, "Re-register trigger fails as expected: %s", test_tuple_string
);
369 /* Test that a trigger can be unregistered */
370 loop_ret
= lttng_unregister_trigger(trigger
);
371 ok(loop_ret
== 0, "Unregister trigger: %s", test_tuple_string
);
374 * Test that unregistration of a non-previously
375 * registered trigger fail.
377 loop_ret
= lttng_unregister_trigger(trigger
);
378 ok(loop_ret
== -LTTNG_ERR_TRIGGER_NOT_FOUND
, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string
);
380 ok(loop_ret
== -LTTNG_ERR_INVALID_TRIGGER
, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string
);
384 free(test_tuple_string
);
385 lttng_trigger_destroy(trigger
);
386 lttng_condition_destroy(condition
);
390 lttng_action_destroy(action
);
394 void wait_data_pending(const char *session_name
)
399 ret
= lttng_data_pending(session_name
);
405 int setup_buffer_usage_condition(struct lttng_condition
*condition
,
406 const char *condition_name
,
407 const char *session_name
,
408 const char *channel_name
,
409 const enum lttng_domain_type domain_type
)
411 enum lttng_condition_status condition_status
;
414 condition_status
= lttng_condition_buffer_usage_set_session_name(
415 condition
, session_name
);
416 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
417 fail("Failed to set session name on creation of condition `%s`",
423 condition_status
= lttng_condition_buffer_usage_set_channel_name(
424 condition
, channel_name
);
425 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
426 fail("Failed to set channel name on creation of condition `%s`",
432 condition_status
= lttng_condition_buffer_usage_set_domain_type(
433 condition
, domain_type
);
434 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
435 fail("Failed to set domain type on creation of condition `%s`",
446 void test_invalid_channel_subscription(
447 const enum lttng_domain_type domain_type
)
449 enum lttng_condition_status condition_status
;
450 enum lttng_notification_channel_status nc_status
;
451 struct lttng_condition
*dummy_condition
= NULL
;
452 struct lttng_condition
*dummy_invalid_condition
= NULL
;
453 struct lttng_notification_channel
*notification_channel
= NULL
;
456 notification_channel
= lttng_notification_channel_create(
457 lttng_session_daemon_notification_endpoint
);
458 ok(notification_channel
, "Notification channel object creation");
459 if (!notification_channel
) {
464 * Create a dummy, empty (thus invalid) condition to test error paths.
466 dummy_invalid_condition
= lttng_condition_buffer_usage_low_create();
467 if (!dummy_invalid_condition
) {
468 fail("Setup error on condition creation");
473 * Test subscription and unsubscription of an invalid condition to/from
476 nc_status
= lttng_notification_channel_subscribe(
477 notification_channel
, dummy_invalid_condition
);
478 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
,
479 "Subscribing to an invalid condition");
481 nc_status
= lttng_notification_channel_unsubscribe(
482 notification_channel
, dummy_invalid_condition
);
483 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
,
484 "Unsubscribing from an invalid condition");
486 /* Create a valid dummy condition with a ratio of 0.5 */
487 dummy_condition
= lttng_condition_buffer_usage_low_create();
488 if (!dummy_condition
) {
489 fail("Setup error on dummy_condition creation");
493 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
494 dummy_condition
, 0.5);
495 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
496 fail("Setup error on condition creation");
500 ret
= setup_buffer_usage_condition(dummy_condition
, "dummy_condition",
501 "dummy_session", "dummy_channel", domain_type
);
503 fail("Setup error on dummy condition creation");
508 * Test subscription and unsubscription to/from a channel with invalid
511 nc_status
= lttng_notification_channel_subscribe(NULL
, NULL
);
512 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
,
513 "Notification channel subscription is invalid: NULL, NULL");
515 nc_status
= lttng_notification_channel_subscribe(
516 notification_channel
, NULL
);
517 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
,
518 "Notification channel subscription is invalid: NON-NULL, NULL");
520 nc_status
= lttng_notification_channel_subscribe(NULL
, dummy_condition
);
521 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
,
522 "Notification channel subscription is invalid: NULL, NON-NULL");
524 nc_status
= lttng_notification_channel_unsubscribe(
525 notification_channel
, dummy_condition
);
526 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION
,
527 "Unsubscribing from a valid unknown condition");
530 lttng_notification_channel_destroy(notification_channel
);
531 lttng_condition_destroy(dummy_invalid_condition
);
532 lttng_condition_destroy(dummy_condition
);
536 enum buffer_usage_type
{
537 BUFFER_USAGE_TYPE_LOW
,
538 BUFFER_USAGE_TYPE_HIGH
,
541 static int register_buffer_usage_notify_trigger(const char *session_name
,
542 const char *channel_name
,
543 const enum lttng_domain_type domain_type
,
544 enum buffer_usage_type buffer_usage_type
,
546 struct lttng_condition
**condition
,
547 struct lttng_action
**action
,
548 struct lttng_trigger
**trigger
)
550 enum lttng_condition_status condition_status
;
551 struct lttng_action
*tmp_action
= NULL
;
552 struct lttng_condition
*tmp_condition
= NULL
;
553 struct lttng_trigger
*tmp_trigger
= NULL
;
557 tmp_action
= lttng_action_notify_create();
559 fail("Setup error on action creation");
564 if (buffer_usage_type
== BUFFER_USAGE_TYPE_LOW
) {
565 tmp_condition
= lttng_condition_buffer_usage_low_create();
567 tmp_condition
= lttng_condition_buffer_usage_high_create();
570 if (!tmp_condition
) {
571 fail("Setup error on condition creation");
576 /* Set the buffer usage threashold */
577 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
578 tmp_condition
, ratio
);
579 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
580 fail("Setup error on condition creation");
585 ret
= setup_buffer_usage_condition(tmp_condition
, "condition_name",
586 session_name
, channel_name
, domain_type
);
588 fail("Setup error on condition creation");
593 /* Register the trigger for condition. */
594 tmp_trigger
= lttng_trigger_create(tmp_condition
, tmp_action
);
596 fail("Setup error on trigger creation");
601 ret
= lttng_register_trigger(tmp_trigger
);
603 fail("Setup error on trigger registration");
608 *condition
= tmp_condition
;
609 *trigger
= tmp_trigger
;
610 *action
= tmp_action
;
614 lttng_action_destroy(tmp_action
);
615 lttng_condition_destroy(tmp_condition
);
616 lttng_trigger_destroy(tmp_trigger
);
622 static void test_subscription_twice(const char *session_name
,
623 const char *channel_name
,
624 const enum lttng_domain_type domain_type
)
627 enum lttng_notification_channel_status nc_status
;
629 struct lttng_action
*action
= NULL
;
630 struct lttng_notification_channel
*notification_channel
= NULL
;
631 struct lttng_trigger
*trigger
= NULL
;
633 struct lttng_condition
*condition
= NULL
;
635 ret
= register_buffer_usage_notify_trigger(session_name
, channel_name
,
636 domain_type
, BUFFER_USAGE_TYPE_LOW
, 0.99, &condition
,
639 fail("Setup error on trigger registration");
644 notification_channel
= lttng_notification_channel_create(
645 lttng_session_daemon_notification_endpoint
);
646 ok(notification_channel
, "Notification channel object creation");
647 if (!notification_channel
) {
651 /* Subscribe a valid condition. */
652 nc_status
= lttng_notification_channel_subscribe(
653 notification_channel
, condition
);
654 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
655 "Subscribe to condition");
657 /* Subscribing again should fail. */
658 nc_status
= lttng_notification_channel_subscribe(
659 notification_channel
, condition
);
660 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
,
661 "Subscribe to a condition for which subscription was already done");
664 lttng_unregister_trigger(trigger
);
665 lttng_trigger_destroy(trigger
);
666 lttng_notification_channel_destroy(notification_channel
);
667 lttng_action_destroy(action
);
668 lttng_condition_destroy(condition
);
671 static void test_buffer_usage_notification_channel(const char *session_name
,
672 const char *channel_name
,
673 const enum lttng_domain_type domain_type
,
677 enum lttng_notification_channel_status nc_status
;
679 struct lttng_action
*low_action
= NULL
;
680 struct lttng_action
*high_action
= NULL
;
681 struct lttng_notification
*notification
= NULL
;
682 struct lttng_notification_channel
*notification_channel
= NULL
;
683 struct lttng_trigger
*low_trigger
= NULL
;
684 struct lttng_trigger
*high_trigger
= NULL
;
686 struct lttng_condition
*low_condition
= NULL
;
687 struct lttng_condition
*high_condition
= NULL
;
689 const double low_ratio
= 0.0;
690 const double high_ratio
= 0.90;
692 ret
= register_buffer_usage_notify_trigger(session_name
, channel_name
,
693 domain_type
, BUFFER_USAGE_TYPE_LOW
, low_ratio
,
694 &low_condition
, &low_action
, &low_trigger
);
696 fail("Setup error on low trigger registration");
700 ret
= register_buffer_usage_notify_trigger(session_name
, channel_name
,
701 domain_type
, BUFFER_USAGE_TYPE_HIGH
, high_ratio
,
702 &high_condition
, &high_action
, &high_trigger
);
704 fail("Setup error on high trigger registration");
709 notification_channel
= lttng_notification_channel_create(
710 lttng_session_daemon_notification_endpoint
);
711 ok(notification_channel
, "Notification channel object creation");
712 if (!notification_channel
) {
716 /* Subscribe a valid low condition */
717 nc_status
= lttng_notification_channel_subscribe(
718 notification_channel
, low_condition
);
719 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
720 "Subscribe to low condition");
722 /* Subscribe a valid high condition */
723 nc_status
= lttng_notification_channel_subscribe(
724 notification_channel
, high_condition
);
725 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
726 "Subscribe to high condition");
728 resume_application();
730 /* Wait for notification to happen */
732 lttng_start_tracing(session_name
);
734 /* Wait for high notification */
736 nc_status
= lttng_notification_channel_get_next_notification(
737 notification_channel
, ¬ification
);
738 } while (nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
);
739 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
740 lttng_condition_get_type(lttng_notification_get_condition(
742 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
743 "High notification received after intermediary communication");
744 lttng_notification_destroy(notification
);
747 suspend_application();
748 lttng_stop_tracing_no_wait(session_name
);
749 resume_consumer(argv
);
750 wait_data_pending(session_name
);
753 * Test that communication still work even if there is notification
754 * waiting for consumption.
757 nc_status
= lttng_notification_channel_unsubscribe(
758 notification_channel
, low_condition
);
759 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
760 "Unsubscribe with pending notification");
762 nc_status
= lttng_notification_channel_subscribe(
763 notification_channel
, low_condition
);
764 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
765 "Subscribe with pending notification");
768 nc_status
= lttng_notification_channel_get_next_notification(
769 notification_channel
, ¬ification
);
770 } while (nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
);
771 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
772 lttng_condition_get_type(lttng_notification_get_condition(
774 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
775 "Low notification received after intermediary communication");
776 lttng_notification_destroy(notification
);
779 /* Stop consumer to force a high notification */
781 resume_application();
782 lttng_start_tracing(session_name
);
785 nc_status
= lttng_notification_channel_get_next_notification(
786 notification_channel
, ¬ification
);
787 } while (nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
);
788 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
789 lttng_condition_get_type(lttng_notification_get_condition(
791 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
792 "High notification received after intermediary communication");
793 lttng_notification_destroy(notification
);
796 suspend_application();
797 lttng_stop_tracing_no_wait(session_name
);
798 resume_consumer(argv
);
799 wait_data_pending(session_name
);
802 nc_status
= lttng_notification_channel_get_next_notification(
803 notification_channel
, ¬ification
);
804 } while (nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
);
805 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
806 lttng_condition_get_type(lttng_notification_get_condition(
808 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
809 "Low notification received after re-subscription");
810 lttng_notification_destroy(notification
);
814 resume_application();
815 /* Stop consumer to force a high notification */
816 lttng_start_tracing(session_name
);
819 nc_status
= lttng_notification_channel_get_next_notification(
820 notification_channel
, ¬ification
);
821 } while (nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED
);
822 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
823 lttng_condition_get_type(lttng_notification_get_condition(
825 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
826 "High notification");
827 lttng_notification_destroy(notification
);
830 suspend_application();
832 /* Resume consumer to allow event consumption */
833 lttng_stop_tracing_no_wait(session_name
);
834 resume_consumer(argv
);
835 wait_data_pending(session_name
);
837 nc_status
= lttng_notification_channel_unsubscribe(
838 notification_channel
, low_condition
);
839 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
840 "Unsubscribe low condition with pending notification");
842 nc_status
= lttng_notification_channel_unsubscribe(
843 notification_channel
, high_condition
);
844 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
845 "Unsubscribe high condition with pending notification");
848 lttng_notification_channel_destroy(notification_channel
);
849 lttng_trigger_destroy(low_trigger
);
850 lttng_trigger_destroy(high_trigger
);
851 lttng_action_destroy(low_action
);
852 lttng_action_destroy(high_action
);
853 lttng_condition_destroy(low_condition
);
854 lttng_condition_destroy(high_condition
);
857 static void create_tracepoint_event_rule_trigger(const char *event_pattern
,
858 const char *trigger_name
,
860 unsigned int exclusion_count
,
861 const char * const *exclusions
,
862 enum lttng_domain_type domain_type
,
863 struct lttng_condition
**condition
,
864 struct lttng_trigger
**trigger
)
866 enum lttng_event_rule_status event_rule_status
;
867 enum lttng_trigger_status trigger_status
;
869 struct lttng_action
*tmp_action
= NULL
;
870 struct lttng_event_rule
*event_rule
= NULL
;
871 struct lttng_condition
*tmp_condition
= NULL
;
872 struct lttng_trigger
*tmp_trigger
= NULL
;
875 assert(event_pattern
);
876 assert(trigger_name
);
880 event_rule
= lttng_event_rule_tracepoint_create(domain_type
);
881 ok(event_rule
, "Tracepoint event rule object creation");
883 event_rule_status
= lttng_event_rule_tracepoint_set_pattern(
884 event_rule
, event_pattern
);
885 ok(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
,
886 "Setting tracepoint event rule pattern: '%s'",
890 event_rule_status
= lttng_event_rule_tracepoint_set_filter(
892 ok(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
,
893 "Setting tracepoint event rule filter: '%s'",
901 assert(domain_type
== LTTNG_DOMAIN_UST
);
902 assert(exclusion_count
> 0);
904 for (i
= 0; i
< exclusion_count
; i
++) {
906 lttng_event_rule_tracepoint_add_exclusion(
909 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
910 fail("Setting tracepoint event rule exclusion '%s'.",
916 ok(success
, "Setting tracepoint event rule exclusions");
919 tmp_condition
= lttng_condition_event_rule_create(event_rule
);
920 ok(tmp_condition
, "Condition event rule object creation");
922 tmp_action
= lttng_action_notify_create();
923 ok(tmp_action
, "Action event rule object creation");
925 tmp_trigger
= lttng_trigger_create(tmp_condition
, tmp_action
);
926 ok(tmp_trigger
, "Trigger object creation %s", trigger_name
);
928 trigger_status
= lttng_trigger_set_name(tmp_trigger
, trigger_name
);
929 ok(trigger_status
== LTTNG_TRIGGER_STATUS_OK
,
930 "Setting name to trigger %s", trigger_name
);
932 ret
= lttng_register_trigger(tmp_trigger
);
933 ok(ret
== 0, "Trigger registration %s", trigger_name
);
935 lttng_event_rule_destroy(event_rule
);
937 *condition
= tmp_condition
;
938 *trigger
= tmp_trigger
;
943 static char *get_next_notification_trigger_name(
944 struct lttng_notification_channel
*notification_channel
)
946 struct lttng_notification
*notification
;
947 enum lttng_notification_channel_status status
;
948 const struct lttng_evaluation
*notification_evaluation
;
949 char *trigger_name
= NULL
;
951 enum lttng_condition_type notification_evaluation_type
;
953 /* Receive the next notification. */
954 status
= lttng_notification_channel_get_next_notification(
955 notification_channel
, ¬ification
);
958 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
:
961 /* Unhandled conditions / errors. */
962 fail("Failed to get next notification channel notification: status = %d",
967 notification_evaluation
=
968 lttng_notification_get_evaluation(notification
);
970 notification_evaluation_type
=
971 lttng_evaluation_get_type(notification_evaluation
);
972 switch (notification_evaluation_type
) {
973 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT
:
974 lttng_evaluation_event_rule_get_trigger_name(
975 notification_evaluation
, &name
);
977 trigger_name
= strdup(name
);
980 fail("Unexpected notification evaluation type: notification type = %d",
981 notification_evaluation_type
);
985 lttng_notification_destroy(notification
);
991 static void test_tracepoint_event_rule_notification(
992 enum lttng_domain_type domain_type
)
995 const int notification_count
= 3;
996 enum lttng_notification_channel_status nc_status
;
997 struct lttng_action
*action
= NULL
;
998 struct lttng_condition
*condition
= NULL
;
999 struct lttng_notification_channel
*notification_channel
= NULL
;
1000 struct lttng_trigger
*trigger
= NULL
;
1001 const char * const trigger_name
= "my_precious";
1002 const char *pattern
;
1004 if (domain_type
== LTTNG_DOMAIN_UST
) {
1005 pattern
= "tp:tptest";
1007 pattern
= "lttng_test_filter_event";
1010 create_tracepoint_event_rule_trigger(pattern
, trigger_name
, NULL
, 0,
1011 NULL
, domain_type
, &condition
, &trigger
);
1013 notification_channel
= lttng_notification_channel_create(
1014 lttng_session_daemon_notification_endpoint
);
1015 ok(notification_channel
, "Notification channel object creation");
1017 nc_status
= lttng_notification_channel_subscribe(
1018 notification_channel
, condition
);
1019 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1020 "Subscribe to tracepoint event rule condition");
1022 resume_application();
1024 /* Get 3 notifications. */
1025 for (i
= 0; i
< notification_count
; i
++) {
1026 char *name
= get_next_notification_trigger_name(
1027 notification_channel
);
1029 ok(strcmp(trigger_name
, name
) == 0,
1030 "Received notification for the expected trigger name: '%s' (%d/%d)",
1031 trigger_name
, i
+ 1, notification_count
);
1035 suspend_application();
1036 lttng_notification_channel_destroy(notification_channel
);
1037 lttng_unregister_trigger(trigger
);
1038 lttng_trigger_destroy(trigger
);
1039 lttng_action_destroy(action
);
1040 lttng_condition_destroy(condition
);
1044 static void test_tracepoint_event_rule_notification_filter(
1045 enum lttng_domain_type domain_type
)
1048 enum lttng_notification_channel_status nc_status
;
1050 struct lttng_condition
*ctrl_condition
= NULL
, *condition
= NULL
;
1051 struct lttng_notification_channel
*notification_channel
= NULL
;
1052 struct lttng_trigger
*ctrl_trigger
= NULL
, *trigger
= NULL
;
1053 const char * const ctrl_trigger_name
= "control_trigger";
1054 const char * const trigger_name
= "trigger";
1055 const char *pattern
;
1056 int ctrl_count
= 0, count
= 0;
1058 if (domain_type
== LTTNG_DOMAIN_UST
) {
1059 pattern
= "tp:tptest";
1061 pattern
= "lttng_test_filter_event";
1064 notification_channel
= lttng_notification_channel_create(
1065 lttng_session_daemon_notification_endpoint
);
1066 ok(notification_channel
, "Notification channel object creation");
1068 create_tracepoint_event_rule_trigger(pattern
, ctrl_trigger_name
, NULL
,
1069 0, NULL
, domain_type
, &ctrl_condition
, &ctrl_trigger
);
1071 nc_status
= lttng_notification_channel_subscribe(
1072 notification_channel
, ctrl_condition
);
1073 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1074 "Subscribe to tracepoint event rule condition");
1077 * Attach a filter expression to get notification only if the
1078 * `intfield` is even.
1080 create_tracepoint_event_rule_trigger(pattern
, trigger_name
,
1081 "(intfield & 1) == 0", 0, NULL
, domain_type
, &condition
,
1084 nc_status
= lttng_notification_channel_subscribe(
1085 notification_channel
, condition
);
1086 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1087 "Subscribe to tracepoint event rule condition");
1090 * We registered 2 notifications triggers, one with a filter and one
1091 * without (control). The one with a filter will only fired when the
1092 * `intfield` is a multiple of 2. We should get two times as many
1093 * control notifications as filter notifications.
1095 resume_application();
1098 * Get 3 notifications. We should get 1 for the regular trigger (with
1099 * the filter) and 2 from the control trigger. This works whatever
1100 * the order we receive the notifications.
1102 for (i
= 0; i
< 3; i
++) {
1103 char *name
= get_next_notification_trigger_name(
1104 notification_channel
);
1106 if (strcmp(ctrl_trigger_name
, name
) == 0) {
1108 } else if (strcmp(trigger_name
, name
) == 0) {
1115 ok(ctrl_count
/ 2 == count
,
1116 "Get twice as many control notif as of regular notif");
1118 suspend_application();
1120 lttng_unregister_trigger(trigger
);
1121 lttng_unregister_trigger(ctrl_trigger
);
1122 lttng_notification_channel_destroy(notification_channel
);
1123 lttng_trigger_destroy(trigger
);
1124 lttng_trigger_destroy(ctrl_trigger
);
1125 lttng_condition_destroy(condition
);
1126 lttng_condition_destroy(ctrl_condition
);
1129 static void test_tracepoint_event_rule_notification_exclusion(
1130 enum lttng_domain_type domain_type
)
1132 enum lttng_notification_channel_status nc_status
;
1133 struct lttng_condition
*ctrl_condition
= NULL
, *condition
= NULL
;
1134 struct lttng_notification_channel
*notification_channel
= NULL
;
1135 struct lttng_trigger
*ctrl_trigger
= NULL
, *trigger
= NULL
;
1136 int ctrl_count
= 0, count
= 0, i
;
1137 const char * const ctrl_trigger_name
= "control_exclusion_trigger";
1138 const char * const trigger_name
= "exclusion_trigger";
1139 const char * const pattern
= "tp:tptest*";
1140 const char * const exclusions
[] = {
1147 notification_channel
= lttng_notification_channel_create(
1148 lttng_session_daemon_notification_endpoint
);
1149 ok(notification_channel
, "Notification channel object creation");
1151 create_tracepoint_event_rule_trigger(pattern
, ctrl_trigger_name
, NULL
,
1152 0, NULL
, domain_type
, &ctrl_condition
, &ctrl_trigger
);
1154 nc_status
= lttng_notification_channel_subscribe(
1155 notification_channel
, ctrl_condition
);
1156 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1157 "Subscribe to tracepoint event rule condition");
1159 create_tracepoint_event_rule_trigger(pattern
, trigger_name
, NULL
, 4,
1160 exclusions
, domain_type
, &condition
, &trigger
);
1162 nc_status
= lttng_notification_channel_subscribe(
1163 notification_channel
, condition
);
1164 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1165 "Subscribe to tracepoint event rule condition");
1168 * We registered 2 notifications triggers, one with an exclusion and
1169 * one without (control).
1170 * - The trigger with an exclusion will fire once every iteration.
1171 * - The trigger without an exclusion will fire 5 times every
1174 * We should get 5 times as many notifications from the control
1177 resume_application();
1180 * Get 6 notifications. We should get 1 for the regular trigger (with
1181 * the exclusion) and 5 from the control trigger. This works whatever
1182 * the order we receive the notifications.
1184 for (i
= 0; i
< 6; i
++) {
1185 char *name
= get_next_notification_trigger_name(
1186 notification_channel
);
1188 if (strcmp(ctrl_trigger_name
, name
) == 0) {
1190 } else if (strcmp(trigger_name
, name
) == 0) {
1197 ok(ctrl_count
/ 5 == count
,
1198 "Got 5 times as many control notif as of regular notif");
1200 suspend_application();
1202 lttng_unregister_trigger(trigger
);
1203 lttng_unregister_trigger(ctrl_trigger
);
1204 lttng_notification_channel_destroy(notification_channel
);
1205 lttng_trigger_destroy(trigger
);
1206 lttng_trigger_destroy(ctrl_trigger
);
1207 lttng_condition_destroy(condition
);
1208 lttng_condition_destroy(ctrl_condition
);
1212 static void test_kprobe_event_rule_notification(
1213 enum lttng_domain_type domain_type
)
1216 const int notification_count
= 3;
1217 enum lttng_notification_channel_status nc_status
;
1218 enum lttng_event_rule_status event_rule_status
;
1219 enum lttng_trigger_status trigger_status
;
1220 struct lttng_notification_channel
*notification_channel
= NULL
;
1221 struct lttng_condition
*condition
= NULL
;
1222 struct lttng_kernel_probe_location
*location
= NULL
;
1223 struct lttng_event_rule
*event_rule
= NULL
;
1224 struct lttng_action
*action
= NULL
;
1225 struct lttng_trigger
*trigger
= NULL
;
1226 const char * const trigger_name
= "kprobe_trigger";
1227 const char * const symbol_name
= "lttng_test_filter_event_write";
1229 action
= lttng_action_notify_create();
1231 fail("Failed to create notify action");
1235 location
= lttng_kernel_probe_location_symbol_create(symbol_name
, 0);
1237 fail("Failed to create kernel probe location");
1241 notification_channel
= lttng_notification_channel_create(
1242 lttng_session_daemon_notification_endpoint
);
1243 ok(notification_channel
, "Notification channel object creation");
1245 event_rule
= lttng_event_rule_kprobe_create();
1246 ok(event_rule
, "kprobe event rule object creation");
1248 event_rule_status
= lttng_event_rule_kprobe_set_location(
1249 event_rule
, location
);
1250 ok(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
,
1251 "Setting kprobe event rule location: '%s'", symbol_name
);
1253 event_rule_status
= lttng_event_rule_kprobe_set_name(
1254 event_rule
, trigger_name
);
1255 ok(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
,
1256 "Setting kprobe event rule name: '%s'", trigger_name
);
1258 condition
= lttng_condition_event_rule_create(event_rule
);
1259 ok(condition
, "Condition event rule object creation");
1261 /* Register the trigger for condition. */
1262 trigger
= lttng_trigger_create(condition
, action
);
1264 fail("Failed to create trigger with kernel probe event rule condition and notify action");
1268 trigger_status
= lttng_trigger_set_name(trigger
, trigger_name
);
1269 ok(trigger_status
== LTTNG_TRIGGER_STATUS_OK
,
1270 "Setting trigger name to '%s'", trigger_name
);
1272 ret
= lttng_register_trigger(trigger
);
1274 fail("Failed to register trigger with kernel probe event rule condition and notify action");
1278 nc_status
= lttng_notification_channel_subscribe(
1279 notification_channel
, condition
);
1280 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
1281 "Subscribe to tracepoint event rule condition");
1283 resume_application();
1285 for (i
= 0; i
< notification_count
; i
++) {
1286 char *name
= get_next_notification_trigger_name(
1287 notification_channel
);
1289 ok(strcmp(trigger_name
, name
) == 0,
1290 "Received notification for the expected trigger name: '%s' (%d/%d)",
1291 trigger_name
, i
+ 1, notification_count
);
1296 suspend_application();
1297 lttng_notification_channel_destroy(notification_channel
);
1298 lttng_unregister_trigger(trigger
);
1299 lttng_trigger_destroy(trigger
);
1300 lttng_action_destroy(action
);
1301 lttng_condition_destroy(condition
);
1302 lttng_kernel_probe_location_destroy(location
);
1306 int main(int argc
, const char *argv
[])
1309 const char *session_name
= NULL
;
1310 const char *channel_name
= NULL
;
1311 const char *domain_type_string
= NULL
;
1312 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
1315 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
1319 test_scenario
= atoi(argv
[1]);
1320 domain_type_string
= argv
[2];
1321 app_pid
= (pid_t
) atoi(argv
[3]);
1322 app_state_file
= argv
[4];
1324 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
1325 domain_type
= LTTNG_DOMAIN_UST
;
1327 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
1328 domain_type
= LTTNG_DOMAIN_KERNEL
;
1330 if (domain_type
== LTTNG_DOMAIN_NONE
) {
1331 fail("Unknown domain type");
1336 * Test cases are responsible for resuming the app when needed
1337 * and making sure it's suspended when returning.
1339 suspend_application();
1341 switch (test_scenario
) {
1346 /* Test cases that need gen-ust-event testapp. */
1347 diag("Test basic notification error paths for %s domain",
1348 domain_type_string
);
1349 test_invalid_channel_subscription(domain_type
);
1351 diag("Test tracepoint event rule notifications for domain %s",
1352 domain_type_string
);
1353 test_tracepoint_event_rule_notification(domain_type
);
1355 diag("Test tracepoint event rule notifications with filter for domain %s",
1356 domain_type_string
);
1357 test_tracepoint_event_rule_notification_filter(domain_type
);
1362 /* Test cases that need a tracing session enabled. */
1366 * Argument 7 and upward are named pipe location for consumerd
1369 named_pipe_args_start
= 7;
1372 fail("Missing parameter for tests to run %d", argc
);
1378 session_name
= argv
[5];
1379 channel_name
= argv
[6];
1381 test_subscription_twice(session_name
, channel_name
,
1384 diag("Test trigger for domain %s with buffer_usage_low condition",
1385 domain_type_string
);
1386 test_triggers_buffer_usage_condition(session_name
, channel_name
,
1388 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
);
1390 diag("Test trigger for domain %s with buffer_usage_high condition",
1391 domain_type_string
);
1392 test_triggers_buffer_usage_condition(session_name
, channel_name
,
1394 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
);
1396 diag("Test buffer usage notification channel api for domain %s",
1397 domain_type_string
);
1398 test_buffer_usage_notification_channel(session_name
, channel_name
,
1405 * Test cases that need a test app with more than one event
1411 * At the moment, the only test case of this scenario is
1412 * exclusion which is only supported by UST.
1414 assert(domain_type
== LTTNG_DOMAIN_UST
);
1415 diag("Test tracepoint event rule notifications with exclusion for domain %s",
1416 domain_type_string
);
1417 test_tracepoint_event_rule_notification_exclusion(domain_type
);
1425 /* Test cases that need the kernel tracer. */
1426 assert(domain_type
== LTTNG_DOMAIN_KERNEL
);
1427 diag("Test kprobe event rule notifications for domain %s",
1428 domain_type_string
);
1430 test_kprobe_event_rule_notification(domain_type
);
1439 return exit_status();