]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtla/tests: Add unit tests for actions module
authorTomas Glozar <tglozar@redhat.com>
Fri, 24 Apr 2026 14:02:44 +0000 (16:02 +0200)
committerTomas Glozar <tglozar@redhat.com>
Mon, 18 May 2026 09:00:52 +0000 (11:00 +0200)
Add unit tests covering all functions in the actions module, including
both valid and invalid inputs and all action types, except for
actions_perform(), where only shell and continue actions are tested.

To support testing multiple modules, the unit test build was modified so
that it links the entire rtla-in.o file. For this to work, the main()
function in rtla.c was declared weak, so that the unit test main is able
to override it.

Other included minor changes to unit tests are:

- Make unit test output verbose to show which tests are being run, now
  that we have more than 3 tests.
- Add unit_tests file to .gitignore.
- Split unit test sources to one file per test suite, and keep only
  main() function in unit_tests.c.
- Fix Makefile dependencies so that "make unit-tests" will rebuild the
  binary with the changes in the commit.

Also with the linking the entire rtla-in.o file, it now has rtla's
nr_cpus symbol, so the declaration in utils unit tests is made extern.

Assisted-by: Composer:composer-2-fast
Link: https://lore.kernel.org/r/20260424140244.958495-1-tglozar@redhat.com
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
tools/tracing/rtla/.gitignore
tools/tracing/rtla/src/rtla.c
tools/tracing/rtla/tests/unit/Build
tools/tracing/rtla/tests/unit/Makefile.unit
tools/tracing/rtla/tests/unit/actions.c [new file with mode: 0644]
tools/tracing/rtla/tests/unit/unit_tests.c
tools/tracing/rtla/tests/unit/utils.c [new file with mode: 0644]

index 4d39d64ac08c002c3163c08db4a8499e2624122e..231fb8d67f9790fb6f5b86934c74a3828e3da6be 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 rtla
 rtla-static
+unit_tests
 fixdep
 feature
 FEATURE-DUMP
index 7635c70123ab17af3b21818e1e4347ed690645a0..3398250076ea11140bf51540f2849285f28c8c16 100644 (file)
@@ -61,6 +61,9 @@ ran:
        return 1;
 }
 
