event-rule: userspace probe: rename get/set_name to get/set_event_name
[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{
582 const char *name = NULL;
583 enum lttng_evaluation_status status;
584 const struct lttng_evaluation *evaluation;
585 evaluation = lttng_notification_get_evaluation(notification);
586 if (evaluation == NULL) {
587 fail("lttng_notification_get_evaluation");
588 goto end;
589 }
590
591 switch (lttng_evaluation_get_type(evaluation)) {
d602bd6a 592 case LTTNG_CONDITION_TYPE_ON_EVENT:
d150e7e5 593 {
d602bd6a 594 status = lttng_evaluation_on_event_get_trigger_name(
d150e7e5
JR
595 evaluation, &name);
596 if (status != LTTNG_EVALUATION_STATUS_OK) {
d602bd6a 597 fail("lttng_evaluation_on_event_get_trigger_name");
d150e7e5
JR
598 name = NULL;
599 goto end;
600 }
601 break;
602 }
603 default:
604 fail("Wrong notification evaluation type \n");
605 goto end;
606 }
607end:
608 return name;
609}
610
611static int validator_notification_trigger_name(
612 struct lttng_notification *notification,
613 const char *trigger_name)
614{
615 int ret;
616 bool name_is_equal;
617 const char *name;
618
619 assert(notification);
620 assert(trigger_name);
621
622 name = get_notification_trigger_name(notification);
623 if (name == NULL) {
624 ret = 1;
625 goto end;
626 }
627
628 name_is_equal = (strcmp(trigger_name, name) == 0);
629 ok(name_is_equal, "Expected trigger name: %s got %s", trigger_name,
630 name);
631
632 ret = !name_is_equal;
633
634end:
635 return ret;
636}
637
854382b8
JR
638static
639void wait_on_file(const char *path, bool file_exist)
640{
641 if (!path) {
642 return;
643 }
644 for (;;) {
645 int ret;
646 struct stat buf;
647
648 ret = stat(path, &buf);
649 if (ret == -1 && errno == ENOENT) {
650 if (file_exist) {
f0784451
FD
651 /*
652 * The file does not exist. wait a bit and
653 * continue looping until it does.
654 */
655 (void) poll(NULL, 0, 10);
656 continue;
854382b8 657 }
f0784451
FD
658
659 /*
660 * File does not exist and the exit condition we want.
661 * Break from the loop and return.
662 */
663 break;
854382b8
JR
664 }
665 if (ret) {
666 perror("stat");
667 exit(EXIT_FAILURE);
668 }
f0784451
FD
669 /*
670 * stat() returned 0, so the file exists. break now only if
671 * that's the exit condition we want.
672 */
673 if (file_exist) {
674 break;
675 }
854382b8
JR
676 }
677}
434f8068 678
f12eb9c1 679static
434f8068
JR
680int write_pipe(const char *path, uint8_t data)
681{
682 int ret = 0;
683 int fd = 0;
684
685 fd = open(path, O_WRONLY | O_NONBLOCK);
686 if (fd < 0) {
687 perror("Could not open consumer control named pipe");
688 goto end;
689 }
690
691 ret = write(fd, &data , sizeof(data));
692 if (ret < 1) {
693 perror("Named pipe write failed");
eff748d0
JR
694 if (close(fd)) {
695 perror("Named pipe close failed");
696 }
434f8068
JR
697 ret = -1;
698 goto end;
699 }
700
701 ret = close(fd);
702 if (ret < 0) {
703 perror("Name pipe closing failed");
704 ret = -1;
705 goto end;
706 }
707end:
708 return ret;
709}
710
f12eb9c1 711static
434f8068
JR
712int stop_consumer(const char **argv)
713{
9df6c82a
JG
714 int ret = 0, i;
715
716 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
717 ret = write_pipe(argv[i], 49);
718 }
719 return ret;
720}
721
f12eb9c1 722static
434f8068
JR
723int resume_consumer(const char **argv)
724{
9df6c82a
JG
725 int ret = 0, i;
726
727 for (i = named_pipe_args_start; i < nb_args; i++) {
434f8068
JR
728 ret = write_pipe(argv[i], 0);
729 }
730 return ret;
731}
732
f12eb9c1
SM
733static
734int suspend_application(void)
854382b8
JR
735{
736 int ret;
737 struct stat buf;
738
739 if (!stat(app_state_file, &buf)) {
740 fail("App is already in a suspended state.");
741 ret = -1;
742 goto error;
743 }
744
745 /*
746 * Send SIGUSR1 to application instructing it to bypass tracepoint.
747 */
7344b6a3
FD
748 assert(app_pid > 1);
749
854382b8
JR
750 ret = kill(app_pid, SIGUSR1);
751 if (ret) {
752 fail("SIGUSR1 failed. errno %d", errno);
753 ret = -1;
754 goto error;
755 }
756
757 wait_on_file(app_state_file, true);
758
759error:
760 return ret;
761
762}
763
f12eb9c1 764static
a3ecaea8 765int resume_application(void)
854382b8
JR
766{
767 int ret;
768 struct stat buf;
769
770 ret = stat(app_state_file, &buf);
771 if (ret == -1 && errno == ENOENT) {
772 fail("State file does not exist");
773 goto error;
774 }
775 if (ret) {
776 perror("stat");
777 goto error;
778 }
779
7344b6a3
FD
780 assert(app_pid > 1);
781
854382b8
JR
782 ret = kill(app_pid, SIGUSR1);
783 if (ret) {
784 fail("SIGUSR1 failed. errno %d", errno);
785 ret = -1;
786 goto error;
787 }
788
789 wait_on_file(app_state_file, false);
790
791error:
792 return ret;
793
794}
795
796
f12eb9c1 797static
434f8068
JR
798void test_triggers_buffer_usage_condition(const char *session_name,
799 const char *channel_name,
800 enum lttng_domain_type domain_type,
801 enum lttng_condition_type condition_type)
802{
9df6c82a 803 unsigned int test_vector_size = 5, i;
434f8068
JR
804 enum lttng_condition_status condition_status;
805 struct lttng_action *action;
806
807 /* Set-up */
808 action = lttng_action_notify_create();
809 if (!action) {
810 fail("Setup error on action creation");
811 goto end;
812 }
813
814 /* Test lttng_register_trigger with null value */
815 ok(lttng_register_trigger(NULL) == -LTTNG_ERR_INVALID, "Registering a NULL trigger fails as expected");
816
817 /* Test: register a trigger */
9df6c82a
JG
818
819 for (i = 0; i < pow(2,test_vector_size); i++) {
434f8068
JR
820 int loop_ret = 0;
821 char *test_tuple_string = NULL;
822 unsigned int mask_position = 0;
823 bool session_name_set = false;
824 bool channel_name_set = false;
825 bool threshold_ratio_set = false;
826 bool threshold_byte_set = false;
827 bool domain_type_set = false;
828
829 struct lttng_trigger *trigger = NULL;
830 struct lttng_condition *condition = NULL;
831
832 /* Create base condition */
833 switch (condition_type) {
834 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
835 condition = lttng_condition_buffer_usage_low_create();
836 break;
837 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
838 condition = lttng_condition_buffer_usage_high_create();
839 break;
840 default:
841 loop_ret = 1;
842 goto loop_end;
843 }
844
845 if (!condition) {
846 loop_ret = 1;
847 goto loop_end;
848
849 }
850
851 /* Prepare the condition for trigger registration test */
852
853 /* Set session name */
854 if ((1 << mask_position) & i) {
855 condition_status = lttng_condition_buffer_usage_set_session_name(
856 condition, session_name);
857 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
858 loop_ret = 1;
859 goto loop_end;
860 }
861 session_name_set = true;
862 }
863 mask_position++;
864
865 /* Set channel name */
866 if ((1 << mask_position) & i) {
867 condition_status = lttng_condition_buffer_usage_set_channel_name(
868 condition, channel_name);
869 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
870 loop_ret = 1;
871 goto loop_end;
872 }
873 channel_name_set = true;
874 }
875 mask_position++;
876
877 /* Set threshold ratio */
878 if ((1 << mask_position) & i) {
879 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
880 condition, 0.0);
881 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
882 loop_ret = 1;
883 goto loop_end;
884 }
885 threshold_ratio_set = true;
886 }
887 mask_position++;
888
889 /* Set threshold byte */
890 if ((1 << mask_position) & i) {
891 condition_status = lttng_condition_buffer_usage_set_threshold(
892 condition, 0);
893 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
894 loop_ret = 1;
895 goto loop_end;
896 }
897 threshold_byte_set = true;
898 }
899 mask_position++;
900
901 /* Set domain type */
902 if ((1 << mask_position) & i) {
903 condition_status = lttng_condition_buffer_usage_set_domain_type(
904 condition, LTTNG_DOMAIN_UST);
905 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
906 loop_ret = 1;
907 goto loop_end;
908 }
909 domain_type_set = true;
910 }
911
912 /* Safety check */
913 if (mask_position != test_vector_size -1) {
914 assert("Logic error for test vector generation");
915 }
916
9479b7a7 917 loop_ret = asprintf(&test_tuple_string, "session name %s, channel name %s, threshold ratio %s, threshold byte %s, domain type %s",
434f8068
JR
918 session_name_set ? "set" : "unset",
919 channel_name_set ? "set" : "unset",
920 threshold_ratio_set ? "set" : "unset",
921 threshold_byte_set ? "set" : "unset",
922 domain_type_set? "set" : "unset");
923 if (!test_tuple_string || loop_ret < 0) {
924 loop_ret = 1;
925 goto loop_end;
926 }
927
928 /* Create trigger */
929 trigger = lttng_trigger_create(condition, action);
930 if (!trigger) {
931 loop_ret = 1;
932 goto loop_end;
933 }
934
935 loop_ret = lttng_register_trigger(trigger);
936
937loop_end:
938 if (loop_ret == 1) {
939 fail("Setup error occurred for tuple: %s", test_tuple_string);
940 goto loop_cleanup;
941 }
942
943 /* This combination happens three times */
944 if (session_name_set && channel_name_set
945 && (threshold_ratio_set || threshold_byte_set)
946 && domain_type_set) {
947 ok(loop_ret == 0, "Trigger is registered: %s", test_tuple_string);
948
949 /*
950 * Test that a trigger cannot be registered
951 * multiple time.
952 */
953 loop_ret = lttng_register_trigger(trigger);
954 ok(loop_ret == -LTTNG_ERR_TRIGGER_EXISTS, "Re-register trigger fails as expected: %s", test_tuple_string);
955
956 /* Test that a trigger can be unregistered */
957 loop_ret = lttng_unregister_trigger(trigger);
958 ok(loop_ret == 0, "Unregister trigger: %s", test_tuple_string);
959
960 /*
961 * Test that unregistration of a non-previously
962 * registered trigger fail.
963 */
964 loop_ret = lttng_unregister_trigger(trigger);
43e0c204 965 ok(loop_ret == -LTTNG_ERR_TRIGGER_NOT_FOUND, "Unregister of a non-registered trigger fails as expected: %s", test_tuple_string);
434f8068
JR
966 } else {
967 ok(loop_ret == -LTTNG_ERR_INVALID_TRIGGER, "Trigger is invalid as expected and cannot be registered: %s", test_tuple_string);
968 }
969
970loop_cleanup:
971 free(test_tuple_string);
972 lttng_trigger_destroy(trigger);
973 lttng_condition_destroy(condition);
974 }
975
976end:
977 lttng_action_destroy(action);
978}
979
ff2b03c8
JG
980static
981void wait_data_pending(const char *session_name)
982{
983 int ret;
984
985 do {
986 ret = lttng_data_pending(session_name);
987 assert(ret >= 0);
988 } while (ret != 0);
989}
990
f12eb9c1 991static
17423302
FD
992int setup_buffer_usage_condition(struct lttng_condition *condition,
993 const char *condition_name,
994 const char *session_name,
995 const char *channel_name,
996 const enum lttng_domain_type domain_type)
997{
998 enum lttng_condition_status condition_status;
999 int ret = 0;
1000
1001 condition_status = lttng_condition_buffer_usage_set_session_name(
1002 condition, session_name);
1003 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1004 fail("Failed to set session name on creation of condition `%s`",
1005 condition_name);
1006 ret = -1;
1007 goto end;
1008 }
1009
1010 condition_status = lttng_condition_buffer_usage_set_channel_name(
1011 condition, channel_name);
1012 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1013 fail("Failed to set channel name on creation of condition `%s`",
1014 condition_name);
1015 ret = -1;
1016 goto end;
1017 }
1018
1019 condition_status = lttng_condition_buffer_usage_set_domain_type(
1020 condition, domain_type);
1021 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1022 fail("Failed to set domain type on creation of condition `%s`",
1023 condition_name);
1024 ret = -1;
1025 goto end;
1026 }
1027
1028end:
1029 return ret;
1030}
1031
1032static
90fcb2ec
FD
1033void test_invalid_channel_subscription(
1034 const enum lttng_domain_type domain_type)
434f8068 1035{
434f8068
JR
1036 enum lttng_condition_status condition_status;
1037 enum lttng_notification_channel_status nc_status;
434f8068 1038 struct lttng_condition *dummy_condition = NULL;
90fcb2ec
FD
1039 struct lttng_condition *dummy_invalid_condition = NULL;
1040 struct lttng_notification_channel *notification_channel = NULL;
1041 int ret = 0;
434f8068 1042
90fcb2ec
FD
1043 notification_channel = lttng_notification_channel_create(
1044 lttng_session_daemon_notification_endpoint);
1045 ok(notification_channel, "Notification channel object creation");
1046 if (!notification_channel) {
434f8068
JR
1047 goto end;
1048 }
1049
90fcb2ec
FD
1050 /*
1051 * Create a dummy, empty (thus invalid) condition to test error paths.
1052 */
434f8068
JR
1053 dummy_invalid_condition = lttng_condition_buffer_usage_low_create();
1054 if (!dummy_invalid_condition) {
1055 fail("Setup error on condition creation");
1056 goto end;
1057 }
1058
90fcb2ec
FD
1059 /*
1060 * Test subscription and unsubscription of an invalid condition to/from
1061 * a channel.
1062 */
1063 nc_status = lttng_notification_channel_subscribe(
1064 notification_channel, dummy_invalid_condition);
1065 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1066 "Subscribing to an invalid condition");
1067
1068 nc_status = lttng_notification_channel_unsubscribe(
1069 notification_channel, dummy_invalid_condition);
1070 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1071 "Unsubscribing from an invalid condition");
1072
434f8068
JR
1073 /* Create a valid dummy condition with a ratio of 0.5 */
1074 dummy_condition = lttng_condition_buffer_usage_low_create();
1075 if (!dummy_condition) {
1076 fail("Setup error on dummy_condition creation");
1077 goto end;
434f8068 1078 }
90fcb2ec 1079
434f8068
JR
1080 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
1081 dummy_condition, 0.5);
1082 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1083 fail("Setup error on condition creation");
1084 goto end;
1085 }
1086
17423302 1087 ret = setup_buffer_usage_condition(dummy_condition, "dummy_condition",
90fcb2ec 1088 "dummy_session", "dummy_channel", domain_type);
17423302
FD
1089 if (ret) {
1090 fail("Setup error on dummy condition creation");
434f8068
JR
1091 goto end;
1092 }
1093
90fcb2ec
FD
1094 /*
1095 * Test subscription and unsubscription to/from a channel with invalid
1096 * parameters.
1097 */
1098 nc_status = lttng_notification_channel_subscribe(NULL, NULL);
1099 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1100 "Notification channel subscription is invalid: NULL, NULL");
1101
1102 nc_status = lttng_notification_channel_subscribe(
1103 notification_channel, NULL);
1104 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1105 "Notification channel subscription is invalid: NON-NULL, NULL");
1106
1107 nc_status = lttng_notification_channel_subscribe(NULL, dummy_condition);
1108 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID,
1109 "Notification channel subscription is invalid: NULL, NON-NULL");
1110
1111 nc_status = lttng_notification_channel_unsubscribe(
1112 notification_channel, dummy_condition);
1113 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION,
1114 "Unsubscribing from a valid unknown condition");
1115
1116end:
1117 lttng_notification_channel_destroy(notification_channel);
1118 lttng_condition_destroy(dummy_invalid_condition);
1119 lttng_condition_destroy(dummy_condition);
1120 return;
1121}
1122
3780613c
FD
1123enum buffer_usage_type {
1124 BUFFER_USAGE_TYPE_LOW,
1125 BUFFER_USAGE_TYPE_HIGH,
1126};
1127
1128static int register_buffer_usage_notify_trigger(const char *session_name,
90fcb2ec
FD
1129 const char *channel_name,
1130 const enum lttng_domain_type domain_type,
3780613c
FD
1131 enum buffer_usage_type buffer_usage_type,
1132 double ratio,
1133 struct lttng_condition **condition,
1134 struct lttng_action **action,
1135 struct lttng_trigger **trigger)
90fcb2ec 1136{
90fcb2ec 1137 enum lttng_condition_status condition_status;
3780613c
FD
1138 struct lttng_action *tmp_action = NULL;
1139 struct lttng_condition *tmp_condition = NULL;
1140 struct lttng_trigger *tmp_trigger = NULL;
1141 int ret = 0;
90fcb2ec
FD
1142
1143 /* Set-up */
3780613c 1144 tmp_action = lttng_action_notify_create();
90fcb2ec
FD
1145 if (!action) {
1146 fail("Setup error on action creation");
3780613c
FD
1147 ret = -1;
1148 goto error;
434f8068
JR
1149 }
1150
3780613c
FD
1151 if (buffer_usage_type == BUFFER_USAGE_TYPE_LOW) {
1152 tmp_condition = lttng_condition_buffer_usage_low_create();
1153 } else {
1154 tmp_condition = lttng_condition_buffer_usage_high_create();
434f8068
JR
1155 }
1156
3780613c
FD
1157 if (!tmp_condition) {
1158 fail("Setup error on condition creation");
1159 ret = -1;
1160 goto error;
434f8068
JR
1161 }
1162
3780613c 1163 /* Set the buffer usage threashold */
434f8068 1164 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
3780613c 1165 tmp_condition, ratio);
434f8068 1166 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
3780613c
FD
1167 fail("Setup error on condition creation");
1168 ret = -1;
1169 goto error;
434f8068
JR
1170 }
1171
3780613c 1172 ret = setup_buffer_usage_condition(tmp_condition, "condition_name",
17423302
FD
1173 session_name, channel_name, domain_type);
1174 if (ret) {
3780613c
FD
1175 fail("Setup error on condition creation");
1176 ret = -1;
1177 goto error;
434f8068
JR
1178 }
1179
3780613c
FD
1180 /* Register the trigger for condition. */
1181 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
1182 if (!tmp_trigger) {
1183 fail("Setup error on trigger creation");
1184 ret = -1;
1185 goto error;
434f8068
JR
1186 }
1187
3780613c 1188 ret = lttng_register_trigger(tmp_trigger);
434f8068 1189 if (ret) {
3780613c
FD
1190 fail("Setup error on trigger registration");
1191 ret = -1;
1192 goto error;
434f8068
JR
1193 }
1194
3780613c
FD
1195 *condition = tmp_condition;
1196 *trigger = tmp_trigger;
1197 *action = tmp_action;
1198 goto end;
434f8068 1199
3780613c
FD
1200error:
1201 lttng_action_destroy(tmp_action);
1202 lttng_condition_destroy(tmp_condition);
1203 lttng_trigger_destroy(tmp_trigger);
1204
1205end:
1206 return ret;
1207}
1208
fa448dbe
FD
1209static void test_subscription_twice(const char *session_name,
1210 const char *channel_name,
1211 const enum lttng_domain_type domain_type)
1212{
1213 int ret = 0;
1214 enum lttng_notification_channel_status nc_status;
1215
1216 struct lttng_action *action = NULL;
1217 struct lttng_notification_channel *notification_channel = NULL;
1218 struct lttng_trigger *trigger = NULL;
1219
1220 struct lttng_condition *condition = NULL;
1221
1222 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1223 domain_type, BUFFER_USAGE_TYPE_LOW, 0.99, &condition,
1224 &action, &trigger);
1225 if (ret) {
1226 fail("Setup error on trigger registration");
1227 goto end;
1228 }
1229
1230 /* Begin testing. */
1231 notification_channel = lttng_notification_channel_create(
1232 lttng_session_daemon_notification_endpoint);
1233 ok(notification_channel, "Notification channel object creation");
1234 if (!notification_channel) {
1235 goto end;
1236 }
1237
1238 /* Subscribe a valid condition. */
1239 nc_status = lttng_notification_channel_subscribe(
1240 notification_channel, condition);
1241 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1242 "Subscribe to condition");
1243
1244 /* Subscribing again should fail. */
1245 nc_status = lttng_notification_channel_subscribe(
1246 notification_channel, condition);
1247 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED,
1248 "Subscribe to a condition for which subscription was already done");
1249
1250end:
1251 lttng_unregister_trigger(trigger);
1252 lttng_trigger_destroy(trigger);
1253 lttng_notification_channel_destroy(notification_channel);
1254 lttng_action_destroy(action);
1255 lttng_condition_destroy(condition);
1256}
1257
40ac6709 1258static void test_buffer_usage_notification_channel(const char *session_name,
3780613c
FD
1259 const char *channel_name,
1260 const enum lttng_domain_type domain_type,
1261 const char **argv)
1262{
1263 int ret = 0;
1264 enum lttng_notification_channel_status nc_status;
1265
1266 struct lttng_action *low_action = NULL;
1267 struct lttng_action *high_action = NULL;
1268 struct lttng_notification *notification = NULL;
1269 struct lttng_notification_channel *notification_channel = NULL;
1270 struct lttng_trigger *low_trigger = NULL;
1271 struct lttng_trigger *high_trigger = NULL;
1272
1273 struct lttng_condition *low_condition = NULL;
1274 struct lttng_condition *high_condition = NULL;
1275
1276 const double low_ratio = 0.0;
1277 const double high_ratio = 0.90;
1278
1279 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1280 domain_type, BUFFER_USAGE_TYPE_LOW, low_ratio,
1281 &low_condition, &low_action, &low_trigger);
1282 if (ret) {
1283 fail("Setup error on low trigger registration");
434f8068
JR
1284 goto end;
1285 }
1286
3780613c
FD
1287 ret = register_buffer_usage_notify_trigger(session_name, channel_name,
1288 domain_type, BUFFER_USAGE_TYPE_HIGH, high_ratio,
1289 &high_condition, &high_action, &high_trigger);
434f8068
JR
1290 if (ret) {
1291 fail("Setup error on high trigger registration");
1292 goto end;
1293 }
1294
1295 /* Begin testing */
a6ae2480
FD
1296 notification_channel = lttng_notification_channel_create(
1297 lttng_session_daemon_notification_endpoint);
434f8068
JR
1298 ok(notification_channel, "Notification channel object creation");
1299 if (!notification_channel) {
1300 goto end;
1301 }
1302
434f8068 1303 /* Subscribe a valid low condition */
a6ae2480
FD
1304 nc_status = lttng_notification_channel_subscribe(
1305 notification_channel, low_condition);
1306 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 1307 "Subscribe to low condition");
434f8068
JR
1308
1309 /* Subscribe a valid high condition */
a6ae2480
FD
1310 nc_status = lttng_notification_channel_subscribe(
1311 notification_channel, high_condition);
1312 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
40ac6709 1313 "Subscribe to high condition");
434f8068 1314
7676e0d2
FD
1315 resume_application();
1316
434f8068 1317 /* Wait for notification to happen */
434f8068 1318 stop_consumer(argv);
ff2b03c8 1319 lttng_start_tracing(session_name);
434f8068
JR
1320
1321 /* Wait for high notification */
67c93c15 1322 do {
a6ae2480
FD
1323 nc_status = lttng_notification_channel_get_next_notification(
1324 notification_channel, &notification);
67c93c15 1325 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
1326 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
1327 lttng_condition_get_type(lttng_notification_get_condition(
1328 notification)) ==
1329 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1330 "High notification received after intermediary communication");
1331 lttng_notification_destroy(notification);
1332 notification = NULL;
1333
854382b8 1334 suspend_application();
ff2b03c8 1335 lttng_stop_tracing_no_wait(session_name);
434f8068 1336 resume_consumer(argv);
ff2b03c8 1337 wait_data_pending(session_name);
434f8068
JR
1338
1339 /*
1340 * Test that communication still work even if there is notification
1341 * waiting for consumption.
1342 */
1343
a6ae2480
FD
1344 nc_status = lttng_notification_channel_unsubscribe(
1345 notification_channel, low_condition);
1346 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1347 "Unsubscribe with pending notification");
434f8068 1348
a6ae2480
FD
1349 nc_status = lttng_notification_channel_subscribe(
1350 notification_channel, low_condition);
1351 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1352 "Subscribe with pending notification");
434f8068 1353
67c93c15 1354 do {
a6ae2480
FD
1355 nc_status = lttng_notification_channel_get_next_notification(
1356 notification_channel, &notification);
67c93c15 1357 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
a6ae2480
FD
1358 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
1359 lttng_condition_get_type(lttng_notification_get_condition(
1360 notification)) ==
1361 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
1362 "Low notification received after intermediary communication");
1363 lttng_notification_destroy(notification);
1364 notification = NULL;
1365
1366 /* Stop consumer to force a high notification */
ff2b03c8 1367 stop_consumer(argv);
854382b8 1368 resume_application();
434f8068 1369 lttng_start_tracing(session_name);
434f8068 1370
67c93c15 1371 do {
a6ae2480
FD
1372 nc_status = lttng_notification_channel_get_next_notification(
1373 notification_channel, &notification);
67c93c15 1374 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1375 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1376 lttng_condition_get_type(lttng_notification_get_condition(
1377 notification)) ==
1378 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1379 "High notification received after intermediary communication");
1380 lttng_notification_destroy(notification);
1381 notification = NULL;
1382
854382b8 1383 suspend_application();
ff2b03c8 1384 lttng_stop_tracing_no_wait(session_name);
434f8068 1385 resume_consumer(argv);
ff2b03c8 1386 wait_data_pending(session_name);
434f8068 1387
67c93c15 1388 do {
a6ae2480
FD
1389 nc_status = lttng_notification_channel_get_next_notification(
1390 notification_channel, &notification);
67c93c15 1391 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1392 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1393 lttng_condition_get_type(lttng_notification_get_condition(
1394 notification)) ==
1395 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW,
434f8068
JR
1396 "Low notification received after re-subscription");
1397 lttng_notification_destroy(notification);
1398 notification = NULL;
1399
ff2b03c8 1400 stop_consumer(argv);
854382b8 1401 resume_application();
434f8068
JR
1402 /* Stop consumer to force a high notification */
1403 lttng_start_tracing(session_name);
434f8068 1404
67c93c15 1405 do {
a6ae2480
FD
1406 nc_status = lttng_notification_channel_get_next_notification(
1407 notification_channel, &notification);
67c93c15 1408 } while (nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED);
434f8068 1409 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification &&
a6ae2480
FD
1410 lttng_condition_get_type(lttng_notification_get_condition(
1411 notification)) ==
1412 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH,
434f8068
JR
1413 "High notification");
1414 lttng_notification_destroy(notification);
1415 notification = NULL;
1416
ff2b03c8 1417 suspend_application();
7676e0d2
FD
1418
1419 /* Resume consumer to allow event consumption */
ff2b03c8 1420 lttng_stop_tracing_no_wait(session_name);
434f8068 1421 resume_consumer(argv);
ff2b03c8 1422 wait_data_pending(session_name);
434f8068 1423
a6ae2480
FD
1424 nc_status = lttng_notification_channel_unsubscribe(
1425 notification_channel, low_condition);
1426 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1427 "Unsubscribe low condition with pending notification");
1428
1429 nc_status = lttng_notification_channel_unsubscribe(
1430 notification_channel, high_condition);
1431 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1432 "Unsubscribe high condition with pending notification");
434f8068
JR
1433
1434end:
1435 lttng_notification_channel_destroy(notification_channel);
3780613c
FD
1436 lttng_trigger_destroy(low_trigger);
1437 lttng_trigger_destroy(high_trigger);
1438 lttng_action_destroy(low_action);
1439 lttng_action_destroy(high_action);
434f8068 1440 lttng_condition_destroy(low_condition);
eff748d0 1441 lttng_condition_destroy(high_condition);
434f8068
JR
1442}
1443
7948461b
FD
1444static void create_tracepoint_event_rule_trigger(const char *event_pattern,
1445 const char *trigger_name,
1446 const char *filter,
1447 unsigned int exclusion_count,
3e4ee3b3 1448 const char * const *exclusions,
7948461b 1449 enum lttng_domain_type domain_type,
26e2f47b 1450 condition_capture_desc_cb capture_desc_cb,
7948461b
FD
1451 struct lttng_condition **condition,
1452 struct lttng_trigger **trigger)
1453{
1454 enum lttng_event_rule_status event_rule_status;
1455 enum lttng_trigger_status trigger_status;
1456
1457 struct lttng_action *tmp_action = NULL;
1458 struct lttng_event_rule *event_rule = NULL;
1459 struct lttng_condition *tmp_condition = NULL;
1460 struct lttng_trigger *tmp_trigger = NULL;
1461 int ret;
1462
1463 assert(event_pattern);
1464 assert(trigger_name);
1465 assert(condition);
1466 assert(trigger);
1467
1468 event_rule = lttng_event_rule_tracepoint_create(domain_type);
1469 ok(event_rule, "Tracepoint event rule object creation");
1470
1471 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
1472 event_rule, event_pattern);
1473 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1474 "Setting tracepoint event rule pattern: '%s'",
1475 event_pattern);
1476
1477 if (filter) {
1478 event_rule_status = lttng_event_rule_tracepoint_set_filter(
1479 event_rule, filter);
1480 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1481 "Setting tracepoint event rule filter: '%s'",
1482 filter);
1483 }
1484
1485 if (exclusions) {
1486 int i;
1487 bool success = true;
1488
1489 assert(domain_type == LTTNG_DOMAIN_UST);
1490 assert(exclusion_count > 0);
1491
1492 for (i = 0; i < exclusion_count; i++) {
1493 event_rule_status =
1494 lttng_event_rule_tracepoint_add_exclusion(
1495 event_rule,
1496 exclusions[i]);
1497 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1498 fail("Setting tracepoint event rule exclusion '%s'.",
1499 exclusions[i]);
1500 success = false;
1501 }
1502 }
1503
1504 ok(success, "Setting tracepoint event rule exclusions");
1505 }
1506
d602bd6a 1507 tmp_condition = lttng_condition_on_event_create(event_rule);
7948461b
FD
1508 ok(tmp_condition, "Condition event rule object creation");
1509
26e2f47b
JR
1510 if (capture_desc_cb) {
1511 ret = capture_desc_cb(tmp_condition);
1512 if (ret) {
1513 fail("Failed to generate the condition capture descriptor");
1514 abort();
1515 }
1516 }
1517
7948461b
FD
1518 tmp_action = lttng_action_notify_create();
1519 ok(tmp_action, "Action event rule object creation");
1520
1521 tmp_trigger = lttng_trigger_create(tmp_condition, tmp_action);
1522 ok(tmp_trigger, "Trigger object creation %s", trigger_name);
1523
1524 trigger_status = lttng_trigger_set_name(tmp_trigger, trigger_name);
1525 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1526 "Setting name to trigger %s", trigger_name);
1527
1528 ret = lttng_register_trigger(tmp_trigger);
1529 ok(ret == 0, "Trigger registration %s", trigger_name);
1530
1531 lttng_event_rule_destroy(event_rule);
1532
1533 *condition = tmp_condition;
1534 *trigger = tmp_trigger;
1535
1536 return;
1537}
1538
d150e7e5 1539static struct lttng_notification *get_next_notification(
7948461b
FD
1540 struct lttng_notification_channel *notification_channel)
1541{
d150e7e5 1542 struct lttng_notification *local_notification = NULL;
7948461b 1543 enum lttng_notification_channel_status status;
7948461b
FD
1544
1545 /* Receive the next notification. */
1546 status = lttng_notification_channel_get_next_notification(
d150e7e5 1547 notification_channel, &local_notification);
7948461b
FD
1548
1549 switch (status) {
1550 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
1551 break;
d150e7e5
JR
1552 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
1553 fail("Notifications have been dropped");
1554 local_notification = NULL;
7948461b
FD
1555 break;
1556 default:
d150e7e5
JR
1557 /* Unhandled conditions / errors. */
1558 fail("Failed to get next notification (unknown notification channel status): status = %d",
1559 (int) status);
1560 local_notification = NULL;
7948461b
FD
1561 break;
1562 }
1563
d150e7e5 1564 return local_notification;
7948461b
FD
1565}
1566
1567static void test_tracepoint_event_rule_notification(
1568 enum lttng_domain_type domain_type)
1569{
1570 int i;
d150e7e5 1571 int ret;
7948461b
FD
1572 const int notification_count = 3;
1573 enum lttng_notification_channel_status nc_status;
1574 struct lttng_action *action = NULL;
1575 struct lttng_condition *condition = NULL;
1576 struct lttng_notification_channel *notification_channel = NULL;
1577 struct lttng_trigger *trigger = NULL;
1578 const char * const trigger_name = "my_precious";
1579 const char *pattern;
1580
1581 if (domain_type == LTTNG_DOMAIN_UST) {
1582 pattern = "tp:tptest";
1583 } else {
1584 pattern = "lttng_test_filter_event";
1585 }
1586
1587 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
26e2f47b 1588 NULL, domain_type, NULL, &condition, &trigger);
7948461b
FD
1589
1590 notification_channel = lttng_notification_channel_create(
1591 lttng_session_daemon_notification_endpoint);
1592 ok(notification_channel, "Notification channel object creation");
1593
1594 nc_status = lttng_notification_channel_subscribe(
1595 notification_channel, condition);
1596 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1597 "Subscribe to tracepoint event rule condition");
1598
1599 resume_application();
1600
d150e7e5 1601 /* Get notifications. */
7948461b 1602 for (i = 0; i < notification_count; i++) {
d150e7e5 1603 struct lttng_notification *notification = get_next_notification(
7948461b
FD
1604 notification_channel);
1605
d150e7e5
JR
1606 ok(notification, "Received notification (%d/%d)", i + 1,
1607 notification_count);
1608
1609 /* Error. */
1610 if (notification == NULL) {
1611 goto end;
1612 }
1613
1614 ret = validator_notification_trigger_name(notification, trigger_name);
1615 lttng_notification_destroy(notification);
1616 if (ret) {
1617 goto end;
1618 }
7948461b
FD
1619 }
1620
d150e7e5 1621end:
7948461b
FD
1622 suspend_application();
1623 lttng_notification_channel_destroy(notification_channel);
1624 lttng_unregister_trigger(trigger);
1625 lttng_trigger_destroy(trigger);
1626 lttng_action_destroy(action);
1627 lttng_condition_destroy(condition);
1628 return;
1629}
1630
a740a242
FD
1631static void test_tracepoint_event_rule_notification_filter(
1632 enum lttng_domain_type domain_type)
1633{
1634 int i;
d150e7e5 1635 const int notification_count = 3;
a740a242 1636 enum lttng_notification_channel_status nc_status;
a740a242
FD
1637 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1638 struct lttng_notification_channel *notification_channel = NULL;
1639 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1640 const char * const ctrl_trigger_name = "control_trigger";
1641 const char * const trigger_name = "trigger";
1642 const char *pattern;
1643 int ctrl_count = 0, count = 0;
1644
1645 if (domain_type == LTTNG_DOMAIN_UST) {
1646 pattern = "tp:tptest";
1647 } else {
1648 pattern = "lttng_test_filter_event";
1649 }
1650
1651 notification_channel = lttng_notification_channel_create(
1652 lttng_session_daemon_notification_endpoint);
1653 ok(notification_channel, "Notification channel object creation");
1654
1655 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
26e2f47b 1656 0, NULL, domain_type, NULL, &ctrl_condition, &ctrl_trigger);
a740a242
FD
1657
1658 nc_status = lttng_notification_channel_subscribe(
1659 notification_channel, ctrl_condition);
1660 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1661 "Subscribe to tracepoint event rule condition");
1662
1663 /*
1664 * Attach a filter expression to get notification only if the
1665 * `intfield` is even.
1666 */
1667 create_tracepoint_event_rule_trigger(pattern, trigger_name,
26e2f47b 1668 "(intfield & 1) == 0", 0, NULL, domain_type, NULL, &condition,
a740a242
FD
1669 &trigger);
1670
1671 nc_status = lttng_notification_channel_subscribe(
1672 notification_channel, condition);
1673 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1674 "Subscribe to tracepoint event rule condition");
1675
1676 /*
1677 * We registered 2 notifications triggers, one with a filter and one
1678 * without (control). The one with a filter will only fired when the
1679 * `intfield` is a multiple of 2. We should get two times as many
1680 * control notifications as filter notifications.
1681 */
1682 resume_application();
1683
1684 /*
1685 * Get 3 notifications. We should get 1 for the regular trigger (with
1686 * the filter) and 2 from the control trigger. This works whatever
1687 * the order we receive the notifications.
1688 */
d150e7e5
JR
1689 for (i = 0; i < notification_count; i++) {
1690 const char *name;
1691 struct lttng_notification *notification = get_next_notification(
a740a242
FD
1692 notification_channel);
1693
d150e7e5
JR
1694 ok(notification, "Received notification (%d/%d)", i + 1,
1695 notification_count);
1696
1697 /* Error. */
1698 if (notification == NULL) {
1699 goto end;
1700 }
1701
1702 name = get_notification_trigger_name(notification);
1703 if (name == NULL) {
1704 lttng_notification_destroy(notification);
1705 goto end;
1706 }
1707
a740a242
FD
1708 if (strcmp(ctrl_trigger_name, name) == 0) {
1709 ctrl_count++;
1710 } else if (strcmp(trigger_name, name) == 0) {
1711 count++;
1712 }
1713
d150e7e5 1714 lttng_notification_destroy(notification);
a740a242
FD
1715 }
1716
1717 ok(ctrl_count / 2 == count,
1718 "Get twice as many control notif as of regular notif");
1719
d150e7e5 1720end:
a740a242
FD
1721 suspend_application();
1722
1723 lttng_unregister_trigger(trigger);
1724 lttng_unregister_trigger(ctrl_trigger);
1725 lttng_notification_channel_destroy(notification_channel);
1726 lttng_trigger_destroy(trigger);
1727 lttng_trigger_destroy(ctrl_trigger);
1728 lttng_condition_destroy(condition);
1729 lttng_condition_destroy(ctrl_condition);
1730}
1731
3e4ee3b3
FD
1732static void test_tracepoint_event_rule_notification_exclusion(
1733 enum lttng_domain_type domain_type)
1734{
1735 enum lttng_notification_channel_status nc_status;
1736 struct lttng_condition *ctrl_condition = NULL, *condition = NULL;
1737 struct lttng_notification_channel *notification_channel = NULL;
1738 struct lttng_trigger *ctrl_trigger = NULL, *trigger = NULL;
1739 int ctrl_count = 0, count = 0, i;
d150e7e5 1740 const int notification_count = 6;
3e4ee3b3
FD
1741 const char * const ctrl_trigger_name = "control_exclusion_trigger";
1742 const char * const trigger_name = "exclusion_trigger";
1743 const char * const pattern = "tp:tptest*";
1744 const char * const exclusions[] = {
1745 "tp:tptest2",
1746 "tp:tptest3",
1747 "tp:tptest4",
1748 "tp:tptest5"
1749 };
1750
1751 notification_channel = lttng_notification_channel_create(
1752 lttng_session_daemon_notification_endpoint);
1753 ok(notification_channel, "Notification channel object creation");
1754
1755 create_tracepoint_event_rule_trigger(pattern, ctrl_trigger_name, NULL,
26e2f47b
JR
1756 0, NULL, domain_type, NULL, &ctrl_condition,
1757 &ctrl_trigger);
3e4ee3b3
FD
1758
1759 nc_status = lttng_notification_channel_subscribe(
1760 notification_channel, ctrl_condition);
1761 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1762 "Subscribe to tracepoint event rule condition");
1763
1764 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 4,
26e2f47b
JR
1765 exclusions, domain_type, NULL, &condition,
1766 &trigger);
3e4ee3b3
FD
1767
1768 nc_status = lttng_notification_channel_subscribe(
1769 notification_channel, condition);
1770 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1771 "Subscribe to tracepoint event rule condition");
1772
1773 /*
1774 * We registered 2 notifications triggers, one with an exclusion and
1775 * one without (control).
1776 * - The trigger with an exclusion will fire once every iteration.
1777 * - The trigger without an exclusion will fire 5 times every
1778 * iteration.
1779 *
1780 * We should get 5 times as many notifications from the control
1781 * trigger.
1782 */
1783 resume_application();
1784
1785 /*
1786 * Get 6 notifications. We should get 1 for the regular trigger (with
1787 * the exclusion) and 5 from the control trigger. This works whatever
1788 * the order we receive the notifications.
1789 */
d150e7e5
JR
1790 for (i = 0; i < notification_count; i++) {
1791 const char *name;
1792 struct lttng_notification *notification = get_next_notification(
3e4ee3b3
FD
1793 notification_channel);
1794
d150e7e5
JR
1795 ok(notification, "Received notification (%d/%d)", i + 1,
1796 notification_count);
1797
1798 /* Error. */
1799 if (notification == NULL) {
1800 goto end;
1801 }
1802
1803 name = get_notification_trigger_name(notification);
1804 if (name == NULL) {
1805 lttng_notification_destroy(notification);
1806 goto end;
1807 }
1808
3e4ee3b3
FD
1809 if (strcmp(ctrl_trigger_name, name) == 0) {
1810 ctrl_count++;
1811 } else if (strcmp(trigger_name, name) == 0) {
1812 count++;
1813 }
1814
d150e7e5 1815 lttng_notification_destroy(notification);
3e4ee3b3
FD
1816 }
1817
1818 ok(ctrl_count / 5 == count,
1819 "Got 5 times as many control notif as of regular notif");
1820
d150e7e5 1821end:
3e4ee3b3
FD
1822 suspend_application();
1823
1824 lttng_unregister_trigger(trigger);
1825 lttng_unregister_trigger(ctrl_trigger);
1826 lttng_notification_channel_destroy(notification_channel);
1827 lttng_trigger_destroy(trigger);
1828 lttng_trigger_destroy(ctrl_trigger);
1829 lttng_condition_destroy(condition);
1830 lttng_condition_destroy(ctrl_condition);
1831 return;
1832}
1833
51704c8e
FD
1834static void test_kprobe_event_rule_notification(
1835 enum lttng_domain_type domain_type)
1836{
1837 int i, ret;
1838 const int notification_count = 3;
1839 enum lttng_notification_channel_status nc_status;
1840 enum lttng_event_rule_status event_rule_status;
1841 enum lttng_trigger_status trigger_status;
1842 struct lttng_notification_channel *notification_channel = NULL;
1843 struct lttng_condition *condition = NULL;
1844 struct lttng_kernel_probe_location *location = NULL;
1845 struct lttng_event_rule *event_rule = NULL;
1846 struct lttng_action *action = NULL;
1847 struct lttng_trigger *trigger = NULL;
1848 const char * const trigger_name = "kprobe_trigger";
1849 const char * const symbol_name = "lttng_test_filter_event_write";
1850
1851 action = lttng_action_notify_create();
1852 if (!action) {
1853 fail("Failed to create notify action");
1854 goto end;
1855 }
1856
1857 location = lttng_kernel_probe_location_symbol_create(symbol_name, 0);
1858 if (!location) {
1859 fail("Failed to create kernel probe location");
1860 goto end;
1861 }
1862
1863 notification_channel = lttng_notification_channel_create(
1864 lttng_session_daemon_notification_endpoint);
1865 ok(notification_channel, "Notification channel object creation");
1866
602a6d40 1867 event_rule = lttng_event_rule_kernel_probe_create(location);
51704c8e
FD
1868 ok(event_rule, "kprobe event rule object creation");
1869
d891bb52 1870 event_rule_status = lttng_event_rule_kernel_probe_set_event_name(
51704c8e
FD
1871 event_rule, trigger_name);
1872 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1873 "Setting kprobe event rule name: '%s'", trigger_name);
1874
d602bd6a 1875 condition = lttng_condition_on_event_create(event_rule);
51704c8e
FD
1876 ok(condition, "Condition event rule object creation");
1877
1878 /* Register the trigger for condition. */
1879 trigger = lttng_trigger_create(condition, action);
1880 if (!trigger) {
1881 fail("Failed to create trigger with kernel probe event rule condition and notify action");
1882 goto end;
1883 }
1884
1885 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
1886 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
1887 "Setting trigger name to '%s'", trigger_name);
1888
1889 ret = lttng_register_trigger(trigger);
1890 if (ret) {
1891 fail("Failed to register trigger with kernel probe event rule condition and notify action");
1892 goto end;
1893 }
1894
1895 nc_status = lttng_notification_channel_subscribe(
1896 notification_channel, condition);
1897 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
1898 "Subscribe to tracepoint event rule condition");
1899
1900 resume_application();
1901
1902 for (i = 0; i < notification_count; i++) {
d150e7e5 1903 struct lttng_notification *notification = get_next_notification(
51704c8e
FD
1904 notification_channel);
1905
d150e7e5
JR
1906 ok(notification, "Received notification (%d/%d)", i + 1,
1907 notification_count);
1908
1909 /* Error. */
1910 if (notification == NULL) {
1911 goto end;
1912 }
1913
1914 ret = validator_notification_trigger_name(notification, trigger_name);
1915 lttng_notification_destroy(notification);
1916 if (ret) {
1917 goto end;
1918 }
51704c8e
FD
1919 }
1920
1921end:
1922 suspend_application();
1923 lttng_notification_channel_destroy(notification_channel);
1924 lttng_unregister_trigger(trigger);
1925 lttng_trigger_destroy(trigger);
1926 lttng_action_destroy(action);
aab0598f 1927 lttng_event_rule_destroy(event_rule);
51704c8e
FD
1928 lttng_condition_destroy(condition);
1929 lttng_kernel_probe_location_destroy(location);
1930 return;
1931}
1932
45294d8a
FD
1933static void test_uprobe_event_rule_notification(
1934 enum lttng_domain_type domain_type,
1935 const char *testapp_path,
1936 const char *test_symbol_name)
1937{
1938 int i, ret;
1939 const int notification_count = 3;
1940 enum lttng_notification_channel_status nc_status;
1941 enum lttng_event_rule_status event_rule_status;
1942 enum lttng_trigger_status trigger_status;
1943 struct lttng_notification_channel *notification_channel = NULL;
1944 struct lttng_userspace_probe_location *probe_location = NULL;
1945 struct lttng_userspace_probe_location_lookup_method *lookup_method =
1946 NULL;
1947 struct lttng_condition *condition = NULL;
1948 struct lttng_event_rule *event_rule = NULL;
1949 struct lttng_action *action = NULL;
1950 struct lttng_trigger *trigger = NULL;
1951 const char * const trigger_name = "uprobe_trigger";
1952
1953 action = lttng_action_notify_create();
1954 if (!action) {
1955 fail("Failed to create notify action");
1956 goto end;
1957 }
1958
1959 lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
1960 if (!lookup_method) {
1961 fail("Setup error on userspace probe lookup method creation");
1962 goto end;
1963 }
1964
1965 probe_location = lttng_userspace_probe_location_function_create(
1966 testapp_path, test_symbol_name, lookup_method);
1967 if (!probe_location) {
1968 fail("Failed to create userspace probe location");
1969 goto end;
1970 }
1971
1972 notification_channel = lttng_notification_channel_create(
1973 lttng_session_daemon_notification_endpoint);
1974 ok(notification_channel, "Notification channel object creation");
1975
1f1567a5 1976 event_rule = lttng_event_rule_userspace_probe_create();
45294d8a
FD
1977 ok(event_rule, "kprobe event rule object creation");
1978
1f1567a5 1979 event_rule_status = lttng_event_rule_userspace_probe_set_location(
45294d8a
FD
1980 event_rule, probe_location);
1981 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1982 "Setting uprobe event rule location");
1983
405f9e7d 1984 event_rule_status = lttng_event_rule_userspace_probe_set_event_name(
45294d8a
FD
1985 event_rule, trigger_name);
1986 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
1987 "Setting uprobe event rule name: '%s'", trigger_name);
1988
d602bd6a 1989 condition = lttng_condition_on_event_create(event_rule);
45294d8a
FD
1990 ok(condition, "Condition event rule object creation");
1991
1992 /* Register the trigger for condition. */
1993 trigger = lttng_trigger_create(condition, action);
1994 if (!trigger) {
1995 fail("Failed to create trigger with userspace probe event rule condition and notify action");
1996 goto end;
1997 }
1998
1999 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
2000 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
2001 "Setting name to trigger '%s'", trigger_name);
2002
2003 ret = lttng_register_trigger(trigger);
2004 if (ret) {
2005 fail("Failed to register trigger with userspace probe event rule condition and notify action");
2006 goto end;
2007 }
2008
2009 nc_status = lttng_notification_channel_subscribe(
2010 notification_channel, condition);
2011 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2012 "Subscribe to tracepoint event rule condition");
2013
2014 resume_application();
2015
d150e7e5
JR
2016 for (i = 0; i < 3; i++) {
2017 struct lttng_notification *notification = get_next_notification(
45294d8a
FD
2018 notification_channel);
2019
d150e7e5
JR
2020 ok(notification, "Received notification (%d/%d)", i + 1,
2021 notification_count);
2022
2023 /* Error. */
2024 if (notification == NULL) {
2025 goto end;
2026 }
2027
2028 ret = validator_notification_trigger_name(notification, trigger_name);
2029 lttng_notification_destroy(notification);
2030 if (ret) {
2031 goto end;
2032 }
45294d8a
FD
2033 }
2034end:
2035 suspend_application();
2036
2037 lttng_notification_channel_destroy(notification_channel);
2038 lttng_unregister_trigger(trigger);
2039 lttng_trigger_destroy(trigger);
2040 lttng_action_destroy(action);
a877d1b5 2041 lttng_userspace_probe_location_destroy(probe_location);
45294d8a
FD
2042 lttng_event_rule_destroy(event_rule);
2043 lttng_condition_destroy(condition);
2044 return;
2045}
2046
aab0598f
FD
2047static void test_syscall_event_rule_notification(
2048 enum lttng_domain_type domain_type)
2049{
2050 int i, ret;
2051 const int notification_count = 3;
2052 enum lttng_notification_channel_status nc_status;
2053 enum lttng_event_rule_status event_rule_status;
2054 enum lttng_trigger_status trigger_status;
2055 struct lttng_notification_channel *notification_channel = NULL;
2056 struct lttng_condition *condition = NULL;
2057 struct lttng_event_rule *event_rule = NULL;
2058 struct lttng_action *action = NULL;
2059 struct lttng_trigger *trigger = NULL;
2060 const char * const trigger_name = "syscall_trigger";
2061 const char * const syscall_name = "openat";
2062
2063 action = lttng_action_notify_create();
2064 if (!action) {
2065 fail("Failed to create notify action");
2066 goto end;
2067 }
2068
2069 notification_channel = lttng_notification_channel_create(
2070 lttng_session_daemon_notification_endpoint);
2071 ok(notification_channel, "Notification channel object creation");
2072
2073 event_rule = lttng_event_rule_syscall_create();
2074 ok(event_rule, "syscall event rule object creation");
2075
2076 event_rule_status = lttng_event_rule_syscall_set_pattern(
2077 event_rule, syscall_name);
2078 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2079 "Setting syscall event rule pattern: '%s'", syscall_name);
2080
d602bd6a 2081 condition = lttng_condition_on_event_create(event_rule);
aab0598f
FD
2082 ok(condition, "Condition syscall event rule object creation");
2083
2084 /* Register the trigger for condition. */
2085 trigger = lttng_trigger_create(condition, action);
2086 if (!trigger) {
2087 fail("Failed to create trigger with syscall event rule condition and notify action");
2088 goto end;
2089 }
2090
2091 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
2092 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
2093 "Setting name to trigger '%s'", trigger_name);
2094
2095 ret = lttng_register_trigger(trigger);
2096 if (ret) {
2097 fail("Failed to register trigger with syscall event rule condition and notify action");
2098 goto end;
2099 }
2100
2101 nc_status = lttng_notification_channel_subscribe(
2102 notification_channel, condition);
2103 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2104 "Subscribe to tracepoint event rule condition");
2105
2106 resume_application();
2107
2108 for (i = 0; i < notification_count; i++) {
d150e7e5 2109 struct lttng_notification *notification = get_next_notification(
aab0598f
FD
2110 notification_channel);
2111
d150e7e5
JR
2112 ok(notification, "Received notification (%d/%d)", i + 1,
2113 notification_count);
2114
2115 /* Error. */
2116 if (notification == NULL) {
2117 goto end;
2118 }
2119
2120 ret = validator_notification_trigger_name(notification, trigger_name);
2121 lttng_notification_destroy(notification);
2122 if (ret) {
2123 goto end;
2124 }
aab0598f
FD
2125 }
2126end:
2127 suspend_application();
2128 lttng_notification_channel_destroy(notification_channel);
2129 lttng_unregister_trigger(trigger);
2130 lttng_trigger_destroy(trigger);
2131 lttng_action_destroy(action);
2132 lttng_condition_destroy(condition);
2133 return;
2134}
2135
acb98866
FD
2136static void test_syscall_event_rule_notification_filter(
2137 enum lttng_domain_type domain_type)
2138{
2139 int i, ret;
2140 const int notification_count = 3;
2141 enum lttng_notification_channel_status nc_status;
2142 enum lttng_event_rule_status event_rule_status;
2143 enum lttng_trigger_status trigger_status;
2144 struct lttng_notification_channel *notification_channel = NULL;
2145 struct lttng_condition *condition = NULL;
2146 struct lttng_event_rule *event_rule = NULL;
2147 struct lttng_action *action = NULL;
2148 struct lttng_trigger *trigger = NULL;
2149 const char * const trigger_name = "syscall_trigger";
2150 const char * const syscall_name = "openat";
2151 const char * const filter_pattern = "filename == \"/proc/cpuinfo\"";
2152
2153 action = lttng_action_notify_create();
2154 if (!action) {
2155 fail("Failed to create notify action");
2156 goto end;
2157 }
2158
2159 notification_channel = lttng_notification_channel_create(
2160 lttng_session_daemon_notification_endpoint);
2161 ok(notification_channel, "Notification channel object creation");
2162
2163 event_rule = lttng_event_rule_syscall_create();
2164 ok(event_rule, "syscall event rule object creation");
2165
2166 event_rule_status = lttng_event_rule_syscall_set_pattern(
2167 event_rule, syscall_name);
2168 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2169 "Setting syscall event rule pattern: '%s'", syscall_name);
2170
2171 event_rule_status = lttng_event_rule_syscall_set_filter(
2172 event_rule, filter_pattern);
2173 ok(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK,
2174 "Setting filter: '%s'", filter_pattern);
2175
d602bd6a 2176 condition = lttng_condition_on_event_create(event_rule);
acb98866
FD
2177 ok(condition, "Condition event rule object creation");
2178
2179 /* Register the triggers for condition */
2180 trigger = lttng_trigger_create(condition, action);
2181 if (!trigger) {
2182 fail("Failed to create trigger with syscall filtering event rule condition and notify action");
2183 goto end;
2184 }
2185
2186 trigger_status = lttng_trigger_set_name(trigger, trigger_name);
2187 ok(trigger_status == LTTNG_TRIGGER_STATUS_OK,
2188 "Setting name to trigger '%s'", trigger_name);
2189
2190 ret = lttng_register_trigger(trigger);
2191 if (ret) {
2192 fail("Failed to register trigger with syscall filtering event rule condition and notify action");
2193 goto end;
2194 }
2195
2196 nc_status = lttng_notification_channel_subscribe(
2197 notification_channel, condition);
2198 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2199 "Subscribe to tracepoint event rule condition");
2200
2201 resume_application();
2202
d150e7e5
JR
2203 for (i = 0; i < notification_count; i++) {
2204 struct lttng_notification *notification = get_next_notification(
acb98866
FD
2205 notification_channel);
2206
d150e7e5
JR
2207 ok(notification, "Received notification (%d/%d)", i + 1,
2208 notification_count);
2209
2210 /* Error. */
2211 if (notification == NULL) {
2212 goto end;
2213 }
2214
2215 ret = validator_notification_trigger_name(notification, trigger_name);
2216 lttng_notification_destroy(notification);
2217 if (ret) {
2218 goto end;
2219 }
acb98866
FD
2220 }
2221
2222end:
2223 suspend_application();
2224
2225 lttng_unregister_trigger(trigger);
2226 lttng_notification_channel_destroy(notification_channel);
2227 lttng_trigger_destroy(trigger);
2228 lttng_event_rule_destroy(event_rule);
2229 lttng_condition_destroy(condition);
2230 return;
2231}
2232
26e2f47b
JR
2233static int generate_capture_descr(struct lttng_condition *condition)
2234{
2235 int ret, i;
2236 struct lttng_event_expr *expr = NULL;
2237 const unsigned int basic_field_count = sizeof(test_capture_base_fields) /
2238 sizeof(*test_capture_base_fields);
2239 enum lttng_condition_status cond_status;
2240
2241 for (i = 0; i < basic_field_count; i++) {
2242 diag("Adding capture descriptor '%s'",
2243 test_capture_base_fields[i].field_name);
2244
2245 switch (test_capture_base_fields[i].field_type) {
2246 case FIELD_TYPE_PAYLOAD:
2247 expr = lttng_event_expr_event_payload_field_create(
2248 test_capture_base_fields[i].field_name);
2249 break;
2250 case FIELD_TYPE_CONTEXT:
2251 expr = lttng_event_expr_channel_context_field_create(
2252 test_capture_base_fields[i].field_name);
2253 break;
2254 case FIELD_TYPE_ARRAY_FIELD:
2255 {
2256 int nb_matches;
2257 unsigned int index;
2258 char field_name[FIELD_NAME_MAX_LEN];
2259 struct lttng_event_expr *array_expr = NULL;
2260
2261 nb_matches = sscanf(test_capture_base_fields[i].field_name,
2262 "%[^[][%u]", field_name, &index);
2263 if (nb_matches != 2) {
2264 fail("Unexpected array field name format: field name = '%s'",
2265 test_capture_base_fields[i].field_name);
2266 ret = 1;
2267 goto end;
2268 }
2269
2270 array_expr = lttng_event_expr_event_payload_field_create(
2271 field_name);
2272
2273 expr = lttng_event_expr_array_field_element_create(
2274 array_expr, index);
2275 break;
2276 }
2277 case FIELD_TYPE_APP_CONTEXT:
2278 fail("Application context tests are not implemented yet.");
2279 /* fallthrough. */
2280 default:
2281 ret = 1;
2282 goto end;
2283 }
2284
2285 if (expr == NULL) {
2286 fail("Failed to create capture expression");
2287 ret = -1;
2288 goto end;
2289 }
2290
d602bd6a 2291 cond_status = lttng_condition_on_event_append_capture_descriptor(
26e2f47b
JR
2292 condition, expr);
2293 if (cond_status != LTTNG_CONDITION_STATUS_OK) {
2294 fail("Failed to append capture descriptor");
2295 ret = -1;
2296 lttng_event_expr_destroy(expr);
2297 goto end;
2298 }
2299 }
2300
2301 ret = 0;
2302
2303end:
2304 return ret;
2305}
2306
2307static int validator_notification_trigger_capture(
2308 enum lttng_domain_type domain,
2309 struct lttng_notification *notification,
2310 const int iteration)
2311{
2312 int ret;
2313 unsigned int capture_count, i;
2314 enum lttng_evaluation_status evaluation_status;
2315 enum lttng_event_field_value_status event_field_value_status;
2316 const struct lttng_evaluation *evaluation;
2317 const struct lttng_event_field_value *captured_fields;
2318 bool at_least_one_error = false;
2319
2320 evaluation = lttng_notification_get_evaluation(notification);
2321 if (evaluation == NULL) {
2322 fail("Failed to get evaluation from notification during trigger capture test");
2323 ret = 1;
2324 goto end;
2325 }
2326
d602bd6a 2327 evaluation_status = lttng_evaluation_on_event_get_captured_values(
26e2f47b
JR
2328 evaluation, &captured_fields);
2329 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
2330 diag("Failed to get event rule evaluation captured values: status = %d",
2331 (int) evaluation_status);
2332 ret = 1;
2333 goto end;
2334 }
2335
2336 event_field_value_status =
2337 lttng_event_field_value_array_get_length(captured_fields,
2338 &capture_count);
2339 if (event_field_value_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
2340 fail("Failed to get count of captured value field array");
2341 ret = 1;
2342 goto end;
2343 }
2344
2345 for (i = 0; i < capture_count; i++) {
2346 const struct lttng_event_field_value *captured_field = NULL;
2347 validate_cb validate;
2348 bool expected;
2349
2350 diag("Validating capture of field '%s'",
2351 test_capture_base_fields[i].field_name);
2352 event_field_value_status =
2353 lttng_event_field_value_array_get_element_at_index(
2354 captured_fields, i,
2355 &captured_field);
2356
2357 switch(domain) {
2358 case LTTNG_DOMAIN_UST:
2359 expected = test_capture_base_fields[i].expected_ust;
2360 break;
2361 case LTTNG_DOMAIN_KERNEL:
2362 expected = test_capture_base_fields[i].expected_kernel;
2363 break;
2364 default:
2365 fail("Unexpected domain encountered: domain = %d",
2366 (int) domain);
2367 ret = 1;
2368 goto end;
2369 }
2370
2371 if (domain == LTTNG_DOMAIN_UST) {
2372 validate = test_capture_base_fields[i].validate_ust;
2373 } else {
2374 validate = test_capture_base_fields[i].validate_kernel;
2375 }
2376
2377 if (!expected) {
2378 ok(event_field_value_status == LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE,
2379 "No payload captured");
2380 continue;
2381 }
2382
2383 if (event_field_value_status != LTTNG_EVENT_FIELD_VALUE_STATUS_OK) {
2384 if (event_field_value_status ==
2385 LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE) {
2386 fail("Expected a capture but it is unavailable");
2387 } else {
2388 fail("lttng_event_field_value_array_get_element_at_index returned an error: status = %d",
2389 (int) event_field_value_status);
2390 }
2391
2392 ret = 1;
2393 goto end;
2394 }
2395
2396 diag("Captured field of type %s",
2397 field_value_type_to_str(
2398 lttng_event_field_value_get_type(captured_field)));
2399
2400 assert(validate);
2401 ret = validate(captured_field, iteration);
2402 if (ret) {
2403 at_least_one_error = true;
2404 }
2405 }
2406
2407 ret = at_least_one_error;
2408
2409end:
2410 return ret;
2411}
2412
2413static void test_tracepoint_event_rule_notification_capture(
2414 enum lttng_domain_type domain_type)
2415{
2416 enum lttng_notification_channel_status nc_status;
2417
2418 int i, ret;
2419 struct lttng_condition *condition = NULL;
2420 struct lttng_notification_channel *notification_channel = NULL;
2421 struct lttng_trigger *trigger = NULL;
2422 const char *trigger_name = "my_precious";
2423 const char *pattern;
2424
2425 if (domain_type == LTTNG_DOMAIN_UST) {
2426 pattern = "tp:tptest";
2427 } else {
2428 pattern = "lttng_test_filter_event";
2429 }
2430
2431 create_tracepoint_event_rule_trigger(pattern, trigger_name, NULL, 0,
2432 NULL, domain_type, generate_capture_descr, &condition,
2433 &trigger);
2434
2435 notification_channel = lttng_notification_channel_create(
2436 lttng_session_daemon_notification_endpoint);
2437 ok(notification_channel, "Notification channel object creation");
2438
2439 nc_status = lttng_notification_channel_subscribe(
2440 notification_channel, condition);
2441 ok(nc_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
2442 "Subscribe to tracepoint event rule condition");
2443
2444 resume_application();
2445
2446 /* Get 3 notifications */
2447 for (i = 0; i < 3; i++) {
2448 struct lttng_notification *notification = get_next_notification(
2449 notification_channel);
2450 ok(notification, "Received notification");
2451
2452 /* Error */
2453 if (notification == NULL) {
2454 goto end;
2455 }
2456
2457 ret = validator_notification_trigger_name(notification, trigger_name);
2458 if (ret) {
2459 lttng_notification_destroy(notification);
2460 goto end;
2461 }
2462
2463 ret = validator_notification_trigger_capture(domain_type, notification, i);
2464 if (ret) {
2465 lttng_notification_destroy(notification);
2466 goto end;
2467 }
2468
2469 lttng_notification_destroy(notification);
2470 }
2471
2472end:
2473 suspend_application();
2474 lttng_notification_channel_destroy(notification_channel);
2475 lttng_unregister_trigger(trigger);
2476 lttng_trigger_destroy(trigger);
2477 lttng_condition_destroy(condition);
2478 return;
2479}
2480
434f8068
JR
2481int main(int argc, const char *argv[])
2482{
069fc1c5 2483 int test_scenario;
434f8068
JR
2484 const char *domain_type_string = NULL;
2485 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
2486
a740a242
FD
2487 if (argc < 5) {
2488 fail("Missing test scenario, domain type, pid, or application state file argument(s)");
434f8068
JR
2489 goto error;
2490 }
2491
069fc1c5
FD
2492 test_scenario = atoi(argv[1]);
2493 domain_type_string = argv[2];
a740a242
FD
2494 app_pid = (pid_t) atoi(argv[3]);
2495 app_state_file = argv[4];
434f8068
JR
2496
2497 if (!strcmp("LTTNG_DOMAIN_UST", domain_type_string)) {
2498 domain_type = LTTNG_DOMAIN_UST;
2499 }
2500 if (!strcmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
2501 domain_type = LTTNG_DOMAIN_KERNEL;
2502 }
2503 if (domain_type == LTTNG_DOMAIN_NONE) {
2504 fail("Unknown domain type");
2505 goto error;
2506 }
2507
a740a242
FD
2508 /*
2509 * Test cases are responsible for resuming the app when needed
2510 * and making sure it's suspended when returning.
2511 */
2512 suspend_application();
2513
069fc1c5
FD
2514 switch (test_scenario) {
2515 case 1:
2516 {
d150e7e5 2517 plan_tests(44);
7948461b 2518
069fc1c5 2519 /* Test cases that need gen-ust-event testapp. */
a740a242 2520 diag("Test basic notification error paths for %s domain",
069fc1c5
FD
2521 domain_type_string);
2522 test_invalid_channel_subscription(domain_type);
7948461b
FD
2523
2524 diag("Test tracepoint event rule notifications for domain %s",
2525 domain_type_string);
2526 test_tracepoint_event_rule_notification(domain_type);
2527
a740a242
FD
2528 diag("Test tracepoint event rule notifications with filter for domain %s",
2529 domain_type_string);
2530 test_tracepoint_event_rule_notification_filter(domain_type);
069fc1c5
FD
2531 break;
2532 }
2533 case 2:
2534 {
45294d8a 2535 const char *session_name, *channel_name;
d150e7e5 2536
069fc1c5
FD
2537 /* Test cases that need a tracing session enabled. */
2538 plan_tests(99);
7676e0d2 2539
069fc1c5
FD
2540 /*
2541 * Argument 7 and upward are named pipe location for consumerd
2542 * control.
2543 */
2544 named_pipe_args_start = 7;
2545
2546 if (argc < 8) {
2547 fail("Missing parameter for tests to run %d", argc);
2548 goto error;
2549 }
434f8068 2550
069fc1c5
FD
2551 nb_args = argc;
2552
a740a242
FD
2553 session_name = argv[5];
2554 channel_name = argv[6];
069fc1c5
FD
2555
2556 test_subscription_twice(session_name, channel_name,
2557 domain_type);
2558
2559 diag("Test trigger for domain %s with buffer_usage_low condition",
2560 domain_type_string);
2561 test_triggers_buffer_usage_condition(session_name, channel_name,
2562 domain_type,
2563 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW);
2564
2565 diag("Test trigger for domain %s with buffer_usage_high condition",
2566 domain_type_string);
2567 test_triggers_buffer_usage_condition(session_name, channel_name,
2568 domain_type,
2569 LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH);
2570
2571 diag("Test buffer usage notification channel api for domain %s",
2572 domain_type_string);
2573 test_buffer_usage_notification_channel(session_name, channel_name,
2574 domain_type, argv);
2575 break;
2576 }
3e4ee3b3
FD
2577 case 3:
2578 {
2579 /*
2580 * Test cases that need a test app with more than one event
2581 * type.
2582 */
d150e7e5 2583 plan_tests(25);
3e4ee3b3
FD
2584
2585 /*
2586 * At the moment, the only test case of this scenario is
2587 * exclusion which is only supported by UST.
2588 */
2589 assert(domain_type == LTTNG_DOMAIN_UST);
2590 diag("Test tracepoint event rule notifications with exclusion for domain %s",
2591 domain_type_string);
2592 test_tracepoint_event_rule_notification_exclusion(domain_type);
2593
2594 break;
2595 }
51704c8e
FD
2596 case 4:
2597 {
602a6d40 2598 plan_tests(12);
51704c8e
FD
2599 /* Test cases that need the kernel tracer. */
2600 assert(domain_type == LTTNG_DOMAIN_KERNEL);
aab0598f 2601
51704c8e
FD
2602 diag("Test kprobe event rule notifications for domain %s",
2603 domain_type_string);
2604
2605 test_kprobe_event_rule_notification(domain_type);
2606
2607 break;
2608 }
aab0598f
FD
2609 case 5:
2610 {
d150e7e5 2611 plan_tests(25);
aab0598f
FD
2612 /* Test cases that need the kernel tracer. */
2613 assert(domain_type == LTTNG_DOMAIN_KERNEL);
2614
2615 diag("Test syscall event rule notifications for domain %s",
2616 domain_type_string);
2617
2618 test_syscall_event_rule_notification(domain_type);
2619
acb98866
FD
2620 diag("Test syscall filtering event rule notifications for domain %s",
2621 domain_type_string);
2622
2623 test_syscall_event_rule_notification_filter(domain_type);
2624
aab0598f
FD
2625 break;
2626 }
45294d8a
FD
2627 case 6:
2628 {
2629 const char *testapp_path, *test_symbol_name;
2630
d150e7e5 2631 plan_tests(13);
45294d8a
FD
2632
2633 if (argc < 7) {
2634 fail("Missing parameter for tests to run %d", argc);
2635 goto error;
2636 }
2637
2638 testapp_path = argv[5];
2639 test_symbol_name = argv[6];
2640 /* Test cases that need the kernel tracer. */
2641 assert(domain_type == LTTNG_DOMAIN_KERNEL);
2642
2643 diag("Test userspace-probe event rule notifications for domain %s",
2644 domain_type_string);
2645
2646 test_uprobe_event_rule_notification(
2647 domain_type, testapp_path, test_symbol_name);
2648
2649 break;
2650 }
26e2f47b
JR
2651 case 7:
2652 {
2653 switch(domain_type) {
2654 case LTTNG_DOMAIN_UST:
2655 plan_tests(222);
2656 break;
2657 case LTTNG_DOMAIN_KERNEL:
2658 plan_tests(216);
2659 break;
2660 default:
2661 assert(0);
2662 }
2663
2664 diag("Test tracepoint event rule notification captures for domain %s",
2665 domain_type_string);
2666 test_tracepoint_event_rule_notification_capture(domain_type);
2667
2668 break;
2669 }
2670
069fc1c5
FD
2671 default:
2672 abort();
2673 }
90fcb2ec 2674
434f8068
JR
2675error:
2676 return exit_status();
2677}
2678
This page took 0.249684 seconds and 4 git commands to generate.