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