+/* Set main as weak to allow overriding it for building unit test binary */
+#pragma weak main
+
 int main(int argc, char *argv[])
 {
        int retval;
index 5f1e531ea8c93cf597543c6b64bed6b4ae3bb451..2749f4cf202ac0446e752063f2ae627f5b2af4c0 100644 (file)
@@ -1,2 +1,3 @@
+unit_tests-y += utils.o
+unit_tests-y += actions.o
 unit_tests-y += unit_tests.o
-unit_tests-y +=../../src/utils.o
index 2088c9cc3571593ded03d2eeb1548679f3a8bff8..bacb00164e46687407b420dfc8c167e4423287bc 100644 (file)
@@ -3,10 +3,10 @@
 UNIT_TESTS := $(OUTPUT)unit_tests
 UNIT_TESTS_IN := $(UNIT_TESTS)-in.o
 
-$(UNIT_TESTS): $(UNIT_TESTS_IN)
-       $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $^ -lcheck
+$(UNIT_TESTS): $(UNIT_TESTS_IN) $(RTLA_IN)
+       $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $^ $(EXTLIBS) -lcheck
 
-$(UNIT_TESTS_IN):
+$(UNIT_TESTS_IN): fixdep
        make $(build)=unit_tests
 
 unit-tests: FORCE
diff --git a/tools/tracing/rtla/tests/unit/actions.c b/tools/tracing/rtla/tests/unit/actions.c
new file mode 100644 (file)
index 0000000..a5808ab
--- /dev/null
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <check.h>
+#include <signal.h>
+
+#include "../../src/actions.h"
+
+static struct actions actions_fixture;
+
+static void actions_fixture_setup(void)
+{
+       actions_init(&actions_fixture);
+}
+
+static void actions_fixture_teardown(void)
+{
+       actions_destroy(&actions_fixture);
+}
+
+START_TEST(test_actions_init)
+{
+       struct actions actions;
+
+       actions_init(&actions);
+
+       ck_assert_int_eq(actions.len, 0);
+       ck_assert_int_eq(actions.size, action_default_size);
+       ck_assert(!actions.continue_flag);
+       ck_assert_ptr_eq(actions.trace_output_inst, NULL);
+}
+END_TEST
+
+START_TEST(test_actions_destroy)
+{
+       struct actions actions;
+
+       actions_init(&actions);
+       actions_destroy(&actions);
+}
+END_TEST
+
+START_TEST(test_actions_reallocate)
+{
+       struct actions actions;
+       int i;
+
+       actions_init(&actions);
+
+       ck_assert_int_eq(actions.len, 0);
+       ck_assert_int_eq(actions.size, action_default_size);
+
+       /* Fill size of actions array */
+       for (i = 0; i < action_default_size; i++)
+               actions_add_continue(&actions);
+
+       ck_assert_int_eq(actions.len, action_default_size);
+       ck_assert_int_eq(actions.size, action_default_size);
+
+       /* Add one more action to trigger reallocation */
+       actions_add_continue(&actions);
+
+       ck_assert_int_eq(actions.len, action_default_size + 1);
+       ck_assert_int_eq(actions.size, action_default_size * 2);
+
+       actions_destroy(&actions);
+}
+END_TEST
+
+START_TEST(test_actions_add_trace_output)
+{
+       actions_add_trace_output(&actions_fixture, "trace_output.txt");
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[0].trace_output, "trace_output.txt");
+       ck_assert(actions_fixture.present[ACTION_TRACE_OUTPUT]);
+}
+END_TEST
+
+START_TEST(test_actions_add_signal)
+{
+       actions_add_signal(&actions_fixture, SIGINT, 1234);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SIGNAL);
+       ck_assert_int_eq(actions_fixture.list[0].signal, SIGINT);
+       ck_assert_int_eq(actions_fixture.list[0].pid, 1234);
+       ck_assert(actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_add_shell)
+{
+       actions_add_shell(&actions_fixture, "echo Hello");
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SHELL);
+       ck_assert_str_eq(actions_fixture.list[0].command, "echo Hello");
+       ck_assert(actions_fixture.present[ACTION_SHELL]);
+}
+END_TEST
+
+START_TEST(test_actions_add_continue)
+{
+       actions_add_continue(&actions_fixture);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_CONTINUE);
+       ck_assert(actions_fixture.present[ACTION_CONTINUE]);
+}
+END_TEST
+
+START_TEST(test_actions_add_multiple_same_action)
+{
+       actions_add_trace_output(&actions_fixture, "trace1.txt");
+       actions_add_trace_output(&actions_fixture, "trace2.txt");
+
+       ck_assert_int_eq(actions_fixture.len, 2);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[0].trace_output, "trace1.txt");
+       ck_assert_int_eq(actions_fixture.list[1].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[1].trace_output, "trace2.txt");
+       ck_assert(actions_fixture.present[ACTION_TRACE_OUTPUT]);
+}
+END_TEST
+
+START_TEST(test_actions_add_multiple_different_action)
+{
+       actions_add_trace_output(&actions_fixture, "trace_output.txt");
+       actions_add_signal(&actions_fixture, SIGINT, 1234);
+
+       ck_assert_int_eq(actions_fixture.len, 2);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[0].trace_output, "trace_output.txt");
+       ck_assert(actions_fixture.present[ACTION_TRACE_OUTPUT]);
+       ck_assert_int_eq(actions_fixture.list[1].type, ACTION_SIGNAL);
+       ck_assert_int_eq(actions_fixture.list[1].signal, SIGINT);
+       ck_assert_int_eq(actions_fixture.list[1].pid, 1234);
+       ck_assert(actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_trace_output)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "trace", "trace.txt"), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[0].trace_output, "trace.txt");
+       ck_assert(actions_fixture.present[ACTION_TRACE_OUTPUT]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_trace_output_arg)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "trace,file=trace2.txt", "trace1.txt"), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_TRACE_OUTPUT);
+       ck_assert_str_eq(actions_fixture.list[0].trace_output, "trace2.txt");
+       ck_assert(actions_fixture.present[ACTION_TRACE_OUTPUT]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_trace_output_arg_bad)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "trace,foo=bar", "trace_output.txt"), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_TRACE_OUTPUT]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,num=1,pid=1234", NULL), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SIGNAL);
+       ck_assert_int_eq(actions_fixture.list[0].signal, 1);
+       ck_assert_int_eq(actions_fixture.list[0].pid, 1234);
+       ck_assert(actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_swapped)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,pid=1234,num=1", NULL), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SIGNAL);
+       ck_assert_int_eq(actions_fixture.list[0].signal, 1);
+       ck_assert_int_eq(actions_fixture.list[0].pid, 1234);
+       ck_assert(actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_parent)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,pid=parent,num=1", NULL), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SIGNAL);
+       ck_assert_int_eq(actions_fixture.list[0].signal, 1);
+       ck_assert_int_eq(actions_fixture.list[0].pid, -1);
+       ck_assert(actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_no_arg)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_no_pid)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,num=1", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_no_num)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,pid=1234", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_signal_arg_bad)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "signal,foo=bar", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SIGNAL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_shell)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "shell,command=echo Hello", NULL), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_SHELL);
+       ck_assert_str_eq(actions_fixture.list[0].command, "echo Hello");
+       ck_assert(actions_fixture.present[ACTION_SHELL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_shell_no_arg)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "shell", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SHELL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_shell_arg_bad)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "shell,foo=bar", NULL), -1);
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_SHELL]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_continue)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "continue", NULL), 0);
+
+       ck_assert_int_eq(actions_fixture.len, 1);
+       ck_assert_int_eq(actions_fixture.list[0].type, ACTION_CONTINUE);
+       ck_assert(actions_fixture.present[ACTION_CONTINUE]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_continue_arg_bad)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "continue,foo=bar", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+       ck_assert(!actions_fixture.present[ACTION_CONTINUE]);
+}
+END_TEST
+
+START_TEST(test_actions_parse_invalid)
+{
+       ck_assert_int_eq(actions_parse(&actions_fixture, "foobar", NULL), -1);
+
+       ck_assert_int_eq(actions_fixture.len, 0);
+}
+END_TEST
+
+START_TEST(test_actions_perform_continue)
+{
+       actions_add_continue(&actions_fixture);
+       ck_assert_int_eq(actions_perform(&actions_fixture), 0);
+
+       ck_assert(actions_fixture.continue_flag);
+}
+END_TEST
+
+START_TEST(test_actions_perform_continue_after_successful_shell_command)
+{
+       actions_add_shell(&actions_fixture, "exit 0");
+       actions_add_continue(&actions_fixture);
+       ck_assert_int_eq(actions_perform(&actions_fixture), 0 << 8);
+
+       ck_assert(actions_fixture.continue_flag);
+}
+END_TEST
+
+START_TEST(test_actions_perform_continue_after_failed_shell_command)
+{
+       actions_add_shell(&actions_fixture, "exit 1");
+       actions_add_continue(&actions_fixture);
+       ck_assert_int_eq(actions_perform(&actions_fixture), 1 << 8);
+
+       ck_assert(!actions_fixture.continue_flag);
+}
+END_TEST
+
+Suite *actions_suite(void)
+{
+       Suite *s = suite_create("actions");
+       TCase *tc;
+
+       tc = tcase_create("alloc");
+       tcase_add_test(tc, test_actions_init);
+       tcase_add_test(tc, test_actions_destroy);
+       tcase_add_test(tc, test_actions_reallocate);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("add");
+       tcase_add_checked_fixture(tc, actions_fixture_setup, actions_fixture_teardown);
+       tcase_add_test(tc, test_actions_add_trace_output);
+       tcase_add_test(tc, test_actions_add_signal);
+       tcase_add_test(tc, test_actions_add_shell);
+       tcase_add_test(tc, test_actions_add_continue);
+       tcase_add_test(tc, test_actions_add_multiple_same_action);
+       tcase_add_test(tc, test_actions_add_multiple_different_action);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("parse");
+       tcase_add_checked_fixture(tc, actions_fixture_setup, actions_fixture_teardown);
+       tcase_add_test(tc, test_actions_parse_trace_output);
+       tcase_add_test(tc, test_actions_parse_trace_output_arg);
+       tcase_add_test(tc, test_actions_parse_trace_output_arg_bad);
+       tcase_add_test(tc, test_actions_parse_signal);
+       tcase_add_test(tc, test_actions_parse_signal_swapped);
+       tcase_add_test(tc, test_actions_parse_signal_parent);
+       tcase_add_test(tc, test_actions_parse_signal_no_arg);
+       tcase_add_test(tc, test_actions_parse_signal_no_pid);
+       tcase_add_test(tc, test_actions_parse_signal_no_num);
+       tcase_add_test(tc, test_actions_parse_signal_arg_bad);
+       tcase_add_test(tc, test_actions_parse_shell);
+       tcase_add_test(tc, test_actions_parse_shell_no_arg);
+       tcase_add_test(tc, test_actions_parse_shell_arg_bad);
+       tcase_add_test(tc, test_actions_parse_continue);
+       tcase_add_test(tc, test_actions_parse_continue_arg_bad);
+       tcase_add_test(tc, test_actions_parse_invalid);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("perform");
+       tcase_add_checked_fixture(tc, actions_fixture_setup, actions_fixture_teardown);
+       tcase_add_test(tc, test_actions_perform_continue);
+       tcase_add_test(tc, test_actions_perform_continue_after_successful_shell_command);
+       tcase_add_test(tc, test_actions_perform_continue_after_failed_shell_command);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
index f3c6d89e3300c3b2b99c353867a792a02f74f22b..f87d761f9b12ee8725ea850599f58f7684ea0290 100644 (file)
 
 #define _GNU_SOURCE
 #include <check.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sched.h>
-#include <limits.h>
-#include <unistd.h>
-#include <sys/sysinfo.h>
+#include <stdbool.h>
 
 #include "../../src/utils.h"
-int nr_cpus;
 
-START_TEST(test_strtoi)
-{
-       int result;
-       char buf[64];
-
-       ck_assert_int_eq(strtoi("123", &result), 0);
-       ck_assert_int_eq(result, 123);
-       ck_assert_int_eq(strtoi(" -456", &result), 0);
-       ck_assert_int_eq(result, -456);
-
-       snprintf(buf, sizeof(buf), "%d", INT_MAX);
-       ck_assert_int_eq(strtoi(buf, &result), 0);
-       snprintf(buf, sizeof(buf), "%ld", (long)INT_MAX + 1);
-       ck_assert_int_eq(strtoi(buf, &result), -1);
-
-       ck_assert_int_eq(strtoi("", &result), -1);
-       ck_assert_int_eq(strtoi("123abc", &result), -1);
-       ck_assert_int_eq(strtoi("123 ", &result), -1);
-}
-END_TEST
-
-START_TEST(test_parse_cpu_set)
-{
-       cpu_set_t set;
+Suite *utils_suite(void);
+Suite *actions_suite(void);
 
-       nr_cpus = 8;
-       ck_assert_int_eq(parse_cpu_set("0", &set), 0);
-       ck_assert(CPU_ISSET(0, &set));
-       ck_assert(!CPU_ISSET(1, &set));
-
-       ck_assert_int_eq(parse_cpu_set("0,2", &set), 0);
-       ck_assert(CPU_ISSET(0, &set));
-       ck_assert(CPU_ISSET(2, &set));
-
-       ck_assert_int_eq(parse_cpu_set("0-3", &set), 0);
-       ck_assert(CPU_ISSET(0, &set));
-       ck_assert(CPU_ISSET(1, &set));
-       ck_assert(CPU_ISSET(2, &set));
-       ck_assert(CPU_ISSET(3, &set));
-
-       ck_assert_int_eq(parse_cpu_set("1-3,5", &set), 0);
-       ck_assert(!CPU_ISSET(0, &set));
-       ck_assert(CPU_ISSET(1, &set));
-       ck_assert(CPU_ISSET(2, &set));
-       ck_assert(CPU_ISSET(3, &set));
-       ck_assert(!CPU_ISSET(4, &set));
-       ck_assert(CPU_ISSET(5, &set));
-
-       ck_assert_int_eq(parse_cpu_set("-1", &set), 1);
-       ck_assert_int_eq(parse_cpu_set("abc", &set), 1);
-       ck_assert_int_eq(parse_cpu_set("9999", &set), 1);
-}
-END_TEST
-
-START_TEST(test_parse_prio)
-{
-       struct sched_attr attr;
-
-       ck_assert_int_eq(parse_prio("f:50", &attr), 0);
-       ck_assert_uint_eq(attr.sched_policy, SCHED_FIFO);
-       ck_assert_uint_eq(attr.sched_priority, 50U);
-
-       ck_assert_int_eq(parse_prio("r:30", &attr), 0);
-       ck_assert_uint_eq(attr.sched_policy, SCHED_RR);
-
-       ck_assert_int_eq(parse_prio("o:0", &attr), 0);
-       ck_assert_uint_eq(attr.sched_policy, SCHED_OTHER);
-       ck_assert_int_eq(attr.sched_nice, 0);
-
-       ck_assert_int_eq(parse_prio("d:10ms:100ms", &attr), 0);
-       ck_assert_uint_eq(attr.sched_policy, 6U);
-
-       ck_assert_int_eq(parse_prio("f:999", &attr), -1);
-       ck_assert_int_eq(parse_prio("o:-20", &attr), -1);
-       ck_assert_int_eq(parse_prio("d:100ms:10ms", &attr), -1);
-       ck_assert_int_eq(parse_prio("x:50", &attr), -1);
-}
-END_TEST
-
-Suite *utils_suite(void)
-{
-       Suite *s = suite_create("utils");
-       TCase *tc = tcase_create("core");
-
-       tcase_add_test(tc, test_strtoi);
-       tcase_add_test(tc, test_parse_cpu_set);
-       tcase_add_test(tc, test_parse_prio);
-
-       suite_add_tcase(s, tc);
-       return s;
-}
-
-int main(void)
+int main(int argc, char *argv[])
 {
        int num_failed;
        SRunner *sr;
 
        sr = srunner_create(utils_suite());
-       srunner_run_all(sr, CK_NORMAL);
+       srunner_add_suite(sr, actions_suite());
+
+       srunner_run_all(sr, CK_VERBOSE);
        num_failed = srunner_ntests_failed(sr);
 
        srunner_free(sr);
diff --git a/tools/tracing/rtla/tests/unit/utils.c b/tools/tracing/rtla/tests/unit/utils.c
new file mode 100644 (file)
index 0000000..ce53cab
--- /dev/null
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <check.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/sysinfo.h>
+
+#include "../../src/utils.h"
+
+extern int nr_cpus;
+
+START_TEST(test_strtoi)
+{
+       int result;
+       char buf[64];
+
+       ck_assert_int_eq(strtoi("123", &result), 0);
+       ck_assert_int_eq(result, 123);
+       ck_assert_int_eq(strtoi(" -456", &result), 0);
+       ck_assert_int_eq(result, -456);
+
+       snprintf(buf, sizeof(buf), "%d", INT_MAX);
+       ck_assert_int_eq(strtoi(buf, &result), 0);
+       snprintf(buf, sizeof(buf), "%ld", (long)INT_MAX + 1);
+       ck_assert_int_eq(strtoi(buf, &result), -1);
+
+       ck_assert_int_eq(strtoi("", &result), -1);
+       ck_assert_int_eq(strtoi("123abc", &result), -1);
+       ck_assert_int_eq(strtoi("123 ", &result), -1);
+}
+END_TEST
+
+START_TEST(test_parse_cpu_set)
+{
+       cpu_set_t set;
+
+       nr_cpus = 8;
+       ck_assert_int_eq(parse_cpu_set("0", &set), 0);
+       ck_assert(CPU_ISSET(0, &set));
+       ck_assert(!CPU_ISSET(1, &set));
+
+       ck_assert_int_eq(parse_cpu_set("0,2", &set), 0);
+       ck_assert(CPU_ISSET(0, &set));
+       ck_assert(CPU_ISSET(2, &set));
+
+       ck_assert_int_eq(parse_cpu_set("0-3", &set), 0);
+       ck_assert(CPU_ISSET(0, &set));
+       ck_assert(CPU_ISSET(1, &set));
+       ck_assert(CPU_ISSET(2, &set));
+       ck_assert(CPU_ISSET(3, &set));
+
+       ck_assert_int_eq(parse_cpu_set("1-3,5", &set), 0);
+       ck_assert(!CPU_ISSET(0, &set));
+       ck_assert(CPU_ISSET(1, &set));
+       ck_assert(CPU_ISSET(2, &set));
+       ck_assert(CPU_ISSET(3, &set));
+       ck_assert(!CPU_ISSET(4, &set));
+       ck_assert(CPU_ISSET(5, &set));
+
+       ck_assert_int_eq(parse_cpu_set("-1", &set), 1);
+       ck_assert_int_eq(parse_cpu_set("abc", &set), 1);
+       ck_assert_int_eq(parse_cpu_set("9999", &set), 1);
+}
+END_TEST
+
+START_TEST(test_parse_prio)
+{
+       struct sched_attr attr;
+
+       ck_assert_int_eq(parse_prio("f:50", &attr), 0);
+       ck_assert_uint_eq(attr.sched_policy, SCHED_FIFO);
+       ck_assert_uint_eq(attr.sched_priority, 50U);
+
+       ck_assert_int_eq(parse_prio("r:30", &attr), 0);
+       ck_assert_uint_eq(attr.sched_policy, SCHED_RR);
+
+       ck_assert_int_eq(parse_prio("o:0", &attr), 0);
+       ck_assert_uint_eq(attr.sched_policy, SCHED_OTHER);
+       ck_assert_int_eq(attr.sched_nice, 0);
+
+       ck_assert_int_eq(parse_prio("d:10ms:100ms", &attr), 0);
+       ck_assert_uint_eq(attr.sched_policy, 6U);
+
+       ck_assert_int_eq(parse_prio("f:999", &attr), -1);
+       ck_assert_int_eq(parse_prio("o:-20", &attr), -1);
+       ck_assert_int_eq(parse_prio("d:100ms:10ms", &attr), -1);
+       ck_assert_int_eq(parse_prio("x:50", &attr), -1);
+}
+END_TEST
+
+Suite *utils_suite(void)
+{
+       Suite *s = suite_create("utils");
+       TCase *tc = tcase_create("core");
+
+       tcase_add_test(tc, test_strtoi);
+       tcase_add_test(tc, test_parse_cpu_set);
+       tcase_add_test(tc, test_parse_prio);
+
+       suite_add_tcase(s, tc);
+       return s;
+}