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