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