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>
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/domain.h>
33 #include <lttng/endpoint.h>
34 #include <lttng/lttng-error.h>
35 #include <lttng/notification/channel.h>
36 #include <lttng/notification/notification.h>
37 #include <lttng/trigger/trigger.h>
38 #include <lttng/lttng.h>
45 int named_pipe_args_start
= 0;
47 const char *app_state_file
= NULL
;
50 void wait_on_file(const char *path
, bool file_exist
)
59 ret
= stat(path
, &buf
);
60 if (ret
== -1 && errno
== ENOENT
) {
63 * The file does not exist. wait a bit and
64 * continue looping until it does.
66 (void) poll(NULL
, 0, 10);
71 * File does not exist and the exit condition we want.
72 * Break from the loop and return.
81 * stat() returned 0, so the file exists. break now only if
82 * that's the exit condition we want.
90 int write_pipe(const char *path
, uint8_t data
)
95 fd
= open(path
, O_WRONLY
| O_NONBLOCK
);
97 perror("Could not open consumer control named pipe");
101 ret
= write(fd
, &data
, sizeof(data
));
103 perror("Named pipe write failed");
105 perror("Named pipe close failed");
113 perror("Name pipe closing failed");
121 int stop_consumer(const char **argv
)
125 for (i
= named_pipe_args_start
; i
< nb_args
; i
++) {
126 ret
= write_pipe(argv
[i
], 49);
131 int resume_consumer(const char **argv
)
135 for (i
= named_pipe_args_start
; i
< nb_args
; i
++) {
136 ret
= write_pipe(argv
[i
], 0);
141 int suspend_application()
146 if (!stat(app_state_file
, &buf
)) {
147 fail("App is already in a suspended state.");
153 * Send SIGUSR1 to application instructing it to bypass tracepoint.
155 ret
= kill(app_pid
, SIGUSR1
);
157 fail("SIGUSR1 failed. errno %d", errno
);
162 wait_on_file(app_state_file
, true);
169 int resume_application()
174 ret
= stat(app_state_file
, &buf
);
175 if (ret
== -1 && errno
== ENOENT
) {
176 fail("State file does not exist");
184 ret
= kill(app_pid
, SIGUSR1
);
186 fail("SIGUSR1 failed. errno %d", errno
);
191 wait_on_file(app_state_file
, false);
199 void test_triggers_buffer_usage_condition(const char *session_name
,
200 const char *channel_name
,
201 enum lttng_domain_type domain_type
,
202 enum lttng_condition_type condition_type
)
204 unsigned int test_vector_size
= 5, i
;
205 enum lttng_condition_status condition_status
;
206 struct lttng_action
*action
;
209 action
= lttng_action_notify_create();
211 fail("Setup error on action creation");
215 /* Test lttng_register_trigger with null value */
216 ok(lttng_register_trigger(NULL
) == -LTTNG_ERR_INVALID
, "Registering a NULL trigger fails as expected");
218 /* Test: register a trigger */
220 for (i
= 0; i
< pow(2,test_vector_size
); i
++) {
222 char *test_tuple_string
= NULL
;
223 unsigned int mask_position
= 0;
224 bool session_name_set
= false;
225 bool channel_name_set
= false;
226 bool threshold_ratio_set
= false;
227 bool threshold_byte_set
= false;
228 bool domain_type_set
= false;
230 struct lttng_trigger
*trigger
= NULL
;
231 struct lttng_condition
*condition
= NULL
;
233 /* Create base condition */
234 switch (condition_type
) {
235 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
236 condition
= lttng_condition_buffer_usage_low_create();
238 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
239 condition
= lttng_condition_buffer_usage_high_create();
252 /* Prepare the condition for trigger registration test */
254 /* Set session name */
255 if ((1 << mask_position
) & i
) {
256 condition_status
= lttng_condition_buffer_usage_set_session_name(
257 condition
, session_name
);
258 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
262 session_name_set
= true;
266 /* Set channel name */
267 if ((1 << mask_position
) & i
) {
268 condition_status
= lttng_condition_buffer_usage_set_channel_name(
269 condition
, channel_name
);
270 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
274 channel_name_set
= true;
278 /* Set threshold ratio */
279 if ((1 << mask_position
) & i
) {
280 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
282 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
286 threshold_ratio_set
= true;
290 /* Set threshold byte */
291 if ((1 << mask_position
) & i
) {
292 condition_status
= lttng_condition_buffer_usage_set_threshold(
294 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
298 threshold_byte_set
= true;
302 /* Set domain type */
303 if ((1 << mask_position
) & i
) {
304 condition_status
= lttng_condition_buffer_usage_set_domain_type(
305 condition
, LTTNG_DOMAIN_UST
);
306 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
310 domain_type_set
= true;
314 if (mask_position
!= test_vector_size
-1) {
315 assert("Logic error for test vector generation");
318 loop_ret
= asprintf(&test_tuple_string
, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
319 session_name_set
? "set" : "unset",
320 channel_name_set
? "set" : "unset",
321 threshold_ratio_set
? "set" : "unset",
322 threshold_byte_set
? "set" : "unset",
323 domain_type_set
? "set" : "unset");
324 if (!test_tuple_string
|| loop_ret
< 0) {
330 trigger
= lttng_trigger_create(condition
, action
);
336 loop_ret
= lttng_register_trigger(trigger
);
340 fail("Setup error occurred for tuple: %s", test_tuple_string
);
344 /* This combination happens three times */
345 if (session_name_set
&& channel_name_set
346 && (threshold_ratio_set
|| threshold_byte_set
)
347 && domain_type_set
) {
348 ok(loop_ret
== 0, "Trigger is registered: %s", test_tuple_string
);
351 * Test that a trigger cannot be registered
354 loop_ret
= lttng_register_trigger(trigger
);
355 ok(loop_ret
== -LTTNG_ERR_TRIGGER_EXISTS
, "Re-register trigger fails as expected: %s", test_tuple_string
);
357 /* Test that a trigger can be unregistered */
358 loop_ret
= lttng_unregister_trigger(trigger
);
359 ok(loop_ret
== 0, "Unregister trigger: %s", test_tuple_string
);
362 * Test that unregistration of a non-previously
363 * registered trigger fail.
365 loop_ret
= lttng_unregister_trigger(trigger
);
366 ok(loop_ret
== -LTTNG_ERR_TRIGGER_NOT_FOUND
, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string
);
368 ok(loop_ret
== -LTTNG_ERR_INVALID_TRIGGER
, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string
);
372 free(test_tuple_string
);
373 lttng_trigger_destroy(trigger
);
374 lttng_condition_destroy(condition
);
378 lttng_action_destroy(action
);
382 void wait_data_pending(const char *session_name
)
387 ret
= lttng_data_pending(session_name
);
392 void test_notification_channel(const char *session_name
, const char *channel_name
, const enum lttng_domain_type domain_type
, const char **argv
)
395 enum lttng_condition_status condition_status
;
396 enum lttng_notification_channel_status nc_status
;
398 struct lttng_action
*action
= NULL
;
399 struct lttng_notification
*notification
= NULL
;
400 struct lttng_notification_channel
*notification_channel
= NULL
;
401 struct lttng_trigger
*trigger
= NULL
;
403 struct lttng_condition
*low_condition
= NULL
;
404 struct lttng_condition
*high_condition
= NULL
;
405 struct lttng_condition
*dummy_invalid_condition
= NULL
;
406 struct lttng_condition
*dummy_condition
= NULL
;
408 double low_ratio
= 0.0;
409 double high_ratio
= 0.99;
412 action
= lttng_action_notify_create();
414 fail("Setup error on action creation");
418 /* Create a dummy, empty condition for later test */
419 dummy_invalid_condition
= lttng_condition_buffer_usage_low_create();
420 if (!dummy_invalid_condition
) {
421 fail("Setup error on condition creation");
425 /* Create a valid dummy condition with a ratio of 0.5 */
426 dummy_condition
= lttng_condition_buffer_usage_low_create();
427 if (!dummy_condition
) {
428 fail("Setup error on dummy_condition creation");
432 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
433 dummy_condition
, 0.5);
434 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
435 fail("Setup error on condition creation");
439 condition_status
= lttng_condition_buffer_usage_set_session_name(
440 dummy_condition
, session_name
);
441 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
442 fail("Setup error on dummy_condition creation");
445 condition_status
= lttng_condition_buffer_usage_set_channel_name(
446 dummy_condition
, channel_name
);
447 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
448 fail("Setup error on dummy_condition creation");
451 condition_status
= lttng_condition_buffer_usage_set_domain_type(
452 dummy_condition
, domain_type
);
453 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
454 fail("Setup error on dummy_condition creation");
458 /* Register a low condition with a ratio */
459 low_condition
= lttng_condition_buffer_usage_low_create();
460 if (!low_condition
) {
461 fail("Setup error on low_condition creation");
464 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
465 low_condition
, low_ratio
);
466 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
467 fail("Setup error on low_condition creation");
471 condition_status
= lttng_condition_buffer_usage_set_session_name(
472 low_condition
, session_name
);
473 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
474 fail("Setup error on low_condition creation");
477 condition_status
= lttng_condition_buffer_usage_set_channel_name(
478 low_condition
, channel_name
);
479 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
480 fail("Setup error on low_condition creation");
483 condition_status
= lttng_condition_buffer_usage_set_domain_type(
484 low_condition
, domain_type
);
485 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
486 fail("Setup error on low_condition creation");
491 /* Register a high condition with a ratio */
492 high_condition
= lttng_condition_buffer_usage_high_create();
493 if (!high_condition
) {
494 fail("Setup error on high_condition creation");
498 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
499 high_condition
, high_ratio
);
500 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
501 fail("Setup error on high_condition creation");
505 condition_status
= lttng_condition_buffer_usage_set_session_name(
506 high_condition
, session_name
);
507 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
508 fail("Setup error on high_condition creation");
511 condition_status
= lttng_condition_buffer_usage_set_channel_name(
512 high_condition
, channel_name
);
513 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
514 fail("Setup error on high_condition creation");
517 condition_status
= lttng_condition_buffer_usage_set_domain_type(
518 high_condition
, domain_type
);
519 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
520 fail("Setup error on high_condition creation");
524 /* Register the triggers for low and high condition */
525 trigger
= lttng_trigger_create(low_condition
, action
);
527 fail("Setup error on low trigger creation");
531 ret
= lttng_register_trigger(trigger
);
533 fail("Setup error on low trigger registration");
537 lttng_trigger_destroy(trigger
);
540 trigger
= lttng_trigger_create(high_condition
, action
);
542 fail("Setup error on high trigger creation");
546 ret
= lttng_register_trigger(trigger
);
548 fail("Setup error on high trigger registration");
553 notification_channel
= lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
554 ok(notification_channel
, "Notification channel object creation");
555 if (!notification_channel
) {
559 /* Basic error path check */
560 nc_status
= lttng_notification_channel_subscribe(NULL
, NULL
);
561 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NULL");
563 nc_status
= lttng_notification_channel_subscribe(notification_channel
, NULL
);
564 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NON-NULL, NULL");
566 nc_status
= lttng_notification_channel_subscribe(NULL
, low_condition
);
567 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NON-NULL");
569 nc_status
= lttng_notification_channel_subscribe(notification_channel
, dummy_invalid_condition
);
570 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Subscribing to an invalid condition");
572 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_invalid_condition
);
573 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Unsubscribing from an invalid condition");
575 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_condition
);
576 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION
, "Unsubscribing from a valid unknown condition");
578 /* Subscribe a valid low condition */
579 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
580 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
582 /* Subscribe a valid high condition */
583 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
584 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
586 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
587 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
589 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
590 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
592 /* Wait for notification to happen */
594 lttng_start_tracing(session_name
);
596 /* Wait for high notification */
597 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
598 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
600 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
601 "High notification received after intermediary communication");
602 lttng_notification_destroy(notification
);
605 suspend_application();
606 lttng_stop_tracing_no_wait(session_name
);
607 resume_consumer(argv
);
608 wait_data_pending(session_name
);
611 * Test that communication still work even if there is notification
612 * waiting for consumption.
615 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
616 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe with pending notification");
618 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
619 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "subscribe with pending notification");
621 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
622 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
624 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
625 "Low notification received after intermediary communication");
626 lttng_notification_destroy(notification
);
629 /* Stop consumer to force a high notification */
631 resume_application();
632 lttng_start_tracing(session_name
);
634 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
635 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
636 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
637 "High notification received after intermediary communication");
638 lttng_notification_destroy(notification
);
641 suspend_application();
642 lttng_stop_tracing_no_wait(session_name
);
643 resume_consumer(argv
);
644 wait_data_pending(session_name
);
646 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
647 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
648 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
649 "Low notification received after re-subscription");
650 lttng_notification_destroy(notification
);
654 resume_application();
655 /* Stop consumer to force a high notification */
656 lttng_start_tracing(session_name
);
658 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
659 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
660 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
661 "High notification");
662 lttng_notification_destroy(notification
);
665 /* Resume consumer to allow event consumption */
666 suspend_application();
667 lttng_stop_tracing_no_wait(session_name
);
668 resume_consumer(argv
);
669 wait_data_pending(session_name
);
671 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
672 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe low condition with pending notification");
673 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, high_condition
);
674 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe high condition with pending notification");
677 lttng_notification_channel_destroy(notification_channel
);
678 lttng_trigger_destroy(trigger
);
679 lttng_action_destroy(action
);
680 lttng_condition_destroy(low_condition
);
681 lttng_condition_destroy(high_condition
);
682 lttng_condition_destroy(dummy_invalid_condition
);
683 lttng_condition_destroy(dummy_condition
);
686 int main(int argc
, const char *argv
[])
688 const char *session_name
= NULL
;
689 const char *channel_name
= NULL
;
690 const char *domain_type_string
= NULL
;
691 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
693 plan_tests(NUM_TESTS
);
695 /* Argument 6 and upward are named pipe location for consumerd control */
696 named_pipe_args_start
= 6;
699 fail("Missing parameter for tests to run %d", argc
);
705 domain_type_string
= argv
[1];
706 session_name
= argv
[2];
707 channel_name
= argv
[3];
708 app_pid
= (pid_t
) atoi(argv
[4]);
709 app_state_file
= argv
[5];
711 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
712 domain_type
= LTTNG_DOMAIN_UST
;
714 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
715 domain_type
= LTTNG_DOMAIN_KERNEL
;
717 if (domain_type
== LTTNG_DOMAIN_NONE
) {
718 fail("Unknown domain type");
722 diag("Test trigger for domain %s with buffer_usage_low condition", domain_type_string
);
723 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
);
724 diag("Test trigger for domain %s with buffer_usage_high condition", domain_type_string
);
725 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
);
727 diag("Test notification channel api for domain %s", domain_type_string
);
728 test_notification_channel(session_name
, channel_name
, domain_type
, argv
);
730 return exit_status();