--- /dev/null
+/*
+ * schedule_api.c
+ *
+ * Unit tests for the session rotation schedule API
+ *
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <tap/tap.h>
+
+#include <lttng/lttng.h>
+
+#define NUM_TESTS 26
+
+#define SIZE_THRESHOLD_BYTES 1024
+#define PERIODIC_TIME_US 1000000
+
+const char *session_name;
+
+bool schedules_equal(const struct lttng_rotation_schedule *a,
+ const struct lttng_rotation_schedule *b)
+{
+ bool equal = false;
+ enum lttng_rotation_schedule_type a_type, b_type;
+ uint64_t a_value, b_value;
+ enum lttng_rotation_status status;
+
+ a_type = lttng_rotation_schedule_get_type(a);
+ b_type = lttng_rotation_schedule_get_type(b);
+ if (a_type != b_type) {
+ diag("Schedules are not of the same type (%i != %i)",
+ a_type, b_type);
+ goto end;
+ }
+
+ switch (a_type) {
+ case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
+ {
+ status = lttng_rotation_schedule_size_threshold_get_threshold(a,
+ &a_value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ diag("Failed to retrieve size threshold of schedule 'a'");
+ goto end;
+ }
+ status = lttng_rotation_schedule_size_threshold_get_threshold(b,
+ &b_value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ diag("Failed to retrieve size threshold of schedule 'b'");
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
+ {
+ status = lttng_rotation_schedule_periodic_get_period(a,
+ &a_value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ diag("Failed to retrieve period of schedule 'a'");
+ goto end;
+ }
+ status = lttng_rotation_schedule_periodic_get_period(b,
+ &b_value);
+ if (status != LTTNG_ROTATION_STATUS_OK) {
+ diag("Failed to retrieve period of schedule 'b'");
+ goto end;
+ }
+ break;
+ }
+ default:
+ diag("Unexpected schedule type: %i", a_type);
+ goto end;
+ }
+
+ equal = a_value == b_value;
+ if (!equal) {
+ diag("Schedules have different values");
+ }
+end:
+ return equal;
+}
+
+void test_add_null_session(void)
+{
+ enum lttng_rotation_status status;
+ struct lttng_rotation_schedule *size_schedule = NULL;
+
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+
+ status = lttng_session_add_rotation_schedule(NULL, size_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "NULL session name rejected by lttng_session_add_rotation_schedule()");
+}
+
+void test_add_null_schedule(void)
+{
+ enum lttng_rotation_status status;
+
+ status = lttng_session_add_rotation_schedule(session_name, NULL);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "NULL schedule rejected by lttng_session_add_rotation_schedule()");
+}
+
+void test_add_uninitialized_schedule(void)
+{
+ enum lttng_rotation_status status;
+ struct lttng_rotation_schedule *size_schedule = NULL,
+ *periodic_schedule = NULL;
+
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+ ok(size_schedule, "Created a size threshold session rotation schedule");
+
+ status = lttng_session_add_rotation_schedule(session_name,
+ size_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "Uninitialized size schedule rejected by lttng_session_add_rotation_schedule()");
+
+ periodic_schedule = lttng_rotation_schedule_periodic_create();
+ ok(periodic_schedule, "Created a periodic session rotation schedule");
+
+ status = lttng_session_add_rotation_schedule(session_name,
+ periodic_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "Uninitialized periodic schedule rejected by lttng_session_add_rotation_schedule()");
+
+ lttng_rotation_schedule_destroy(size_schedule);
+ lttng_rotation_schedule_destroy(periodic_schedule);
+}
+
+void test_remove_null_session(void)
+{
+ enum lttng_rotation_status status;
+ struct lttng_rotation_schedule *size_schedule = NULL;
+
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+
+ status = lttng_session_remove_rotation_schedule(NULL, size_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "NULL session name rejected by lttng_session_remove_rotation_schedule()");
+}
+
+void test_remove_null_schedule(void)
+{
+ enum lttng_rotation_status status;
+
+ status = lttng_session_remove_rotation_schedule(session_name, NULL);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "NULL schedule rejected by lttng_session_remove_rotation_schedule()");
+}
+
+void test_remove_uninitialized_schedule(void)
+{
+ enum lttng_rotation_status status;
+ struct lttng_rotation_schedule *size_schedule = NULL,
+ *periodic_schedule = NULL;
+
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+ status = lttng_session_remove_rotation_schedule(session_name,
+ size_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "Uninitialized size schedule rejected by lttng_session_remove_rotation_schedule()");
+
+ periodic_schedule = lttng_rotation_schedule_periodic_create();
+ status = lttng_session_remove_rotation_schedule(session_name,
+ periodic_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_INVALID,
+ "Uninitialized periodic schedule rejected by lttng_session_remove_rotation_schedule()");
+
+ lttng_rotation_schedule_destroy(size_schedule);
+ lttng_rotation_schedule_destroy(periodic_schedule);
+}
+
+void test_uninitialized_schedule_get(void)
+{
+ uint64_t value;
+ enum lttng_rotation_status status;
+ struct lttng_rotation_schedule *size_schedule = NULL,
+ *periodic_schedule = NULL;
+
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+ periodic_schedule = lttng_rotation_schedule_periodic_create();
+
+ status = lttng_rotation_schedule_size_threshold_get_threshold(
+ size_schedule, &value);
+ ok(status == LTTNG_ROTATION_STATUS_UNAVAILABLE,
+ "Getter on size threshold rotation schedule returns LTTNG_ROTATION_STATUS_UNAVAILABLE by default");
+ status = lttng_rotation_schedule_periodic_get_period(periodic_schedule,
+ &value);
+ ok(status == LTTNG_ROTATION_STATUS_UNAVAILABLE,
+ "Getter on periodic rotation schedule returns LTTNG_ROTATION_STATUS_UNAVAILABLE by default");
+
+ lttng_rotation_schedule_destroy(size_schedule);
+ lttng_rotation_schedule_destroy(periodic_schedule);
+
+}
+
+void test_add_list_remove_schedule(
+ const struct lttng_rotation_schedule *original_schedule)
+{
+ int ret;
+ unsigned int schedules_count = 0;
+ enum lttng_rotation_status status;
+ const struct lttng_rotation_schedule *list_schedule;
+ struct lttng_rotation_schedules *list_schedules;
+
+ status = lttng_session_add_rotation_schedule(session_name,
+ original_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_OK,
+ "Add a rotation schedule to session \'%s\'",
+ session_name);
+
+ ret = lttng_session_list_rotation_schedules(session_name,
+ &list_schedules);
+ ok(ret == LTTNG_OK && list_schedules,
+ "List rotation schedules of session \'%s\'",
+ session_name);
+
+ status = lttng_rotation_schedules_get_count(list_schedules,
+ &schedules_count);
+ ok(status == LTTNG_ROTATION_STATUS_OK && schedules_count == 1,
+ "Listing returned 1 rotation schedule");
+
+ list_schedule = lttng_rotation_schedules_get_at_index(list_schedules,
+ 0);
+ ok(list_schedule,
+ "Obtain the first schedule of a schedules list");
+
+ ok(schedules_equal(original_schedule, list_schedule),
+ "Schedule returned by the listing is equal to the reference schedule that was added");
+
+ status = lttng_session_remove_rotation_schedule(session_name,
+ list_schedule);
+ ok(status == LTTNG_ROTATION_STATUS_OK,
+ "Remove rotation schedule returned by the schedules listing");
+ lttng_rotation_schedules_destroy(list_schedules);
+
+ (void) lttng_session_list_rotation_schedules(session_name,
+ &list_schedules);
+ status = lttng_rotation_schedules_get_count(list_schedules,
+ &schedules_count);
+ ok(status == LTTNG_ROTATION_STATUS_OK && schedules_count == 0,
+ "Listing returned 0 rotation schedules after removal");
+
+}
+
+void test_add_list_remove_size_schedule(void)
+{
+ struct lttng_rotation_schedule *size_schedule;
+
+ diag("Add, list, and remove a size threshold rotation schedule");
+ size_schedule = lttng_rotation_schedule_size_threshold_create();
+ (void) lttng_rotation_schedule_size_threshold_set_threshold(
+ size_schedule, SIZE_THRESHOLD_BYTES);
+ test_add_list_remove_schedule(size_schedule);
+ lttng_rotation_schedule_destroy(size_schedule);
+}
+
+void test_add_list_remove_periodic_schedule(void)
+{
+ struct lttng_rotation_schedule *periodic_schedule;
+
+ diag("Add, list, and remove a periodic rotation schedule");
+ periodic_schedule = lttng_rotation_schedule_periodic_create();
+ (void) lttng_rotation_schedule_periodic_set_period(
+ periodic_schedule, PERIODIC_TIME_US);
+ test_add_list_remove_schedule(periodic_schedule);
+ lttng_rotation_schedule_destroy(periodic_schedule);
+}
+
+int main(int argc, char **argv)
+{
+ plan_tests(NUM_TESTS);
+
+ if (argc < 2) {
+ diag("Usage: schedule_api SESSION_NAME");
+ goto end;
+ }
+
+ session_name = argv[1];
+
+ diag("Argument validation");
+ test_add_null_session();
+ test_add_null_schedule();
+ test_add_uninitialized_schedule();
+ test_remove_null_session();
+ test_remove_null_schedule();
+ test_remove_uninitialized_schedule();
+ test_uninitialized_schedule_get();
+
+ test_add_list_remove_size_schedule();
+ test_add_list_remove_periodic_schedule();
+end:
+ return exit_status();
+}