Fix: argpar: Error out when passing an argument to long option that takes no argument
[lttng-tools.git] / tests / regression / tools / notification / base_client.c
CommitLineData
434f8068
JR
1/*
2 * base_client.c
3 *
4 * Base client application for testing of LTTng notification API
5 *
6 * Copyright 2017 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
7 *
9d16b343 8 * SPDX-License-Identifier: MIT
434f8068 9 *
434f8068
JR
10 */
11
12#include <stdio.h>
13#include <stdbool.h>
14#include <string.h>
15#include <unistd.h>
16#include <inttypes.h>
17#include <assert.h>
18
19#include <lttng/action/action.h>
ad63a966 20#include <lttng/action/list.h>
434f8068
JR
21#include <lttng/action/notify.h>
22#include <lttng/condition/buffer-usage.h>
23#include <lttng/condition/condition.h>
24#include <lttng/condition/evaluation.h>
25#include <lttng/domain.h>
26#include <lttng/endpoint.h>
27#include <lttng/notification/channel.h>
28#include <lttng/notification/notification.h>
29#include <lttng/trigger/trigger.h>
25040abc 30#include <lttng/lttng-error.h>
434f8068
JR
31
32static unsigned int nr_notifications = 0;
33static unsigned int nr_expected_notifications = 0;
34static const char *session_name = NULL;
35static const char *channel_name = NULL;
36static double threshold_ratio = 0.0;
37static uint64_t threshold_bytes = 0;
38static bool is_threshold_ratio = false;
702f26c8 39static bool use_action_list = false;
434f8068
JR
40static enum lttng_condition_type buffer_usage_type = LTTNG_CONDITION_TYPE_UNKNOWN;
41static enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
42
43int handle_condition(
44 const struct lttng_condition *condition,
45 const struct lttng_evaluation *condition_evaluation);
46
53089c7c
SM
47static
48int parse_arguments(char **argv)
49{
e062fb02 50 int sscanf_ret;
434f8068
JR
51 const char *domain_type_string = NULL;
52 const char *buffer_usage_type_string = NULL;
53 const char *buffer_usage_threshold_type = NULL;
54 const char *buffer_usage_threshold_value = NULL;
55 const char *nr_expected_notifications_string = NULL;
702f26c8 56 const char *use_action_list_value = NULL;
434f8068
JR
57
58 session_name = argv[1];
59 channel_name = argv[2];
60 domain_type_string = argv[3];
61 buffer_usage_type_string = argv[4];
62 buffer_usage_threshold_type = argv[5];
63 buffer_usage_threshold_value = argv[6];
64 nr_expected_notifications_string = argv[7];
702f26c8 65 use_action_list_value = argv[8];
434f8068
JR
66
67 /* Parse arguments */
68 /* Domain type */
69 if (!strcasecmp("LTTNG_DOMAIN_UST", domain_type_string)) {
70 domain_type = LTTNG_DOMAIN_UST;
71 }
72 if (!strcasecmp("LTTNG_DOMAIN_KERNEL", domain_type_string)) {
73 domain_type = LTTNG_DOMAIN_KERNEL;
74 }
75 if (domain_type == LTTNG_DOMAIN_NONE) {
76 printf("error: Unknown domain type\n");
77 goto error;
78 }
79
80 /* Buffer usage condition type */
81 if (!strcasecmp("low", buffer_usage_type_string)) {
82 buffer_usage_type = LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW;
83 }
84 if (!strcasecmp("high", buffer_usage_type_string)) {
85 buffer_usage_type = LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH;
86 }
87 if (buffer_usage_type == LTTNG_CONDITION_TYPE_UNKNOWN) {
88 printf("error: Unknown condition type\n");
89 goto error;
90 }
91
92 /* Ratio or bytes ? */
93 if (!strcasecmp("bytes", buffer_usage_threshold_type)) {
94 is_threshold_ratio = false;
95 sscanf(buffer_usage_threshold_value, "%" SCNu64, &threshold_bytes);
96 }
97
98 if (!strcasecmp("ratio", buffer_usage_threshold_type)) {
99 is_threshold_ratio = true;
100 sscanf(buffer_usage_threshold_value, "%lf", &threshold_ratio);
101 }
102
103 /* Number of notification to expect */
e062fb02
JG
104 sscanf_ret = sscanf(nr_expected_notifications_string, "%d",
105 &nr_expected_notifications);
106 if (sscanf_ret != 1) {
107 printf("error: Invalid nr_expected_notifications, sscanf returned %d\n",
108 sscanf_ret);
109 goto error;
110 }
434f8068 111
091fa780 112 /* Put notify action in a group. */
702f26c8
JR
113 if (!strcasecmp("1", use_action_list_value)) {
114 use_action_list = true;
091fa780
FD
115 }
116
434f8068
JR
117 return 0;
118error:
119 return 1;
120}
121
122int main(int argc, char **argv)
123{
124 int ret = 0;
125 enum lttng_condition_status condition_status;
091fa780 126 enum lttng_action_status action_status;
434f8068
JR
127 enum lttng_notification_channel_status nc_status;
128 struct lttng_notification_channel *notification_channel = NULL;
129 struct lttng_condition *condition = NULL;
130 struct lttng_action *action = NULL;
131 struct lttng_trigger *trigger = NULL;
a5c2d2a7 132 enum lttng_error_code ret_code;
434f8068
JR
133
134 /*
135 * Disable buffering on stdout.
136 * Safety measure to prevent hang on the validation side since
137 * stdout is used for outside synchronization.
138 */
139 setbuf(stdout, NULL);
140
091fa780 141 if (argc < 9) {
434f8068
JR
142 printf("error: Missing arguments for tests\n");
143 ret = 1;
144 goto end;
145 }
146
147 ret = parse_arguments(argv);
148 if (ret) {
149 printf("error: Could not parse arguments\n");
150 goto end;
151 }
152
153 /* Setup */
154 notification_channel = lttng_notification_channel_create(
155 lttng_session_daemon_notification_endpoint);
156 if (!notification_channel) {
157 printf("error: Could not create notification channel\n");
158 ret = 1;
159 goto end;
160 }
161
162 switch (buffer_usage_type) {
163 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
164 condition = lttng_condition_buffer_usage_low_create();
165 break;
166 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
167 condition = lttng_condition_buffer_usage_high_create();
168 break;
169 default:
170 printf("error: Invalid buffer_usage_type\n");
171 ret = 1;
172 goto end;
173 }
174
175 if (!condition) {
176 printf("error: Could not create condition object\n");
177 ret = 1;
178 goto end;
179 }
180
181 if (is_threshold_ratio) {
182 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
183 condition, threshold_ratio);
184 } else {
185 condition_status = lttng_condition_buffer_usage_set_threshold(
186 condition, threshold_bytes);
187 }
188
189 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
190 printf("error: Could not set threshold\n");
191 ret = 1;
192 goto end;
193 }
194
195 condition_status = lttng_condition_buffer_usage_set_session_name(
196 condition, session_name);
197 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
198 printf("error: Could not set session name\n");
199 ret = 1;
200 goto end;
201 }
202 condition_status = lttng_condition_buffer_usage_set_channel_name(
203 condition, channel_name);
204 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
205 printf("error: Could not set channel name\n");
206 ret = 1;
207 goto end;
208 }
209 condition_status = lttng_condition_buffer_usage_set_domain_type(
854382b8 210 condition, domain_type);
434f8068
JR
211 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
212 printf("error: Could not set domain type\n");
213 ret = 1;
214 goto end;
215 }
216
702f26c8 217 if (use_action_list) {
091fa780
FD
218 struct lttng_action *notify, *group;
219
702f26c8 220 group = lttng_action_list_create();
091fa780 221 if (!group) {
702f26c8 222 printf("error: Could not create action list\n");
091fa780
FD
223 ret = 1;
224 goto end;
225 }
226
227 notify = lttng_action_notify_create();
228 if (!notify) {
229 lttng_action_destroy(group);
230 printf("error: Could not create action notify\n");
231 ret = 1;
232 goto end;
233 }
234
702f26c8 235 action_status = lttng_action_list_add_action(group, notify);
091fa780 236 if (action_status != LTTNG_ACTION_STATUS_OK) {
702f26c8 237 printf("error: Could not add action notify to action list\n");
091fa780
FD
238 lttng_action_destroy(group);
239 lttng_action_destroy(notify);
240 ret = 1;
241 goto end;
242 }
243
244 action = group;
245 } else {
246 action = lttng_action_notify_create();
247 if (!action) {
248 printf("error: Could not create action notify\n");
249 ret = 1;
250 goto end;
251 }
434f8068
JR
252 }
253
254 trigger = lttng_trigger_create(condition, action);
255 if (!trigger) {
256 printf("error: Could not create trigger\n");
257 ret = 1;
258 goto end;
259 }
260
a5c2d2a7 261 ret_code = lttng_register_trigger_with_automatic_name(trigger);
434f8068
JR
262
263 /*
264 * An equivalent trigger might already be registered if an other app
265 * registered an equivalent trigger.
266 */
a5c2d2a7
JG
267 if (ret_code != LTTNG_OK && ret_code != LTTNG_ERR_TRIGGER_EXISTS) {
268 printf("error: %s\n", lttng_strerror(-ret_code));
434f8068
JR
269 ret = 1;
270 goto end;
271 }
272
273 nc_status = lttng_notification_channel_subscribe(notification_channel, condition);
274 if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
275 printf("error: Could not subscribe\n");
276 ret = 1;
277 goto end;
278 }
279
280 /* Tell outside process that the client is ready */
281 printf("sync: ready\n");
282
283 for (;;) {
284 struct lttng_notification *notification;
285 enum lttng_notification_channel_status status;
286 const struct lttng_evaluation *notification_evaluation;
287 const struct lttng_condition *notification_condition;
288
289 if (nr_notifications == nr_expected_notifications) {
290 ret = 0;
291 goto end;
292 }
293 /* Receive the next notification. */
294 status = lttng_notification_channel_get_next_notification(
295 notification_channel,
296 &notification);
297
298 switch (status) {
299 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
300 break;
301 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
302 ret = 1;
303 printf("error: No drop should be observed during this test app\n");
304 goto end;
305 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
306 /*
307 * The notification channel has been closed by the
308 * session daemon. This is typically caused by a session
309 * daemon shutting down (cleanly or because of a crash).
310 */
311 printf("error: Notification channel was closed\n");
312 ret = 1;
313 goto end;
314 default:
315 /* Unhandled conditions / errors. */
091fa780 316 printf("error: Unknown notification channel status (%d) \n", status);
434f8068
JR
317 ret = 1;
318 goto end;
319 }
320
321 notification_condition = lttng_notification_get_condition(notification);
322 notification_evaluation = lttng_notification_get_evaluation(notification);
323
324 ret = handle_condition(notification_condition, notification_evaluation);
325 nr_notifications++;
326
327 lttng_notification_destroy(notification);
328 if (ret != 0) {
329 goto end;
330 }
331 }
332end:
333 if (trigger) {
334 lttng_unregister_trigger(trigger);
335 }
eff748d0
JR
336 if (lttng_notification_channel_unsubscribe(notification_channel, condition)) {
337 printf("error: channel unsubscribe error\n");
338 }
434f8068
JR
339 lttng_trigger_destroy(trigger);
340 lttng_condition_destroy(condition);
341 lttng_action_destroy(action);
342 lttng_notification_channel_destroy(notification_channel);
343 printf("exit: %d\n", ret);
344 return ret;
345}
346
347int handle_condition(
348 const struct lttng_condition *condition,
349 const struct lttng_evaluation *evaluation)
350{
351 int ret = 0;
352 const char *string_low = "low";
353 const char *string_high = "high";
354 const char *string_condition_type = NULL;
355 const char *condition_session_name = NULL;
356 const char *condition_channel_name = NULL;
357 enum lttng_condition_type condition_type;
358 enum lttng_domain_type condition_domain_type;
359 double buffer_usage_ratio;
360 uint64_t buffer_usage_bytes;
361
362 condition_type = lttng_condition_get_type(condition);
363
364 if (condition_type != buffer_usage_type) {
365 ret = 1;
366 printf("error: condition type and buffer usage type are not the same\n");
367 goto end;
368 }
369
370 /* Fetch info to test */
eff748d0 371 ret = lttng_condition_buffer_usage_get_session_name(condition,
434f8068 372 &condition_session_name);
eff748d0
JR
373 if (ret) {
374 printf("error: session name could not be fetched\n");
375 ret = 1;
376 goto end;
377 }
378 ret = lttng_condition_buffer_usage_get_channel_name(condition,
434f8068 379 &condition_channel_name);
eff748d0
JR
380 if (ret) {
381 printf("error: channel name could not be fetched\n");
382 ret = 1;
383 goto end;
384 }
385 ret = lttng_condition_buffer_usage_get_domain_type(condition,
434f8068 386 &condition_domain_type);
eff748d0
JR
387 if (ret) {
388 printf("error: domain type could not be fetched\n");
389 ret = 1;
390 goto end;
391 }
434f8068
JR
392
393 if (strcmp(condition_session_name, session_name) != 0) {
394 printf("error: session name differs\n");
395 ret = 1;
396 goto end;
397 }
398
399 if (strcmp(condition_channel_name, channel_name) != 0) {
400 printf("error: channel name differs\n");
401 ret = 1;
402 goto end;
403 }
404
405 if (condition_domain_type != domain_type) {
406 printf("error: domain type differs\n");
407 ret = 1;
408 goto end;
409 }
410
411 if (is_threshold_ratio) {
412 lttng_evaluation_buffer_usage_get_usage_ratio(
413 evaluation, &buffer_usage_ratio);
414 switch (condition_type) {
415 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
416 if (buffer_usage_ratio > threshold_ratio) {
417 printf("error: buffer usage ratio is bigger than set threshold ratio\n");
418 ret = 1;
419 goto end;
420 }
421 break;
422 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
423 if (buffer_usage_ratio < threshold_ratio) {
424 printf("error: buffer usage ratio is lower than set threshold ratio\n");
425 ret = 1;
426 goto end;
427 }
428 break;
429 default:
430 printf("error: Unknown condition type\n");
431 ret = 1;
432 goto end;
433 }
434 } else {
435 lttng_evaluation_buffer_usage_get_usage(
436 evaluation, &buffer_usage_bytes);
437 switch (condition_type) {
438 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
439 if (buffer_usage_bytes > threshold_bytes) {
440 printf("error: buffer usage ratio is bigger than set threshold bytes\n");
441 ret = 1;
442 goto end;
443 }
444 break;
445 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
446 if (buffer_usage_bytes < threshold_bytes) {
447 printf("error: buffer usage ratio is lower than set threshold bytes\n");
448 ret = 1;
449 goto end;
450 }
451 break;
452 default:
453 printf("error: Unknown condition type\n");
454 ret = 1;
455 goto end;
456 }
457 }
458
459 switch (condition_type) {
460 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
461 string_condition_type = string_low;
462 break;
463 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
464 string_condition_type = string_high;
465 break;
466 default:
467 printf("error: Unknown condition type\n");
468 ret = 1;
469 goto end;
470 }
471
472 printf("notification: %s %d\n", string_condition_type, nr_notifications);
473end:
474 return ret;
475}
This page took 0.04956 seconds and 4 git commands to generate.