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