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