Fix: tests: base notification client: unchecked sscanf return value
[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;
9d596320
JG
95 sscanf_ret = sscanf(buffer_usage_threshold_value, "%" SCNu64,
96 &threshold_bytes);
97 if (sscanf_ret != 1) {
98 printf("error: Invalid buffer usage threshold value bytes (integer), sscanf returned %d\n",
99 sscanf_ret);
100 goto error;
101 }
434f8068
JR
102 }
103
104 if (!strcasecmp("ratio", buffer_usage_threshold_type)) {
105 is_threshold_ratio = true;
9d596320
JG
106 sscanf_ret = sscanf(buffer_usage_threshold_value, "%lf",
107 &threshold_ratio);
108 if (sscanf_ret != 1) {
109 printf("error: Invalid buffer usage threshold value ratio (float), sscanf returned %d\n",
110 sscanf_ret);
111 goto error;
112 }
434f8068
JR
113 }
114
115 /* Number of notification to expect */
e062fb02
JG
116 sscanf_ret = sscanf(nr_expected_notifications_string, "%d",
117 &nr_expected_notifications);
118 if (sscanf_ret != 1) {
119 printf("error: Invalid nr_expected_notifications, sscanf returned %d\n",
120 sscanf_ret);
121 goto error;
122 }
434f8068 123
091fa780 124 /* Put notify action in a group. */
702f26c8
JR
125 if (!strcasecmp("1", use_action_list_value)) {
126 use_action_list = true;
091fa780
FD
127 }
128
434f8068
JR
129 return 0;
130error:
131 return 1;
132}
133
134int main(int argc, char **argv)
135{
136 int ret = 0;
137 enum lttng_condition_status condition_status;
091fa780 138 enum lttng_action_status action_status;
434f8068
JR
139 enum lttng_notification_channel_status nc_status;
140 struct lttng_notification_channel *notification_channel = NULL;
141 struct lttng_condition *condition = NULL;
142 struct lttng_action *action = NULL;
143 struct lttng_trigger *trigger = NULL;
a5c2d2a7 144 enum lttng_error_code ret_code;
434f8068
JR
145
146 /*
147 * Disable buffering on stdout.
148 * Safety measure to prevent hang on the validation side since
149 * stdout is used for outside synchronization.
150 */
151 setbuf(stdout, NULL);
152
091fa780 153 if (argc < 9) {
434f8068
JR
154 printf("error: Missing arguments for tests\n");
155 ret = 1;
156 goto end;
157 }
158
159 ret = parse_arguments(argv);
160 if (ret) {
161 printf("error: Could not parse arguments\n");
162 goto end;
163 }
164
165 /* Setup */
166 notification_channel = lttng_notification_channel_create(
167 lttng_session_daemon_notification_endpoint);
168 if (!notification_channel) {
169 printf("error: Could not create notification channel\n");
170 ret = 1;
171 goto end;
172 }
173
174 switch (buffer_usage_type) {
175 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
176 condition = lttng_condition_buffer_usage_low_create();
177 break;
178 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
179 condition = lttng_condition_buffer_usage_high_create();
180 break;
181 default:
182 printf("error: Invalid buffer_usage_type\n");
183 ret = 1;
184 goto end;
185 }
186
187 if (!condition) {
188 printf("error: Could not create condition object\n");
189 ret = 1;
190 goto end;
191 }
192
193 if (is_threshold_ratio) {
194 condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
195 condition, threshold_ratio);
196 } else {
197 condition_status = lttng_condition_buffer_usage_set_threshold(
198 condition, threshold_bytes);
199 }
200
201 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
202 printf("error: Could not set threshold\n");
203 ret = 1;
204 goto end;
205 }
206
207 condition_status = lttng_condition_buffer_usage_set_session_name(
208 condition, session_name);
209 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
210 printf("error: Could not set session name\n");
211 ret = 1;
212 goto end;
213 }
214 condition_status = lttng_condition_buffer_usage_set_channel_name(
215 condition, channel_name);
216 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
217 printf("error: Could not set channel name\n");
218 ret = 1;
219 goto end;
220 }
221 condition_status = lttng_condition_buffer_usage_set_domain_type(
854382b8 222 condition, domain_type);
434f8068
JR
223 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
224 printf("error: Could not set domain type\n");
225 ret = 1;
226 goto end;
227 }
228
702f26c8 229 if (use_action_list) {
091fa780
FD
230 struct lttng_action *notify, *group;
231
702f26c8 232 group = lttng_action_list_create();
091fa780 233 if (!group) {
702f26c8 234 printf("error: Could not create action list\n");
091fa780
FD
235 ret = 1;
236 goto end;
237 }
238
239 notify = lttng_action_notify_create();
240 if (!notify) {
241 lttng_action_destroy(group);
242 printf("error: Could not create action notify\n");
243 ret = 1;
244 goto end;
245 }
246
702f26c8 247 action_status = lttng_action_list_add_action(group, notify);
091fa780 248 if (action_status != LTTNG_ACTION_STATUS_OK) {
702f26c8 249 printf("error: Could not add action notify to action list\n");
091fa780
FD
250 lttng_action_destroy(group);
251 lttng_action_destroy(notify);
252 ret = 1;
253 goto end;
254 }
255
256 action = group;
257 } else {
258 action = lttng_action_notify_create();
259 if (!action) {
260 printf("error: Could not create action notify\n");
261 ret = 1;
262 goto end;
263 }
434f8068
JR
264 }
265
266 trigger = lttng_trigger_create(condition, action);
267 if (!trigger) {
268 printf("error: Could not create trigger\n");
269 ret = 1;
270 goto end;
271 }
272
a5c2d2a7 273 ret_code = lttng_register_trigger_with_automatic_name(trigger);
434f8068
JR
274
275 /*
276 * An equivalent trigger might already be registered if an other app
277 * registered an equivalent trigger.
278 */
a5c2d2a7
JG
279 if (ret_code != LTTNG_OK && ret_code != LTTNG_ERR_TRIGGER_EXISTS) {
280 printf("error: %s\n", lttng_strerror(-ret_code));
434f8068
JR
281 ret = 1;
282 goto end;
283 }
284
285 nc_status = lttng_notification_channel_subscribe(notification_channel, condition);
286 if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
287 printf("error: Could not subscribe\n");
288 ret = 1;
289 goto end;
290 }
291
292 /* Tell outside process that the client is ready */
293 printf("sync: ready\n");
294
295 for (;;) {
296 struct lttng_notification *notification;
297 enum lttng_notification_channel_status status;
298 const struct lttng_evaluation *notification_evaluation;
299 const struct lttng_condition *notification_condition;
300
301 if (nr_notifications == nr_expected_notifications) {
302 ret = 0;
303 goto end;
304 }
305 /* Receive the next notification. */
306 status = lttng_notification_channel_get_next_notification(
307 notification_channel,
308 &notification);
309
310 switch (status) {
311 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
312 break;
313 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
314 ret = 1;
315 printf("error: No drop should be observed during this test app\n");
316 goto end;
317 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
318 /*
319 * The notification channel has been closed by the
320 * session daemon. This is typically caused by a session
321 * daemon shutting down (cleanly or because of a crash).
322 */
323 printf("error: Notification channel was closed\n");
324 ret = 1;
325 goto end;
326 default:
327 /* Unhandled conditions / errors. */
091fa780 328 printf("error: Unknown notification channel status (%d) \n", status);
434f8068
JR
329 ret = 1;
330 goto end;
331 }
332
333 notification_condition = lttng_notification_get_condition(notification);
334 notification_evaluation = lttng_notification_get_evaluation(notification);
335
336 ret = handle_condition(notification_condition, notification_evaluation);
337 nr_notifications++;
338
339 lttng_notification_destroy(notification);
340 if (ret != 0) {
341 goto end;
342 }
343 }
344end:
345 if (trigger) {
346 lttng_unregister_trigger(trigger);
347 }
eff748d0
JR
348 if (lttng_notification_channel_unsubscribe(notification_channel, condition)) {
349 printf("error: channel unsubscribe error\n");
350 }
434f8068
JR
351 lttng_trigger_destroy(trigger);
352 lttng_condition_destroy(condition);
353 lttng_action_destroy(action);
354 lttng_notification_channel_destroy(notification_channel);
355 printf("exit: %d\n", ret);
356 return ret;
357}
358
359int handle_condition(
360 const struct lttng_condition *condition,
361 const struct lttng_evaluation *evaluation)
362{
363 int ret = 0;
364 const char *string_low = "low";
365 const char *string_high = "high";
366 const char *string_condition_type = NULL;
367 const char *condition_session_name = NULL;
368 const char *condition_channel_name = NULL;
369 enum lttng_condition_type condition_type;
370 enum lttng_domain_type condition_domain_type;
371 double buffer_usage_ratio;
372 uint64_t buffer_usage_bytes;
373
374 condition_type = lttng_condition_get_type(condition);
375
376 if (condition_type != buffer_usage_type) {
377 ret = 1;
378 printf("error: condition type and buffer usage type are not the same\n");
379 goto end;
380 }
381
382 /* Fetch info to test */
eff748d0 383 ret = lttng_condition_buffer_usage_get_session_name(condition,
434f8068 384 &condition_session_name);
eff748d0
JR
385 if (ret) {
386 printf("error: session name could not be fetched\n");
387 ret = 1;
388 goto end;
389 }
390 ret = lttng_condition_buffer_usage_get_channel_name(condition,
434f8068 391 &condition_channel_name);
eff748d0
JR
392 if (ret) {
393 printf("error: channel name could not be fetched\n");
394 ret = 1;
395 goto end;
396 }
397 ret = lttng_condition_buffer_usage_get_domain_type(condition,
434f8068 398 &condition_domain_type);
eff748d0
JR
399 if (ret) {
400 printf("error: domain type could not be fetched\n");
401 ret = 1;
402 goto end;
403 }
434f8068
JR
404
405 if (strcmp(condition_session_name, session_name) != 0) {
406 printf("error: session name differs\n");
407 ret = 1;
408 goto end;
409 }
410
411 if (strcmp(condition_channel_name, channel_name) != 0) {
412 printf("error: channel name differs\n");
413 ret = 1;
414 goto end;
415 }
416
417 if (condition_domain_type != domain_type) {
418 printf("error: domain type differs\n");
419 ret = 1;
420 goto end;
421 }
422
423 if (is_threshold_ratio) {
424 lttng_evaluation_buffer_usage_get_usage_ratio(
425 evaluation, &buffer_usage_ratio);
426 switch (condition_type) {
427 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
428 if (buffer_usage_ratio > threshold_ratio) {
429 printf("error: buffer usage ratio is bigger than set threshold ratio\n");
430 ret = 1;
431 goto end;
432 }
433 break;
434 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
435 if (buffer_usage_ratio < threshold_ratio) {
436 printf("error: buffer usage ratio is lower than set threshold ratio\n");
437 ret = 1;
438 goto end;
439 }
440 break;
441 default:
442 printf("error: Unknown condition type\n");
443 ret = 1;
444 goto end;
445 }
446 } else {
447 lttng_evaluation_buffer_usage_get_usage(
448 evaluation, &buffer_usage_bytes);
449 switch (condition_type) {
450 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
451 if (buffer_usage_bytes > threshold_bytes) {
452 printf("error: buffer usage ratio is bigger than set threshold bytes\n");
453 ret = 1;
454 goto end;
455 }
456 break;
457 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
458 if (buffer_usage_bytes < threshold_bytes) {
459 printf("error: buffer usage ratio is lower than set threshold bytes\n");
460 ret = 1;
461 goto end;
462 }
463 break;
464 default:
465 printf("error: Unknown condition type\n");
466 ret = 1;
467 goto end;
468 }
469 }
470
471 switch (condition_type) {
472 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
473 string_condition_type = string_low;
474 break;
475 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
476 string_condition_type = string_high;
477 break;
478 default:
479 printf("error: Unknown condition type\n");
480 ret = 1;
481 goto end;
482 }
483
484 printf("notification: %s %d\n", string_condition_type, nr_notifications);
485end:
486 return ret;
487}
This page took 0.050062 seconds and 4 git commands to generate.