Tests: triggers: Add syscall event rule condition kernel tests
[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>
7948461b 32#include <lttng/condition/event-rule.h>
434f8068
JR
33#include <lttng/domain.h>
34#include <lttng/endpoint.h>
51704c8e 35#include <lttng/event-rule/kprobe.h>
aab0598f 36#include <lttng/event-rule/syscall.h>
7948461b 37#include <lttng/event-rule/tracepoint.h>
51704c8e 38#include <lttng/kernel-probe.h>
434f8068 39#include <lttng/lttng-error.h>
7948461b 40#include <lttng/lttng.h>
434f8068
JR
41#include <lttng/notification/channel.h>
42#include <lttng/notification/notification.h>
43#include <lttng/trigger/trigger.h>
44
45#include <tap/tap.h>
46
434f8068
JR
47int nb_args = 0;
48int named_pipe_args_start = 0;
7344b6a3 49pid_t app_pid = 0;
854382b8
JR
50const char *app_state_file = NULL;
51
52static
53void wait_on_file(const char *path, bool file_exist)
54{
55 if (!path) {
56 return;
57 }
58 for (;;) {
59 int ret;
60 struct stat buf;
61
62 ret = stat(path, &buf);
63 if (ret == -1 && errno == ENOENT) {
64 if (file_exist) {
f0784451
FD
65 /*
66 * The file does not exist. wait a bit and
67 * continue looping until it does.
68 */
69 (void) poll(NULL, 0, 10);
70 continue;
854382b8 71 }
f0784451
FD
72
73 /*
74 * File does not exist and the exit condition we want.
75 * Break from the loop and return.
76 */
77 break;
854382b8
JR
78 }
79 if (ret) {
80 perror("stat");
81 exit(EXIT_FAILURE);
82 }
f0784451
FD
83 /*
84 * stat() returned 0, so the file exists. break now only if
85 * that's the exit condition we want.
86 */
87 if (file_exist) {
88 break;
89 }
854382b8
JR
90 }
91}
434f8068 92
f12eb9c1 93static
434f8068
JR
94int write_pipe(const char *path, uint8_t data)
95{
96 int ret = 0;
97 int fd = 0;
98
99 fd = open(path, O_WRONLY | O_NONBLOCK);
100 if (fd < 0) {
101 perror("Could not open consumer control named pipe");
102 goto end;
103 }
104
105 ret = write(fd, &data , sizeof(data));
106 if (ret < 1) {
107 perror("Named pipe write failed");
eff748d0
JR
108 if (close(fd)) {
109 perror("Named pipe close failed");
110 }
434f8068
JR
111 ret = -1;
112 goto end;
113 }
114
115 ret = close(fd);
116 if (ret < 0) {
117 perror("Name pipe closing failed");
118 ret = -1;
119 goto end;
120 }
121end:
122 return ret;
123}
124
f12eb9c1 125static
434f8068
JR
126int stop_consumer(const char **argv)
127{
9df6c82a
JG
128 int ret = 0, i;
129
130 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
131 ret = write_pipe(argv[i], 49);
132 }
133 return ret;
134}
135
f12eb9c1 136static
434f8068
JR
137int resume_consumer(const char **argv)
138{
9df6c82a
JG
139 int ret = 0, i;
140
141 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
142 ret = write_pipe(argv[i], 0);
143 }
144 return ret;
145}
146
f12eb9c1
SM
147static
148int suspend_application(void)
854382b8
JR
149{
150 int ret;
151 struct stat buf;
152
153 if (!stat(app_state_file, &buf)) {
154 fail("App is already in a suspended state.");
155 ret = -1;
156 goto error;
157 }
158
159 /*
160 * Send SIGUSR1 to application instructing it to bypass tracepoint.
161 */
7344b6a3
FD
162 assert(app_pid > 1);
163
854382b8
JR
164 ret = kill(app_pid, SIGUSR1);
165 if (ret) {
166 fail("SIGUSR1 failed. errno %d", errno);
167 ret = -1;
168 goto error;
169 }
170
171 wait_on_file(app_state_file, true);
172
173error:
174 return ret;
175
176}
177
f12eb9c1 178static
a3ecaea8 179int resume_application(void)
854382b8
JR
180{
181 int ret;
182 struct stat buf;
183
184 ret = stat(app_state_file, &buf);
185 if (ret == -1 && errno == ENOENT) {
186 fail("State file does not exist");
187 goto error;
188 }
189 if (ret) {
190 perror("stat");
191 goto error;
192 }
193
7344b6a3
FD
194 assert(app_pid > 1);
195
854382b8
JR
196 ret = kill(app_pid, SIGUSR1);
197 if (ret) {
198 fail("SIGUSR1 failed. errno %d", errno);
199 ret = -1;
200 goto error;
201 }
202
203 wait_on_file(app_state_file, false);
204
205error:
206 return ret;
207
208}
209
210
f12eb9c1 211static
434f8068
JR
212void test_triggers_buffer_usage_condition(const char *session_name,
213 const char *channel_name,
214 enum lttng_domain_type domain_type,
215 enum lttng_condition_type condition_type)
216{
9df6c82a 217 unsigned int test_vector_size = 5, i;
434f8068
JR
218 enum lttng_condition_status condition_status;
219 struct lttng_action *action;
220
221 /* Set-up */
222 action = lttng_action_notify_create();
223 if (!action) {
224 fail("Setup error on action creation");
225 goto end;
226 }
227
228 /* Test lttng_register_trigger with null value */
229 ok(lttng_register_trigger(NULL) == -LTTNG_ERR_INVALID, "Registering a NULL trigger fails as expected");
230
231 /* Test: register a trigger */
9df6c82a
JG
232
233 for (i = 0; i < pow(2,test_vector_size); i++) {
434f8068
JR
234 int loop_ret = 0;
235 char *test_tuple_string = NULL;
236 unsigned int mask_position = 0;
237 bool session_name_set = false;
238 bool channel_name_set = false;
239 bool threshold_ratio_set = false;
240 bool threshold_byte_set = false;
241 bool domain_type_set = false;
242
243 struct lttng_trigger *trigger = NULL;
244 struct lttng_condition *condition = NULL;
245
246 /* Create base condition */
247 switch (condition_type) {
248 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
249 condition = lttng_condition_buffer_usage_low_create();
250 break;
251 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
252 condition = lttng_condition_buffer_usage_high_create();
253 break;
254 default:
255 loop_ret = 1;
256 goto loop_end;
257 }
258
259 if (!condition) {
260 loop_ret = 1;
261 goto loop_end;
262
263 }
264
265 /* Prepare the condition for trigger registration test */
266
267 /* Set session name */
268 if ((1 << mask_position) & i) {
269 condition_status = lttng_condition_buffer_usage_set_session_name(
270 condition, session_name);
271 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
272 loop_ret = 1;
273 goto loop_end;
274 }
275 session_name_set = true;
276 }
277 mask_position++;
278
279 /* Set channel name */
280 if ((1 << mask_position) & i) {
281 condition_status = lttng_condition_buffer_usage_set_channel_name(
282 condition, channel_name);
283 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
284 loop_ret = 1;
285 goto loop_end;
286 }
287 channel_name_set = true;
288 }
289 mask_position++;
290
291 /* Set threshold ratio */
292 if ((1 << mask_position) & i) {
293 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
294 condition, 0.0);
295 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
296 loop_ret = 1;
297 goto loop_end;
298 }
299 threshold_ratio_set = true;
300 }
301 mask_position++;
302
303 /* Set threshold byte */
304 if ((1 << mask_position) & i) {
305 condition_status = lttng_condition_buffer_usage_set_threshold(
306 condition, 0);
307 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
308 loop_ret = 1;
309 goto loop_end;
310 }
311 threshold_byte_set = true;
312 }
313 mask_position++;
314
315 /* Set domain type */
316 if ((1 << mask_position) & i) {
317 condition_status = lttng_condition_buffer_usage_set_domain_type(
318 condition, LTTNG_DOMAIN_UST);
319 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
320 loop_ret = 1;
321 goto loop_end;
322 }
323 domain_type_set = true;
324 }
325
326 /* Safety check */
327 if (mask_position != test_vector_size -1) {
328 assert("Logic error for test vector generation");
329 }
330
9479b7a7 331 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
434f8068
JR
332 session_name_set ? "set" : "unset",
333 channel_name_set ? "set" : "unset",
334 threshold_ratio_set ? "set" : "unset",
335 threshold_byte_set ? "set" : "unset",
336 domain_type_set? "set" : "unset");
337 if (!test_tuple_string || loop_ret < 0) {
338 loop_ret = 1;
339 goto loop_end;
340 }
341
342 /* Create trigger */
343 trigger = lttng_trigger_create(condition, action);
344 if (!trigger) {
345 loop_ret = 1;
346 goto loop_end;
347 }
348
349 loop_ret = lttng_register_trigger(trigger);
350
351loop_end:
352 if (loop_ret == 1) {
353 fail("Setup error occurred for tuple: %s", test_tuple_string);
354 goto loop_cleanup;
355 }
356
357 /* This combination happens three times */
358 if (session_name_set && channel_name_set
359 && (threshold_ratio_set || threshold_byte_set)
360 && domain_type_set) {
361 ok(loop_ret == 0, "Trigger is registered: %s", test_tuple_string);
362
363 /*
364 * Test that a trigger cannot be registered
365 * multiple time.
366 */
367 loop_ret = lttng_register_trigger(trigger);
368 ok(loop_ret == -LTTNG_ERR_TRIGGER_EXISTS, "Re-register trigger fails as expected: %s", test_tuple_string);
369
370 /* Test that a trigger can be unregistered */
371 loop_ret = lttng_unregister_trigger(trigger);
372 ok(loop_ret == 0, "Unregister trigger: %s", test_tuple_string);
373
374 /*
375 * Test that unregistration of a non-previously
376 * registered trigger fail.
377 */
378 loop_ret = lttng_unregister_trigger(trigger);
43e0c204 379 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
434f8068
JR
380 } else {
381 ok(loop_ret == -LTTNG_ERR_INVALID_TRIGGER, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string);
382 }
383
384loop_cleanup:
385 free(test_tuple_string);
386 lttng_trigger_destroy(trigger);
387 lttng_condition_destroy(condition);
388 }
389
390end:
391 lttng_action_destroy(action);
392}
393
ff2b03c8
JG
394static
395void wait_data_pending(const char *session_name)
396{
397 int ret;
398
399 do {
400 ret = lttng_data_pending(session_name);
401 assert(ret >= 0);
402 } while (ret != 0);
403}
404
f12eb9c1 405static
17423302
FD
406int setup_buffer_usage_condition(struct lttng_condition *condition,
407 const char *condition_name,
408 const char *session_name,
409 const char *channel_name,
410 const enum lttng_domain_type domain_type)
411{
412 enum lttng_condition_status condition_status;
413 int ret = 0;
414
415 condition_status = lttng_condition_buffer_usage_set_session_name(
416 condition, session_name);
417 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
418 fail("Failed to set session name on creation of condition `%s`",
419 condition_name);
420 ret = -1;
421 goto end;
422 }
423
424 condition_status = lttng_condition_buffer_usage_set_channel_name(
425 condition, channel_name);
426 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
427 fail("Failed to set channel name on creation of condition `%s`",
428 condition_name);
429 ret = -1;
430 goto end;
431 }
432
433 condition_status = lttng_condition_buffer_usage_set_domain_type(
434 condition, domain_type);
435 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
436 fail("Failed to set domain type on creation of condition `%s`",
437 condition_name);
438 ret = -1;
439 goto end;
440 }
441
442end:
443 return ret;
444}
445
446static
90fcb2ec
FD
447void test_invalid_channel_subscription(
448 const enum lttng_domain_type domain_type)
434f8068 449{
434f8068
JR
450 enum lttng_condition_status condition_status;
451 enum lttng_notification_channel_status nc_status;
434f8068 452 struct lttng_condition *dummy_condition = NULL;
90fcb2ec
FD
453 struct lttng_condition *dummy_invalid_condition = NULL;
454 struct lttng_notification_channel *notification_channel = NULL;
455 int ret = 0;
434f8068 456
90fcb2ec
FD
457 notification_channel = lttng_notification_channel_create(
458 lttng_session_daemon_notification_endpoint);
459 ok(notification_channel, "Notification channel object creation");
460 if (!notification_channel) {
434f8068
JR
461 goto end;
462 }
463
90fcb2ec
FD
464 /*
465 * Create a dummy, empty (thus invalid) condition to test error paths.
466 */
434f8068
JR
467 dummy_invalid_condition = lttng_condition_buffer_usage_low_create();
468 if (!dummy_invalid_condition) {
469 fail("Setup error on condition creation");
470 goto end;
471 }
472
90fcb2ec
FD
473 /*
474 * Test subscription and unsubscription of an invalid condition to/from
475 * a channel.
476 */
477 nc_status = lttng_notification_channel_subscribe(
478 notification_channel, dummy_invalid_condition);
479 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
480 "Subscribing to an invalid condition");
481
482 nc_status = lttng_notification_channel_unsubscribe(
483 notification_channel, dummy_invalid_condition);
484 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
485 "Unsubscribing from an invalid condition");
486
434f8068
JR
487 /* Create a valid dummy condition with a ratio of 0.5 */
488 dummy_condition = lttng_condition_buffer_usage_low_create();
489 if (!dummy_condition) {
490 fail("Setup error on dummy_condition creation");
491 goto end;
434f8068 492 }
90fcb2ec 493
434f8068
JR
494 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
495 dummy_condition, 0.5);
496 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
497 fail("Setup error on condition creation");
498 goto end;
499 }
500
17423302 501 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
90fcb2ec 502 "dummy_session", "dummy_channel", domain_type);
17423302
FD
503 if (ret) {
504 fail("Setup error on dummy condition creation");
434f8068
JR
505 goto end;
506 }
507
90fcb2ec
FD
508 /*
509 * Test subscription and unsubscription to/from a channel with invalid
510 * parameters.
511 */
512 nc_status = lttng_notification_channel_subscribe(NULL, NULL);
513 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
514 "Notification channel subscription is invalid: NULL, NULL");
515
516 nc_status = lttng_notification_channel_subscribe(
517 notification_channel, NULL);
518 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
519 "Notification channel subscription is invalid: NON-NULL, NULL");
520
521 nc_status = lttng_notification_channel_subscribe(NULL, dummy_condition);
522 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
523 "Notification channel subscription is invalid: NULL, NON-NULL");
524
525 nc_status = lttng_notification_channel_unsubscribe(
526 notification_channel, dummy_condition);
527 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION,
528 "Unsubscribing from a valid unknown condition");
529
530end:
531 lttng_notification_channel_destroy(notification_channel);
532 lttng_condition_destroy(dummy_invalid_condition);
533 lttng_condition_destroy(dummy_condition);
534 return;
535}
536
3780613c
FD
537enum buffer_usage_type {
538 BUFFER_USAGE_TYPE_LOW,
539 BUFFER_USAGE_TYPE_HIGH,
540};
541
542static int register_buffer_usage_notify_trigger(const char *session_name,
90fcb2ec
FD
543 const char *channel_name,
544 const enum lttng_domain_type domain_type,
3780613c
FD
545 enum buffer_usage_type buffer_usage_type,
546 double ratio,
547 struct lttng_condition **condition,
548 struct lttng_action **action,
549 struct lttng_trigger **trigger)
90fcb2ec 550{
90fcb2ec 551 enum lttng_condition_status condition_status;
3780613c
FD
552 struct lttng_action *tmp_action = NULL;
553 struct lttng_condition *tmp_condition = NULL;
554 struct lttng_trigger *tmp_trigger = NULL;
555 int ret = 0;
90fcb2ec
FD
556
557 /* Set-up */
3780613c 558 tmp_action = lttng_action_notify_create();
90fcb2ec
FD
559 if (!action) {
560 fail("Setup error on action creation");
3780613c
FD
561 ret = -1;
562 goto error;
434f8068
JR
563 }
564
3780613c
FD
565 if (buffer_usage_type == BUFFER_USAGE_TYPE_LOW) {
566 tmp_condition = lttng_condition_buffer_usage_low_create();
567 } else {
568 tmp_condition = lttng_condition_buffer_usage_high_create();
434f8068
JR
569 }
570
3780613c
FD
571 if (!tmp_condition) {
572 fail("Setup error on condition creation");
573 ret = -1;
574 goto error;
434f8068
JR
575 }
576
3780613c 577 /* Set the buffer usage threashold */
434f8068 578 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
3780613c 579 tmp_condition, ratio);
434f8068 580 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
3780613c
FD
581 fail("Setup error on condition creation");
582 ret = -1;
583 goto error;
434f8068
JR
584 }
585
3780613c 586 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
17423302
FD
587 session_name, channel_name, domain_type);
588 if (ret) {
3780613c
FD
589 fail("Setup error on condition creation");
590 ret = -1;
591 goto error;
434f8068
JR
592 }
593
3780613c
FD
594 /* Register the trigger for condition. */
595 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
596 if (!tmp_trigger) {
597 fail("Setup error on trigger creation");
598 ret = -1;
599 goto error;
434f8068
JR
600 }
601
3780613c 602 ret = lttng_register_trigger(tmp_trigger);
434f8068 603 if (ret) {
3780613c
FD
604 fail("Setup error on trigger registration");
605 ret = -1;
606 goto error;
434f8068
JR
607 }
608
3780613c
FD
609 *condition = tmp_condition;
610 *trigger = tmp_trigger;
611 *action = tmp_action;
612 goto end;
434f8068 613
3780613c
FD
614error:
615 lttng_action_destroy(tmp_action);
616 lttng_condition_destroy(tmp_condition);
617 lttng_trigger_destroy(tmp_trigger);
618
619end:
620 return ret;
621}
622
fa448dbe
FD
623static void test_subscription_twice(const char *session_name,
624 const char *channel_name,
625 const enum lttng_domain_type domain_type)
626{
627 int ret = 0;
628 enum lttng_notification_channel_status nc_status;
629
630 struct lttng_action *action = NULL;
631 struct lttng_notification_channel *notification_channel = NULL;
632 struct lttng_trigger *trigger = NULL;
633
634 struct lttng_condition *condition = NULL;
635
636 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
637 domain_type, BUFFER_USAGE_TYPE_LOW, 0.99, &condition,
638 &action, &trigger);
639 if (ret) {
640 fail("Setup error on trigger registration");
641 goto end;
642 }
643
644 /* Begin testing. */
645 notification_channel = lttng_notification_channel_create(
646 lttng_session_daemon_notification_endpoint);
647 ok(notification_channel, "Notification channel object creation");
648 if (!notification_channel) {
649 goto end;
650 }
651
652 /* Subscribe a valid condition. */
653 nc_status = lttng_notification_channel_subscribe(
654 notification_channel, condition);
655 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
656 "Subscribe to condition");
657
658 /* Subscribing again should fail. */
659 nc_status = lttng_notification_channel_subscribe(
660 notification_channel, condition);
661 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED,
662 "Subscribe to a condition for which subscription was already done");
663
664end:
665 lttng_unregister_trigger(trigger);
666 lttng_trigger_destroy(trigger);
667 lttng_notification_channel_destroy(notification_channel);
668 lttng_action_destroy(action);
669 lttng_condition_destroy(condition);
670}
671
40ac6709 672static void test_buffer_usage_notification_channel(const char *session_name,
3780613c
FD
673 const char *channel_name,
674 const enum lttng_domain_type domain_type,
675 const char **argv)
676{
677 int ret = 0;
678 enum lttng_notification_channel_status nc_status;
679
680 struct lttng_action *low_action = NULL;
681 struct lttng_action *high_action = NULL;
682 struct lttng_notification *notification = NULL;
683 struct lttng_notification_channel *notification_channel = NULL;
684 struct lttng_trigger *low_trigger = NULL;
685 struct lttng_trigger *high_trigger = NULL;
686
687 struct lttng_condition *low_condition = NULL;
688 struct lttng_condition *high_condition = NULL;
689
690 const double low_ratio = 0.0;
691 const double high_ratio = 0.90;
692
693 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
694 domain_type, BUFFER_USAGE_TYPE_LOW, low_ratio,
695 &low_condition, &low_action, &low_trigger);
696 if (ret) {
697 fail("Setup error on low trigger registration");
434f8068
JR
698 goto end;
699 }
700
3780613c
FD
701 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
702 domain_type, BUFFER_USAGE_TYPE_HIGH, high_ratio,
703 &high_condition, &high_action, &high_trigger);
434f8068
JR
704 if (ret) {
705 fail("Setup error on high trigger registration");
706 goto end;
707 }
708
709 /* Begin testing */
a6ae2480
FD
710 notification_channel = lttng_notification_channel_create(
711 lttng_session_daemon_notification_endpoint);
434f8068
JR
712 ok(notification_channel, "Notification channel object creation");
713 if (!notification_channel) {
714 goto end;
715 }
716
434f8068 717 /* Subscribe a valid low condition */
a6ae2480
FD
718 nc_status = lttng_notification_channel_subscribe(
719 notification_channel, low_condition);
720 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 721 "Subscribe to low condition");
434f8068
JR
722
723 /* Subscribe a valid high condition */
a6ae2480
FD
724 nc_status = lttng_notification_channel_subscribe(
725 notification_channel, high_condition);
726 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 727 "Subscribe to high condition");
434f8068 728
7676e0d2
FD
729 resume_application();
730
434f8068 731 /* Wait for notification to happen */
434f8068 732 stop_consumer(argv);
ff2b03c8 733 lttng_start_tracing(session_name);
434f8068
JR
734
735 /* Wait for high notification */
67c93c15 736 do {
a6ae2480
FD
737 nc_status = lttng_notification_channel_get_next_notification(
738 notification_channel, &notification);
67c93c15 739 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
740 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
741 lttng_condition_get_type(lttng_notification_get_condition(
742 notification)) ==
743 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
744 "High notification received after intermediary communication");
745 lttng_notification_destroy(notification);
746 notification = NULL;
747
854382b8 748 suspend_application();
ff2b03c8 749 lttng_stop_tracing_no_wait(session_name);
434f8068 750 resume_consumer(argv);
ff2b03c8 751 wait_data_pending(session_name);
434f8068
JR
752
753 /*
754 * Test that communication still work even if there is notification
755 * waiting for consumption.
756 */
757
a6ae2480
FD
758 nc_status = lttng_notification_channel_unsubscribe(
759 notification_channel, low_condition);
760 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
761 "Unsubscribe with pending notification");
434f8068 762
a6ae2480
FD
763 nc_status = lttng_notification_channel_subscribe(
764 notification_channel, low_condition);
765 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
766 "Subscribe with pending notification");
434f8068 767
67c93c15 768 do {
a6ae2480
FD
769 nc_status = lttng_notification_channel_get_next_notification(
770 notification_channel, &notification);
67c93c15 771 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
772 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
773 lttng_condition_get_type(lttng_notification_get_condition(
774 notification)) ==
775 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
776 "Low notification received after intermediary communication");
777 lttng_notification_destroy(notification);
778 notification = NULL;
779
780 /* Stop consumer to force a high notification */
ff2b03c8 781 stop_consumer(argv);
854382b8 782 resume_application();
434f8068 783 lttng_start_tracing(session_name);
434f8068 784
67c93c15 785 do {
a6ae2480
FD
786 nc_status = lttng_notification_channel_get_next_notification(
787 notification_channel, &notification);
67c93c15 788 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 789 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
790 lttng_condition_get_type(lttng_notification_get_condition(
791 notification)) ==
792 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
793 "High notification received after intermediary communication");
794 lttng_notification_destroy(notification);
795 notification = NULL;
796
854382b8 797 suspend_application();
ff2b03c8 798 lttng_stop_tracing_no_wait(session_name);
434f8068 799 resume_consumer(argv);
ff2b03c8 800 wait_data_pending(session_name);
434f8068 801
67c93c15 802 do {
a6ae2480
FD
803 nc_status = lttng_notification_channel_get_next_notification(
804 notification_channel, &notification);
67c93c15 805 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 806 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
807 lttng_condition_get_type(lttng_notification_get_condition(
808 notification)) ==
809 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
810 "Low notification received after re-subscription");
811 lttng_notification_destroy(notification);
812 notification = NULL;
813
ff2b03c8 814 stop_consumer(argv);
854382b8 815 resume_application();
434f8068
JR
816 /* Stop consumer to force a high notification */
817 lttng_start_tracing(session_name);
434f8068 818
67c93c15 819 do {
a6ae2480
FD
820 nc_status = lttng_notification_channel_get_next_notification(
821 notification_channel, &notification);
67c93c15 822 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 823 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
824 lttng_condition_get_type(lttng_notification_get_condition(
825 notification)) ==
826 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
827 "High notification");
828 lttng_notification_destroy(notification);
829 notification = NULL;
830
ff2b03c8 831 suspend_application();
7676e0d2
FD
832
833 /* Resume consumer to allow event consumption */
ff2b03c8 834 lttng_stop_tracing_no_wait(session_name);
434f8068 835 resume_consumer(argv);
ff2b03c8 836 wait_data_pending(session_name);
434f8068 837
a6ae2480
FD
838 nc_status = lttng_notification_channel_unsubscribe(
839 notification_channel, low_condition);
840 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
841 "Unsubscribe low condition with pending notification");
842
843 nc_status = lttng_notification_channel_unsubscribe(
844 notification_channel, high_condition);
845 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
846 "Unsubscribe high condition with pending notification");
434f8068
JR
847
848end:
849 lttng_notification_channel_destroy(notification_channel);
3780613c
FD
850 lttng_trigger_destroy(low_trigger);
851 lttng_trigger_destroy(high_trigger);
852 lttng_action_destroy(low_action);
853 lttng_action_destroy(high_action);
434f8068 854 lttng_condition_destroy(low_condition);
eff748d0 855 lttng_condition_destroy(high_condition);
434f8068
JR
856}
857
7948461b
FD
858static void create_tracepoint_event_rule_trigger(const char *event_pattern,
859 const char *trigger_name,
860 const char *filter,
861 unsigned int exclusion_count,
3e4ee3b3 862 const char * const *exclusions,
7948461b
FD
863 enum lttng_domain_type domain_type,
864 struct lttng_condition **condition,
865 struct lttng_trigger **trigger)
866{
867 enum lttng_event_rule_status event_rule_status;
868 enum lttng_trigger_status trigger_status;
869
870 struct lttng_action *tmp_action = NULL;
871 struct lttng_event_rule *event_rule = NULL;
872 struct lttng_condition *tmp_condition = NULL;
873 struct lttng_trigger *tmp_trigger = NULL;
874 int ret;
875
876 assert(event_pattern);
877 assert(trigger_name);
878 assert(condition);
879 assert(trigger);
880
881 event_rule = lttng_event_rule_tracepoint_create(domain_type);
882 ok(event_rule, "Tracepoint event rule object creation");
883
884 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
885 event_rule, event_pattern);
886 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
887 "Setting tracepoint event rule pattern: '%s'",
888 event_pattern);
889
890 if (filter) {
891 event_rule_status = lttng_event_rule_tracepoint_set_filter(
892 event_rule, filter);
893 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
894 "Setting tracepoint event rule filter: '%s'",
895 filter);
896 }
897
898 if (exclusions) {
899 int i;
900 bool success = true;
901
902 assert(domain_type == LTTNG_DOMAIN_UST);
903 assert(exclusion_count > 0);
904
905 for (i = 0; i < exclusion_count; i++) {
906 event_rule_status =
907 lttng_event_rule_tracepoint_add_exclusion(
908 event_rule,
909 exclusions[i]);
910 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
911 fail("Setting tracepoint event rule exclusion '%s'.",
912 exclusions[i]);
913 success = false;
914 }
915 }
916
917 ok(success, "Setting tracepoint event rule exclusions");
918 }
919
920 tmp_condition = lttng_condition_event_rule_create(event_rule);
921 ok(tmp_condition, "Condition event rule object creation");
922
923 tmp_action = lttng_action_notify_create();
924 ok(tmp_action, "Action event rule object creation");
925
926 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
927 ok(tmp_trigger, "Trigger object creation %s", trigger_name);
928
929 trigger_status = lttng_trigger_set_name(tmp_trigger, trigger_name);
930 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
931 "Setting name to trigger %s", trigger_name);
932
933 ret = lttng_register_trigger(tmp_trigger);
934 ok(ret == 0, "Trigger registration %s", trigger_name);
935
936 lttng_event_rule_destroy(event_rule);
937
938 *condition = tmp_condition;
939 *trigger = tmp_trigger;
940
941 return;
942}
943
944static char *get_next_notification_trigger_name(
945 struct lttng_notification_channel *notification_channel)
946{
947 struct lttng_notification *notification;
948 enum lttng_notification_channel_status status;
949 const struct lttng_evaluation *notification_evaluation;
950 char *trigger_name = NULL;
951 const char *name;
952 enum lttng_condition_type notification_evaluation_type;
953
954 /* Receive the next notification. */
955 status = lttng_notification_channel_get_next_notification(
956 notification_channel, &notification);
957
958 switch (status) {
959 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
960 break;
961 default:
962 /* Unhandled conditions / errors. */
963 fail("Failed to get next notification channel notification: status = %d",
964 status);
965 goto end;
966 }
967
968 notification_evaluation =
969 lttng_notification_get_evaluation(notification);
970
971 notification_evaluation_type =
972 lttng_evaluation_get_type(notification_evaluation);
973 switch (notification_evaluation_type) {
974 case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
975 lttng_evaluation_event_rule_get_trigger_name(
976 notification_evaluation, &name);
977
978 trigger_name = strdup(name);
979 break;
980 default:
981 fail("Unexpected notification evaluation type: notification type = %d",
982 notification_evaluation_type);
983 break;
984 }
985
986 lttng_notification_destroy(notification);
987
988end:
989 return trigger_name;
990}
991
992static void test_tracepoint_event_rule_notification(
993 enum lttng_domain_type domain_type)
994{
995 int i;
996 const int notification_count = 3;
997 enum lttng_notification_channel_status nc_status;
998 struct lttng_action *action = NULL;
999 struct lttng_condition *condition = NULL;
1000 struct lttng_notification_channel *notification_channel = NULL;
1001 struct lttng_trigger *trigger = NULL;
1002 const char * const trigger_name = "my_precious";
1003 const char *pattern;
1004
1005 if (domain_type == LTTNG_DOMAIN_UST) {
1006 pattern = "tp:tptest";
1007 } else {
1008 pattern = "lttng_test_filter_event";
1009 }
1010
1011 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
1012 NULL, domain_type, &condition, &trigger);
1013
1014 notification_channel = lttng_notification_channel_create(
1015 lttng_session_daemon_notification_endpoint);
1016 ok(notification_channel, "Notification channel object creation");
1017
1018 nc_status = lttng_notification_channel_subscribe(
1019 notification_channel, condition);
1020 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1021 "Subscribe to tracepoint event rule condition");
1022
1023 resume_application();
1024
1025 /* Get 3 notifications. */
1026 for (i = 0; i < notification_count; i++) {
1027 char *name = get_next_notification_trigger_name(
1028 notification_channel);
1029
1030 ok(strcmp(trigger_name, name) == 0,
1031 "Received notification for the expected trigger name: '%s' (%d/%d)",
1032 trigger_name, i + 1, notification_count);
1033 free(name);
1034 }
1035
1036 suspend_application();
1037 lttng_notification_channel_destroy(notification_channel);
1038 lttng_unregister_trigger(trigger);
1039 lttng_trigger_destroy(trigger);
1040 lttng_action_destroy(action);
1041 lttng_condition_destroy(condition);
1042 return;
1043}
1044
a740a242
FD
1045static void test_tracepoint_event_rule_notification_filter(
1046 enum lttng_domain_type domain_type)
1047{
1048 int i;
1049 enum lttng_notification_channel_status nc_status;
1050
1051 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1052 struct lttng_notification_channel *notification_channel = NULL;
1053 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1054 const char * const ctrl_trigger_name = "control_trigger";
1055 const char * const trigger_name = "trigger";
1056 const char *pattern;
1057 int ctrl_count = 0, count = 0;
1058
1059 if (domain_type == LTTNG_DOMAIN_UST) {
1060 pattern = "tp:tptest";
1061 } else {
1062 pattern = "lttng_test_filter_event";
1063 }
1064
1065 notification_channel = lttng_notification_channel_create(
1066 lttng_session_daemon_notification_endpoint);
1067 ok(notification_channel, "Notification channel object creation");
1068
1069 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
1070 0, NULL, domain_type, &ctrl_condition, &ctrl_trigger);
1071
1072 nc_status = lttng_notification_channel_subscribe(
1073 notification_channel, ctrl_condition);
1074 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1075 "Subscribe to tracepoint event rule condition");
1076
1077 /*
1078 * Attach a filter expression to get notification only if the
1079 * `intfield` is even.
1080 */
1081 create_tracepoint_event_rule_trigger(pattern, trigger_name,
1082 "(intfield & 1) == 0", 0, NULL, domain_type, &condition,
1083 &trigger);
1084
1085 nc_status = lttng_notification_channel_subscribe(
1086 notification_channel, condition);
1087 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1088 "Subscribe to tracepoint event rule condition");
1089
1090 /*
1091 * We registered 2 notifications triggers, one with a filter and one
1092 * without (control). The one with a filter will only fired when the
1093 * `intfield` is a multiple of 2. We should get two times as many
1094 * control notifications as filter notifications.
1095 */
1096 resume_application();
1097
1098 /*
1099 * Get 3 notifications. We should get 1 for the regular trigger (with
1100 * the filter) and 2 from the control trigger. This works whatever
1101 * the order we receive the notifications.
1102 */
1103 for (i = 0; i < 3; i++) {
1104 char *name = get_next_notification_trigger_name(
1105 notification_channel);
1106
1107 if (strcmp(ctrl_trigger_name, name) == 0) {
1108 ctrl_count++;
1109 } else if (strcmp(trigger_name, name) == 0) {
1110 count++;
1111 }
1112
1113 free(name);
1114 }
1115
1116 ok(ctrl_count / 2 == count,
1117 "Get twice as many control notif as of regular notif");
1118
1119 suspend_application();
1120
1121 lttng_unregister_trigger(trigger);
1122 lttng_unregister_trigger(ctrl_trigger);
1123 lttng_notification_channel_destroy(notification_channel);
1124 lttng_trigger_destroy(trigger);
1125 lttng_trigger_destroy(ctrl_trigger);
1126 lttng_condition_destroy(condition);
1127 lttng_condition_destroy(ctrl_condition);
1128}
1129
3e4ee3b3
FD
1130static void test_tracepoint_event_rule_notification_exclusion(
1131 enum lttng_domain_type domain_type)
1132{
1133 enum lttng_notification_channel_status nc_status;
1134 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1135 struct lttng_notification_channel *notification_channel = NULL;
1136 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1137 int ctrl_count = 0, count = 0, i;
1138 const char * const ctrl_trigger_name = "control_exclusion_trigger";
1139 const char * const trigger_name = "exclusion_trigger";
1140 const char * const pattern = "tp:tptest*";
1141 const char * const exclusions[] = {
1142 "tp:tptest2",
1143 "tp:tptest3",
1144 "tp:tptest4",
1145 "tp:tptest5"
1146 };
1147
1148 notification_channel = lttng_notification_channel_create(
1149 lttng_session_daemon_notification_endpoint);
1150 ok(notification_channel, "Notification channel object creation");
1151
1152 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
1153 0, NULL, domain_type, &ctrl_condition, &ctrl_trigger);
1154
1155 nc_status = lttng_notification_channel_subscribe(
1156 notification_channel, ctrl_condition);
1157 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1158 "Subscribe to tracepoint event rule condition");
1159
1160 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 4,
1161 exclusions, domain_type, &condition, &trigger);
1162
1163 nc_status = lttng_notification_channel_subscribe(
1164 notification_channel, condition);
1165 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1166 "Subscribe to tracepoint event rule condition");
1167
1168 /*
1169 * We registered 2 notifications triggers, one with an exclusion and
1170 * one without (control).
1171 * - The trigger with an exclusion will fire once every iteration.
1172 * - The trigger without an exclusion will fire 5 times every
1173 * iteration.
1174 *
1175 * We should get 5 times as many notifications from the control
1176 * trigger.
1177 */
1178 resume_application();
1179
1180 /*
1181 * Get 6 notifications. We should get 1 for the regular trigger (with
1182 * the exclusion) and 5 from the control trigger. This works whatever
1183 * the order we receive the notifications.
1184 */
1185 for (i = 0; i < 6; i++) {
1186 char *name = get_next_notification_trigger_name(
1187 notification_channel);
1188
1189 if (strcmp(ctrl_trigger_name, name) == 0) {
1190 ctrl_count++;
1191 } else if (strcmp(trigger_name, name) == 0) {
1192 count++;
1193 }
1194
1195 free(name);
1196 }
1197
1198 ok(ctrl_count / 5 == count,
1199 "Got 5 times as many control notif as of regular notif");
1200
1201 suspend_application();
1202
1203 lttng_unregister_trigger(trigger);
1204 lttng_unregister_trigger(ctrl_trigger);
1205 lttng_notification_channel_destroy(notification_channel);
1206 lttng_trigger_destroy(trigger);
1207 lttng_trigger_destroy(ctrl_trigger);
1208 lttng_condition_destroy(condition);
1209 lttng_condition_destroy(ctrl_condition);
1210 return;
1211}
1212
51704c8e
FD
1213static void test_kprobe_event_rule_notification(
1214 enum lttng_domain_type domain_type)
1215{
1216 int i, ret;
1217 const int notification_count = 3;
1218 enum lttng_notification_channel_status nc_status;
1219 enum lttng_event_rule_status event_rule_status;
1220 enum lttng_trigger_status trigger_status;
1221 struct lttng_notification_channel *notification_channel = NULL;
1222 struct lttng_condition *condition = NULL;
1223 struct lttng_kernel_probe_location *location = NULL;
1224 struct lttng_event_rule *event_rule = NULL;
1225 struct lttng_action *action = NULL;
1226 struct lttng_trigger *trigger = NULL;
1227 const char * const trigger_name = "kprobe_trigger";
1228 const char * const symbol_name = "lttng_test_filter_event_write";
1229
1230 action = lttng_action_notify_create();
1231 if (!action) {
1232 fail("Failed to create notify action");
1233 goto end;
1234 }
1235
1236 location = lttng_kernel_probe_location_symbol_create(symbol_name, 0);
1237 if (!location) {
1238 fail("Failed to create kernel probe location");
1239 goto end;
1240 }
1241
1242 notification_channel = lttng_notification_channel_create(
1243 lttng_session_daemon_notification_endpoint);
1244 ok(notification_channel, "Notification channel object creation");
1245
1246 event_rule = lttng_event_rule_kprobe_create();
1247 ok(event_rule, "kprobe event rule object creation");
1248
1249 event_rule_status = lttng_event_rule_kprobe_set_location(
1250 event_rule, location);
1251 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1252 "Setting kprobe event rule location: '%s'", symbol_name);
1253
1254 event_rule_status = lttng_event_rule_kprobe_set_name(
1255 event_rule, trigger_name);
1256 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1257 "Setting kprobe event rule name: '%s'", trigger_name);
1258
1259 condition = lttng_condition_event_rule_create(event_rule);
1260 ok(condition, "Condition event rule object creation");
1261
1262 /* Register the trigger for condition. */
1263 trigger = lttng_trigger_create(condition, action);
1264 if (!trigger) {
1265 fail("Failed to create trigger with kernel probe event rule condition and notify action");
1266 goto end;
1267 }
1268
1269 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1270 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1271 "Setting trigger name to '%s'", trigger_name);
1272
1273 ret = lttng_register_trigger(trigger);
1274 if (ret) {
1275 fail("Failed to register trigger with kernel probe event rule condition and notify action");
1276 goto end;
1277 }
1278
1279 nc_status = lttng_notification_channel_subscribe(
1280 notification_channel, condition);
1281 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1282 "Subscribe to tracepoint event rule condition");
1283
1284 resume_application();
1285
1286 for (i = 0; i < notification_count; i++) {
1287 char *name = get_next_notification_trigger_name(
1288 notification_channel);
1289
1290 ok(strcmp(trigger_name, name) == 0,
1291 "Received notification for the expected trigger name: '%s' (%d/%d)",
1292 trigger_name, i + 1, notification_count);
1293 free(name);
1294 }
1295
1296end:
1297 suspend_application();
1298 lttng_notification_channel_destroy(notification_channel);
1299 lttng_unregister_trigger(trigger);
1300 lttng_trigger_destroy(trigger);
1301 lttng_action_destroy(action);
aab0598f 1302 lttng_event_rule_destroy(event_rule);
51704c8e
FD
1303 lttng_condition_destroy(condition);
1304 lttng_kernel_probe_location_destroy(location);
1305 return;
1306}
1307
aab0598f
FD
1308static void test_syscall_event_rule_notification(
1309 enum lttng_domain_type domain_type)
1310{
1311 int i, ret;
1312 const int notification_count = 3;
1313 enum lttng_notification_channel_status nc_status;
1314 enum lttng_event_rule_status event_rule_status;
1315 enum lttng_trigger_status trigger_status;
1316 struct lttng_notification_channel *notification_channel = NULL;
1317 struct lttng_condition *condition = NULL;
1318 struct lttng_event_rule *event_rule = NULL;
1319 struct lttng_action *action = NULL;
1320 struct lttng_trigger *trigger = NULL;
1321 const char * const trigger_name = "syscall_trigger";
1322 const char * const syscall_name = "openat";
1323
1324 action = lttng_action_notify_create();
1325 if (!action) {
1326 fail("Failed to create notify action");
1327 goto end;
1328 }
1329
1330 notification_channel = lttng_notification_channel_create(
1331 lttng_session_daemon_notification_endpoint);
1332 ok(notification_channel, "Notification channel object creation");
1333
1334 event_rule = lttng_event_rule_syscall_create();
1335 ok(event_rule, "syscall event rule object creation");
1336
1337 event_rule_status = lttng_event_rule_syscall_set_pattern(
1338 event_rule, syscall_name);
1339 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1340 "Setting syscall event rule pattern: '%s'", syscall_name);
1341
1342 condition = lttng_condition_event_rule_create(event_rule);
1343 ok(condition, "Condition syscall event rule object creation");
1344
1345 /* Register the trigger for condition. */
1346 trigger = lttng_trigger_create(condition, action);
1347 if (!trigger) {
1348 fail("Failed to create trigger with syscall event rule condition and notify action");
1349 goto end;
1350 }
1351
1352 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1353 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1354 "Setting name to trigger '%s'", trigger_name);
1355
1356 ret = lttng_register_trigger(trigger);
1357 if (ret) {
1358 fail("Failed to register trigger with syscall event rule condition and notify action");
1359 goto end;
1360 }
1361
1362 nc_status = lttng_notification_channel_subscribe(
1363 notification_channel, condition);
1364 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1365 "Subscribe to tracepoint event rule condition");
1366
1367 resume_application();
1368
1369 for (i = 0; i < notification_count; i++) {
1370 char *name = get_next_notification_trigger_name(
1371 notification_channel);
1372
1373 ok(strcmp(trigger_name, name) == 0,
1374 "Received notification for the expected trigger name: '%s' (%d/%d)",
1375 trigger_name, i + 1, notification_count);
1376 free(name);
1377 }
1378end:
1379 suspend_application();
1380 lttng_notification_channel_destroy(notification_channel);
1381 lttng_unregister_trigger(trigger);
1382 lttng_trigger_destroy(trigger);
1383 lttng_action_destroy(action);
1384 lttng_condition_destroy(condition);
1385 return;
1386}
1387
434f8068
JR
1388int main(int argc, const char *argv[])
1389{
069fc1c5 1390 int test_scenario;
434f8068
JR
1391 const char *session_name = NULL;
1392 const char *channel_name = NULL;
1393 const char *domain_type_string = NULL;
1394 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
1395
a740a242
FD
1396 if (argc < 5) {
1397 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
434f8068
JR
1398 goto error;
1399 }
1400
069fc1c5
FD
1401 test_scenario = atoi(argv[1]);
1402 domain_type_string = argv[2];
a740a242
FD
1403 app_pid = (pid_t) atoi(argv[3]);
1404 app_state_file = argv[4];
434f8068
JR
1405
1406 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
1407 domain_type = LTTNG_DOMAIN_UST;
1408 }
1409 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
1410 domain_type = LTTNG_DOMAIN_KERNEL;
1411 }
1412 if (domain_type == LTTNG_DOMAIN_NONE) {
1413 fail("Unknown domain type");
1414 goto error;
1415 }
1416
a740a242
FD
1417 /*
1418 * Test cases are responsible for resuming the app when needed
1419 * and making sure it's suspended when returning.
1420 */
1421 suspend_application();
1422
069fc1c5
FD
1423 switch (test_scenario) {
1424 case 1:
1425 {
a740a242 1426 plan_tests(38);
7948461b 1427
069fc1c5 1428 /* Test cases that need gen-ust-event testapp. */
a740a242 1429 diag("Test basic notification error paths for %s domain",
069fc1c5
FD
1430 domain_type_string);
1431 test_invalid_channel_subscription(domain_type);
7948461b
FD
1432
1433 diag("Test tracepoint event rule notifications for domain %s",
1434 domain_type_string);
1435 test_tracepoint_event_rule_notification(domain_type);
1436
a740a242
FD
1437 diag("Test tracepoint event rule notifications with filter for domain %s",
1438 domain_type_string);
1439 test_tracepoint_event_rule_notification_filter(domain_type);
069fc1c5
FD
1440 break;
1441 }
1442 case 2:
1443 {
1444 /* Test cases that need a tracing session enabled. */
1445 plan_tests(99);
7676e0d2 1446
069fc1c5
FD
1447 /*
1448 * Argument 7 and upward are named pipe location for consumerd
1449 * control.
1450 */
1451 named_pipe_args_start = 7;
1452
1453 if (argc < 8) {
1454 fail("Missing parameter for tests to run %d", argc);
1455 goto error;
1456 }
434f8068 1457
069fc1c5
FD
1458 nb_args = argc;
1459
a740a242
FD
1460 session_name = argv[5];
1461 channel_name = argv[6];
069fc1c5
FD
1462
1463 test_subscription_twice(session_name, channel_name,
1464 domain_type);
1465
1466 diag("Test trigger for domain %s with buffer_usage_low condition",
1467 domain_type_string);
1468 test_triggers_buffer_usage_condition(session_name, channel_name,
1469 domain_type,
1470 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
1471
1472 diag("Test trigger for domain %s with buffer_usage_high condition",
1473 domain_type_string);
1474 test_triggers_buffer_usage_condition(session_name, channel_name,
1475 domain_type,
1476 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
1477
1478 diag("Test buffer usage notification channel api for domain %s",
1479 domain_type_string);
1480 test_buffer_usage_notification_channel(session_name, channel_name,
1481 domain_type, argv);
1482 break;
1483 }
3e4ee3b3
FD
1484 case 3:
1485 {
1486 /*
1487 * Test cases that need a test app with more than one event
1488 * type.
1489 */
1490 plan_tests(19);
1491
1492 /*
1493 * At the moment, the only test case of this scenario is
1494 * exclusion which is only supported by UST.
1495 */
1496 assert(domain_type == LTTNG_DOMAIN_UST);
1497 diag("Test tracepoint event rule notifications with exclusion for domain %s",
1498 domain_type_string);
1499 test_tracepoint_event_rule_notification_exclusion(domain_type);
1500
1501 break;
1502 }
51704c8e
FD
1503 case 4:
1504 {
1505 plan_tests(10);
1506
1507 /* Test cases that need the kernel tracer. */
1508 assert(domain_type == LTTNG_DOMAIN_KERNEL);
aab0598f 1509
51704c8e
FD
1510 diag("Test kprobe event rule notifications for domain %s",
1511 domain_type_string);
1512
1513 test_kprobe_event_rule_notification(domain_type);
1514
1515 break;
1516 }
aab0598f
FD
1517 case 5:
1518 {
1519 plan_tests(10);
1520 /* Test cases that need the kernel tracer. */
1521 assert(domain_type == LTTNG_DOMAIN_KERNEL);
1522
1523 diag("Test syscall event rule notifications for domain %s",
1524 domain_type_string);
1525
1526 test_syscall_event_rule_notification(domain_type);
1527
1528 break;
1529 }
069fc1c5
FD
1530 default:
1531 abort();
1532 }
90fcb2ec 1533
434f8068
JR
1534error:
1535 return exit_status();
1536}
1537
This page took 0.161965 seconds and 4 git commands to generate.