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
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>
33 const char *output_path
;
36 uint64_t expected_rotation_id
= UINT64_MAX
;
39 int test_condition(struct lttng_condition
*condition
, const char *type_name
)
42 const char *out_session_name
;
43 const char * const session_name
= "test session name";
44 enum lttng_condition_status status
;
46 status
= lttng_condition_session_rotation_get_session_name(condition
,
48 ok(status
== LTTNG_CONDITION_STATUS_UNSET
,
49 "Getting unset name of %s condition fails with LTTNG_CONDITION_STATUS_UNSET",
52 status
= lttng_condition_session_rotation_set_session_name(condition
,
54 ok(status
== LTTNG_CONDITION_STATUS_OK
,
55 "Setting session name \"%s\" of %s condition succeeds",
56 session_name
, type_name
);
58 status
= lttng_condition_session_rotation_get_session_name(condition
,
60 ok(status
== LTTNG_CONDITION_STATUS_OK
,
61 "Getting name of %s condition succeeds",
64 ok(out_session_name
&& !strcmp(session_name
, out_session_name
),
65 "Session name returned by %s condition matches the expected name",
71 int setup_rotation_trigger(const struct session
*session
,
72 struct lttng_notification_channel
*notification_channel
)
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
;
83 notify
= lttng_action_notify_create();
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
) {
97 ret
= test_condition(rotation_ongoing_condition
, "rotation ongoing");
101 condition_status
= lttng_condition_session_rotation_set_session_name(
102 rotation_ongoing_condition
, session
->name
);
103 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
105 diag("Failed to set session name on session rotation ongoing condition");
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
) {
116 ret
= test_condition(rotation_completed_condition
, "rotation completed");
118 diag("Failed to set session name on session rotation completed condition");
121 condition_status
= lttng_condition_session_rotation_set_session_name(
122 rotation_completed_condition
, session
->name
);
123 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
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
) {
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
) {
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
) {
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
) {
164 /* Register rotation ongoing and completed triggers. */
165 ret
= lttng_register_trigger(rotation_ongoing_trigger
);
166 ok(ret
== 0, "Registered session rotation ongoing trigger");
171 ret
= lttng_register_trigger(rotation_completed_trigger
);
172 ok(ret
== 0, "Registered session rotation completed trigger");
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
);
186 int 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
)
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
;
207 notification_channel_status
= lttng_notification_channel_has_pending_notification(
208 notification_channel
, ¬ification_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
) {
217 ok(notification_pending
,
218 "Session %s notification is pending on notification channel",
219 expected_notification_type_name
);
220 if (!notification_pending
) {
225 notification_channel_status
= lttng_notification_channel_get_next_notification(
226 notification_channel
, ¬ification
);
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
) {
235 condition
= lttng_notification_get_condition(notification
);
237 diag("Failed to get notification condition");
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
) {
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
) {
261 evaluation
= lttng_notification_get_evaluation(notification
);
263 diag("Failed to get notification evaluation");
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
) {
276 evaluation_status
= lttng_evaluation_session_rotation_get_id(evaluation
,
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
) {
286 if (expected_condition_type
!= LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
) {
288 * Remaining tests only apply to "session rotation completed"
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
) {
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'");
307 location_status
= lttng_trace_archive_location_local_get_absolute_path(
308 location
, &chunk_path
);
309 ok(location_status
== LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK
&& chunk_path
,
310 "Retrieved path from location returned by the session rotation completed notification");
311 diag("Chunk available at %s", chunk_path
? chunk_path
: "NULL");
313 ok(chunk_path
&& !strncmp(session
->output_path
, chunk_path
, strlen(session
->output_path
)),
314 "Returned path from location starts with the output path");
317 lttng_notification_destroy(notification
);
322 int test_rotation_ongoing_notification(
323 struct lttng_notification_channel
*notification_channel
,
324 struct session
*session
)
326 return test_notification(notification_channel
, session
,
328 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
332 int test_rotation_completed_notification(
333 struct lttng_notification_channel
*notification_channel
,
334 struct session
*session
)
336 return test_notification(notification_channel
, session
,
337 "rotation completed",
338 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
341 int main(int argc
, const char *argv
[])
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
;
352 puts("Usage: rotation SESSION_NAME SESSION_OUTPUT_PATH");
357 session
.name
= argv
[1];
358 session
.output_path
= argv
[2];
360 plan_tests(TEST_COUNT
);
362 notification_channel
= lttng_notification_channel_create(
363 lttng_session_daemon_notification_endpoint
);
364 if (!notification_channel
) {
365 diag("Failed to create notification channel");
370 ret
= setup_rotation_trigger(&session
, notification_channel
);
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\"",
379 if (ret
< 0 || !rotation_handle
) {
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
);
393 * After a rotation has completed, we can expect two notifications to
395 * - Session rotation ongoing
396 * - Session rotation completed
398 ret
= test_rotation_ongoing_notification(notification_channel
,
404 ret
= test_rotation_completed_notification(notification_channel
,
410 lttng_notification_channel_destroy(notification_channel
);
411 lttng_rotation_handle_destroy(rotation_handle
);
412 return exit_status();