lttng-ctl: separate support of named/unnamed trigger registration
[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>
7948461b 27#include <lttng/lttng.h>
434f8068
JR
28
29#include <tap/tap.h>
30
26e2f47b
JR
31#define FIELD_NAME_MAX_LEN 256
32
33/* A callback to populate the condition capture descriptor. */
34typedef int (*condition_capture_desc_cb)(struct lttng_condition *condition);
35
36/* A callback for captured field validation. */
37typedef int (*validate_cb)(const struct lttng_event_field_value *event_field, unsigned iteration);
38
434f8068
JR
39int nb_args = 0;
40int named_pipe_args_start = 0;
7344b6a3 41pid_t app_pid = 0;
854382b8
JR
42const char *app_state_file = NULL;
43
26e2f47b
JR
44enum field_type {
45 FIELD_TYPE_PAYLOAD,
46 FIELD_TYPE_CONTEXT,
47 FIELD_TYPE_APP_CONTEXT,
48 FIELD_TYPE_ARRAY_FIELD,
49};
50
51struct capture_base_field_tuple {
52 char* field_name;
53 enum field_type field_type;
54 /* Do we expect a userspace capture? */
55 bool expected_ust;
56 /* Do we expect a kernel capture? */
57 bool expected_kernel;
58 validate_cb validate_ust;
59 validate_cb validate_kernel;
60};
61
62static
63const char *field_value_type_to_str(enum lttng_event_field_value_type type)
64{
65 switch (type) {
66 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNKNOWN:
67 return "UNKNOWN";
68 case LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID:
69 return "INVALID";
70 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
71 return "UNSIGNED INT";
72 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
73 return "SIGNED INT";
74 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
75 return "UNSIGNED ENUM";
76 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
77 return "SIGNED ENUM";
78 case LTTNG_EVENT_FIELD_VALUE_TYPE_REAL:
79 return "REAL";
80 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
81 return "STRING";
82 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
83 return "ARRAY";
84 default:
85 abort();
86 }
87}
88
89static int validate_type(const struct lttng_event_field_value *event_field,
90 enum lttng_event_field_value_type expect)
91{
92 int ret;
93 enum lttng_event_field_value_type value;
94
95 value = lttng_event_field_value_get_type(event_field);
96 if (value == LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID) {
97 ret = 1;
98 goto end;
99 }
100
101 ok(expect == value, "Expected field type %s, got %s",
102 field_value_type_to_str(expect),
103 field_value_type_to_str(value));
104
105 ret = expect != value;
106
107end:
108 return ret;
109}
110
111/*
112 * Validate unsigned captured field against the iteration number.
113 */
114static int validate_unsigned_int_field(
115 const struct lttng_event_field_value *event_field,
116 unsigned int expected_value)
117{
118 int ret;
119 uint64_t value;
120 enum lttng_event_field_value_status status;
121
122 ret = validate_type(
123 event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT);
124 if (ret) {
125 goto end;
126 }
127
128 status = lttng_event_field_value_unsigned_int_get_value(
129 event_field, &value);
130 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
131 fail("lttng_event_field_value_unsigned_int_get_value returned an error: status = %d",
132 (int) status);
133 ret = 1;
134 goto end;
135 }
136
137 ok(value == (uint64_t) expected_value,
138 "Expected unsigned integer value %u, got %" PRIu64,
139 expected_value, value);
140
141 ret = value != (uint64_t) expected_value;
142
143end:
144 return ret;
145}
146
147/*
148 * Validate signed captured field.
149 */
150static int validate_signed_int_field(
151 const struct lttng_event_field_value *event_field,
152 unsigned int iteration)
153{
154 int ret;
155 const int64_t expected = -1;
156 int64_t value;
157 enum lttng_event_field_value_status status;
158
159 /* Unused. */
160 (void) iteration;
161
162 ret = validate_type(
163 event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT);
164 if (ret) {
165 goto end;
166 }
167
168 status = lttng_event_field_value_signed_int_get_value(
169 event_field, &value);
170 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
171 fail("lttng_event_field_value_signed_int_get_value returned an error: status = %d",
172 (int) status);
173 ret = 1;
174 goto end;
175 }
176
177 ok(value == expected,
178 "Expected signed integer value %" PRId64
179 ", got %" PRId64,
180 expected, value);
181
182 ret = value != expected;
183
184end:
185
186 return ret;
187}
188
189/*
190 * Validate array of unsigned int.
191 */
192static int validate_array_unsigned_int_field(
193 const struct lttng_event_field_value *event_field,
194 unsigned int iteration)
195{
196 int ret;
197 enum lttng_event_field_value_status status;
198 const unsigned int expected = 3;
199 unsigned int i, count;
200
201 /* Unused. */
202 (void) iteration;
203
204 ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY);
205 if (ret) {
206 goto end;
207 }
208
209 status = lttng_event_field_value_array_get_length(event_field, &count);
210 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
211 fail("lttng_event_field_value_array_get_length");
212 ret = 1;
213 goto end;
214 }
215
216 ok(count == expected, "Expected %d subelements, got %d", expected,
217 count);
218 if (count != expected) {
219 ret = 1;
220 goto end;
221 }
222
223 for (i = 1; i < count + 1; i++) {
224 const struct lttng_event_field_value *value;
225
226 status = lttng_event_field_value_array_get_element_at_index(
227 event_field, i - 1, &value);
228 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
229 fail("lttng_event_field_value_array_get_element_at_index returned an error: status = %d",
230 (int) status);
231 ret = 1;
232 goto end;
233 }
234
235 ret = validate_unsigned_int_field(value, i);
236 if (ret) {
237 goto end;
238 }
239 }
240
241 ret = 0;
242end:
243
244 return ret;
245}
246
247static int validate_array_unsigned_int_field_at_index(
248 const struct lttng_event_field_value *event_field,
249 unsigned int iteration)
250{
251 int ret;
252 const uint64_t expected_value = 2;
253 enum lttng_event_field_value_status status;
254 uint64_t value;
255
256 /* Unused. */
257 (void) iteration;
258
259 ret = validate_type(
260 event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT);
261 if (ret) {
262 goto end;
263 }
264
265 status = lttng_event_field_value_unsigned_int_get_value(
266 event_field, &value);
267 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
268 fail("lttng_event_field_value_unsigned_int_get_value returned an error: status = %d",
269 (int) status);
270 ret = 1;
271 goto end;
272 }
273
274 ok(value == expected_value,
275 "Expected unsigned integer value %u, got %" PRIu64,
276 expected_value, value);
277
278 ret = 0;
279end:
280 return ret;
281}
282
283/*
284 * Validate sequence for a string (seqfield1):
285 *
286 * Value: "test" encoded in UTF-8: [116, 101, 115, 116]
287 */
288static int validate_seqfield1(const struct lttng_event_field_value *event_field,
289 unsigned int iteration)
290{
291 int ret;
292 enum lttng_event_field_value_status status;
293 unsigned int i, count;
294 const unsigned int expect[] = {116, 101, 115, 116};
295 const size_t array_count = sizeof(expect) / sizeof(*expect);
296
297 /* Unused. */
298 (void) iteration;
299
300 ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY);
301 if (ret) {
302 goto end;
303 }
304
305 status = lttng_event_field_value_array_get_length(event_field, &count);
306 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
307 fail("lttng_event_field_value_array_get_length returned an error: status = %d",
308 (int) status);
309 ret = 1;
310 goto end;
311 }
312
313 ok(count == array_count, "Expected %zu array sub-elements, got %d",
314 array_count, count);
315 if (count != array_count) {
316 ret = 1;
317 goto end;
318 }
319
320 for (i = 0; i < count; i++) {
321 const struct lttng_event_field_value *value;
322
323 status = lttng_event_field_value_array_get_element_at_index(
324 event_field, i, &value);
325 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
326 fail("lttng_event_field_value_array_get_element_at_index returned an error: status = %d",
327 (int) status);
328 ret = 1;
329 goto end;
330 }
331
332 ret = validate_unsigned_int_field(value, expect[i]);
333 if (ret) {
334 goto end;
335 }
336 }
337
338 ret = 0;
339end:
340 return ret;
341}
342
343static int validate_string(
344 const struct lttng_event_field_value *event_field,
345 const char *expect)
346{
347 int ret;
348 const char *value = NULL;
349 enum lttng_event_field_value_status status;
350
351 ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_STRING);
352 if (ret) {
353 goto end;
354 }
355
356 status = lttng_event_field_value_string_get_value(event_field, &value);
357 if (!value) {
358 fail("lttng_event_field_value_array_get_length returned an error: status = %d",
359 (int) status);
360 ret = 1;
361 goto end;
362 }
363
364 ok(!strcmp(value, expect), "Expected string value \"%s\", got \"%s\"",
365 expect, value);
366
367 ret = 0;
368end:
369
370 return ret;
371}
372
373/*
374 * Validate string. Expected value is "test".
375 */
376static int validate_string_test(
377 const struct lttng_event_field_value *event_field,
378 unsigned int iteration)
379{
380 const char * const expect = "test";
381
382 /* Unused. */
383 (void) iteration;
384
385 return validate_string(event_field, expect);
386}
387
388/*
389 * Validate escaped string. Expected value is "\*".
390 */
391static int validate_string_escaped(
392 const struct lttng_event_field_value *event_field,
393 unsigned int iteration)
394{
395 const char * const expect = "\\*";
396
397 /* Unused. */
398 (void) iteration;
399
400 return validate_string(event_field, expect);
401}
402
403/*
404 * Validate real field.
405 */
406static int validate_real(
407 const struct lttng_event_field_value *event_field,
408 double expect)
409{
410 int ret;
411 double value;
412 enum lttng_event_field_value_status status;
413
414 ret = validate_type(event_field, LTTNG_EVENT_FIELD_VALUE_TYPE_REAL);
415 if (ret) {
416 goto end;
417 }
418
419 status = lttng_event_field_value_real_get_value(event_field, &value);
420 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
421 fail("lttng_event_field_value_real_get_value returned an error: status = %d",
422 (int) status);
423 ret = 1;
424 goto end;
425 }
426
427 ok(value == expect, "Expected real value %f, got %f", expect, value);
428 ret = value != expect;
429end:
430 return ret;
431}
432
433/*
434 * Validate floatfield.
435 */
436static int validate_floatfield(
437 const struct lttng_event_field_value *event_field,
438 unsigned int iteration)
439{
440 const double expect = 2222.0;
441
442 /* Unused. */
443 (void) iteration;
444
445 return validate_real(event_field, expect);
446}
447
448/*
449 * Validate doublefield.
450 */
451static int validate_doublefield(
452 const struct lttng_event_field_value *event_field,
453 unsigned int iteration)
454{
455 const double expect = 2.0;
456
457 /* Unused. */
458 (void) iteration;
459
460 return validate_real(event_field, expect);
461}
462
463/*
464 * Validate enum0: enum0 = ( "AUTO: EXPECT 0" : container = 0 )
465 */
466static int validate_enum0(const struct lttng_event_field_value *event_field,
467 unsigned int iteration)
468{
469 int ret;
470 enum lttng_event_field_value_status status;
471 uint64_t value;
472 const uint64_t expected_value = 0;
473
474 /* Unused. */
475 (void) iteration;
476
477 ret = validate_type(event_field,
478 LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM);
479 if (ret) {
480 goto end;
481 }
482
483 status = lttng_event_field_value_unsigned_int_get_value(
484 event_field, &value);
485 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
486 fail("lttng_event_field_value_unsigned_int_get_value returned an error: status = %d",
487 (int) status);
488 ret = 1;
489 goto end;
490 }
491
492 ok(value == expected_value,
493 "Expected enum value %" PRIu64 ", got %" PRIu64,
494 expected_value, value);
495
496end:
497 return ret;
498}
499
500/*
501 * Validate enumnegative: enumnegative = ( "AUTO: EXPECT 0" : container = 0 )
502 *
503 * We expect 2 labels here.
504 */
505static int validate_enumnegative(
506 const struct lttng_event_field_value *event_field,
507 unsigned int iteration)
508{
509 int ret;
510 enum lttng_event_field_value_status status;
511 int64_t value;
512 const int64_t expected_value = -1;
513
514 /* Unused. */
515 (void) iteration;
516
517 ret = validate_type(event_field,
518 LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM);
519 if (ret) {
520 goto end;
521 }
522
523 status = lttng_event_field_value_signed_int_get_value(
524 event_field, &value);
525 if (status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
526 fail("lttng_event_field_value_unsigned_int_get_value");
527 ret = 1;
528 goto end;
529 }
530
531 ok(value == expected_value,
532 "Expected enum value %" PRId64 ", got %" PRId64,
533 expected_value, value);
534
535end:
536 return ret;
537}
538
539static int validate_context_procname_ust(
540 const struct lttng_event_field_value *event_field,
541 unsigned int iteration)
542{
543 /* Unused. */
544 (void) iteration;
545 return validate_string(event_field, "gen-ust-events");
546}
547
548static int validate_context_procname_kernel(
549 const struct lttng_event_field_value *event_field,
550 unsigned int iteration)
551{
552 /* Unused. */
553 (void) iteration;
554 return validate_string(event_field, "echo");
555}
556
557struct capture_base_field_tuple test_capture_base_fields[] = {
558 { "DOESNOTEXIST", FIELD_TYPE_PAYLOAD, false, false, NULL, NULL },
559 { "intfield", FIELD_TYPE_PAYLOAD, true, true, validate_unsigned_int_field, validate_unsigned_int_field },
560 { "longfield", FIELD_TYPE_PAYLOAD, true, true, validate_unsigned_int_field, validate_unsigned_int_field },
561 { "signedfield", FIELD_TYPE_PAYLOAD, true, true, validate_signed_int_field, validate_signed_int_field },
562 { "arrfield1", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field },
563 { "arrfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test },
564 { "arrfield3", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field },
565 { "seqfield1", FIELD_TYPE_PAYLOAD, true, true, validate_seqfield1, validate_seqfield1 },
566 { "seqfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test },
567 { "seqfield3", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field },
568 { "seqfield4", FIELD_TYPE_PAYLOAD, true, true, validate_array_unsigned_int_field, validate_array_unsigned_int_field },
569 { "arrfield1[1]", FIELD_TYPE_ARRAY_FIELD, true, true, validate_array_unsigned_int_field_at_index, validate_array_unsigned_int_field_at_index },
570 { "stringfield", FIELD_TYPE_PAYLOAD, true, true, validate_string_test, validate_string_test },
571 { "stringfield2", FIELD_TYPE_PAYLOAD, true, true, validate_string_escaped, validate_string_escaped },
572 { "floatfield", FIELD_TYPE_PAYLOAD, true, false, validate_floatfield, validate_floatfield },
573 { "doublefield", FIELD_TYPE_PAYLOAD, true, false, validate_doublefield, validate_doublefield },
574 { "enum0", FIELD_TYPE_PAYLOAD, true, true, validate_enum0, validate_enum0 },
575 { "enumnegative", FIELD_TYPE_PAYLOAD, true, true, validate_enumnegative, validate_enumnegative },
576 { "$ctx.procname", FIELD_TYPE_CONTEXT, true, true, validate_context_procname_ust, validate_context_procname_kernel },
577};
578
d150e7e5
JR
579static const char *get_notification_trigger_name(
580 struct lttng_notification *notification)
581{
65f64978
JG
582 const char *trigger_name = NULL;
583 enum lttng_trigger_status trigger_status;
584 const struct lttng_trigger *trigger;
585
586 trigger = lttng_notification_get_trigger(notification);
587 if (!trigger) {
588 fail("Failed to get trigger from notification");
d150e7e5
JR
589 goto end;
590 }
591
65f64978 592 trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
0efb2ad7
JG
593 switch (trigger_status) {
594 case LTTNG_TRIGGER_STATUS_OK:
595 break;
596 case LTTNG_TRIGGER_STATUS_UNSET:
597 trigger_name = "(anonymous)";
598 break;
599 default:
65f64978 600 fail("Failed to get name from notification's trigger");
d150e7e5
JR
601 goto end;
602 }
65f64978 603
d150e7e5 604end:
65f64978 605 return trigger_name;
d150e7e5
JR
606}
607
608static int validator_notification_trigger_name(
609 struct lttng_notification *notification,
610 const char *trigger_name)
611{
612 int ret;
613 bool name_is_equal;
614 const char *name;
615
616 assert(notification);
617 assert(trigger_name);
618
619 name = get_notification_trigger_name(notification);
620 if (name == NULL) {
621 ret = 1;
622 goto end;
623 }
624
625 name_is_equal = (strcmp(trigger_name, name) == 0);
626 ok(name_is_equal, "Expected trigger name: %s got %s", trigger_name,
627 name);
628
629 ret = !name_is_equal;
630
631end:
632 return ret;
633}
634
854382b8
JR
635static
636void wait_on_file(const char *path, bool file_exist)
637{
638 if (!path) {
639 return;
640 }
641 for (;;) {
642 int ret;
643 struct stat buf;
644
645 ret = stat(path, &buf);
646 if (ret == -1 && errno == ENOENT) {
647 if (file_exist) {
f0784451
FD
648 /*
649 * The file does not exist. wait a bit and
650 * continue looping until it does.
651 */
652 (void) poll(NULL, 0, 10);
653 continue;
854382b8 654 }
f0784451
FD
655
656 /*
657 * File does not exist and the exit condition we want.
658 * Break from the loop and return.
659 */
660 break;
854382b8
JR
661 }
662 if (ret) {
663 perror("stat");
664 exit(EXIT_FAILURE);
665 }
f0784451
FD
666 /*
667 * stat() returned 0, so the file exists. break now only if
668 * that's the exit condition we want.
669 */
670 if (file_exist) {
671 break;
672 }
854382b8
JR
673 }
674}
434f8068 675
f12eb9c1 676static
434f8068
JR
677int write_pipe(const char *path, uint8_t data)
678{
679 int ret = 0;
680 int fd = 0;
681
682 fd = open(path, O_WRONLY | O_NONBLOCK);
683 if (fd < 0) {
684 perror("Could not open consumer control named pipe");
685 goto end;
686 }
687
688 ret = write(fd, &data , sizeof(data));
689 if (ret < 1) {
690 perror("Named pipe write failed");
eff748d0
JR
691 if (close(fd)) {
692 perror("Named pipe close failed");
693 }
434f8068
JR
694 ret = -1;
695 goto end;
696 }
697
698 ret = close(fd);
699 if (ret < 0) {
700 perror("Name pipe closing failed");
701 ret = -1;
702 goto end;
703 }
704end:
705 return ret;
706}
707
f12eb9c1 708static
434f8068
JR
709int stop_consumer(const char **argv)
710{
9df6c82a
JG
711 int ret = 0, i;
712
713 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
714 ret = write_pipe(argv[i], 49);
715 }
716 return ret;
717}
718
f12eb9c1 719static
434f8068
JR
720int resume_consumer(const char **argv)
721{
9df6c82a
JG
722 int ret = 0, i;
723
724 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
725 ret = write_pipe(argv[i], 0);
726 }
727 return ret;
728}
729
f12eb9c1
SM
730static
731int suspend_application(void)
854382b8
JR
732{
733 int ret;
734 struct stat buf;
735
736 if (!stat(app_state_file, &buf)) {
737 fail("App is already in a suspended state.");
738 ret = -1;
739 goto error;
740 }
741
742 /*
743 * Send SIGUSR1 to application instructing it to bypass tracepoint.
744 */
7344b6a3
FD
745 assert(app_pid > 1);
746
854382b8
JR
747 ret = kill(app_pid, SIGUSR1);
748 if (ret) {
749 fail("SIGUSR1 failed. errno %d", errno);
750 ret = -1;
751 goto error;
752 }
753
754 wait_on_file(app_state_file, true);
755
756error:
757 return ret;
758
759}
760
f12eb9c1 761static
a3ecaea8 762int resume_application(void)
854382b8
JR
763{
764 int ret;
765 struct stat buf;
766
767 ret = stat(app_state_file, &buf);
768 if (ret == -1 && errno == ENOENT) {
769 fail("State file does not exist");
770 goto error;
771 }
772 if (ret) {
773 perror("stat");
774 goto error;
775 }
776
7344b6a3
FD
777 assert(app_pid > 1);
778
854382b8
JR
779 ret = kill(app_pid, SIGUSR1);
780 if (ret) {
781 fail("SIGUSR1 failed. errno %d", errno);
782 ret = -1;
783 goto error;
784 }
785
786 wait_on_file(app_state_file, false);
787
788error:
789 return ret;
790
791}
792
793
f12eb9c1 794static
434f8068
JR
795void test_triggers_buffer_usage_condition(const char *session_name,
796 const char *channel_name,
797 enum lttng_domain_type domain_type,
798 enum lttng_condition_type condition_type)
799{
9df6c82a 800 unsigned int test_vector_size = 5, i;
434f8068
JR
801 enum lttng_condition_status condition_status;
802 struct lttng_action *action;
803
804 /* Set-up */
805 action = lttng_action_notify_create();
806 if (!action) {
807 fail("Setup error on action creation");
808 goto end;
809 }
810
811 /* Test lttng_register_trigger with null value */
812 ok(lttng_register_trigger(NULL) == -LTTNG_ERR_INVALID, "Registering a NULL trigger fails as expected");
813
814 /* Test: register a trigger */
9df6c82a
JG
815
816 for (i = 0; i < pow(2,test_vector_size); i++) {
434f8068
JR
817 int loop_ret = 0;
818 char *test_tuple_string = NULL;
819 unsigned int mask_position = 0;
820 bool session_name_set = false;
821 bool channel_name_set = false;
822 bool threshold_ratio_set = false;
823 bool threshold_byte_set = false;
824 bool domain_type_set = false;
825
826 struct lttng_trigger *trigger = NULL;
827 struct lttng_condition *condition = NULL;
828
829 /* Create base condition */
830 switch (condition_type) {
831 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
832 condition = lttng_condition_buffer_usage_low_create();
833 break;
834 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
835 condition = lttng_condition_buffer_usage_high_create();
836 break;
837 default:
838 loop_ret = 1;
839 goto loop_end;
840 }
841
842 if (!condition) {
843 loop_ret = 1;
844 goto loop_end;
845
846 }
847
848 /* Prepare the condition for trigger registration test */
849
850 /* Set session name */
851 if ((1 << mask_position) & i) {
852 condition_status = lttng_condition_buffer_usage_set_session_name(
853 condition, session_name);
854 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
855 loop_ret = 1;
856 goto loop_end;
857 }
858 session_name_set = true;
859 }
860 mask_position++;
861
862 /* Set channel name */
863 if ((1 << mask_position) & i) {
864 condition_status = lttng_condition_buffer_usage_set_channel_name(
865 condition, channel_name);
866 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
867 loop_ret = 1;
868 goto loop_end;
869 }
870 channel_name_set = true;
871 }
872 mask_position++;
873
874 /* Set threshold ratio */
875 if ((1 << mask_position) & i) {
876 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
877 condition, 0.0);
878 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
879 loop_ret = 1;
880 goto loop_end;
881 }
882 threshold_ratio_set = true;
883 }
884 mask_position++;
885
886 /* Set threshold byte */
887 if ((1 << mask_position) & i) {
888 condition_status = lttng_condition_buffer_usage_set_threshold(
889 condition, 0);
890 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
891 loop_ret = 1;
892 goto loop_end;
893 }
894 threshold_byte_set = true;
895 }
896 mask_position++;
897
898 /* Set domain type */
899 if ((1 << mask_position) & i) {
900 condition_status = lttng_condition_buffer_usage_set_domain_type(
901 condition, LTTNG_DOMAIN_UST);
902 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
903 loop_ret = 1;
904 goto loop_end;
905 }
906 domain_type_set = true;
907 }
908
909 /* Safety check */
910 if (mask_position != test_vector_size -1) {
911 assert("Logic error for test vector generation");
912 }
913
9479b7a7 914 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
434f8068
JR
915 session_name_set ? "set" : "unset",
916 channel_name_set ? "set" : "unset",
917 threshold_ratio_set ? "set" : "unset",
918 threshold_byte_set ? "set" : "unset",
919 domain_type_set? "set" : "unset");
920 if (!test_tuple_string || loop_ret < 0) {
921 loop_ret = 1;
922 goto loop_end;
923 }
924
925 /* Create trigger */
926 trigger = lttng_trigger_create(condition, action);
927 if (!trigger) {
928 loop_ret = 1;
929 goto loop_end;
930 }
931
932 loop_ret = lttng_register_trigger(trigger);
933
934loop_end:
935 if (loop_ret == 1) {
936 fail("Setup error occurred for tuple: %s", test_tuple_string);
937 goto loop_cleanup;
938 }
939
940 /* This combination happens three times */
941 if (session_name_set && channel_name_set
942 && (threshold_ratio_set || threshold_byte_set)
943 && domain_type_set) {
944 ok(loop_ret == 0, "Trigger is registered: %s", test_tuple_string);
945
946 /*
947 * Test that a trigger cannot be registered
948 * multiple time.
949 */
950 loop_ret = lttng_register_trigger(trigger);
951 ok(loop_ret == -LTTNG_ERR_TRIGGER_EXISTS, "Re-register trigger fails as expected: %s", test_tuple_string);
952
953 /* Test that a trigger can be unregistered */
954 loop_ret = lttng_unregister_trigger(trigger);
955 ok(loop_ret == 0, "Unregister trigger: %s", test_tuple_string);
956
957 /*
958 * Test that unregistration of a non-previously
959 * registered trigger fail.
960 */
961 loop_ret = lttng_unregister_trigger(trigger);
43e0c204 962 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
434f8068
JR
963 } else {
964 ok(loop_ret == -LTTNG_ERR_INVALID_TRIGGER, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string);
965 }
966
967loop_cleanup:
968 free(test_tuple_string);
969 lttng_trigger_destroy(trigger);
970 lttng_condition_destroy(condition);
971 }
972
973end:
974 lttng_action_destroy(action);
975}
976
ff2b03c8
JG
977static
978void wait_data_pending(const char *session_name)
979{
980 int ret;
981
982 do {
983 ret = lttng_data_pending(session_name);
984 assert(ret >= 0);
985 } while (ret != 0);
986}
987
f12eb9c1 988static
17423302
FD
989int setup_buffer_usage_condition(struct lttng_condition *condition,
990 const char *condition_name,
991 const char *session_name,
992 const char *channel_name,
993 const enum lttng_domain_type domain_type)
994{
995 enum lttng_condition_status condition_status;
996 int ret = 0;
997
998 condition_status = lttng_condition_buffer_usage_set_session_name(
999 condition, session_name);
1000 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1001 fail("Failed to set session name on creation of condition `%s`",
1002 condition_name);
1003 ret = -1;
1004 goto end;
1005 }
1006
1007 condition_status = lttng_condition_buffer_usage_set_channel_name(
1008 condition, channel_name);
1009 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1010 fail("Failed to set channel name on creation of condition `%s`",
1011 condition_name);
1012 ret = -1;
1013 goto end;
1014 }
1015
1016 condition_status = lttng_condition_buffer_usage_set_domain_type(
1017 condition, domain_type);
1018 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1019 fail("Failed to set domain type on creation of condition `%s`",
1020 condition_name);
1021 ret = -1;
1022 goto end;
1023 }
1024
1025end:
1026 return ret;
1027}
1028
1029static
90fcb2ec
FD
1030void test_invalid_channel_subscription(
1031 const enum lttng_domain_type domain_type)
434f8068 1032{
434f8068
JR
1033 enum lttng_condition_status condition_status;
1034 enum lttng_notification_channel_status nc_status;
434f8068 1035 struct lttng_condition *dummy_condition = NULL;
90fcb2ec
FD
1036 struct lttng_condition *dummy_invalid_condition = NULL;
1037 struct lttng_notification_channel *notification_channel = NULL;
1038 int ret = 0;
434f8068 1039
90fcb2ec
FD
1040 notification_channel = lttng_notification_channel_create(
1041 lttng_session_daemon_notification_endpoint);
1042 ok(notification_channel, "Notification channel object creation");
1043 if (!notification_channel) {
434f8068
JR
1044 goto end;
1045 }
1046
90fcb2ec
FD
1047 /*
1048 * Create a dummy, empty (thus invalid) condition to test error paths.
1049 */
434f8068
JR
1050 dummy_invalid_condition = lttng_condition_buffer_usage_low_create();
1051 if (!dummy_invalid_condition) {
1052 fail("Setup error on condition creation");
1053 goto end;
1054 }
1055
90fcb2ec
FD
1056 /*
1057 * Test subscription and unsubscription of an invalid condition to/from
1058 * a channel.
1059 */
1060 nc_status = lttng_notification_channel_subscribe(
1061 notification_channel, dummy_invalid_condition);
1062 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1063 "Subscribing to an invalid condition");
1064
1065 nc_status = lttng_notification_channel_unsubscribe(
1066 notification_channel, dummy_invalid_condition);
1067 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1068 "Unsubscribing from an invalid condition");
1069
434f8068
JR
1070 /* Create a valid dummy condition with a ratio of 0.5 */
1071 dummy_condition = lttng_condition_buffer_usage_low_create();
1072 if (!dummy_condition) {
1073 fail("Setup error on dummy_condition creation");
1074 goto end;
434f8068 1075 }
90fcb2ec 1076
434f8068
JR
1077 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
1078 dummy_condition, 0.5);
1079 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1080 fail("Setup error on condition creation");
1081 goto end;
1082 }
1083
17423302 1084 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
90fcb2ec 1085 "dummy_session", "dummy_channel", domain_type);
17423302
FD
1086 if (ret) {
1087 fail("Setup error on dummy condition creation");
434f8068
JR
1088 goto end;
1089 }
1090
90fcb2ec
FD
1091 /*
1092 * Test subscription and unsubscription to/from a channel with invalid
1093 * parameters.
1094 */
1095 nc_status = lttng_notification_channel_subscribe(NULL, NULL);
1096 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1097 "Notification channel subscription is invalid: NULL, NULL");
1098
1099 nc_status = lttng_notification_channel_subscribe(
1100 notification_channel, NULL);
1101 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1102 "Notification channel subscription is invalid: NON-NULL, NULL");
1103
1104 nc_status = lttng_notification_channel_subscribe(NULL, dummy_condition);
1105 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1106 "Notification channel subscription is invalid: NULL, NON-NULL");
1107
1108 nc_status = lttng_notification_channel_unsubscribe(
1109 notification_channel, dummy_condition);
1110 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION,
1111 "Unsubscribing from a valid unknown condition");
1112
1113end:
1114 lttng_notification_channel_destroy(notification_channel);
1115 lttng_condition_destroy(dummy_invalid_condition);
1116 lttng_condition_destroy(dummy_condition);
1117 return;
1118}
1119
3780613c
FD
1120enum buffer_usage_type {
1121 BUFFER_USAGE_TYPE_LOW,
1122 BUFFER_USAGE_TYPE_HIGH,
1123};
1124
1125static int register_buffer_usage_notify_trigger(const char *session_name,
90fcb2ec
FD
1126 const char *channel_name,
1127 const enum lttng_domain_type domain_type,
3780613c
FD
1128 enum buffer_usage_type buffer_usage_type,
1129 double ratio,
1130 struct lttng_condition **condition,
1131 struct lttng_action **action,
1132 struct lttng_trigger **trigger)
90fcb2ec 1133{
90fcb2ec 1134 enum lttng_condition_status condition_status;
3780613c
FD
1135 struct lttng_action *tmp_action = NULL;
1136 struct lttng_condition *tmp_condition = NULL;
1137 struct lttng_trigger *tmp_trigger = NULL;
1138 int ret = 0;
90fcb2ec
FD
1139
1140 /* Set-up */
3780613c 1141 tmp_action = lttng_action_notify_create();
90fcb2ec
FD
1142 if (!action) {
1143 fail("Setup error on action creation");
3780613c
FD
1144 ret = -1;
1145 goto error;
434f8068
JR
1146 }
1147
3780613c
FD
1148 if (buffer_usage_type == BUFFER_USAGE_TYPE_LOW) {
1149 tmp_condition = lttng_condition_buffer_usage_low_create();
1150 } else {
1151 tmp_condition = lttng_condition_buffer_usage_high_create();
434f8068
JR
1152 }
1153
3780613c
FD
1154 if (!tmp_condition) {
1155 fail("Setup error on condition creation");
1156 ret = -1;
1157 goto error;
434f8068
JR
1158 }
1159
3780613c 1160 /* Set the buffer usage threashold */
434f8068 1161 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
3780613c 1162 tmp_condition, ratio);
434f8068 1163 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
3780613c
FD
1164 fail("Setup error on condition creation");
1165 ret = -1;
1166 goto error;
434f8068
JR
1167 }
1168
3780613c 1169 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
17423302
FD
1170 session_name, channel_name, domain_type);
1171 if (ret) {
3780613c
FD
1172 fail("Setup error on condition creation");
1173 ret = -1;
1174 goto error;
434f8068
JR
1175 }
1176
3780613c
FD
1177 /* Register the trigger for condition. */
1178 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
1179 if (!tmp_trigger) {
1180 fail("Setup error on trigger creation");
1181 ret = -1;
1182 goto error;
434f8068
JR
1183 }
1184
3780613c 1185 ret = lttng_register_trigger(tmp_trigger);
434f8068 1186 if (ret) {
3780613c
FD
1187 fail("Setup error on trigger registration");
1188 ret = -1;
1189 goto error;
434f8068
JR
1190 }
1191
3780613c
FD
1192 *condition = tmp_condition;
1193 *trigger = tmp_trigger;
1194 *action = tmp_action;
1195 goto end;
434f8068 1196
3780613c
FD
1197error:
1198 lttng_action_destroy(tmp_action);
1199 lttng_condition_destroy(tmp_condition);
1200 lttng_trigger_destroy(tmp_trigger);
1201
1202end:
1203 return ret;
1204}
1205
fa448dbe
FD
1206static void test_subscription_twice(const char *session_name,
1207 const char *channel_name,
1208 const enum lttng_domain_type domain_type)
1209{
1210 int ret = 0;
1211 enum lttng_notification_channel_status nc_status;
1212
1213 struct lttng_action *action = NULL;
1214 struct lttng_notification_channel *notification_channel = NULL;
1215 struct lttng_trigger *trigger = NULL;
1216
1217 struct lttng_condition *condition = NULL;
1218
1219 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1220 domain_type, BUFFER_USAGE_TYPE_LOW, 0.99, &condition,
1221 &action, &trigger);
1222 if (ret) {
1223 fail("Setup error on trigger registration");
1224 goto end;
1225 }
1226
1227 /* Begin testing. */
1228 notification_channel = lttng_notification_channel_create(
1229 lttng_session_daemon_notification_endpoint);
1230 ok(notification_channel, "Notification channel object creation");
1231 if (!notification_channel) {
1232 goto end;
1233 }
1234
1235 /* Subscribe a valid condition. */
1236 nc_status = lttng_notification_channel_subscribe(
1237 notification_channel, condition);
1238 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1239 "Subscribe to condition");
1240
1241 /* Subscribing again should fail. */
1242 nc_status = lttng_notification_channel_subscribe(
1243 notification_channel, condition);
1244 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED,
1245 "Subscribe to a condition for which subscription was already done");
1246
1247end:
1248 lttng_unregister_trigger(trigger);
1249 lttng_trigger_destroy(trigger);
1250 lttng_notification_channel_destroy(notification_channel);
1251 lttng_action_destroy(action);
1252 lttng_condition_destroy(condition);
1253}
1254
40ac6709 1255static void test_buffer_usage_notification_channel(const char *session_name,
3780613c
FD
1256 const char *channel_name,
1257 const enum lttng_domain_type domain_type,
1258 const char **argv)
1259{
1260 int ret = 0;
1261 enum lttng_notification_channel_status nc_status;
1262
1263 struct lttng_action *low_action = NULL;
1264 struct lttng_action *high_action = NULL;
1265 struct lttng_notification *notification = NULL;
1266 struct lttng_notification_channel *notification_channel = NULL;
1267 struct lttng_trigger *low_trigger = NULL;
1268 struct lttng_trigger *high_trigger = NULL;
1269
1270 struct lttng_condition *low_condition = NULL;
1271 struct lttng_condition *high_condition = NULL;
1272
1273 const double low_ratio = 0.0;
1274 const double high_ratio = 0.90;
1275
1276 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1277 domain_type, BUFFER_USAGE_TYPE_LOW, low_ratio,
1278 &low_condition, &low_action, &low_trigger);
1279 if (ret) {
1280 fail("Setup error on low trigger registration");
434f8068
JR
1281 goto end;
1282 }
1283
3780613c
FD
1284 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1285 domain_type, BUFFER_USAGE_TYPE_HIGH, high_ratio,
1286 &high_condition, &high_action, &high_trigger);
434f8068
JR
1287 if (ret) {
1288 fail("Setup error on high trigger registration");
1289 goto end;
1290 }
1291
1292 /* Begin testing */
a6ae2480
FD
1293 notification_channel = lttng_notification_channel_create(
1294 lttng_session_daemon_notification_endpoint);
434f8068
JR
1295 ok(notification_channel, "Notification channel object creation");
1296 if (!notification_channel) {
1297 goto end;
1298 }
1299
434f8068 1300 /* Subscribe a valid low condition */
a6ae2480
FD
1301 nc_status = lttng_notification_channel_subscribe(
1302 notification_channel, low_condition);
1303 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 1304 "Subscribe to low condition");
434f8068
JR
1305
1306 /* Subscribe a valid high condition */
a6ae2480
FD
1307 nc_status = lttng_notification_channel_subscribe(
1308 notification_channel, high_condition);
1309 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 1310 "Subscribe to high condition");
434f8068 1311
7676e0d2
FD
1312 resume_application();
1313
434f8068 1314 /* Wait for notification to happen */
434f8068 1315 stop_consumer(argv);
ff2b03c8 1316 lttng_start_tracing(session_name);
434f8068
JR
1317
1318 /* Wait for high notification */
67c93c15 1319 do {
a6ae2480
FD
1320 nc_status = lttng_notification_channel_get_next_notification(
1321 notification_channel, &notification);
67c93c15 1322 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
1323 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
1324 lttng_condition_get_type(lttng_notification_get_condition(
1325 notification)) ==
1326 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1327 "High notification received after intermediary communication");
1328 lttng_notification_destroy(notification);
1329 notification = NULL;
1330
854382b8 1331 suspend_application();
ff2b03c8 1332 lttng_stop_tracing_no_wait(session_name);
434f8068 1333 resume_consumer(argv);
ff2b03c8 1334 wait_data_pending(session_name);
434f8068
JR
1335
1336 /*
1337 * Test that communication still work even if there is notification
1338 * waiting for consumption.
1339 */
1340
a6ae2480
FD
1341 nc_status = lttng_notification_channel_unsubscribe(
1342 notification_channel, low_condition);
1343 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1344 "Unsubscribe with pending notification");
434f8068 1345
a6ae2480
FD
1346 nc_status = lttng_notification_channel_subscribe(
1347 notification_channel, low_condition);
1348 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1349 "Subscribe with pending notification");
434f8068 1350
67c93c15 1351 do {
a6ae2480
FD
1352 nc_status = lttng_notification_channel_get_next_notification(
1353 notification_channel, &notification);
67c93c15 1354 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
1355 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
1356 lttng_condition_get_type(lttng_notification_get_condition(
1357 notification)) ==
1358 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
1359 "Low notification received after intermediary communication");
1360 lttng_notification_destroy(notification);
1361 notification = NULL;
1362
1363 /* Stop consumer to force a high notification */
ff2b03c8 1364 stop_consumer(argv);
854382b8 1365 resume_application();
434f8068 1366 lttng_start_tracing(session_name);
434f8068 1367
67c93c15 1368 do {
a6ae2480
FD
1369 nc_status = lttng_notification_channel_get_next_notification(
1370 notification_channel, &notification);
67c93c15 1371 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1372 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1373 lttng_condition_get_type(lttng_notification_get_condition(
1374 notification)) ==
1375 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1376 "High notification received after intermediary communication");
1377 lttng_notification_destroy(notification);
1378 notification = NULL;
1379
854382b8 1380 suspend_application();
ff2b03c8 1381 lttng_stop_tracing_no_wait(session_name);
434f8068 1382 resume_consumer(argv);
ff2b03c8 1383 wait_data_pending(session_name);
434f8068 1384
67c93c15 1385 do {
a6ae2480
FD
1386 nc_status = lttng_notification_channel_get_next_notification(
1387 notification_channel, &notification);
67c93c15 1388 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1389 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1390 lttng_condition_get_type(lttng_notification_get_condition(
1391 notification)) ==
1392 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
1393 "Low notification received after re-subscription");
1394 lttng_notification_destroy(notification);
1395 notification = NULL;
1396
ff2b03c8 1397 stop_consumer(argv);
854382b8 1398 resume_application();
434f8068
JR
1399 /* Stop consumer to force a high notification */
1400 lttng_start_tracing(session_name);
434f8068 1401
67c93c15 1402 do {
a6ae2480
FD
1403 nc_status = lttng_notification_channel_get_next_notification(
1404 notification_channel, &notification);
67c93c15 1405 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1406 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1407 lttng_condition_get_type(lttng_notification_get_condition(
1408 notification)) ==
1409 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1410 "High notification");
1411 lttng_notification_destroy(notification);
1412 notification = NULL;
1413
ff2b03c8 1414 suspend_application();
7676e0d2
FD
1415
1416 /* Resume consumer to allow event consumption */
ff2b03c8 1417 lttng_stop_tracing_no_wait(session_name);
434f8068 1418 resume_consumer(argv);
ff2b03c8 1419 wait_data_pending(session_name);
434f8068 1420
a6ae2480
FD
1421 nc_status = lttng_notification_channel_unsubscribe(
1422 notification_channel, low_condition);
1423 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1424 "Unsubscribe low condition with pending notification");
1425
1426 nc_status = lttng_notification_channel_unsubscribe(
1427 notification_channel, high_condition);
1428 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1429 "Unsubscribe high condition with pending notification");
434f8068
JR
1430
1431end:
1432 lttng_notification_channel_destroy(notification_channel);
3780613c
FD
1433 lttng_trigger_destroy(low_trigger);
1434 lttng_trigger_destroy(high_trigger);
1435 lttng_action_destroy(low_action);
1436 lttng_action_destroy(high_action);
434f8068 1437 lttng_condition_destroy(low_condition);
eff748d0 1438 lttng_condition_destroy(high_condition);
434f8068
JR
1439}
1440
7948461b
FD
1441static void create_tracepoint_event_rule_trigger(const char *event_pattern,
1442 const char *trigger_name,
1443 const char *filter,
1444 unsigned int exclusion_count,
3e4ee3b3 1445 const char * const *exclusions,
7948461b 1446 enum lttng_domain_type domain_type,
26e2f47b 1447 condition_capture_desc_cb capture_desc_cb,
7948461b
FD
1448 struct lttng_condition **condition,
1449 struct lttng_trigger **trigger)
1450{
1451 enum lttng_event_rule_status event_rule_status;
7948461b
FD
1452 struct lttng_action *tmp_action = NULL;
1453 struct lttng_event_rule *event_rule = NULL;
1454 struct lttng_condition *tmp_condition = NULL;
1455 struct lttng_trigger *tmp_trigger = NULL;
1456 int ret;
a5c2d2a7 1457 enum lttng_error_code ret_code;
7948461b
FD
1458
1459 assert(event_pattern);
1460 assert(trigger_name);
1461 assert(condition);
1462 assert(trigger);
1463
1464 event_rule = lttng_event_rule_tracepoint_create(domain_type);
1465 ok(event_rule, "Tracepoint event rule object creation");
1466
1467 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
1468 event_rule, event_pattern);
1469 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1470 "Setting tracepoint event rule pattern: '%s'",
1471 event_pattern);
1472
1473 if (filter) {
1474 event_rule_status = lttng_event_rule_tracepoint_set_filter(
1475 event_rule, filter);
1476 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1477 "Setting tracepoint event rule filter: '%s'",
1478 filter);
1479 }
1480
1481 if (exclusions) {
1482 int i;
1483 bool success = true;
1484
1485 assert(domain_type == LTTNG_DOMAIN_UST);
1486 assert(exclusion_count > 0);
1487
1488 for (i = 0; i < exclusion_count; i++) {
1489 event_rule_status =
1490 lttng_event_rule_tracepoint_add_exclusion(
1491 event_rule,
1492 exclusions[i]);
1493 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1494 fail("Setting tracepoint event rule exclusion '%s'.",
1495 exclusions[i]);
1496 success = false;
1497 }
1498 }
1499
1500 ok(success, "Setting tracepoint event rule exclusions");
1501 }
1502
8dbb86b8 1503 tmp_condition = lttng_condition_event_rule_matches_create(event_rule);
7948461b
FD
1504 ok(tmp_condition, "Condition event rule object creation");
1505
26e2f47b
JR
1506 if (capture_desc_cb) {
1507 ret = capture_desc_cb(tmp_condition);
1508 if (ret) {
1509 fail("Failed to generate the condition capture descriptor");
1510 abort();
1511 }
1512 }
1513
7948461b
FD
1514 tmp_action = lttng_action_notify_create();
1515 ok(tmp_action, "Action event rule object creation");
1516
1517 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
1518 ok(tmp_trigger, "Trigger object creation %s", trigger_name);
1519
a5c2d2a7
JG
1520 ret_code = lttng_register_trigger_with_name(tmp_trigger, trigger_name);
1521 ok(ret_code == LTTNG_OK, "Trigger registration %s", trigger_name);
7948461b
FD
1522
1523 lttng_event_rule_destroy(event_rule);
1524
1525 *condition = tmp_condition;
1526 *trigger = tmp_trigger;
1527
1528 return;
1529}
1530
d150e7e5 1531static struct lttng_notification *get_next_notification(
7948461b
FD
1532 struct lttng_notification_channel *notification_channel)
1533{
d150e7e5 1534 struct lttng_notification *local_notification = NULL;
7948461b 1535 enum lttng_notification_channel_status status;
7948461b
FD
1536
1537 /* Receive the next notification. */
1538 status = lttng_notification_channel_get_next_notification(
d150e7e5 1539 notification_channel, &local_notification);
7948461b
FD
1540
1541 switch (status) {
1542 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
1543 break;
d150e7e5
JR
1544 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
1545 fail("Notifications have been dropped");
1546 local_notification = NULL;
7948461b
FD
1547 break;
1548 default:
d150e7e5
JR
1549 /* Unhandled conditions / errors. */
1550 fail("Failed to get next notification (unknown notification channel status): status = %d",
1551 (int) status);
1552 local_notification = NULL;
7948461b
FD
1553 break;
1554 }
1555
d150e7e5 1556 return local_notification;
7948461b
FD
1557}
1558
1559static void test_tracepoint_event_rule_notification(
1560 enum lttng_domain_type domain_type)
1561{
1562 int i;
d150e7e5 1563 int ret;
7948461b
FD
1564 const int notification_count = 3;
1565 enum lttng_notification_channel_status nc_status;
1566 struct lttng_action *action = NULL;
1567 struct lttng_condition *condition = NULL;
1568 struct lttng_notification_channel *notification_channel = NULL;
1569 struct lttng_trigger *trigger = NULL;
1570 const char * const trigger_name = "my_precious";
1571 const char *pattern;
1572
1573 if (domain_type == LTTNG_DOMAIN_UST) {
1574 pattern = "tp:tptest";
1575 } else {
1576 pattern = "lttng_test_filter_event";
1577 }
1578
1579 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
26e2f47b 1580 NULL, domain_type, NULL, &condition, &trigger);
7948461b
FD
1581
1582 notification_channel = lttng_notification_channel_create(
1583 lttng_session_daemon_notification_endpoint);
1584 ok(notification_channel, "Notification channel object creation");
1585
1586 nc_status = lttng_notification_channel_subscribe(
1587 notification_channel, condition);
1588 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1589 "Subscribe to tracepoint event rule condition");
1590
1591 resume_application();
1592
d150e7e5 1593 /* Get notifications. */
7948461b 1594 for (i = 0; i < notification_count; i++) {
d150e7e5 1595 struct lttng_notification *notification = get_next_notification(
7948461b
FD
1596 notification_channel);
1597
d150e7e5
JR
1598 ok(notification, "Received notification (%d/%d)", i + 1,
1599 notification_count);
1600
1601 /* Error. */
1602 if (notification == NULL) {
1603 goto end;
1604 }
1605
1606 ret = validator_notification_trigger_name(notification, trigger_name);
1607 lttng_notification_destroy(notification);
1608 if (ret) {
1609 goto end;
1610 }
7948461b
FD
1611 }
1612
d150e7e5 1613end:
7948461b
FD
1614 suspend_application();
1615 lttng_notification_channel_destroy(notification_channel);
1616 lttng_unregister_trigger(trigger);
1617 lttng_trigger_destroy(trigger);
1618 lttng_action_destroy(action);
1619 lttng_condition_destroy(condition);
1620 return;
1621}
1622
a740a242
FD
1623static void test_tracepoint_event_rule_notification_filter(
1624 enum lttng_domain_type domain_type)
1625{
1626 int i;
d150e7e5 1627 const int notification_count = 3;
a740a242 1628 enum lttng_notification_channel_status nc_status;
a740a242
FD
1629 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1630 struct lttng_notification_channel *notification_channel = NULL;
1631 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1632 const char * const ctrl_trigger_name = "control_trigger";
1633 const char * const trigger_name = "trigger";
1634 const char *pattern;
1635 int ctrl_count = 0, count = 0;
1636
1637 if (domain_type == LTTNG_DOMAIN_UST) {
1638 pattern = "tp:tptest";
1639 } else {
1640 pattern = "lttng_test_filter_event";
1641 }
1642
1643 notification_channel = lttng_notification_channel_create(
1644 lttng_session_daemon_notification_endpoint);
1645 ok(notification_channel, "Notification channel object creation");
1646
1647 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
26e2f47b 1648 0, NULL, domain_type, NULL, &ctrl_condition, &ctrl_trigger);
a740a242
FD
1649
1650 nc_status = lttng_notification_channel_subscribe(
1651 notification_channel, ctrl_condition);
1652 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1653 "Subscribe to tracepoint event rule condition");
1654
1655 /*
1656 * Attach a filter expression to get notification only if the
1657 * `intfield` is even.
1658 */
1659 create_tracepoint_event_rule_trigger(pattern, trigger_name,
26e2f47b 1660 "(intfield & 1) == 0", 0, NULL, domain_type, NULL, &condition,
a740a242
FD
1661 &trigger);
1662
1663 nc_status = lttng_notification_channel_subscribe(
1664 notification_channel, condition);
1665 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1666 "Subscribe to tracepoint event rule condition");
1667
1668 /*
1669 * We registered 2 notifications triggers, one with a filter and one
1670 * without (control). The one with a filter will only fired when the
1671 * `intfield` is a multiple of 2. We should get two times as many
1672 * control notifications as filter notifications.
1673 */
1674 resume_application();
1675
1676 /*
1677 * Get 3 notifications. We should get 1 for the regular trigger (with
1678 * the filter) and 2 from the control trigger. This works whatever
1679 * the order we receive the notifications.
1680 */
d150e7e5
JR
1681 for (i = 0; i < notification_count; i++) {
1682 const char *name;
1683 struct lttng_notification *notification = get_next_notification(
a740a242
FD
1684 notification_channel);
1685
d150e7e5
JR
1686 ok(notification, "Received notification (%d/%d)", i + 1,
1687 notification_count);
1688
1689 /* Error. */
1690 if (notification == NULL) {
1691 goto end;
1692 }
1693
1694 name = get_notification_trigger_name(notification);
1695 if (name == NULL) {
1696 lttng_notification_destroy(notification);
1697 goto end;
1698 }
1699
a740a242
FD
1700 if (strcmp(ctrl_trigger_name, name) == 0) {
1701 ctrl_count++;
1702 } else if (strcmp(trigger_name, name) == 0) {
1703 count++;
1704 }
1705
d150e7e5 1706 lttng_notification_destroy(notification);
a740a242
FD
1707 }
1708
1709 ok(ctrl_count / 2 == count,
1710 "Get twice as many control notif as of regular notif");
1711
d150e7e5 1712end:
a740a242
FD
1713 suspend_application();
1714
1715 lttng_unregister_trigger(trigger);
1716 lttng_unregister_trigger(ctrl_trigger);
1717 lttng_notification_channel_destroy(notification_channel);
1718 lttng_trigger_destroy(trigger);
1719 lttng_trigger_destroy(ctrl_trigger);
1720 lttng_condition_destroy(condition);
1721 lttng_condition_destroy(ctrl_condition);
1722}
1723
3e4ee3b3
FD
1724static void test_tracepoint_event_rule_notification_exclusion(
1725 enum lttng_domain_type domain_type)
1726{
1727 enum lttng_notification_channel_status nc_status;
1728 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1729 struct lttng_notification_channel *notification_channel = NULL;
1730 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1731 int ctrl_count = 0, count = 0, i;
d150e7e5 1732 const int notification_count = 6;
3e4ee3b3
FD
1733 const char * const ctrl_trigger_name = "control_exclusion_trigger";
1734 const char * const trigger_name = "exclusion_trigger";
1735 const char * const pattern = "tp:tptest*";
1736 const char * const exclusions[] = {
1737 "tp:tptest2",
1738 "tp:tptest3",
1739 "tp:tptest4",
1740 "tp:tptest5"
1741 };
1742
1743 notification_channel = lttng_notification_channel_create(
1744 lttng_session_daemon_notification_endpoint);
1745 ok(notification_channel, "Notification channel object creation");
1746
1747 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
26e2f47b
JR
1748 0, NULL, domain_type, NULL, &ctrl_condition,
1749 &ctrl_trigger);
3e4ee3b3
FD
1750
1751 nc_status = lttng_notification_channel_subscribe(
1752 notification_channel, ctrl_condition);
1753 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1754 "Subscribe to tracepoint event rule condition");
1755
1756 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 4,
26e2f47b
JR
1757 exclusions, domain_type, NULL, &condition,
1758 &trigger);
3e4ee3b3
FD
1759
1760 nc_status = lttng_notification_channel_subscribe(
1761 notification_channel, condition);
1762 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1763 "Subscribe to tracepoint event rule condition");
1764
1765 /*
1766 * We registered 2 notifications triggers, one with an exclusion and
1767 * one without (control).
1768 * - The trigger with an exclusion will fire once every iteration.
1769 * - The trigger without an exclusion will fire 5 times every
1770 * iteration.
1771 *
1772 * We should get 5 times as many notifications from the control
1773 * trigger.
1774 */
1775 resume_application();
1776
1777 /*
1778 * Get 6 notifications. We should get 1 for the regular trigger (with
1779 * the exclusion) and 5 from the control trigger. This works whatever
1780 * the order we receive the notifications.
1781 */
d150e7e5
JR
1782 for (i = 0; i < notification_count; i++) {
1783 const char *name;
1784 struct lttng_notification *notification = get_next_notification(
3e4ee3b3
FD
1785 notification_channel);
1786
d150e7e5
JR
1787 ok(notification, "Received notification (%d/%d)", i + 1,
1788 notification_count);
1789
1790 /* Error. */
1791 if (notification == NULL) {
1792 goto end;
1793 }
1794
1795 name = get_notification_trigger_name(notification);
1796 if (name == NULL) {
1797 lttng_notification_destroy(notification);
1798 goto end;
1799 }
1800
3e4ee3b3
FD
1801 if (strcmp(ctrl_trigger_name, name) == 0) {
1802 ctrl_count++;
1803 } else if (strcmp(trigger_name, name) == 0) {
1804 count++;
1805 }
1806
d150e7e5 1807 lttng_notification_destroy(notification);
3e4ee3b3
FD
1808 }
1809
1810 ok(ctrl_count / 5 == count,
1811 "Got 5 times as many control notif as of regular notif");
1812
d150e7e5 1813end:
3e4ee3b3
FD
1814 suspend_application();
1815
1816 lttng_unregister_trigger(trigger);
1817 lttng_unregister_trigger(ctrl_trigger);
1818 lttng_notification_channel_destroy(notification_channel);
1819 lttng_trigger_destroy(trigger);
1820 lttng_trigger_destroy(ctrl_trigger);
1821 lttng_condition_destroy(condition);
1822 lttng_condition_destroy(ctrl_condition);
1823 return;
1824}
1825
51704c8e
FD
1826static void test_kprobe_event_rule_notification(
1827 enum lttng_domain_type domain_type)
1828{
1829 int i, ret;
a5c2d2a7 1830 enum lttng_error_code ret_code;
51704c8e
FD
1831 const int notification_count = 3;
1832 enum lttng_notification_channel_status nc_status;
1833 enum lttng_event_rule_status event_rule_status;
51704c8e
FD
1834 struct lttng_notification_channel *notification_channel = NULL;
1835 struct lttng_condition *condition = NULL;
1836 struct lttng_kernel_probe_location *location = NULL;
1837 struct lttng_event_rule *event_rule = NULL;
1838 struct lttng_action *action = NULL;
1839 struct lttng_trigger *trigger = NULL;
1840 const char * const trigger_name = "kprobe_trigger";
1841 const char * const symbol_name = "lttng_test_filter_event_write";
1842
1843 action = lttng_action_notify_create();
1844 if (!action) {
1845 fail("Failed to create notify action");
1846 goto end;
1847 }
1848
1849 location = lttng_kernel_probe_location_symbol_create(symbol_name, 0);
1850 if (!location) {
1851 fail("Failed to create kernel probe location");
1852 goto end;
1853 }
1854
1855 notification_channel = lttng_notification_channel_create(
1856 lttng_session_daemon_notification_endpoint);
1857 ok(notification_channel, "Notification channel object creation");
1858
602a6d40 1859 event_rule = lttng_event_rule_kernel_probe_create(location);
51704c8e
FD
1860 ok(event_rule, "kprobe event rule object creation");
1861
d891bb52 1862 event_rule_status = lttng_event_rule_kernel_probe_set_event_name(
51704c8e
FD
1863 event_rule, trigger_name);
1864 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1865 "Setting kprobe event rule name: '%s'", trigger_name);
1866
8dbb86b8 1867 condition = lttng_condition_event_rule_matches_create(event_rule);
51704c8e
FD
1868 ok(condition, "Condition event rule object creation");
1869
1870 /* Register the trigger for condition. */
1871 trigger = lttng_trigger_create(condition, action);
1872 if (!trigger) {
1873 fail("Failed to create trigger with kernel probe event rule condition and notify action");
1874 goto end;
1875 }
1876
a5c2d2a7
JG
1877 ret_code = lttng_register_trigger_with_name(trigger, trigger_name);
1878 if (ret_code != LTTNG_OK) {
51704c8e
FD
1879 fail("Failed to register trigger with kernel probe event rule condition and notify action");
1880 goto end;
1881 }
1882
1883 nc_status = lttng_notification_channel_subscribe(
1884 notification_channel, condition);
1885 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1886 "Subscribe to tracepoint event rule condition");
1887
1888 resume_application();
1889
1890 for (i = 0; i < notification_count; i++) {
d150e7e5 1891 struct lttng_notification *notification = get_next_notification(
51704c8e
FD
1892 notification_channel);
1893
d150e7e5
JR
1894 ok(notification, "Received notification (%d/%d)", i + 1,
1895 notification_count);
1896
1897 /* Error. */
1898 if (notification == NULL) {
1899 goto end;
1900 }
1901
1902 ret = validator_notification_trigger_name(notification, trigger_name);
1903 lttng_notification_destroy(notification);
1904 if (ret) {
1905 goto end;
1906 }
51704c8e
FD
1907 }
1908
1909end:
1910 suspend_application();
1911 lttng_notification_channel_destroy(notification_channel);
1912 lttng_unregister_trigger(trigger);
1913 lttng_trigger_destroy(trigger);
1914 lttng_action_destroy(action);
aab0598f 1915 lttng_event_rule_destroy(event_rule);
51704c8e
FD
1916 lttng_condition_destroy(condition);
1917 lttng_kernel_probe_location_destroy(location);
1918 return;
1919}
1920
45294d8a
FD
1921static void test_uprobe_event_rule_notification(
1922 enum lttng_domain_type domain_type,
1923 const char *testapp_path,
1924 const char *test_symbol_name)
1925{
1926 int i, ret;
a5c2d2a7 1927 enum lttng_error_code ret_code;
45294d8a
FD
1928 const int notification_count = 3;
1929 enum lttng_notification_channel_status nc_status;
1930 enum lttng_event_rule_status event_rule_status;
45294d8a
FD
1931 struct lttng_notification_channel *notification_channel = NULL;
1932 struct lttng_userspace_probe_location *probe_location = NULL;
1933 struct lttng_userspace_probe_location_lookup_method *lookup_method =
1934 NULL;
1935 struct lttng_condition *condition = NULL;
1936 struct lttng_event_rule *event_rule = NULL;
1937 struct lttng_action *action = NULL;
1938 struct lttng_trigger *trigger = NULL;
1939 const char * const trigger_name = "uprobe_trigger";
1940
1941 action = lttng_action_notify_create();
1942 if (!action) {
1943 fail("Failed to create notify action");
1944 goto end;
1945 }
1946
1947 lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
1948 if (!lookup_method) {
1949 fail("Setup error on userspace probe lookup method creation");
1950 goto end;
1951 }
1952
1953 probe_location = lttng_userspace_probe_location_function_create(
1954 testapp_path, test_symbol_name, lookup_method);
1955 if (!probe_location) {
1956 fail("Failed to create userspace probe location");
1957 goto end;
1958 }
1959
1960 notification_channel = lttng_notification_channel_create(
1961 lttng_session_daemon_notification_endpoint);
1962 ok(notification_channel, "Notification channel object creation");
1963
10685de6 1964 event_rule = lttng_event_rule_userspace_probe_create(probe_location);
45294d8a
FD
1965 ok(event_rule, "kprobe event rule object creation");
1966
405f9e7d 1967 event_rule_status = lttng_event_rule_userspace_probe_set_event_name(
45294d8a
FD
1968 event_rule, trigger_name);
1969 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1970 "Setting uprobe event rule name: '%s'", trigger_name);
1971
8dbb86b8 1972 condition = lttng_condition_event_rule_matches_create(event_rule);
45294d8a
FD
1973 ok(condition, "Condition event rule object creation");
1974
1975 /* Register the trigger for condition. */
1976 trigger = lttng_trigger_create(condition, action);
1977 if (!trigger) {
1978 fail("Failed to create trigger with userspace probe event rule condition and notify action");
1979 goto end;
1980 }
1981
a5c2d2a7
JG
1982 ret_code = lttng_register_trigger_with_name(trigger, trigger_name);
1983 if (ret_code != LTTNG_OK) {
45294d8a
FD
1984 fail("Failed to register trigger with userspace probe event rule condition and notify action");
1985 goto end;
1986 }
1987
1988 nc_status = lttng_notification_channel_subscribe(
1989 notification_channel, condition);
1990 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1991 "Subscribe to tracepoint event rule condition");
1992
1993 resume_application();
1994
d150e7e5
JR
1995 for (i = 0; i < 3; i++) {
1996 struct lttng_notification *notification = get_next_notification(
45294d8a
FD
1997 notification_channel);
1998
d150e7e5
JR
1999 ok(notification, "Received notification (%d/%d)", i + 1,
2000 notification_count);
2001
2002 /* Error. */
2003 if (notification == NULL) {
2004 goto end;
2005 }
2006
2007 ret = validator_notification_trigger_name(notification, trigger_name);
2008 lttng_notification_destroy(notification);
2009 if (ret) {
2010 goto end;
2011 }
45294d8a
FD
2012 }
2013end:
2014 suspend_application();
2015
2016 lttng_notification_channel_destroy(notification_channel);
2017 lttng_unregister_trigger(trigger);
2018 lttng_trigger_destroy(trigger);
2019 lttng_action_destroy(action);
a877d1b5 2020 lttng_userspace_probe_location_destroy(probe_location);
45294d8a
FD
2021 lttng_event_rule_destroy(event_rule);
2022 lttng_condition_destroy(condition);
2023 return;
2024}
2025
aab0598f
FD
2026static void test_syscall_event_rule_notification(
2027 enum lttng_domain_type domain_type)
2028{
2029 int i, ret;
a5c2d2a7 2030 enum lttng_error_code ret_code;
aab0598f
FD
2031 const int notification_count = 3;
2032 enum lttng_notification_channel_status nc_status;
2033 enum lttng_event_rule_status event_rule_status;
aab0598f
FD
2034 struct lttng_notification_channel *notification_channel = NULL;
2035 struct lttng_condition *condition = NULL;
2036 struct lttng_event_rule *event_rule = NULL;
2037 struct lttng_action *action = NULL;
2038 struct lttng_trigger *trigger = NULL;
2039 const char * const trigger_name = "syscall_trigger";
2040 const char * const syscall_name = "openat";
2041
2042 action = lttng_action_notify_create();
2043 if (!action) {
2044 fail("Failed to create notify action");
2045 goto end;
2046 }
2047
2048 notification_channel = lttng_notification_channel_create(
2049 lttng_session_daemon_notification_endpoint);
2050 ok(notification_channel, "Notification channel object creation");
2051
57739a6b 2052 event_rule = lttng_event_rule_syscall_create(LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY);
aab0598f
FD
2053 ok(event_rule, "syscall event rule object creation");
2054
2055 event_rule_status = lttng_event_rule_syscall_set_pattern(
2056 event_rule, syscall_name);
2057 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2058 "Setting syscall event rule pattern: '%s'", syscall_name);
2059
8dbb86b8 2060 condition = lttng_condition_event_rule_matches_create(event_rule);
aab0598f
FD
2061 ok(condition, "Condition syscall event rule object creation");
2062
2063 /* Register the trigger for condition. */
2064 trigger = lttng_trigger_create(condition, action);
2065 if (!trigger) {
2066 fail("Failed to create trigger with syscall event rule condition and notify action");
2067 goto end;
2068 }
2069
a5c2d2a7
JG
2070 ret_code = lttng_register_trigger_with_name(trigger, trigger_name);
2071 if (ret_code != LTTNG_OK) {
aab0598f
FD
2072 fail("Failed to register trigger with syscall event rule condition and notify action");
2073 goto end;
2074 }
2075
2076 nc_status = lttng_notification_channel_subscribe(
2077 notification_channel, condition);
2078 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2079 "Subscribe to tracepoint event rule condition");
2080
2081 resume_application();
2082
2083 for (i = 0; i < notification_count; i++) {
d150e7e5 2084 struct lttng_notification *notification = get_next_notification(
aab0598f
FD
2085 notification_channel);
2086
d150e7e5
JR
2087 ok(notification, "Received notification (%d/%d)", i + 1,
2088 notification_count);
2089
2090 /* Error. */
2091 if (notification == NULL) {
2092 goto end;
2093 }
2094
2095 ret = validator_notification_trigger_name(notification, trigger_name);
2096 lttng_notification_destroy(notification);
2097 if (ret) {
2098 goto end;
2099 }
aab0598f
FD
2100 }
2101end:
2102 suspend_application();
2103 lttng_notification_channel_destroy(notification_channel);
2104 lttng_unregister_trigger(trigger);
2105 lttng_trigger_destroy(trigger);
2106 lttng_action_destroy(action);
2107 lttng_condition_destroy(condition);
2108 return;
2109}
2110
acb98866
FD
2111static void test_syscall_event_rule_notification_filter(
2112 enum lttng_domain_type domain_type)
2113{
2114 int i, ret;
a5c2d2a7 2115 enum lttng_error_code ret_code;
acb98866
FD
2116 const int notification_count = 3;
2117 enum lttng_notification_channel_status nc_status;
2118 enum lttng_event_rule_status event_rule_status;
acb98866
FD
2119 struct lttng_notification_channel *notification_channel = NULL;
2120 struct lttng_condition *condition = NULL;
2121 struct lttng_event_rule *event_rule = NULL;
2122 struct lttng_action *action = NULL;
2123 struct lttng_trigger *trigger = NULL;
2124 const char * const trigger_name = "syscall_trigger";
2125 const char * const syscall_name = "openat";
2126 const char * const filter_pattern = "filename == \"/proc/cpuinfo\"";
2127
2128 action = lttng_action_notify_create();
2129 if (!action) {
2130 fail("Failed to create notify action");
2131 goto end;
2132 }
2133
2134 notification_channel = lttng_notification_channel_create(
2135 lttng_session_daemon_notification_endpoint);
2136 ok(notification_channel, "Notification channel object creation");
2137
57739a6b 2138 event_rule = lttng_event_rule_syscall_create(LTTNG_EVENT_RULE_SYSCALL_EMISSION_SITE_ENTRY);
acb98866
FD
2139 ok(event_rule, "syscall event rule object creation");
2140
2141 event_rule_status = lttng_event_rule_syscall_set_pattern(
2142 event_rule, syscall_name);
2143 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2144 "Setting syscall event rule pattern: '%s'", syscall_name);
2145
2146 event_rule_status = lttng_event_rule_syscall_set_filter(
2147 event_rule, filter_pattern);
2148 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2149 "Setting filter: '%s'", filter_pattern);
2150
8dbb86b8 2151 condition = lttng_condition_event_rule_matches_create(event_rule);
acb98866
FD
2152 ok(condition, "Condition event rule object creation");
2153
2154 /* Register the triggers for condition */
2155 trigger = lttng_trigger_create(condition, action);
2156 if (!trigger) {
2157 fail("Failed to create trigger with syscall filtering event rule condition and notify action");
2158 goto end;
2159 }
2160
a5c2d2a7
JG
2161 ret_code = lttng_register_trigger_with_name(trigger, trigger_name);
2162 if (ret_code != LTTNG_OK) {
acb98866
FD
2163 fail("Failed to register trigger with syscall filtering event rule condition and notify action");
2164 goto end;
2165 }
2166
2167 nc_status = lttng_notification_channel_subscribe(
2168 notification_channel, condition);
2169 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2170 "Subscribe to tracepoint event rule condition");
2171
2172 resume_application();
2173
d150e7e5
JR
2174 for (i = 0; i < notification_count; i++) {
2175 struct lttng_notification *notification = get_next_notification(
acb98866
FD
2176 notification_channel);
2177
d150e7e5
JR
2178 ok(notification, "Received notification (%d/%d)", i + 1,
2179 notification_count);
2180
2181 /* Error. */
2182 if (notification == NULL) {
2183 goto end;
2184 }
2185
2186 ret = validator_notification_trigger_name(notification, trigger_name);
2187 lttng_notification_destroy(notification);
2188 if (ret) {
2189 goto end;
2190 }
acb98866
FD
2191 }
2192
2193end:
2194 suspend_application();
2195
2196 lttng_unregister_trigger(trigger);
2197 lttng_notification_channel_destroy(notification_channel);
2198 lttng_trigger_destroy(trigger);
2199 lttng_event_rule_destroy(event_rule);
2200 lttng_condition_destroy(condition);
2201 return;
2202}
2203
26e2f47b
JR
2204static int generate_capture_descr(struct lttng_condition *condition)
2205{
2206 int ret, i;
2207 struct lttng_event_expr *expr = NULL;
2208 const unsigned int basic_field_count = sizeof(test_capture_base_fields) /
2209 sizeof(*test_capture_base_fields);
2210 enum lttng_condition_status cond_status;
2211
2212 for (i = 0; i < basic_field_count; i++) {
2213 diag("Adding capture descriptor '%s'",
2214 test_capture_base_fields[i].field_name);
2215
2216 switch (test_capture_base_fields[i].field_type) {
2217 case FIELD_TYPE_PAYLOAD:
2218 expr = lttng_event_expr_event_payload_field_create(
2219 test_capture_base_fields[i].field_name);
2220 break;
2221 case FIELD_TYPE_CONTEXT:
2222 expr = lttng_event_expr_channel_context_field_create(
2223 test_capture_base_fields[i].field_name);
2224 break;
2225 case FIELD_TYPE_ARRAY_FIELD:
2226 {
2227 int nb_matches;
2228 unsigned int index;
2229 char field_name[FIELD_NAME_MAX_LEN];
2230 struct lttng_event_expr *array_expr = NULL;
2231
2232 nb_matches = sscanf(test_capture_base_fields[i].field_name,
2233 "%[^[][%u]", field_name, &index);
2234 if (nb_matches != 2) {
2235 fail("Unexpected array field name format: field name = '%s'",
2236 test_capture_base_fields[i].field_name);
2237 ret = 1;
2238 goto end;
2239 }
2240
2241 array_expr = lttng_event_expr_event_payload_field_create(
2242 field_name);
2243
2244 expr = lttng_event_expr_array_field_element_create(
2245 array_expr, index);
2246 break;
2247 }
2248 case FIELD_TYPE_APP_CONTEXT:
2249 fail("Application context tests are not implemented yet.");
2250 /* fallthrough. */
2251 default:
2252 ret = 1;
2253 goto end;
2254 }
2255
2256 if (expr == NULL) {
2257 fail("Failed to create capture expression");
2258 ret = -1;
2259 goto end;
2260 }
2261
8dbb86b8 2262 cond_status = lttng_condition_event_rule_matches_append_capture_descriptor(
26e2f47b
JR
2263 condition, expr);
2264 if (cond_status != LTTNG_CONDITION_STATUS_OK) {
2265 fail("Failed to append capture descriptor");
2266 ret = -1;
2267 lttng_event_expr_destroy(expr);
2268 goto end;
2269 }
2270 }
2271
2272 ret = 0;
2273
2274end:
2275 return ret;
2276}
2277
2278static int validator_notification_trigger_capture(
2279 enum lttng_domain_type domain,
2280 struct lttng_notification *notification,
2281 const int iteration)
2282{
2283 int ret;
2284 unsigned int capture_count, i;
8dbb86b8
JR
2285 enum lttng_evaluation_event_rule_matches_status
2286 event_rule_matches_evaluation_status;
26e2f47b
JR
2287 enum lttng_event_field_value_status event_field_value_status;
2288 const struct lttng_evaluation *evaluation;
2289 const struct lttng_event_field_value *captured_fields;
2290 bool at_least_one_error = false;
2291
2292 evaluation = lttng_notification_get_evaluation(notification);
2293 if (evaluation == NULL) {
2294 fail("Failed to get evaluation from notification during trigger capture test");
2295 ret = 1;
2296 goto end;
2297 }
2298
8dbb86b8
JR
2299 event_rule_matches_evaluation_status =
2300 lttng_evaluation_event_rule_matches_get_captured_values(
3ce811ee 2301 evaluation, &captured_fields);
8dbb86b8
JR
2302 if (event_rule_matches_evaluation_status !=
2303 LTTNG_EVALUATION_EVENT_RULE_MATCHES_STATUS_OK) {
26e2f47b 2304 diag("Failed to get event rule evaluation captured values: status = %d",
8dbb86b8 2305 (int) event_rule_matches_evaluation_status);
26e2f47b
JR
2306 ret = 1;
2307 goto end;
2308 }
2309
2310 event_field_value_status =
2311 lttng_event_field_value_array_get_length(captured_fields,
2312 &capture_count);
2313 if (event_field_value_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
2314 fail("Failed to get count of captured value field array");
2315 ret = 1;
2316 goto end;
2317 }
2318
2319 for (i = 0; i < capture_count; i++) {
2320 const struct lttng_event_field_value *captured_field = NULL;
2321 validate_cb validate;
2322 bool expected;
2323
2324 diag("Validating capture of field '%s'",
2325 test_capture_base_fields[i].field_name);
2326 event_field_value_status =
2327 lttng_event_field_value_array_get_element_at_index(
2328 captured_fields, i,
2329 &captured_field);
2330
2331 switch(domain) {
2332 case LTTNG_DOMAIN_UST:
2333 expected = test_capture_base_fields[i].expected_ust;
2334 break;
2335 case LTTNG_DOMAIN_KERNEL:
2336 expected = test_capture_base_fields[i].expected_kernel;
2337 break;
2338 default:
2339 fail("Unexpected domain encountered: domain = %d",
2340 (int) domain);
2341 ret = 1;
2342 goto end;
2343 }
2344
2345 if (domain == LTTNG_DOMAIN_UST) {
2346 validate = test_capture_base_fields[i].validate_ust;
2347 } else {
2348 validate = test_capture_base_fields[i].validate_kernel;
2349 }
2350
2351 if (!expected) {
2352 ok(event_field_value_status == LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE,
2353 "No payload captured");
2354 continue;
2355 }
2356
2357 if (event_field_value_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
2358 if (event_field_value_status ==
2359 LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE) {
2360 fail("Expected a capture but it is unavailable");
2361 } else {
2362 fail("lttng_event_field_value_array_get_element_at_index returned an error: status = %d",
2363 (int) event_field_value_status);
2364 }
2365
2366 ret = 1;
2367 goto end;
2368 }
2369
2370 diag("Captured field of type %s",
2371 field_value_type_to_str(
2372 lttng_event_field_value_get_type(captured_field)));
2373
2374 assert(validate);
2375 ret = validate(captured_field, iteration);
2376 if (ret) {
2377 at_least_one_error = true;
2378 }
2379 }
2380
2381 ret = at_least_one_error;
2382
2383end:
2384 return ret;
2385}
2386
2387static void test_tracepoint_event_rule_notification_capture(
2388 enum lttng_domain_type domain_type)
2389{
2390 enum lttng_notification_channel_status nc_status;
2391
2392 int i, ret;
2393 struct lttng_condition *condition = NULL;
2394 struct lttng_notification_channel *notification_channel = NULL;
2395 struct lttng_trigger *trigger = NULL;
2396 const char *trigger_name = "my_precious";
2397 const char *pattern;
2398
2399 if (domain_type == LTTNG_DOMAIN_UST) {
2400 pattern = "tp:tptest";
2401 } else {
2402 pattern = "lttng_test_filter_event";
2403 }
2404
2405 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
2406 NULL, domain_type, generate_capture_descr, &condition,
2407 &trigger);
2408
2409 notification_channel = lttng_notification_channel_create(
2410 lttng_session_daemon_notification_endpoint);
2411 ok(notification_channel, "Notification channel object creation");
2412
2413 nc_status = lttng_notification_channel_subscribe(
2414 notification_channel, condition);
2415 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2416 "Subscribe to tracepoint event rule condition");
2417
2418 resume_application();
2419
2420 /* Get 3 notifications */
2421 for (i = 0; i < 3; i++) {
2422 struct lttng_notification *notification = get_next_notification(
2423 notification_channel);
2424 ok(notification, "Received notification");
2425
2426 /* Error */
2427 if (notification == NULL) {
2428 goto end;
2429 }
2430
2431 ret = validator_notification_trigger_name(notification, trigger_name);
2432 if (ret) {
2433 lttng_notification_destroy(notification);
2434 goto end;
2435 }
2436
2437 ret = validator_notification_trigger_capture(domain_type, notification, i);
2438 if (ret) {
2439 lttng_notification_destroy(notification);
2440 goto end;
2441 }
2442
2443 lttng_notification_destroy(notification);
2444 }
2445
2446end:
2447 suspend_application();
2448 lttng_notification_channel_destroy(notification_channel);
2449 lttng_unregister_trigger(trigger);
2450 lttng_trigger_destroy(trigger);
2451 lttng_condition_destroy(condition);
2452 return;
2453}
2454
434f8068
JR
2455int main(int argc, const char *argv[])
2456{
069fc1c5 2457 int test_scenario;
434f8068
JR
2458 const char *domain_type_string = NULL;
2459 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
2460
a740a242
FD
2461 if (argc < 5) {
2462 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
434f8068
JR
2463 goto error;
2464 }
2465
069fc1c5
FD
2466 test_scenario = atoi(argv[1]);
2467 domain_type_string = argv[2];
a740a242
FD
2468 app_pid = (pid_t) atoi(argv[3]);
2469 app_state_file = argv[4];
434f8068
JR
2470
2471 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
2472 domain_type = LTTNG_DOMAIN_UST;
2473 }
2474 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
2475 domain_type = LTTNG_DOMAIN_KERNEL;
2476 }
2477 if (domain_type == LTTNG_DOMAIN_NONE) {
2478 fail("Unknown domain type");
2479 goto error;
2480 }
2481
a740a242
FD
2482 /*
2483 * Test cases are responsible for resuming the app when needed
2484 * and making sure it's suspended when returning.
2485 */
2486 suspend_application();
2487
069fc1c5
FD
2488 switch (test_scenario) {
2489 case 1:
2490 {
a5c2d2a7 2491 plan_tests(41);
7948461b 2492
069fc1c5 2493 /* Test cases that need gen-ust-event testapp. */
a740a242 2494 diag("Test basic notification error paths for %s domain",
069fc1c5
FD
2495 domain_type_string);
2496 test_invalid_channel_subscription(domain_type);
7948461b
FD
2497
2498 diag("Test tracepoint event rule notifications for domain %s",
2499 domain_type_string);
2500 test_tracepoint_event_rule_notification(domain_type);
2501
a740a242
FD
2502 diag("Test tracepoint event rule notifications with filter for domain %s",
2503 domain_type_string);
2504 test_tracepoint_event_rule_notification_filter(domain_type);
069fc1c5
FD
2505 break;
2506 }
2507 case 2:
2508 {
45294d8a 2509 const char *session_name, *channel_name;
d150e7e5 2510
069fc1c5
FD
2511 /* Test cases that need a tracing session enabled. */
2512 plan_tests(99);
7676e0d2 2513
069fc1c5
FD
2514 /*
2515 * Argument 7 and upward are named pipe location for consumerd
2516 * control.
2517 */
2518 named_pipe_args_start = 7;
2519
2520 if (argc < 8) {
2521 fail("Missing parameter for tests to run %d", argc);
2522 goto error;
2523 }
434f8068 2524
069fc1c5
FD
2525 nb_args = argc;
2526
a740a242
FD
2527 session_name = argv[5];
2528 channel_name = argv[6];
069fc1c5
FD
2529
2530 test_subscription_twice(session_name, channel_name,
2531 domain_type);
2532
2533 diag("Test trigger for domain %s with buffer_usage_low condition",
2534 domain_type_string);
2535 test_triggers_buffer_usage_condition(session_name, channel_name,
2536 domain_type,
2537 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
2538
2539 diag("Test trigger for domain %s with buffer_usage_high condition",
2540 domain_type_string);
2541 test_triggers_buffer_usage_condition(session_name, channel_name,
2542 domain_type,
2543 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
2544
2545 diag("Test buffer usage notification channel api for domain %s",
2546 domain_type_string);
2547 test_buffer_usage_notification_channel(session_name, channel_name,
2548 domain_type, argv);
2549 break;
2550 }
3e4ee3b3
FD
2551 case 3:
2552 {
2553 /*
2554 * Test cases that need a test app with more than one event
2555 * type.
2556 */
a5c2d2a7 2557 plan_tests(23);
3e4ee3b3
FD
2558
2559 /*
2560 * At the moment, the only test case of this scenario is
2561 * exclusion which is only supported by UST.
2562 */
2563 assert(domain_type == LTTNG_DOMAIN_UST);
2564 diag("Test tracepoint event rule notifications with exclusion for domain %s",
2565 domain_type_string);
2566 test_tracepoint_event_rule_notification_exclusion(domain_type);
2567
2568 break;
2569 }
51704c8e
FD
2570 case 4:
2571 {
602a6d40 2572 plan_tests(12);
51704c8e
FD
2573 /* Test cases that need the kernel tracer. */
2574 assert(domain_type == LTTNG_DOMAIN_KERNEL);
aab0598f 2575
51704c8e
FD
2576 diag("Test kprobe event rule notifications for domain %s",
2577 domain_type_string);
2578
2579 test_kprobe_event_rule_notification(domain_type);
2580
2581 break;
2582 }
aab0598f
FD
2583 case 5:
2584 {
d150e7e5 2585 plan_tests(25);
aab0598f
FD
2586 /* Test cases that need the kernel tracer. */
2587 assert(domain_type == LTTNG_DOMAIN_KERNEL);
2588
2589 diag("Test syscall event rule notifications for domain %s",
2590 domain_type_string);
2591
2592 test_syscall_event_rule_notification(domain_type);
2593
acb98866
FD
2594 diag("Test syscall filtering event rule notifications for domain %s",
2595 domain_type_string);
2596
2597 test_syscall_event_rule_notification_filter(domain_type);
2598
aab0598f
FD
2599 break;
2600 }
45294d8a
FD
2601 case 6:
2602 {
2603 const char *testapp_path, *test_symbol_name;
2604
10685de6 2605 plan_tests(12);
45294d8a
FD
2606
2607 if (argc < 7) {
2608 fail("Missing parameter for tests to run %d", argc);
2609 goto error;
2610 }
2611
2612 testapp_path = argv[5];
2613 test_symbol_name = argv[6];
2614 /* Test cases that need the kernel tracer. */
2615 assert(domain_type == LTTNG_DOMAIN_KERNEL);
2616
2617 diag("Test userspace-probe event rule notifications for domain %s",
2618 domain_type_string);
2619
2620 test_uprobe_event_rule_notification(
2621 domain_type, testapp_path, test_symbol_name);
2622
2623 break;
2624 }
26e2f47b
JR
2625 case 7:
2626 {
2627 switch(domain_type) {
2628 case LTTNG_DOMAIN_UST:
a5c2d2a7 2629 plan_tests(221);
26e2f47b
JR
2630 break;
2631 case LTTNG_DOMAIN_KERNEL:
2632 plan_tests(216);
2633 break;
2634 default:
2635 assert(0);
2636 }
2637
2638 diag("Test tracepoint event rule notification captures for domain %s",
2639 domain_type_string);
2640 test_tracepoint_event_rule_notification_capture(domain_type);
2641
2642 break;
2643 }
2644
069fc1c5
FD
2645 default:
2646 abort();
2647 }
90fcb2ec 2648
434f8068
JR
2649error:
2650 return exit_status();
2651}
2652
This page took 0.152157 seconds and 4 git commands to generate.