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>
39 #include <lttng/action/action.h>
40 #include <lttng/action/notify.h>
41 #include <lttng/condition/buffer-usage.h>
42 #include <lttng/condition/condition.h>
43 #include <lttng/condition/evaluation.h>
44 #include <lttng/domain.h>
45 #include <lttng/endpoint.h>
46 #include <lttng/lttng-error.h>
47 #include <lttng/notification/channel.h>
48 #include <lttng/notification/notification.h>
49 #include <lttng/trigger/trigger.h>
55 int named_pipe_args_start
= 0;
57 int write_pipe(const char *path
, uint8_t data
)
62 fd
= open(path
, O_WRONLY
| O_NONBLOCK
);
64 perror("Could not open consumer control named pipe");
68 ret
= write(fd
, &data
, sizeof(data
));
70 perror("Named pipe write failed");
72 perror("Named pipe close failed");
80 perror("Name pipe closing failed");
88 int stop_consumer(const char **argv
)
91 for (int i
= named_pipe_args_start
; i
< nb_args
; i
++) {
92 ret
= write_pipe(argv
[i
], 49);
97 int resume_consumer(const char **argv
)
100 for (int i
= named_pipe_args_start
; i
< nb_args
; i
++) {
101 ret
= write_pipe(argv
[i
], 0);
106 void test_triggers_buffer_usage_condition(const char *session_name
,
107 const char *channel_name
,
108 enum lttng_domain_type domain_type
,
109 enum lttng_condition_type condition_type
)
111 enum lttng_condition_status condition_status
;
112 struct lttng_action
*action
;
115 action
= lttng_action_notify_create();
117 fail("Setup error on action creation");
121 /* Test lttng_register_trigger with null value */
122 ok(lttng_register_trigger(NULL
) == -LTTNG_ERR_INVALID
, "Registering a NULL trigger fails as expected");
124 /* Test: register a trigger */
125 unsigned int test_vector_size
= 5;
126 for (unsigned int i
= 0; i
< pow(2,test_vector_size
); i
++) {
128 char *test_tuple_string
= NULL
;
129 unsigned int mask_position
= 0;
130 bool session_name_set
= false;
131 bool channel_name_set
= false;
132 bool threshold_ratio_set
= false;
133 bool threshold_byte_set
= false;
134 bool domain_type_set
= false;
136 struct lttng_trigger
*trigger
= NULL
;
137 struct lttng_condition
*condition
= NULL
;
139 /* Create base condition */
140 switch (condition_type
) {
141 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
:
142 condition
= lttng_condition_buffer_usage_low_create();
144 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
:
145 condition
= lttng_condition_buffer_usage_high_create();
158 /* Prepare the condition for trigger registration test */
160 /* Set session name */
161 if ((1 << mask_position
) & i
) {
162 condition_status
= lttng_condition_buffer_usage_set_session_name(
163 condition
, session_name
);
164 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
168 session_name_set
= true;
172 /* Set channel name */
173 if ((1 << mask_position
) & i
) {
174 condition_status
= lttng_condition_buffer_usage_set_channel_name(
175 condition
, channel_name
);
176 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
180 channel_name_set
= true;
184 /* Set threshold ratio */
185 if ((1 << mask_position
) & i
) {
186 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
188 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
192 threshold_ratio_set
= true;
196 /* Set threshold byte */
197 if ((1 << mask_position
) & i
) {
198 condition_status
= lttng_condition_buffer_usage_set_threshold(
200 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
204 threshold_byte_set
= true;
208 /* Set domain type */
209 if ((1 << mask_position
) & i
) {
210 condition_status
= lttng_condition_buffer_usage_set_domain_type(
211 condition
, LTTNG_DOMAIN_UST
);
212 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
216 domain_type_set
= true;
220 if (mask_position
!= test_vector_size
-1) {
221 assert("Logic error for test vector generation");
224 loop_ret
= asprintf(&test_tuple_string
, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
225 session_name_set
? "set" : "unset",
226 channel_name_set
? "set" : "unset",
227 threshold_ratio_set
? "set" : "unset",
228 threshold_byte_set
? "set" : "unset",
229 domain_type_set
? "set" : "unset");
230 if (!test_tuple_string
|| loop_ret
< 0) {
236 trigger
= lttng_trigger_create(condition
, action
);
242 loop_ret
= lttng_register_trigger(trigger
);
246 fail("Setup error occurred for tuple: %s", test_tuple_string
);
250 /* This combination happens three times */
251 if (session_name_set
&& channel_name_set
252 && (threshold_ratio_set
|| threshold_byte_set
)
253 && domain_type_set
) {
254 ok(loop_ret
== 0, "Trigger is registered: %s", test_tuple_string
);
257 * Test that a trigger cannot be registered
260 loop_ret
= lttng_register_trigger(trigger
);
261 ok(loop_ret
== -LTTNG_ERR_TRIGGER_EXISTS
, "Re-register trigger fails as expected: %s", test_tuple_string
);
263 /* Test that a trigger can be unregistered */
264 loop_ret
= lttng_unregister_trigger(trigger
);
265 ok(loop_ret
== 0, "Unregister trigger: %s", test_tuple_string
);
268 * Test that unregistration of a non-previously
269 * registered trigger fail.
271 loop_ret
= lttng_unregister_trigger(trigger
);
272 ok(loop_ret
== -LTTNG_ERR_TRIGGER_NOT_FOUND
, "Unregister of a non-registerd trigger fails as expected: %s", test_tuple_string
);
274 ok(loop_ret
== -LTTNG_ERR_INVALID_TRIGGER
, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string
);
278 free(test_tuple_string
);
279 lttng_trigger_destroy(trigger
);
280 lttng_condition_destroy(condition
);
284 lttng_action_destroy(action
);
287 void test_notification_channel(const char *session_name
, const char *channel_name
, enum lttng_domain_type domain_type
, const char **argv
)
290 enum lttng_condition_status condition_status
;
291 enum lttng_notification_channel_status nc_status
;
293 struct lttng_action
*action
= NULL
;
294 struct lttng_notification
*notification
= NULL
;
295 struct lttng_notification_channel
*notification_channel
= NULL
;
296 struct lttng_trigger
*trigger
= NULL
;
298 struct lttng_condition
*low_condition
= NULL
;
299 struct lttng_condition
*high_condition
= NULL
;
300 struct lttng_condition
*dummy_invalid_condition
= NULL
;
301 struct lttng_condition
*dummy_condition
= NULL
;
303 double low_ratio
= 0.0;
304 double high_ratio
= 0.99;
307 action
= lttng_action_notify_create();
309 fail("Setup error on action creation");
313 /* Create a dummy, empty condition for later test */
314 dummy_invalid_condition
= lttng_condition_buffer_usage_low_create();
315 if (!dummy_invalid_condition
) {
316 fail("Setup error on condition creation");
320 /* Create a valid dummy condition with a ratio of 0.5 */
321 dummy_condition
= lttng_condition_buffer_usage_low_create();
322 if (!dummy_condition
) {
323 fail("Setup error on dummy_condition creation");
327 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
328 dummy_condition
, 0.5);
329 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
330 fail("Setup error on condition creation");
334 condition_status
= lttng_condition_buffer_usage_set_session_name(
335 dummy_condition
, session_name
);
336 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
337 fail("Setup error on dummy_condition creation");
340 condition_status
= lttng_condition_buffer_usage_set_channel_name(
341 dummy_condition
, channel_name
);
342 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
343 fail("Setup error on dummy_condition creation");
346 condition_status
= lttng_condition_buffer_usage_set_domain_type(
347 dummy_condition
, domain_type
);
348 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
349 fail("Setup error on dummy_condition creation");
353 /* Register a low condition with a ratio */
354 low_condition
= lttng_condition_buffer_usage_low_create();
355 if (!low_condition
) {
356 fail("Setup error on low_condition creation");
359 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
360 low_condition
, low_ratio
);
361 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
362 fail("Setup error on low_condition creation");
366 condition_status
= lttng_condition_buffer_usage_set_session_name(
367 low_condition
, session_name
);
368 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
369 fail("Setup error on low_condition creation");
372 condition_status
= lttng_condition_buffer_usage_set_channel_name(
373 low_condition
, channel_name
);
374 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
375 fail("Setup error on low_condition creation");
378 condition_status
= lttng_condition_buffer_usage_set_domain_type(
379 low_condition
, domain_type
);
380 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
381 fail("Setup error on low_condition creation");
386 /* Register a high condition with a ratio */
387 high_condition
= lttng_condition_buffer_usage_high_create();
388 if (!high_condition
) {
389 fail("Setup error on high_condition creation");
393 condition_status
= lttng_condition_buffer_usage_set_threshold_ratio(
394 high_condition
, high_ratio
);
395 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
396 fail("Setup error on high_condition creation");
400 condition_status
= lttng_condition_buffer_usage_set_session_name(
401 high_condition
, session_name
);
402 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
403 fail("Setup error on high_condition creation");
406 condition_status
= lttng_condition_buffer_usage_set_channel_name(
407 high_condition
, channel_name
);
408 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
409 fail("Setup error on high_condition creation");
412 condition_status
= lttng_condition_buffer_usage_set_domain_type(
413 high_condition
, domain_type
);
414 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
415 fail("Setup error on high_condition creation");
419 /* Register the triggers for low and high condition */
420 trigger
= lttng_trigger_create(low_condition
, action
);
422 fail("Setup error on low trigger creation");
426 ret
= lttng_register_trigger(trigger
);
428 fail("Setup error on low trigger registration");
432 lttng_trigger_destroy(trigger
);
435 trigger
= lttng_trigger_create(high_condition
, action
);
437 fail("Setup error on high trigger creation");
441 ret
= lttng_register_trigger(trigger
);
443 fail("Setup error on high trigger registration");
448 notification_channel
= lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
449 ok(notification_channel
, "Notification channel object creation");
450 if (!notification_channel
) {
454 /* Basic error path check */
455 nc_status
= lttng_notification_channel_subscribe(NULL
, NULL
);
456 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NULL");
458 nc_status
= lttng_notification_channel_subscribe(notification_channel
, NULL
);
459 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NON-NULL, NULL");
461 nc_status
= lttng_notification_channel_subscribe(NULL
, low_condition
);
462 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Notification channel subscription is invalid: NULL, NON-NULL");
464 nc_status
= lttng_notification_channel_subscribe(notification_channel
, dummy_invalid_condition
);
465 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Subscribing to an invalid condition");
467 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_invalid_condition
);
468 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID
, "Unsubscribing to an invalid condition");
470 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, dummy_condition
);
471 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION
, "Unsubscribing to an valid unknown condition");
473 /* Subscribe a valid low condition */
474 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
475 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
477 /* Subscribe a valid high condition */
478 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
479 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Subscribe to condition");
481 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
482 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
484 nc_status
= lttng_notification_channel_subscribe(notification_channel
, high_condition
);
485 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED
, "Subscribe to a condition for which subscription was already done");
487 /* Wait for notification to happen */
488 lttng_start_tracing(session_name
);
491 /* Wait for high notification */
492 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
493 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
495 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
496 "High notification received after intermediary communication");
497 lttng_notification_destroy(notification
);
500 resume_consumer(argv
);
501 lttng_stop_tracing(session_name
);
504 * Test that communication still work even if there is notification
505 * waiting for consumption.
508 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
509 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe with pending notification");
511 nc_status
= lttng_notification_channel_subscribe(notification_channel
, low_condition
);
512 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "subscribe with pending notification");
514 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
515 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
517 && lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
518 "Low notification received after intermediary communication");
519 lttng_notification_destroy(notification
);
522 /* Stop consumer to force a high notification */
523 lttng_start_tracing(session_name
);
526 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
527 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
528 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
529 "High notification received after intermediary communication");
530 lttng_notification_destroy(notification
);
533 /* Resume consumer to allow event consumption */
534 resume_consumer(argv
);
535 lttng_stop_tracing(session_name
);
537 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
538 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
539 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
,
540 "Low notification received after re-subscription");
541 lttng_notification_destroy(notification
);
544 /* Stop consumer to force a high notification */
545 lttng_start_tracing(session_name
);
548 nc_status
= lttng_notification_channel_get_next_notification(notification_channel
, ¬ification
);
549 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
&&
550 lttng_condition_get_type(lttng_notification_get_condition(notification
)) == LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
,
551 "High notification");
552 lttng_notification_destroy(notification
);
555 /* Resume consumer to allow event consumption */
556 resume_consumer(argv
);
557 lttng_stop_tracing(session_name
);
559 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, low_condition
);
560 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe low condition with pending notification");
561 nc_status
= lttng_notification_channel_unsubscribe(notification_channel
, high_condition
);
562 ok(nc_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
, "Unsubscribe high condition with pending notification");
565 lttng_notification_channel_destroy(notification_channel
);
566 lttng_trigger_destroy(trigger
);
567 lttng_action_destroy(action
);
568 lttng_condition_destroy(low_condition
);
569 lttng_condition_destroy(high_condition
);
570 lttng_condition_destroy(dummy_invalid_condition
);
571 lttng_condition_destroy(dummy_condition
);
574 int main(int argc
, const char *argv
[])
576 const char *session_name
= NULL
;
577 const char *channel_name
= NULL
;
578 const char *domain_type_string
= NULL
;
579 enum lttng_domain_type domain_type
= LTTNG_DOMAIN_NONE
;
581 plan_tests(NUM_TESTS
);
583 /* Argument 4 and upward are named pipe location for consumerd control */
584 named_pipe_args_start
= 4;
587 fail("Missing parameter for tests to run %d", argc
);
593 session_name
= argv
[1];
594 channel_name
= argv
[2];
595 domain_type_string
= argv
[3];
597 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string
)) {
598 domain_type
= LTTNG_DOMAIN_UST
;
600 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string
)) {
601 domain_type
= LTTNG_DOMAIN_KERNEL
;
603 if (domain_type
== LTTNG_DOMAIN_NONE
) {
604 fail("Unknown domain type");
608 diag("Test trigger for domain %s with buffer_usage_low condition", domain_type_string
);
609 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW
);
610 diag("Test trigger for domain %s with buffer_usage_high condition", domain_type_string
);
611 test_triggers_buffer_usage_condition(session_name
, channel_name
, domain_type
, LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH
);
613 diag("Test notification channel api for domain %s", domain_type_string
);
614 test_notification_channel(session_name
, channel_name
, domain_type
, argv
);
616 return exit_status();