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