4 * Tests suite for LTTng notification API (rotation notifications)
6 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * SPDX-License-Identifier: MIT
12 #include <lttng/lttng.h>
24 const char *output_path
;
27 uint64_t expected_rotation_id
= UINT64_MAX
;
29 static int test_condition(struct lttng_condition
*condition
, const char *type_name
)
32 const char *out_session_name
;
33 const char *const session_name
= "test session name";
34 enum lttng_condition_status status
;
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",
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",
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
);
50 ok(out_session_name
&& !strcmp(session_name
, out_session_name
),
51 "Session name returned by %s condition matches the expected name",
56 static int setup_rotation_trigger(const struct session
*session
,
57 struct lttng_notification_channel
*notification_channel
)
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
;
69 notify
= lttng_action_notify_create();
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
) {
82 ret
= test_condition(rotation_ongoing_condition
, "rotation ongoing");
86 condition_status
= lttng_condition_session_rotation_set_session_name(
87 rotation_ongoing_condition
, session
->name
);
88 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
90 diag("Failed to set session name on session rotation ongoing condition");
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
) {
100 ret
= test_condition(rotation_completed_condition
, "rotation completed");
102 diag("Failed to set session name on session rotation completed condition");
105 condition_status
= lttng_condition_session_rotation_set_session_name(
106 rotation_completed_condition
, session
->name
);
107 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
);
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
)
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
;
188 notification_channel_status
= lttng_notification_channel_has_pending_notification(
189 notification_channel
, ¬ification_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
) {
198 ok(notification_pending
,
199 "Session %s notification is pending on notification channel",
200 expected_notification_type_name
);
201 if (!notification_pending
) {
206 notification_channel_status
= lttng_notification_channel_get_next_notification(
207 notification_channel
, ¬ification
);
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
) {
216 condition
= lttng_notification_get_condition(notification
);
218 diag("Failed to get notification condition");
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
) {
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
) {
242 evaluation
= lttng_notification_get_evaluation(notification
);
244 diag("Failed to get notification evaluation");
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
) {
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
) {
266 if (expected_condition_type
!= LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
) {
268 * Remaining tests only apply to "session rotation completed"
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
) {
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'");
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");
294 ok(chunk_path
&& !strncmp(session
->output_path
, chunk_path
, strlen(session
->output_path
)),
295 "Returned path from location starts with the output path");
298 lttng_notification_destroy(notification
);
303 test_rotation_ongoing_notification(struct lttng_notification_channel
*notification_channel
,
304 struct session
*session
)
306 return test_notification(notification_channel
,
309 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
313 test_rotation_completed_notification(struct lttng_notification_channel
*notification_channel
,
314 struct session
*session
)
316 return test_notification(notification_channel
,
318 "rotation completed",
319 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
322 int main(int argc
, const char *argv
[])
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
;
332 puts("Usage: rotation SESSION_NAME SESSION_OUTPUT_PATH");
337 session
.name
= argv
[1];
338 session
.output_path
= argv
[2];
340 plan_tests(TEST_COUNT
);
342 notification_channel
=
343 lttng_notification_channel_create(lttng_session_daemon_notification_endpoint
);
344 if (!notification_channel
) {
345 diag("Failed to create notification channel");
350 ret
= setup_rotation_trigger(&session
, notification_channel
);
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
) {
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\"",
372 * After a rotation has completed, we can expect two notifications to
374 * - Session rotation ongoing
375 * - Session rotation completed
377 ret
= test_rotation_ongoing_notification(notification_channel
, &session
);
382 ret
= test_rotation_completed_notification(notification_channel
, &session
);
387 lttng_notification_channel_destroy(notification_channel
);
388 lttng_rotation_handle_destroy(rotation_handle
);
389 return exit_status();