4 * Tests suite for LTTng notification API (rotation notifications)
6 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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
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>
48 const char *output_path
;
51 uint64_t expected_rotation_id
= UINT64_MAX
;
54 int test_condition(struct lttng_condition
*condition
, const char *type_name
)
57 const char *out_session_name
;
58 const char * const session_name
= "test session name";
59 enum lttng_condition_status status
;
61 status
= lttng_condition_session_rotation_get_session_name(condition
,
63 ok(status
== LTTNG_CONDITION_STATUS_UNSET
,
64 "Getting unset name of %s condition fails with LTTNG_CONDITION_STATUS_UNSET",
67 status
= lttng_condition_session_rotation_set_session_name(condition
,
69 ok(status
== LTTNG_CONDITION_STATUS_OK
,
70 "Setting session name \"%s\" of %s condition succeeds",
71 session_name
, type_name
);
73 status
= lttng_condition_session_rotation_get_session_name(condition
,
75 ok(status
== LTTNG_CONDITION_STATUS_OK
,
76 "Getting name of %s condition succeeds",
79 ok(out_session_name
&& !strcmp(session_name
, out_session_name
),
80 "Session name returned by %s condition matches the expected name",
87 int setup_rotation_trigger(const struct session
*session
,
88 struct lttng_notification_channel
*notification_channel
)
91 struct lttng_condition
*rotation_ongoing_condition
= NULL
;
92 struct lttng_condition
*rotation_completed_condition
= NULL
;
93 struct lttng_action
*notify
= NULL
;
94 struct lttng_trigger
*rotation_ongoing_trigger
= NULL
;
95 struct lttng_trigger
*rotation_completed_trigger
= NULL
;
96 enum lttng_condition_status condition_status
;
97 enum lttng_notification_channel_status notification_channel_status
;
99 notify
= lttng_action_notify_create();
105 /* Create rotation ongoing and completed conditions. */
106 rotation_ongoing_condition
=
107 lttng_condition_session_rotation_ongoing_create();
108 ok(rotation_ongoing_condition
, "Create session rotation ongoing condition");
109 if (!rotation_ongoing_condition
) {
113 ret
= test_condition(rotation_ongoing_condition
, "rotation ongoing");
117 condition_status
= lttng_condition_session_rotation_set_session_name(
118 rotation_ongoing_condition
, session
->name
);
119 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
121 diag("Failed to set session name on session rotation ongoing condition");
125 rotation_completed_condition
=
126 lttng_condition_session_rotation_completed_create();
127 ok(rotation_completed_condition
, "Create session rotation completed condition");
128 if (!rotation_completed_condition
) {
132 ret
= test_condition(rotation_completed_condition
, "rotation completed");
134 diag("Failed to set session name on session rotation completed condition");
137 condition_status
= lttng_condition_session_rotation_set_session_name(
138 rotation_completed_condition
, session
->name
);
139 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
) {
144 notification_channel_status
= lttng_notification_channel_subscribe(
145 notification_channel
, rotation_ongoing_condition
);
146 ok(notification_channel_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
147 "Subscribe to session rotation ongoing notifications");
148 if (notification_channel_status
!=
149 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
) {
153 notification_channel_status
= lttng_notification_channel_subscribe(
154 notification_channel
, rotation_completed_condition
);
155 ok(notification_channel_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
156 "Subscribe to session rotation completed notifications");
157 if (notification_channel_status
!=
158 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
) {
163 /* Create rotation ongoing and completed triggers. */
164 rotation_ongoing_trigger
= lttng_trigger_create(
165 rotation_ongoing_condition
, notify
);
166 ok(rotation_ongoing_trigger
, "Create a rotation ongoing notification trigger");
167 if (!rotation_ongoing_trigger
) {
172 rotation_completed_trigger
= lttng_trigger_create(
173 rotation_completed_condition
, notify
);
174 ok(rotation_completed_trigger
, "Create a rotation completed notification trigger");
175 if (!rotation_completed_trigger
) {
180 /* Register rotation ongoing and completed triggers. */
181 ret
= lttng_register_trigger(rotation_ongoing_trigger
);
182 ok(ret
== 0, "Registered session rotation ongoing trigger");
187 ret
= lttng_register_trigger(rotation_completed_trigger
);
188 ok(ret
== 0, "Registered session rotation completed trigger");
193 lttng_trigger_destroy(rotation_ongoing_trigger
);
194 lttng_trigger_destroy(rotation_completed_trigger
);
195 lttng_condition_destroy(rotation_ongoing_condition
);
196 lttng_condition_destroy(rotation_completed_condition
);
197 lttng_action_destroy(notify
);
202 int test_notification(
203 struct lttng_notification_channel
*notification_channel
,
204 const struct session
*session
,
205 const char *expected_notification_type_name
,
206 enum lttng_condition_type expected_condition_type
)
209 bool notification_pending
;
210 enum lttng_notification_channel_status notification_channel_status
;
211 enum lttng_condition_status condition_status
;
212 enum lttng_evaluation_status evaluation_status
;
213 enum lttng_trace_archive_location_status location_status
;
214 enum lttng_condition_type condition_type
;
215 struct lttng_notification
*notification
= NULL
;
216 const struct lttng_condition
*condition
;
217 const struct lttng_evaluation
*evaluation
;
218 const char *session_name
= NULL
;
219 const struct lttng_trace_archive_location
*location
= NULL
;
220 uint64_t rotation_id
= UINT64_MAX
;
221 const char *chunk_path
= NULL
;
223 notification_channel_status
= lttng_notification_channel_has_pending_notification(
224 notification_channel
, ¬ification_pending
);
225 ok(notification_channel_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
,
226 "Check for %s notification pending on notification channel",
227 expected_notification_type_name
);
228 if (notification_channel_status
!= LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
) {
233 ok(notification_pending
,
234 "Session %s notification is pending on notification channel",
235 expected_notification_type_name
);
236 if (!notification_pending
) {
241 notification_channel_status
= lttng_notification_channel_get_next_notification(
242 notification_channel
, ¬ification
);
243 ok(notification_channel_status
== LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
&& notification
,
244 "Get %s notification from notification channel",
245 expected_notification_type_name
);
246 if (notification_channel_status
!= LTTNG_NOTIFICATION_CHANNEL_STATUS_OK
|| !notification
) {
251 condition
= lttng_notification_get_condition(notification
);
253 diag("Failed to get notification condition");
258 condition_type
= lttng_condition_get_type(condition
);
259 ok(condition_type
== expected_condition_type
,
260 "Notification condition obtained from notification channel is of type \"%s\"",
261 expected_notification_type_name
);
262 if (condition_type
!= expected_condition_type
) {
267 condition_status
= lttng_condition_session_rotation_get_session_name(
268 condition
, &session_name
);
269 ok(condition_status
== LTTNG_CONDITION_STATUS_OK
&& session_name
&&
270 !strcmp(session_name
, session
->name
),
271 "Condition obtained from notification has the correct session name assigned");
272 if (condition_status
!= LTTNG_CONDITION_STATUS_OK
|| !session_name
) {
277 evaluation
= lttng_notification_get_evaluation(notification
);
279 diag("Failed to get notification evaluation");
283 condition_type
= lttng_evaluation_get_type(evaluation
);
284 ok(condition_type
== expected_condition_type
,
285 "Condition evaluation obtained from notification channel is of type \"%s\"",
286 expected_notification_type_name
);
287 if (condition_type
!= expected_condition_type
) {
292 evaluation_status
= lttng_evaluation_session_rotation_get_id(evaluation
,
294 ok(evaluation_status
== LTTNG_EVALUATION_STATUS_OK
,
295 "Get %s id from notification evaluation",
296 expected_notification_type_name
);
297 if (evaluation_status
!= LTTNG_EVALUATION_STATUS_OK
) {
302 if (expected_condition_type
!= LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
) {
304 * Remaining tests only apply to "session rotation completed"
310 evaluation_status
= lttng_evaluation_session_rotation_completed_get_location(
311 evaluation
, &location
);
312 ok(evaluation_status
== LTTNG_EVALUATION_STATUS_OK
&& location
,
313 "Get session %s chunk location from evaluation",
314 expected_notification_type_name
);
315 if (evaluation_status
!= LTTNG_EVALUATION_STATUS_OK
|| !location
) {
320 ok(lttng_trace_archive_location_get_type(location
) == LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL
,
321 "Location returned from the session rotation completed notification is of type 'local'");
323 location_status
= lttng_trace_archive_location_local_get_absolute_path(
324 location
, &chunk_path
);
325 ok(location_status
== LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK
&& chunk_path
,
326 "Retrieved path from location returned by the session rotation completed notification");
327 diag("Chunk available at %s", chunk_path
? chunk_path
: "NULL");
329 ok(chunk_path
&& !strncmp(session
->output_path
, chunk_path
, strlen(session
->output_path
)),
330 "Returned path from location starts with the output path");
333 lttng_notification_destroy(notification
);
338 int test_rotation_ongoing_notification(
339 struct lttng_notification_channel
*notification_channel
,
340 struct session
*session
)
342 return test_notification(notification_channel
, session
,
344 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING
);
348 int test_rotation_completed_notification(
349 struct lttng_notification_channel
*notification_channel
,
350 struct session
*session
)
352 return test_notification(notification_channel
, session
,
353 "rotation completed",
354 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED
);
357 int main(int argc
, const char *argv
[])
360 struct session session
= { 0 };
361 struct lttng_notification_channel
*notification_channel
= NULL
;
362 struct lttng_rotation_handle
*rotation_handle
= NULL
;
363 enum lttng_rotation_status rotation_status
;
364 enum lttng_rotation_state rotation_state
=
365 LTTNG_ROTATION_STATE_NO_ROTATION
;
368 puts("Usage: rotation SESSION_NAME SESSION_OUTPUT_PATH");
373 session
.name
= argv
[1];
374 session
.output_path
= argv
[2];
376 plan_tests(TEST_COUNT
);
378 notification_channel
= lttng_notification_channel_create(
379 lttng_session_daemon_notification_endpoint
);
380 if (!notification_channel
) {
381 diag("Failed to create notification channel");
386 ret
= setup_rotation_trigger(&session
, notification_channel
);
391 /* Start rotation and wait for its completion. */
392 ret
= lttng_rotate_session(session
.name
, NULL
, &rotation_handle
);
393 ok(ret
>= 0 && rotation_handle
, "Start rotation of session \"%s\"",
395 if (ret
< 0 || !rotation_handle
) {
400 rotation_status
= lttng_rotation_handle_get_state(
401 rotation_handle
, &rotation_state
);
402 } while (rotation_state
== LTTNG_ROTATION_STATE_ONGOING
&&
403 rotation_status
== LTTNG_ROTATION_STATUS_OK
);
404 ok(rotation_status
== LTTNG_ROTATION_STATUS_OK
&&
405 rotation_state
== LTTNG_ROTATION_STATE_COMPLETED
,
406 "Complete rotation of session \"%s\"", session
.name
);
409 * After a rotation has completed, we can expect two notifications to
411 * - Session rotation ongoing
412 * - Session rotation completed
414 ret
= test_rotation_ongoing_notification(notification_channel
,
420 ret
= test_rotation_completed_notification(notification_channel
,
426 lttng_notification_channel_destroy(notification_channel
);
427 lttng_rotation_handle_destroy(rotation_handle
);