4 * Tests suite for LTTng notification API
6 * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 #include <sys/types.h>
42 #include <lttng/action/action.h>
43 #include <lttng/action/notify.h>
44 #include <lttng/condition/buffer-usage.h>
45 #include <lttng/condition/condition.h>
46 #include <lttng/condition/evaluation.h>
47 #include <lttng/domain.h>
48 #include <lttng/endpoint.h>
49 #include <lttng/lttng-error.h>
50 #include <lttng/notification/channel.h>
51 #include <lttng/notification/notification.h>
52 #include <lttng/trigger/trigger.h>
59 int named_pipe_args_start
= 0;
61 const char *app_state_file
= NULL
;
64 void wait_on_file(const char *path
, bool file_exist
)
73 ret
= stat(path
, &buf
);
74 if (ret
== -1 && errno
== ENOENT
) {
76 (void) poll(NULL
, 0, 10); /* 10 ms delay */
79 break; /* File does not exist */
89 int write_pipe(const char *path
, uint8_t data
)
94 fd
= open(path
, O_WRONLY
| O_NONBLOCK
);
96 perror("Could not open consumer control named pipe");
100 ret
= write(fd
, &data
, sizeof(data
));
102 perror("Named pipe write failed");
104 perror("Named pipe close failed");
112 perror("Name pipe closing failed");
120 int stop_consumer(const char **argv
)
123 for (int i
= named_pipe_args_start
; i
< nb_args
; i
++) {
124 ret
= write_pipe(argv
[i
], 49);
129 int resume_consumer(const char **argv
)
132 for (int i
= named_pipe_args_start
; i
< nb_args
; i
++) {
133 ret
= write_pipe(argv
[i
], 0);
138 int suspend_application()
143 if (!stat(app_state_file
, &buf
)) {
144 fail("App is already in a suspended state.");
150 * Send SIGUSR1 to application instructing it to bypass tracepoint.
152 ret
= kill(app_pid
, SIGUSR1
);
154 fail("SIGUSR1 failed. errno %d", errno
);
159 wait_on_file(app_state_file
, true);
166 int resume_application()
171 ret
= stat(app_state_file
, &buf
);
172 if (ret
== -1 && errno
== ENOENT
) {
173 fail("State file does not exist");
181 ret
= kill(app_pid
, SIGUSR1
);
183 fail("SIGUSR1 failed. errno %d", errno
);
188 wait_on_file(app_state_file
, false);
196 void test_triggers_buffer_usage_condition(const char *session_name
,
197 const char *channel_name
,
198 enum lttng_domain_type domain_type
,
199 enum lttng_condition_type condition_type
)
201 enum lttng_condition_status condition_status
;
202 struct lttng_action
*action
;
205 action
= lttng_action_notify_create();
207 fail("Setup error on action creation");
211 /* Test lttng_register_trigger with null value */
212 ok(lttng_register_trigger(NULL
) == -LTTNG_ERR_INVALID
, "Registering a NULL trigger fails as expected");
214 /* Test: register a trigger */
215 unsigned int test_vector_size
= 5;
216 for (unsigned int i
= 0; i
< pow(2,test_vector_size
); i
++) {
218 char *test_tuple_string
= NULL
;
219 unsigned int mask_position
= 0;
220 bool session_name_set
= false;
221 bool channel_name_set
= false;
222 bool threshold_ratio_set
= false;
223 bool threshold_byte_set
= false;
224 bool domain_type_set
= false;
226 struct lttng_trigger
*trigger
= NULL
;
227 struct lttng_condition
*condition
= NULL
;
229 /* Create base condition */
230 switch (condition_type
) {
231 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
232 condition
= lttng_condition_buffer_usage_low_create();
234 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
235 condition
= lttng_condition_buffer_usage_high_create();
248 /* Prepare the condition for trigger registration test */
250 /* Set session name */
251 if ((1 << mask_position
) & i
) {
252 condition_status
= lttng_condition_buffer_usage_set_session_name(
253 condition
, session_name
);
254 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
258 session_name_set
= true;
262 /* Set channel name */
263 if ((1 << mask_position
) & i
) {
264 condition_status
= lttng_condition_buffer_usage_set_channel_name(
265 condition
, channel_name
);
266 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
270 channel_name_set
= true;
274 /* Set threshold ratio */
275 if ((1 << mask_position
) & i
) {
276 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
278 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
282 threshold_ratio_set
= true;
286 /* Set threshold byte */
287 if ((1 << mask_position
) & i
) {
288 condition_status
= lttng_condition_buffer_usage_set_threshold(
290 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
294 threshold_byte_set
= true;
298 /* Set domain type */
299 if ((1 << mask_position
) & i
) {
300 condition_status
= lttng_condition_buffer_usage_set_domain_type(
301 condition
, LTTNG_DOMAIN_UST
);
302 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
306 domain_type_set
= true;
310 if (mask_position
!= test_vector_size
-1) {
311 assert("Logic error for test vector generation");
314 loop_ret
= asprintf(&test_tuple_string
, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
315 session_name_set
? "set" : "unset",
316 channel_name_set
? "set" : "unset",
317 threshold_ratio_set
? "set" : "unset",
318 threshold_byte_set
? "set" : "unset",
319 domain_type_set
? "set" : "unset");
320 if (!test_tuple_string
|| loop_ret
< 0) {
326 trigger
= lttng_trigger_create(condition
, action
);
332 loop_ret
= lttng_register_trigger(trigger
);
336 fail("Setup error occurred for tuple: %s", test_tuple_string
);
340 /* This combination happens three times */
341 if (session_name_set
&& channel_name_set
342 && (threshold_ratio_set
|| threshold_byte_set
)
343 && domain_type_set
) {
344 ok(loop_ret
== 0, "Trigger is registered: %s", test_tuple_string
);
347 * Test that a trigger cannot be registered
350 loop_ret
= lttng_register_trigger(trigger
);
351 ok(loop_ret
== -LTTNG_ERR_TRIGGER_EXISTS
, "Re-register trigger fails as expected: %s", test_tuple_string
);
353 /* Test that a trigger can be unregistered */
354 loop_ret
= lttng_unregister_trigger(trigger
);
355 ok(loop_ret
== 0, "Unregister trigger: %s", test_tuple_string
);
358 * Test that unregistration of a non-previously
359 * registered trigger fail.
361 loop_ret
= lttng_unregister_trigger(trigger
);
362 ok(loop_ret
== -LTTNG_ERR_TRIGGER_NOT_FOUND
, "Unregister of a non-registerd trigger fails as expected: %s", test_tuple_string
);
364 ok(loop_ret
== -LTTNG_ERR_INVALID_TRIGGER
, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string
);
368 free(test_tuple_string
);
369 lttng_trigger_destroy(trigger
);
370 lttng_condition_destroy(condition
);
374 lttng_action_destroy(action
);
378 void wait_data_pending(const char *session_name
)
383 ret
= lttng_data_pending(session_name
);
388 void test_notification_channel(const char *session_name
, const char *channel_name
, const enum lttng_domain_type domain_type
, const char **argv
)
391 enum lttng_condition_status condition_status
;
392 enum lttng_notification_channel_status nc_status
;
394 struct lttng_action
*action
= NULL
;
395 struct lttng_notification
*notification
= NULL
;
396 struct lttng_notification_channel
*notification_channel
= NULL
;
397 struct lttng_trigger
*trigger
= NULL
;
399 struct lttng_condition
*low_condition
= NULL
;
400 struct lttng_condition
*high_condition
= NULL
;
401 struct lttng_condition
*dummy_invalid_condition
= NULL
;
402 struct lttng_condition
*dummy_condition
= NULL
;
404 double low_ratio
= 0.0;
405 double high_ratio
= 0.99;
408 action
= lttng_action_notify_create();
410 fail("Setup error on action creation");
414 /* Create a dummy, empty condition for later test */
415 dummy_invalid_condition
= lttng_condition_buffer_usage_low_create();
416 if (!dummy_invalid_condition
) {
417 fail("Setup error on condition creation");
421 /* Create a valid dummy condition with a ratio of 0.5 */
422 dummy_condition
= lttng_condition_buffer_usage_low_create();
423 if (!dummy_condition
) {
424 fail("Setup error on dummy_condition creation");
428 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
429 dummy_condition
, 0.5);
430 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
431 fail("Setup error on condition creation");
435 condition_status
= lttng_condition_buffer_usage_set_session_name(
436 dummy_condition
, session_name
);
437 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
438 fail("Setup error on dummy_condition creation");
441 condition_status
= lttng_condition_buffer_usage_set_channel_name(
442 dummy_condition
, channel_name
);
443 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
444 fail("Setup error on dummy_condition creation");
447 condition_status
= lttng_condition_buffer_usage_set_domain_type(
448 dummy_condition
, domain_type
);
449 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
450 fail("Setup error on dummy_condition creation");
454 /* Register a low condition with a ratio */
455 low_condition
= lttng_condition_buffer_usage_low_create();
456 if (!low_condition
) {
457 fail("Setup error on low_condition creation");
460 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
461 low_condition
, low_ratio
);
462 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
463 fail("Setup error on low_condition creation");
467 condition_status
= lttng_condition_buffer_usage_set_session_name(
468 low_condition
, session_name
);
469 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
470 fail("Setup error on low_condition creation");
473 condition_status
= lttng_condition_buffer_usage_set_channel_name(
474 low_condition
, channel_name
);
475 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
476 fail("Setup error on low_condition creation");
479 condition_status
= lttng_condition_buffer_usage_set_domain_type(
480 low_condition
, domain_type
);
481 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
482 fail("Setup error on low_condition creation");
487 /* Register a high condition with a ratio */
488 high_condition
= lttng_condition_buffer_usage_high_create();
489 if (!high_condition
) {
490 fail("Setup error on high_condition creation");
494 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
495 high_condition
, high_ratio
);
496 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
497 fail("Setup error on high_condition creation");
501 condition_status
= lttng_condition_buffer_usage_set_session_name(
502 high_condition
, session_name
);
503 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
504 fail("Setup error on high_condition creation");
507 condition_status
= lttng_condition_buffer_usage_set_channel_name(
508 high_condition
, channel_name
);
509 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
510 fail("Setup error on high_condition creation");
513 condition_status
= lttng_condition_buffer_usage_set_domain_type(
514 high_condition
, domain_type
);
515 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
516 fail("Setup error on high_condition creation");
520 /* Register the triggers for low and high condition */
521 trigger
= lttng_trigger_create(low_condition
, action
);
523 fail("Setup error on low trigger creation");
527 ret
= lttng_register_trigger(trigger
);
529 fail("Setup error on low trigger registration");
533 lttng_trigger_destroy(trigger
);
536 trigger
= lttng_trigger_create(high_condition
, action
);
538 fail("Setup error on high trigger creation");
542 ret
= lttng_register_trigger(trigger
);
544 fail("Setup error on high trigger registration");
549 notification_channel
= lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
550 ok(notification_channel
, "Notification channel object creation");
551 if (!notification_channel
) {
555 /* Basic error path check */
556 nc_status
= lttng_notification_channel_subscribe(NULL
, NULL
);
557 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NULL");
559 nc_status
= lttng_notification_channel_subscribe(notification_channel
, NULL
);
560 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NON-NULL, NULL");
562 nc_status
= lttng_notification_channel_subscribe(NULL
, low_condition
);
563 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NON-NULL");
565 nc_status
= lttng_notification_channel_subscribe(notification_channel
, dummy_invalid_condition
);
566 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Subscribing to an invalid condition");
568 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_invalid_condition
);
569 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Unsubscribing to an invalid condition");
571 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_condition
);
572 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION
, "Unsubscribing to an valid unknown condition");
574 /* Subscribe a valid low condition */
575 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
576 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
578 /* Subscribe a valid high condition */
579 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
580 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
582 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
583 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
585 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
586 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
588 /* Wait for notification to happen */
590 lttng_start_tracing(session_name
);
592 /* Wait for high notification */
593 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
594 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
596 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
597 "High notification received after intermediary communication");
598 lttng_notification_destroy(notification
);
601 suspend_application();
602 lttng_stop_tracing_no_wait(session_name
);
603 resume_consumer(argv
);
604 wait_data_pending(session_name
);
607 * Test that communication still work even if there is notification
608 * waiting for consumption.
611 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
612 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe with pending notification");
614 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
615 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "subscribe with pending notification");
617 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
618 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
620 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
621 "Low notification received after intermediary communication");
622 lttng_notification_destroy(notification
);
625 /* Stop consumer to force a high notification */
627 resume_application();
628 lttng_start_tracing(session_name
);
630 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
631 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
632 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
633 "High notification received after intermediary communication");
634 lttng_notification_destroy(notification
);
637 suspend_application();
638 lttng_stop_tracing_no_wait(session_name
);
639 resume_consumer(argv
);
640 wait_data_pending(session_name
);
642 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
643 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
644 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
645 "Low notification received after re-subscription");
646 lttng_notification_destroy(notification
);
650 resume_application();
651 /* Stop consumer to force a high notification */
652 lttng_start_tracing(session_name
);
654 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
655 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
656 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
657 "High notification");
658 lttng_notification_destroy(notification
);
661 /* Resume consumer to allow event consumption */
662 suspend_application();
663 lttng_stop_tracing_no_wait(session_name
);
664 resume_consumer(argv
);
665 wait_data_pending(session_name
);
667 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
668 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe low condition with pending notification");
669 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, high_condition
);
670 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe high condition with pending notification");
673 lttng_notification_channel_destroy(notification_channel
);
674 lttng_trigger_destroy(trigger
);
675 lttng_action_destroy(action
);
676 lttng_condition_destroy(low_condition
);
677 lttng_condition_destroy(high_condition
);
678 lttng_condition_destroy(dummy_invalid_condition
);
679 lttng_condition_destroy(dummy_condition
);
682 int main(int argc
, const char *argv
[])
684 const char *session_name
= NULL
;
685 const char *channel_name
= NULL
;
686 const char *domain_type_string
= NULL
;
687 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
689 plan_tests(NUM_TESTS
);
691 /* Argument 6 and upward are named pipe location for consumerd control */
692 named_pipe_args_start
= 6;
695 fail("Missing parameter for tests to run %d", argc
);
701 domain_type_string
= argv
[1];
702 session_name
= argv
[2];
703 channel_name
= argv
[3];
704 app_pid
= (pid_t
) atoi(argv
[4]);
705 app_state_file
= argv
[5];
707 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
708 domain_type
= LTTNG_DOMAIN_UST
;
710 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
711 domain_type
= LTTNG_DOMAIN_KERNEL
;
713 if (domain_type
== LTTNG_DOMAIN_NONE
) {
714 fail("Unknown domain type");
718 diag("Test trigger for domain %s with buffer_usage_low condition", domain_type_string
);
719 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
);
720 diag("Test trigger for domain %s with buffer_usage_high condition", domain_type_string
);
721 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
);
723 diag("Test notification channel api for domain %s", domain_type_string
);
724 test_notification_channel(session_name
, channel_name
, domain_type
, argv
);
726 return exit_status();