Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / tests / regression / tools / notification / rotation.c
CommitLineData
88a5c0a9
JG
1/*
2 * rotation.c
3 *
4 * Tests suite for LTTng notification API (rotation notifications)
5 *
6 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
9d16b343 8 * SPDX-License-Identifier: MIT
88a5c0a9 9 *
88a5c0a9
JG
10 */
11
12#include <stdio.h>
13#include <unistd.h>
88a5c0a9
JG
14#include <tap/tap.h>
15#include <stdint.h>
88a5c0a9 16#include <string.h>
a5c2d2a7 17#include <lttng/lttng.h>
88a5c0a9
JG
18
19#define TEST_COUNT 36
20
21struct session {
22 const char *name;
23 const char *output_path;
24};
25
26uint64_t expected_rotation_id = UINT64_MAX;
27
28static
29int test_condition(struct lttng_condition *condition, const char *type_name)
30{
31 int ret = 0;
32 const char *out_session_name;
33 const char * const session_name = "test session name";
34 enum lttng_condition_status status;
35
36 status = lttng_condition_session_rotation_get_session_name(condition,
37 &out_session_name);
38 ok(status == LTTNG_CONDITION_STATUS_UNSET,
39 "Getting unset name of %s condition fails with LTTNG_CONDITION_STATUS_UNSET",
40 type_name);
41
42 status = lttng_condition_session_rotation_set_session_name(condition,
43 session_name);
44 ok(status == LTTNG_CONDITION_STATUS_OK,
45 "Setting session name \"%s\" of %s condition succeeds",
46 session_name, type_name);
47
48 status = lttng_condition_session_rotation_get_session_name(condition,
49 &out_session_name);
50 ok(status == LTTNG_CONDITION_STATUS_OK,
51 "Getting name of %s condition succeeds",
52 type_name);
53
54 ok(out_session_name && !strcmp(session_name, out_session_name),
55 "Session name returned by %s condition matches the expected name",
56 type_name);
88a5c0a9
JG
57 return ret;
58}
59
60static
61int setup_rotation_trigger(const struct session *session,
62 struct lttng_notification_channel *notification_channel)
63{
64 int ret;
65 struct lttng_condition *rotation_ongoing_condition = NULL;
66 struct lttng_condition *rotation_completed_condition = NULL;
67 struct lttng_action *notify = NULL;
68 struct lttng_trigger *rotation_ongoing_trigger = NULL;
69 struct lttng_trigger *rotation_completed_trigger = NULL;
70 enum lttng_condition_status condition_status;
71 enum lttng_notification_channel_status notification_channel_status;
a5c2d2a7 72 enum lttng_error_code ret_code;
88a5c0a9
JG
73
74 notify = lttng_action_notify_create();
75 if (!notify) {
76 ret = -1;
77 goto end;
78 }
79
80 /* Create rotation ongoing and completed conditions. */
81 rotation_ongoing_condition =
82 lttng_condition_session_rotation_ongoing_create();
83 ok(rotation_ongoing_condition, "Create session rotation ongoing condition");
84 if (!rotation_ongoing_condition) {
85 ret = -1;
86 goto end;
87 }
88 ret = test_condition(rotation_ongoing_condition, "rotation ongoing");
89 if (ret) {
90 goto end;
91 }
92 condition_status = lttng_condition_session_rotation_set_session_name(
93 rotation_ongoing_condition, session->name);
94 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
95 ret = -1;
96 diag("Failed to set session name on session rotation ongoing condition");
97 goto end;
98 }
99
100 rotation_completed_condition =
101 lttng_condition_session_rotation_completed_create();
102 ok(rotation_completed_condition, "Create session rotation completed condition");
103 if (!rotation_completed_condition) {
104 ret = -1;
105 goto end;
106 }
107 ret = test_condition(rotation_completed_condition, "rotation completed");
108 if (ret) {
109 diag("Failed to set session name on session rotation completed condition");
110 goto end;
111 }
112 condition_status = lttng_condition_session_rotation_set_session_name(
113 rotation_completed_condition, session->name);
114 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
115 ret = -1;
116 goto end;
117 }
118
119 notification_channel_status = lttng_notification_channel_subscribe(
120 notification_channel, rotation_ongoing_condition);
121 ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
122 "Subscribe to session rotation ongoing notifications");
123 if (notification_channel_status !=
124 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
125 ret = -1;
126 goto end;
127 }
128 notification_channel_status = lttng_notification_channel_subscribe(
129 notification_channel, rotation_completed_condition);
130 ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
131 "Subscribe to session rotation completed notifications");
132 if (notification_channel_status !=
133 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
134 ret = -1;
135 goto end;
136 }
137
138 /* Create rotation ongoing and completed triggers. */
139 rotation_ongoing_trigger = lttng_trigger_create(
140 rotation_ongoing_condition, notify);
141 ok(rotation_ongoing_trigger, "Create a rotation ongoing notification trigger");
142 if (!rotation_ongoing_trigger) {
143 ret = -1;
144 goto end;
145 }
146
147 rotation_completed_trigger = lttng_trigger_create(
148 rotation_completed_condition, notify);
149 ok(rotation_completed_trigger, "Create a rotation completed notification trigger");
150 if (!rotation_completed_trigger) {
151 ret = -1;
152 goto end;
153 }
154
155 /* Register rotation ongoing and completed triggers. */
a5c2d2a7
JG
156 ret_code = lttng_register_trigger_with_automatic_name(
157 rotation_ongoing_trigger);
158 ok(ret_code == LTTNG_OK, "Registered session rotation ongoing trigger");
159 if (ret_code != LTTNG_OK) {
160 ret = -ret_code;
88a5c0a9
JG
161 goto end;
162 }
163
a5c2d2a7
JG
164 ret_code = lttng_register_trigger_with_automatic_name(
165 rotation_completed_trigger);
166 ok(ret_code == LTTNG_OK,
167 "Registered session rotation completed trigger");
168 if (ret_code != LTTNG_OK) {
169 ret = -ret_code;
88a5c0a9
JG
170 goto end;
171 }
a5c2d2a7 172
88a5c0a9
JG
173end:
174 lttng_trigger_destroy(rotation_ongoing_trigger);
175 lttng_trigger_destroy(rotation_completed_trigger);
176 lttng_condition_destroy(rotation_ongoing_condition);
177 lttng_condition_destroy(rotation_completed_condition);
178 lttng_action_destroy(notify);
179 return ret;
180}
181
182static
183int test_notification(
184 struct lttng_notification_channel *notification_channel,
185 const struct session *session,
186 const char *expected_notification_type_name,
187 enum lttng_condition_type expected_condition_type)
188{
189 int ret = 0;
190 bool notification_pending;
191 enum lttng_notification_channel_status notification_channel_status;
192 enum lttng_condition_status condition_status;
193 enum lttng_evaluation_status evaluation_status;
194 enum lttng_trace_archive_location_status location_status;
195 enum lttng_condition_type condition_type;
196 struct lttng_notification *notification = NULL;
197 const struct lttng_condition *condition;
198 const struct lttng_evaluation *evaluation;
199 const char *session_name = NULL;
200 const struct lttng_trace_archive_location *location = NULL;
201 uint64_t rotation_id = UINT64_MAX;
202 const char *chunk_path = NULL;
203
204 notification_channel_status = lttng_notification_channel_has_pending_notification(
205 notification_channel, &notification_pending);
206 ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
207 "Check for %s notification pending on notification channel",
208 expected_notification_type_name);
209 if (notification_channel_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
210 ret = -1;
211 goto end;
212 }
213
214 ok(notification_pending,
215 "Session %s notification is pending on notification channel",
216 expected_notification_type_name);
217 if (!notification_pending) {
218 ret = -1;
219 goto end;
220 }
221
222 notification_channel_status = lttng_notification_channel_get_next_notification(
223 notification_channel, &notification);
224 ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification,
225 "Get %s notification from notification channel",
226 expected_notification_type_name);
227 if (notification_channel_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK || !notification) {
228 ret = -1;
229 goto end;
230 }
231
232 condition = lttng_notification_get_condition(notification);
233 if (!condition) {
234 diag("Failed to get notification condition");
235 ret = -1;
236 goto end;
237 }
238
239 condition_type = lttng_condition_get_type(condition);
240 ok(condition_type == expected_condition_type,
241 "Notification condition obtained from notification channel is of type \"%s\"",
242 expected_notification_type_name);
243 if (condition_type != expected_condition_type) {
244 ret = -1;
245 goto end;
246 }
247
248 condition_status = lttng_condition_session_rotation_get_session_name(
249 condition, &session_name);
250 ok(condition_status == LTTNG_CONDITION_STATUS_OK && session_name &&
251 !strcmp(session_name, session->name),
252 "Condition obtained from notification has the correct session name assigned");
253 if (condition_status != LTTNG_CONDITION_STATUS_OK || !session_name) {
254 ret = -1;
255 goto end;
256 }
257
258 evaluation = lttng_notification_get_evaluation(notification);
259 if (!evaluation) {
260 diag("Failed to get notification evaluation");
261 ret = -1;
262 goto end;
263 }
264 condition_type = lttng_evaluation_get_type(evaluation);
265 ok(condition_type == expected_condition_type,
266 "Condition evaluation obtained from notification channel is of type \"%s\"",
267 expected_notification_type_name);
268 if (condition_type != expected_condition_type) {
269 ret = -1;
270 goto end;
271 }
272
273 evaluation_status = lttng_evaluation_session_rotation_get_id(evaluation,
274 &rotation_id);
275 ok(evaluation_status == LTTNG_EVALUATION_STATUS_OK,
276 "Get %s id from notification evaluation",
277 expected_notification_type_name);
278 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
279 ret = -1;
280 goto end;
281 }
282
283 if (expected_condition_type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
284 /*
285 * Remaining tests only apply to "session rotation completed"
286 * notifications.
287 */
288 goto end;
289 }
290
291 evaluation_status = lttng_evaluation_session_rotation_completed_get_location(
292 evaluation, &location);
293 ok(evaluation_status == LTTNG_EVALUATION_STATUS_OK && location,
294 "Get session %s chunk location from evaluation",
295 expected_notification_type_name);
296 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK || !location) {
297 ret = -1;
298 goto end;
299 }
300
301 ok(lttng_trace_archive_location_get_type(location) == LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL,
302 "Location returned from the session rotation completed notification is of type 'local'");
303
304 location_status = lttng_trace_archive_location_local_get_absolute_path(
305 location, &chunk_path);
c6795a46 306 ok(location_status == LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK && chunk_path,
88a5c0a9
JG
307 "Retrieved path from location returned by the session rotation completed notification");
308 diag("Chunk available at %s", chunk_path ? chunk_path : "NULL");
c6795a46
JG
309
310 ok(chunk_path && !strncmp(session->output_path, chunk_path, strlen(session->output_path)),
88a5c0a9
JG
311 "Returned path from location starts with the output path");
312
313end:
314 lttng_notification_destroy(notification);
315 return ret;
316}
317
318static
319int test_rotation_ongoing_notification(
320 struct lttng_notification_channel *notification_channel,
321 struct session *session)
322{
323 return test_notification(notification_channel, session,
324 "rotation ongoing",
325 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
326}
327
328static
329int test_rotation_completed_notification(
330 struct lttng_notification_channel *notification_channel,
331 struct session *session)
332{
333 return test_notification(notification_channel, session,
334 "rotation completed",
335 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
336}
337
338int main(int argc, const char *argv[])
339{
340 int ret = 0;
341 struct session session = { 0 };
342 struct lttng_notification_channel *notification_channel = NULL;
343 struct lttng_rotation_handle *rotation_handle = NULL;
344 enum lttng_rotation_status rotation_status;
345 enum lttng_rotation_state rotation_state =
346 LTTNG_ROTATION_STATE_NO_ROTATION;
347
348 if (argc != 3) {
349 puts("Usage: rotation SESSION_NAME SESSION_OUTPUT_PATH");
350 ret = 1;
351 goto error;
352 }
353
354 session.name = argv[1];
355 session.output_path = argv[2];
356
357 plan_tests(TEST_COUNT);
88a5c0a9
JG
358
359 notification_channel = lttng_notification_channel_create(
360 lttng_session_daemon_notification_endpoint);
361 if (!notification_channel) {
362 diag("Failed to create notification channel");
363 ret = -1;
364 goto error;
365 }
366
367 ret = setup_rotation_trigger(&session, notification_channel);
368 if (ret) {
369 goto error;
370 }
371
372 /* Start rotation and wait for its completion. */
373 ret = lttng_rotate_session(session.name, NULL, &rotation_handle);
374 ok(ret >= 0 && rotation_handle, "Start rotation of session \"%s\"",
375 session.name);
376 if (ret < 0 || !rotation_handle) {
377 goto error;
378 }
379
380 do {
381 rotation_status = lttng_rotation_handle_get_state(
382 rotation_handle, &rotation_state);
383 } while (rotation_state == LTTNG_ROTATION_STATE_ONGOING &&
384 rotation_status == LTTNG_ROTATION_STATUS_OK);
385 ok(rotation_status == LTTNG_ROTATION_STATUS_OK &&
386 rotation_state == LTTNG_ROTATION_STATE_COMPLETED,
387 "Complete rotation of session \"%s\"", session.name);
388
389 /*
390 * After a rotation has completed, we can expect two notifications to
391 * be queued:
392 * - Session rotation ongoing
393 * - Session rotation completed
394 */
395 ret = test_rotation_ongoing_notification(notification_channel,
396 &session);
397 if (ret) {
398 goto error;
399 }
400
401 ret = test_rotation_completed_notification(notification_channel,
402 &session);
403 if (ret) {
404 goto error;
405 }
406error:
407 lttng_notification_channel_destroy(notification_channel);
408 lttng_rotation_handle_destroy(rotation_handle);
674c3e2c 409 return exit_status();
88a5c0a9 410}
This page took 0.045531 seconds and 4 git commands to generate.