Tests: Cleanup: create `test_subscription_twice()` function
[lttng-tools.git] / tests / regression / tools / notification / notification.c
CommitLineData
434f8068
JR
1/*
2 * notification.c
3 *
4 * Tests suite for LTTng notification API
5 *
6 * Copyright (C) 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
7 *
9d16b343 8 * SPDX-License-Identifier: MIT
434f8068 9 *
434f8068
JR
10 */
11
12#include <assert.h>
13#include <math.h>
14#include <stdbool.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19#include <inttypes.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
854382b8 23#include <signal.h>
854382b8 24#include <poll.h>
434f8068 25
edf4b93e 26#include <common/compat/errno.h>
434f8068
JR
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>
25040abc 38#include <lttng/lttng.h>
434f8068
JR
39
40#include <tap/tap.h>
41
42#define NUM_TESTS 104
854382b8 43
434f8068
JR
44int nb_args = 0;
45int named_pipe_args_start = 0;
854382b8
JR
46pid_t app_pid = -1;
47const char *app_state_file = NULL;
48
49static
50void wait_on_file(const char *path, bool file_exist)
51{
52 if (!path) {
53 return;
54 }
55 for (;;) {
56 int ret;
57 struct stat buf;
58
59 ret = stat(path, &buf);
60 if (ret == -1 && errno == ENOENT) {
61 if (file_exist) {
f0784451
FD
62 /*
63 * The file does not exist. wait a bit and
64 * continue looping until it does.
65 */
66 (void) poll(NULL, 0, 10);
67 continue;
854382b8 68 }
f0784451
FD
69
70 /*
71 * File does not exist and the exit condition we want.
72 * Break from the loop and return.
73 */
74 break;
854382b8
JR
75 }
76 if (ret) {
77 perror("stat");
78 exit(EXIT_FAILURE);
79 }
f0784451
FD
80 /*
81 * stat() returned 0, so the file exists. break now only if
82 * that's the exit condition we want.
83 */
84 if (file_exist) {
85 break;
86 }
854382b8
JR
87 }
88}
434f8068 89
f12eb9c1 90static
434f8068
JR
91int write_pipe(const char *path, uint8_t data)
92{
93 int ret = 0;
94 int fd = 0;
95
96 fd = open(path, O_WRONLY | O_NONBLOCK);
97 if (fd < 0) {
98 perror("Could not open consumer control named pipe");
99 goto end;
100 }
101
102 ret = write(fd, &data , sizeof(data));
103 if (ret < 1) {
104 perror("Named pipe write failed");
eff748d0
JR
105 if (close(fd)) {
106 perror("Named pipe close failed");
107 }
434f8068
JR
108 ret = -1;
109 goto end;
110 }
111
112 ret = close(fd);
113 if (ret < 0) {
114 perror("Name pipe closing failed");
115 ret = -1;
116 goto end;
117 }
118end:
119 return ret;
120}
121
f12eb9c1 122static
434f8068
JR
123int stop_consumer(const char **argv)
124{
9df6c82a
JG
125 int ret = 0, i;
126
127 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
128 ret = write_pipe(argv[i], 49);
129 }
130 return ret;
131}
132
f12eb9c1 133static
434f8068
JR
134int resume_consumer(const char **argv)
135{
9df6c82a
JG
136 int ret = 0, i;
137
138 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
139 ret = write_pipe(argv[i], 0);
140 }
141 return ret;
142}
143
f12eb9c1
SM
144static
145int suspend_application(void)
854382b8
JR
146{
147 int ret;
148 struct stat buf;
149
150 if (!stat(app_state_file, &buf)) {
151 fail("App is already in a suspended state.");
152 ret = -1;
153 goto error;
154 }
155
156 /*
157 * Send SIGUSR1 to application instructing it to bypass tracepoint.
158 */
159 ret = kill(app_pid, SIGUSR1);
160 if (ret) {
161 fail("SIGUSR1 failed. errno %d", errno);
162 ret = -1;
163 goto error;
164 }
165
166 wait_on_file(app_state_file, true);
167
168error:
169 return ret;
170
171}
172
f12eb9c1 173static
a3ecaea8 174int resume_application(void)
854382b8
JR
175{
176 int ret;
177 struct stat buf;
178
179 ret = stat(app_state_file, &buf);
180 if (ret == -1 && errno == ENOENT) {
181 fail("State file does not exist");
182 goto error;
183 }
184 if (ret) {
185 perror("stat");
186 goto error;
187 }
188
189 ret = kill(app_pid, SIGUSR1);
190 if (ret) {
191 fail("SIGUSR1 failed. errno %d", errno);
192 ret = -1;
193 goto error;
194 }
195
196 wait_on_file(app_state_file, false);
197
198error:
199 return ret;
200
201}
202
203
f12eb9c1 204static
434f8068
JR
205void test_triggers_buffer_usage_condition(const char *session_name,
206 const char *channel_name,
207 enum lttng_domain_type domain_type,
208 enum lttng_condition_type condition_type)
209{
9df6c82a 210 unsigned int test_vector_size = 5, i;
434f8068
JR
211 enum lttng_condition_status condition_status;
212 struct lttng_action *action;
213
214 /* Set-up */
215 action = lttng_action_notify_create();
216 if (!action) {
217 fail("Setup error on action creation");
218 goto end;
219 }
220
221 /* Test lttng_register_trigger with null value */
222 ok(lttng_register_trigger(NULL) == -LTTNG_ERR_INVALID, "Registering a NULL trigger fails as expected");
223
224 /* Test: register a trigger */
9df6c82a
JG
225
226 for (i = 0; i < pow(2,test_vector_size); i++) {
434f8068
JR
227 int loop_ret = 0;
228 char *test_tuple_string = NULL;
229 unsigned int mask_position = 0;
230 bool session_name_set = false;
231 bool channel_name_set = false;
232 bool threshold_ratio_set = false;
233 bool threshold_byte_set = false;
234 bool domain_type_set = false;
235
236 struct lttng_trigger *trigger = NULL;
237 struct lttng_condition *condition = NULL;
238
239 /* Create base condition */
240 switch (condition_type) {
241 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
242 condition = lttng_condition_buffer_usage_low_create();
243 break;
244 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
245 condition = lttng_condition_buffer_usage_high_create();
246 break;
247 default:
248 loop_ret = 1;
249 goto loop_end;
250 }
251
252 if (!condition) {
253 loop_ret = 1;
254 goto loop_end;
255
256 }
257
258 /* Prepare the condition for trigger registration test */
259
260 /* Set session name */
261 if ((1 << mask_position) & i) {
262 condition_status = lttng_condition_buffer_usage_set_session_name(
263 condition, session_name);
264 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
265 loop_ret = 1;
266 goto loop_end;
267 }
268 session_name_set = true;
269 }
270 mask_position++;
271
272 /* Set channel name */
273 if ((1 << mask_position) & i) {
274 condition_status = lttng_condition_buffer_usage_set_channel_name(
275 condition, channel_name);
276 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
277 loop_ret = 1;
278 goto loop_end;
279 }
280 channel_name_set = true;
281 }
282 mask_position++;
283
284 /* Set threshold ratio */
285 if ((1 << mask_position) & i) {
286 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
287 condition, 0.0);
288 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
289 loop_ret = 1;
290 goto loop_end;
291 }
292 threshold_ratio_set = true;
293 }
294 mask_position++;
295
296 /* Set threshold byte */
297 if ((1 << mask_position) & i) {
298 condition_status = lttng_condition_buffer_usage_set_threshold(
299 condition, 0);
300 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
301 loop_ret = 1;
302 goto loop_end;
303 }
304 threshold_byte_set = true;
305 }
306 mask_position++;
307
308 /* Set domain type */
309 if ((1 << mask_position) & i) {
310 condition_status = lttng_condition_buffer_usage_set_domain_type(
311 condition, LTTNG_DOMAIN_UST);
312 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
313 loop_ret = 1;
314 goto loop_end;
315 }
316 domain_type_set = true;
317 }
318
319 /* Safety check */
320 if (mask_position != test_vector_size -1) {
321 assert("Logic error for test vector generation");
322 }
323
9479b7a7 324 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
434f8068
JR
325 session_name_set ? "set" : "unset",
326 channel_name_set ? "set" : "unset",
327 threshold_ratio_set ? "set" : "unset",
328 threshold_byte_set ? "set" : "unset",
329 domain_type_set? "set" : "unset");
330 if (!test_tuple_string || loop_ret < 0) {
331 loop_ret = 1;
332 goto loop_end;
333 }
334
335 /* Create trigger */
336 trigger = lttng_trigger_create(condition, action);
337 if (!trigger) {
338 loop_ret = 1;
339 goto loop_end;
340 }
341
342 loop_ret = lttng_register_trigger(trigger);
343
344loop_end:
345 if (loop_ret == 1) {
346 fail("Setup error occurred for tuple: %s", test_tuple_string);
347 goto loop_cleanup;
348 }
349
350 /* This combination happens three times */
351 if (session_name_set && channel_name_set
352 && (threshold_ratio_set || threshold_byte_set)
353 && domain_type_set) {
354 ok(loop_ret == 0, "Trigger is registered: %s", test_tuple_string);
355
356 /*
357 * Test that a trigger cannot be registered
358 * multiple time.
359 */
360 loop_ret = lttng_register_trigger(trigger);
361 ok(loop_ret == -LTTNG_ERR_TRIGGER_EXISTS, "Re-register trigger fails as expected: %s", test_tuple_string);
362
363 /* Test that a trigger can be unregistered */
364 loop_ret = lttng_unregister_trigger(trigger);
365 ok(loop_ret == 0, "Unregister trigger: %s", test_tuple_string);
366
367 /*
368 * Test that unregistration of a non-previously
369 * registered trigger fail.
370 */
371 loop_ret = lttng_unregister_trigger(trigger);
43e0c204 372 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
434f8068
JR
373 } else {
374 ok(loop_ret == -LTTNG_ERR_INVALID_TRIGGER, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string);
375 }
376
377loop_cleanup:
378 free(test_tuple_string);
379 lttng_trigger_destroy(trigger);
380 lttng_condition_destroy(condition);
381 }
382
383end:
384 lttng_action_destroy(action);
385}
386
ff2b03c8
JG
387static
388void wait_data_pending(const char *session_name)
389{
390 int ret;
391
392 do {
393 ret = lttng_data_pending(session_name);
394 assert(ret >= 0);
395 } while (ret != 0);
396}
397
f12eb9c1 398static
17423302
FD
399int setup_buffer_usage_condition(struct lttng_condition *condition,
400 const char *condition_name,
401 const char *session_name,
402 const char *channel_name,
403 const enum lttng_domain_type domain_type)
404{
405 enum lttng_condition_status condition_status;
406 int ret = 0;
407
408 condition_status = lttng_condition_buffer_usage_set_session_name(
409 condition, session_name);
410 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
411 fail("Failed to set session name on creation of condition `%s`",
412 condition_name);
413 ret = -1;
414 goto end;
415 }
416
417 condition_status = lttng_condition_buffer_usage_set_channel_name(
418 condition, channel_name);
419 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
420 fail("Failed to set channel name on creation of condition `%s`",
421 condition_name);
422 ret = -1;
423 goto end;
424 }
425
426 condition_status = lttng_condition_buffer_usage_set_domain_type(
427 condition, domain_type);
428 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
429 fail("Failed to set domain type on creation of condition `%s`",
430 condition_name);
431 ret = -1;
432 goto end;
433 }
434
435end:
436 return ret;
437}
438
439static
90fcb2ec
FD
440void test_invalid_channel_subscription(
441 const enum lttng_domain_type domain_type)
434f8068 442{
434f8068
JR
443 enum lttng_condition_status condition_status;
444 enum lttng_notification_channel_status nc_status;
434f8068 445 struct lttng_condition *dummy_condition = NULL;
90fcb2ec
FD
446 struct lttng_condition *dummy_invalid_condition = NULL;
447 struct lttng_notification_channel *notification_channel = NULL;
448 int ret = 0;
434f8068 449
90fcb2ec
FD
450 notification_channel = lttng_notification_channel_create(
451 lttng_session_daemon_notification_endpoint);
452 ok(notification_channel, "Notification channel object creation");
453 if (!notification_channel) {
434f8068
JR
454 goto end;
455 }
456
90fcb2ec
FD
457 /*
458 * Create a dummy, empty (thus invalid) condition to test error paths.
459 */
434f8068
JR
460 dummy_invalid_condition = lttng_condition_buffer_usage_low_create();
461 if (!dummy_invalid_condition) {
462 fail("Setup error on condition creation");
463 goto end;
464 }
465
90fcb2ec
FD
466 /*
467 * Test subscription and unsubscription of an invalid condition to/from
468 * a channel.
469 */
470 nc_status = lttng_notification_channel_subscribe(
471 notification_channel, dummy_invalid_condition);
472 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
473 "Subscribing to an invalid condition");
474
475 nc_status = lttng_notification_channel_unsubscribe(
476 notification_channel, dummy_invalid_condition);
477 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
478 "Unsubscribing from an invalid condition");
479
434f8068
JR
480 /* Create a valid dummy condition with a ratio of 0.5 */
481 dummy_condition = lttng_condition_buffer_usage_low_create();
482 if (!dummy_condition) {
483 fail("Setup error on dummy_condition creation");
484 goto end;
434f8068 485 }
90fcb2ec 486
434f8068
JR
487 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
488 dummy_condition, 0.5);
489 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
490 fail("Setup error on condition creation");
491 goto end;
492 }
493
17423302 494 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
90fcb2ec 495 "dummy_session", "dummy_channel", domain_type);
17423302
FD
496 if (ret) {
497 fail("Setup error on dummy condition creation");
434f8068
JR
498 goto end;
499 }
500
90fcb2ec
FD
501 /*
502 * Test subscription and unsubscription to/from a channel with invalid
503 * parameters.
504 */
505 nc_status = lttng_notification_channel_subscribe(NULL, NULL);
506 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
507 "Notification channel subscription is invalid: NULL, NULL");
508
509 nc_status = lttng_notification_channel_subscribe(
510 notification_channel, NULL);
511 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
512 "Notification channel subscription is invalid: NON-NULL, NULL");
513
514 nc_status = lttng_notification_channel_subscribe(NULL, dummy_condition);
515 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
516 "Notification channel subscription is invalid: NULL, NON-NULL");
517
518 nc_status = lttng_notification_channel_unsubscribe(
519 notification_channel, dummy_condition);
520 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION,
521 "Unsubscribing from a valid unknown condition");
522
523end:
524 lttng_notification_channel_destroy(notification_channel);
525 lttng_condition_destroy(dummy_invalid_condition);
526 lttng_condition_destroy(dummy_condition);
527 return;
528}
529
3780613c
FD
530enum buffer_usage_type {
531 BUFFER_USAGE_TYPE_LOW,
532 BUFFER_USAGE_TYPE_HIGH,
533};
534
535static int register_buffer_usage_notify_trigger(const char *session_name,
90fcb2ec
FD
536 const char *channel_name,
537 const enum lttng_domain_type domain_type,
3780613c
FD
538 enum buffer_usage_type buffer_usage_type,
539 double ratio,
540 struct lttng_condition **condition,
541 struct lttng_action **action,
542 struct lttng_trigger **trigger)
90fcb2ec 543{
90fcb2ec 544 enum lttng_condition_status condition_status;
3780613c
FD
545 struct lttng_action *tmp_action = NULL;
546 struct lttng_condition *tmp_condition = NULL;
547 struct lttng_trigger *tmp_trigger = NULL;
548 int ret = 0;
90fcb2ec
FD
549
550 /* Set-up */
3780613c 551 tmp_action = lttng_action_notify_create();
90fcb2ec
FD
552 if (!action) {
553 fail("Setup error on action creation");
3780613c
FD
554 ret = -1;
555 goto error;
434f8068
JR
556 }
557
3780613c
FD
558 if (buffer_usage_type == BUFFER_USAGE_TYPE_LOW) {
559 tmp_condition = lttng_condition_buffer_usage_low_create();
560 } else {
561 tmp_condition = lttng_condition_buffer_usage_high_create();
434f8068
JR
562 }
563
3780613c
FD
564 if (!tmp_condition) {
565 fail("Setup error on condition creation");
566 ret = -1;
567 goto error;
434f8068
JR
568 }
569
3780613c 570 /* Set the buffer usage threashold */
434f8068 571 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
3780613c 572 tmp_condition, ratio);
434f8068 573 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
3780613c
FD
574 fail("Setup error on condition creation");
575 ret = -1;
576 goto error;
434f8068
JR
577 }
578
3780613c 579 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
17423302
FD
580 session_name, channel_name, domain_type);
581 if (ret) {
3780613c
FD
582 fail("Setup error on condition creation");
583 ret = -1;
584 goto error;
434f8068
JR
585 }
586
3780613c
FD
587 /* Register the trigger for condition. */
588 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
589 if (!tmp_trigger) {
590 fail("Setup error on trigger creation");
591 ret = -1;
592 goto error;
434f8068
JR
593 }
594
3780613c 595 ret = lttng_register_trigger(tmp_trigger);
434f8068 596 if (ret) {
3780613c
FD
597 fail("Setup error on trigger registration");
598 ret = -1;
599 goto error;
434f8068
JR
600 }
601
3780613c
FD
602 *condition = tmp_condition;
603 *trigger = tmp_trigger;
604 *action = tmp_action;
605 goto end;
434f8068 606
3780613c
FD
607error:
608 lttng_action_destroy(tmp_action);
609 lttng_condition_destroy(tmp_condition);
610 lttng_trigger_destroy(tmp_trigger);
611
612end:
613 return ret;
614}
615
fa448dbe
FD
616static void test_subscription_twice(const char *session_name,
617 const char *channel_name,
618 const enum lttng_domain_type domain_type)
619{
620 int ret = 0;
621 enum lttng_notification_channel_status nc_status;
622
623 struct lttng_action *action = NULL;
624 struct lttng_notification_channel *notification_channel = NULL;
625 struct lttng_trigger *trigger = NULL;
626
627 struct lttng_condition *condition = NULL;
628
629 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
630 domain_type, BUFFER_USAGE_TYPE_LOW, 0.99, &condition,
631 &action, &trigger);
632 if (ret) {
633 fail("Setup error on trigger registration");
634 goto end;
635 }
636
637 /* Begin testing. */
638 notification_channel = lttng_notification_channel_create(
639 lttng_session_daemon_notification_endpoint);
640 ok(notification_channel, "Notification channel object creation");
641 if (!notification_channel) {
642 goto end;
643 }
644
645 /* Subscribe a valid condition. */
646 nc_status = lttng_notification_channel_subscribe(
647 notification_channel, condition);
648 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
649 "Subscribe to condition");
650
651 /* Subscribing again should fail. */
652 nc_status = lttng_notification_channel_subscribe(
653 notification_channel, condition);
654 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED,
655 "Subscribe to a condition for which subscription was already done");
656
657end:
658 lttng_unregister_trigger(trigger);
659 lttng_trigger_destroy(trigger);
660 lttng_notification_channel_destroy(notification_channel);
661 lttng_action_destroy(action);
662 lttng_condition_destroy(condition);
663}
664
3780613c
FD
665static void test_notification_channel(const char *session_name,
666 const char *channel_name,
667 const enum lttng_domain_type domain_type,
668 const char **argv)
669{
670 int ret = 0;
671 enum lttng_notification_channel_status nc_status;
672
673 struct lttng_action *low_action = NULL;
674 struct lttng_action *high_action = NULL;
675 struct lttng_notification *notification = NULL;
676 struct lttng_notification_channel *notification_channel = NULL;
677 struct lttng_trigger *low_trigger = NULL;
678 struct lttng_trigger *high_trigger = NULL;
679
680 struct lttng_condition *low_condition = NULL;
681 struct lttng_condition *high_condition = NULL;
682
683 const double low_ratio = 0.0;
684 const double high_ratio = 0.90;
685
686 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
687 domain_type, BUFFER_USAGE_TYPE_LOW, low_ratio,
688 &low_condition, &low_action, &low_trigger);
689 if (ret) {
690 fail("Setup error on low trigger registration");
434f8068
JR
691 goto end;
692 }
693
3780613c
FD
694 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
695 domain_type, BUFFER_USAGE_TYPE_HIGH, high_ratio,
696 &high_condition, &high_action, &high_trigger);
434f8068
JR
697 if (ret) {
698 fail("Setup error on high trigger registration");
699 goto end;
700 }
701
702 /* Begin testing */
a6ae2480
FD
703 notification_channel = lttng_notification_channel_create(
704 lttng_session_daemon_notification_endpoint);
434f8068
JR
705 ok(notification_channel, "Notification channel object creation");
706 if (!notification_channel) {
707 goto end;
708 }
709
434f8068 710 /* Subscribe a valid low condition */
a6ae2480
FD
711 nc_status = lttng_notification_channel_subscribe(
712 notification_channel, low_condition);
713 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
714 "Subscribe to condition");
434f8068
JR
715
716 /* Subscribe a valid high condition */
a6ae2480
FD
717 nc_status = lttng_notification_channel_subscribe(
718 notification_channel, high_condition);
719 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
720 "Subscribe to condition");
434f8068 721
7676e0d2
FD
722 resume_application();
723
434f8068 724 /* Wait for notification to happen */
434f8068 725 stop_consumer(argv);
ff2b03c8 726 lttng_start_tracing(session_name);
434f8068
JR
727
728 /* Wait for high notification */
67c93c15 729 do {
a6ae2480
FD
730 nc_status = lttng_notification_channel_get_next_notification(
731 notification_channel, &notification);
67c93c15 732 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
733 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
734 lttng_condition_get_type(lttng_notification_get_condition(
735 notification)) ==
736 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
737 "High notification received after intermediary communication");
738 lttng_notification_destroy(notification);
739 notification = NULL;
740
854382b8 741 suspend_application();
ff2b03c8 742 lttng_stop_tracing_no_wait(session_name);
434f8068 743 resume_consumer(argv);
ff2b03c8 744 wait_data_pending(session_name);
434f8068
JR
745
746 /*
747 * Test that communication still work even if there is notification
748 * waiting for consumption.
749 */
750
a6ae2480
FD
751 nc_status = lttng_notification_channel_unsubscribe(
752 notification_channel, low_condition);
753 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
754 "Unsubscribe with pending notification");
434f8068 755
a6ae2480
FD
756 nc_status = lttng_notification_channel_subscribe(
757 notification_channel, low_condition);
758 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
759 "Subscribe with pending notification");
434f8068 760
67c93c15 761 do {
a6ae2480
FD
762 nc_status = lttng_notification_channel_get_next_notification(
763 notification_channel, &notification);
67c93c15 764 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
765 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
766 lttng_condition_get_type(lttng_notification_get_condition(
767 notification)) ==
768 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
769 "Low notification received after intermediary communication");
770 lttng_notification_destroy(notification);
771 notification = NULL;
772
773 /* Stop consumer to force a high notification */
ff2b03c8 774 stop_consumer(argv);
854382b8 775 resume_application();
434f8068 776 lttng_start_tracing(session_name);
434f8068 777
67c93c15 778 do {
a6ae2480
FD
779 nc_status = lttng_notification_channel_get_next_notification(
780 notification_channel, &notification);
67c93c15 781 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 782 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
783 lttng_condition_get_type(lttng_notification_get_condition(
784 notification)) ==
785 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
786 "High notification received after intermediary communication");
787 lttng_notification_destroy(notification);
788 notification = NULL;
789
854382b8 790 suspend_application();
ff2b03c8 791 lttng_stop_tracing_no_wait(session_name);
434f8068 792 resume_consumer(argv);
ff2b03c8 793 wait_data_pending(session_name);
434f8068 794
67c93c15 795 do {
a6ae2480
FD
796 nc_status = lttng_notification_channel_get_next_notification(
797 notification_channel, &notification);
67c93c15 798 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 799 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
800 lttng_condition_get_type(lttng_notification_get_condition(
801 notification)) ==
802 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
803 "Low notification received after re-subscription");
804 lttng_notification_destroy(notification);
805 notification = NULL;
806
ff2b03c8 807 stop_consumer(argv);
854382b8 808 resume_application();
434f8068
JR
809 /* Stop consumer to force a high notification */
810 lttng_start_tracing(session_name);
434f8068 811
67c93c15 812 do {
a6ae2480
FD
813 nc_status = lttng_notification_channel_get_next_notification(
814 notification_channel, &notification);
67c93c15 815 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 816 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
817 lttng_condition_get_type(lttng_notification_get_condition(
818 notification)) ==
819 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
820 "High notification");
821 lttng_notification_destroy(notification);
822 notification = NULL;
823
ff2b03c8 824 suspend_application();
7676e0d2
FD
825
826 /* Resume consumer to allow event consumption */
ff2b03c8 827 lttng_stop_tracing_no_wait(session_name);
434f8068 828 resume_consumer(argv);
ff2b03c8 829 wait_data_pending(session_name);
434f8068 830
a6ae2480
FD
831 nc_status = lttng_notification_channel_unsubscribe(
832 notification_channel, low_condition);
833 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
834 "Unsubscribe low condition with pending notification");
835
836 nc_status = lttng_notification_channel_unsubscribe(
837 notification_channel, high_condition);
838 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
839 "Unsubscribe high condition with pending notification");
434f8068
JR
840
841end:
842 lttng_notification_channel_destroy(notification_channel);
3780613c
FD
843 lttng_trigger_destroy(low_trigger);
844 lttng_trigger_destroy(high_trigger);
845 lttng_action_destroy(low_action);
846 lttng_action_destroy(high_action);
434f8068 847 lttng_condition_destroy(low_condition);
eff748d0 848 lttng_condition_destroy(high_condition);
434f8068
JR
849}
850
851int main(int argc, const char *argv[])
852{
853 const char *session_name = NULL;
854 const char *channel_name = NULL;
855 const char *domain_type_string = NULL;
856 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
857
858 plan_tests(NUM_TESTS);
859
854382b8
JR
860 /* Argument 6 and upward are named pipe location for consumerd control */
861 named_pipe_args_start = 6;
434f8068 862
854382b8 863 if (argc < 7) {
434f8068
JR
864 fail("Missing parameter for tests to run %d", argc);
865 goto error;
866 }
867
868 nb_args = argc;
869
854382b8
JR
870 domain_type_string = argv[1];
871 session_name = argv[2];
872 channel_name = argv[3];
873 app_pid = (pid_t) atoi(argv[4]);
874 app_state_file = argv[5];
434f8068
JR
875
876 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
877 domain_type = LTTNG_DOMAIN_UST;
878 }
879 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
880 domain_type = LTTNG_DOMAIN_KERNEL;
881 }
882 if (domain_type == LTTNG_DOMAIN_NONE) {
883 fail("Unknown domain type");
884 goto error;
885 }
886
7676e0d2
FD
887 /*
888 * Test cases are responsible for resuming the app when needed and
889 * making sure it's suspended when returning.
890 */
891 suspend_application();
892
434f8068
JR
893 diag("Test trigger for domain %s with buffer_usage_low condition", domain_type_string);
894 test_triggers_buffer_usage_condition(session_name, channel_name, domain_type, LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
895 diag("Test trigger for domain %s with buffer_usage_high condition", domain_type_string);
896 test_triggers_buffer_usage_condition(session_name, channel_name, domain_type, LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
897
90fcb2ec
FD
898 /* Basic error path check. */
899 test_invalid_channel_subscription(domain_type);
fa448dbe 900 test_subscription_twice(session_name, channel_name, domain_type);
90fcb2ec 901
434f8068
JR
902 diag("Test notification channel api for domain %s", domain_type_string);
903 test_notification_channel(session_name, channel_name, domain_type, argv);
904error:
905 return exit_status();
906}
907
This page took 0.07001 seconds and 4 git commands to generate.