Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "GPL";
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, unsigned int);
__type(value, unsigned long long);
} rtla_test_map SEC(".maps");
struct trace_event_raw_timerlat_sample;
SEC("tp/timerlat_action")
int action_handler(struct trace_event_raw_timerlat_sample *tp_args)
{
unsigned int key = 0;
unsigned long long value = 42;
bpf_map_update_elem(&rtla_test_map, &key, &value, BPF_ANY);
return 0;
}
@@ -0,0 +1,166 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
test_begin() {
# Count tests to allow the test harness to double-check if all were
# included correctly.
ctr=0
# Set test directory to the directory of the script
scriptfile=$(realpath "$0")
testdir=$(dirname "$scriptfile")
[ -z "$RTLA" ] && RTLA="./rtla"
[ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT"
}
reset_osnoise() {
# Reset osnoise options to default and remove any dangling instances created
# by improperly exited rtla runs.
pushd /sys/kernel/tracing >/dev/null || return 1
# Remove dangling instances created by previous rtla run
echo 0 > tracing_thresh
cd instances
for i in osnoise_top osnoise_hist timerlat_top timerlat_hist
do
[ ! -d "$i" ] && continue
rmdir "$i"
done
# Reset options to default
# Note: those are copied from the default values of osnoise_data
# in kernel/trace/trace_osnoise.c
cd ../osnoise
echo all > cpus
echo DEFAULTS > options
echo 1000000 > period_us
echo 0 > print_stack
echo 1000000 > runtime_us
echo 0 > stop_tracing_total_us
echo 0 > stop_tracing_us
echo 1000 > timerlat_period_us
popd >/dev/null
}
check() {
test_name=$0
tested_command=$1
expected_exitcode=${3:-0}
expected_output=$4
unexpected_output=$5
# Simple check: run rtla with given arguments and test exit code.
# If TEST_COUNT is set, run the test. Otherwise, just count.
ctr=$(($ctr + 1))
if [ -n "$TEST_COUNT" ]
then
# Reset osnoise options before running test.
[ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise
# Create a temporary directory to contain rtla output
tmpdir=$(mktemp -d)
pushd $tmpdir >/dev/null
# Run rtla; in case of failure, include its output as comment
# in the test results.
result=$(eval stdbuf -oL $TIMEOUT "$RTLA" $2 2>&1); exitcode=$?
failbuf=''
fail=0
# Test if the results matches if requested
if [ -n "$expected_output" ] && ! grep -qE "$expected_output" <<< "$result"
then
fail=1
failbuf+=$(printf "# Output match failed: \"%s\"" "$expected_output")
failbuf+=$'\n'
fi
if [ -n "$unexpected_output" ] && grep -qE "$unexpected_output" <<< "$result"
then
fail=1
failbuf+=$(printf "# Output non-match failed: \"%s\"" "$unexpected_output")
failbuf+=$'\n'
fi
if [ $exitcode -eq $expected_exitcode ] && [ $fail -eq 0 ]
then
echo "ok $ctr - $1"
else
# Add rtla output and exit code as comments in case of failure
echo "not ok $ctr - $1"
echo -n "$failbuf"
echo "$result" | col -b | while read line; do echo "# $line"; done
printf "#\n# exit code %s\n" $exitcode
fi
# Remove temporary directory
popd >/dev/null
rm -r $tmpdir
fi
}
check_with_osnoise_options() {
# Do the same as "check", but with pre-set osnoise options.
# Note: rtla should reset the osnoise options, this is used to test
# if it indeed does so.
# Save original arguments
arg1=$1
arg2=$2
arg3=$3
# Apply osnoise options (if not dry run)
if [ -n "$TEST_COUNT" ]
then
[ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise
shift
shift
while shift
do
[ "$1" == "" ] && continue
option=$(echo $1 | cut -d '=' -f 1)
value=$(echo $1 | cut -d '=' -f 2)
echo "$value" > "/sys/kernel/tracing/osnoise/$option" || return 1
done
fi
NO_RESET_OSNOISE=1 check "$arg1" "$arg2" "$arg3"
}
check_top_hist() {
# Test one command with both "top" and "hist" tools, replacing "TOOL" in
# command with either "top" or "hist" respectively, and prefixing the test
# names with "top " and "hist ".
check "top $1" "$(echo "$2" | sed 's/TOOL/top/g')" "${@:3}"
check "hist $1" "$(echo "$2" | sed 's/TOOL/hist/g')" "${@:3}"
}
check_top_q_hist() {
# Same as above, but pass "-q" to top so that strings printed in main
# loop are on their own line for top too, not only for hist.
check "top $1" "$(echo "$2" | sed 's/TOOL/top -q/g')" "${@:3}"
check "hist $1" "$(echo "$2" | sed 's/TOOL/hist/g')" "${@:3}"
}
set_timeout() {
TIMEOUT="timeout -v -k 15s $1"
}
unset_timeout() {
unset TIMEOUT
}
set_no_reset_osnoise() {
NO_RESET_OSNOISE=1
}
unset_no_reset_osnoise() {
unset NO_RESET_OSNOISE
}
test_end() {
# If running without TEST_COUNT, tests are not actually run, just
# counted. In that case, re-run the test with the correct count.
[ -z "$TEST_COUNT" ] && TEST_COUNT=$ctr exec bash $0 || true
}
# Avoid any environmental discrepancies
export LC_ALL=C
unset_timeout
@@ -0,0 +1,22 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source tests/engine.sh
test_begin
set_timeout 2m
check "verify help page" \
"hwnoise --help" 129 "Usage: rtla hwnoise"
check "detect noise higher than one microsecond" \
"hwnoise -c 0 -T 1 -d 5s -q" 0
check "set the automatic trace mode" \
"hwnoise -a 5 -d 10s" 2 "osnoise hit stop tracing"
check "set scheduling param to the osnoise tracer threads" \
"hwnoise -P F:1 -c 0 -r 900000 -d 10s -q"
check "stop the trace if a single sample is higher than 1 us" \
"hwnoise -s 1 -T 1 -t -d 10s" 2 "Saving trace to osnoise_trace.txt"
check "enable a trace event trigger" \
"hwnoise -t -e osnoise:irq_noise --trigger=\"hist:key=desc,duration:sort=desc,duration:vals=hitcount\" -d 10s" \
0 "Saving event osnoise:irq_noise hist to osnoise_irq_noise_hist.txt"
test_end
@@ -0,0 +1,73 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source tests/engine.sh
test_begin
set_timeout 2m
check "verify help page" \
"osnoise --help" 129 "osnoise version"
check_top_hist "verify help page" \
"osnoise TOOL --help" 129 "rtla osnoise"
check_top_q_hist "verify the --stop/-s param" \
"osnoise TOOL -s 30 -T 1" 2 "osnoise hit stop tracing"
check_top_q_hist "verify the --trace param" \
"osnoise TOOL -s 30 -T 1 -t" 2 "Saving trace to osnoise_trace.txt"
# Thread tests
check_top_q_hist "verify the --priority/-P param" \
"osnoise TOOL -P F:1 -c 0 -r 900000 -d 10s -S 1 --on-threshold shell,command=\"$testdir/scripts/check-priority.sh SCHED_FIFO 1\"" \
2 "Priorities are set correctly"
check_top_q_hist "verify the -C/--cgroup param" \
"osnoise TOOL -C -c 0 -r 900000 -d 10s -S 1 --on-threshold shell,command=\"$testdir/scripts/check-cgroup-match.sh\"" \
2 "cgroup matches for all workload PIDs"
check_top_q_hist "verify the -c/--cpus param" \
"osnoise TOOL -P F:1 -c 0 -r 900000 -d 10s -S 1 --on-threshold shell,command=$testdir/scripts/check-cpus.sh" 2 "^Affinity of threads: 0$"
check_top_q_hist "verify the -H/--house-keeping param" \
"osnoise TOOL -P F:1 -H 0 -r 900000 -d 10s -S 1 --on-threshold shell,command=$testdir/scripts/check-housekeeping-cpus.sh" 2 "^Affinity of threads: 0$"
# Histogram tests
check "hist with -b/--bucket-size" \
"osnoise hist -b 1 -d 1s"
check "hist with -E/--entries" \
"osnoise hist -E 10 -d 1s"
check "hist with -E/--entries out of range" \
"osnoise hist -E 1 -d 1s" 1 "^Entries must be > 10 and < 10000000$"
check "hist with --no-header" \
"osnoise hist --no-header -d 1s" 0 "" "RTLA osnoise histogram"
check "hist with --with-zeros" \
"osnoise hist --with-zeros -b 100000 -E 21 -d 1s" 0 '^2000000\s+0\s+'
check "hist with --no-index" \
"osnoise hist --no-index --with-zeros -d 1s" 0 "" "^count:"
check "hist with --no-summary" \
"osnoise hist --no-summary -d 1s" 0 "" "^count:"
# Test setting default period by putting an absurdly high period
# and stopping on threshold.
# If default period is not set, this will time out.
check_with_osnoise_options "apply default period" \
"osnoise hist -s 1" 2 period_us=600000000
# Actions tests
check_top_q_hist "trace output through -t with custom filename" \
"osnoise TOOL -S 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check_top_q_hist "trace output through --on-threshold trace" \
"osnoise TOOL -S 2 --on-threshold trace" 2 "^ Saving trace to osnoise_trace.txt$"
check_top_q_hist "trace output through --on-threshold trace with custom filename" \
"osnoise TOOL -S 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check_top_q_hist "exec command" \
"osnoise TOOL -S 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
check_top_q_hist "multiple actions" \
"osnoise TOOL -S 2 --on-threshold shell,command='echo -n 1' --on-threshold shell,command='echo 2'" 2 "^12$"
check "hist stop at failed action" \
"osnoise hist -S 2 --on-threshold shell,command='echo -n 1; false' --on-threshold shell,command='echo -n 2'" 2 "^1# RTLA osnoise histogram$"
check "top stop at failed action" \
"osnoise top -S 2 --on-threshold shell,command='echo -n abc; false' --on-threshold shell,command='echo -n defgh'" 2 "^abc" "defgh"
check_top_q_hist "with continue" \
"osnoise TOOL -S 2 -d 5s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
check_top_q_hist "with conditional continue" \
"osnoise TOOL -S 2 --on-threshold shell,command='if [ -f a ]; then echo 2; exit 1; else echo -n 1; touch a; fi' --on-threshold continue" 2 "^12$" "^2$"
check_top_hist "with trace output at end" \
"osnoise TOOL -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.txt$"
test_end
@@ -0,0 +1,17 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
. "$(dirname $0)/lib/get_workload_pids.sh"
rtla_pid=$(echo $(ps -o ppid= $$))
rtla_cgroup=$(</proc/$rtla_pid/cgroup)
echo "RTLA cgroup: $rtla_cgroup"
for pid in $(get_workload_pids)
do
pid_cgroup=$(</proc/$pid/cgroup)
echo "PID $pid cgroup: $pid_cgroup"
if ! [ "$pid_cgroup" = "$rtla_cgroup" ]
then
echo "Mismatch!"
exit 0
fi
done
echo "cgroup matches for all workload PIDs"
@@ -0,0 +1,9 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
. "$(dirname $0)/lib/get_workload_pids.sh"
echo -n "Affinity of threads: "
for pid in $(get_workload_pids)
do
echo -n $(taskset -c -p $pid | cut -d ':' -f 2)
done
echo
@@ -0,0 +1,4 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
pid=$(ps -o ppid= $$)
echo "Affinity of threads:$(taskset -c -p $pid | cut -d ':' -f 2)"
@@ -0,0 +1,8 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
. "$(dirname $0)/lib/get_workload_pids.sh"
for pid in $(get_workload_pids)
do
chrt -p $pid | cut -d ':' -f 2 | head -n1 | grep "^ $1\$" >/dev/null
chrt -p $pid | cut -d ':' -f 2 | tail -n1 | grep "^ $2\$" >/dev/null
done && echo "Priorities are set correctly"
@@ -0,0 +1,16 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
. "$(dirname $0)/lib/get_workload_pids.sh"
kthreadd_pid=$(pgrep ^kthreadd$)
cnt_kernel=0
cnt_user=0
for pid in $(get_workload_pids)
do
if [ "$(echo $(ps -o ppid= $pid))" = "$kthreadd_pid" ]
then
((++cnt_kernel))
else
((++cnt_user))
fi
done
echo "$cnt_kernel kernel threads, $cnt_user user threads"
@@ -0,0 +1,11 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
get_workload_pids() {
local shell_pid=$$
local rtla_pid=$(ps -o ppid= $shell_pid)
# kernel threads
pgrep -P $(pgrep ^kthreadd$) -f '^\[?(osnoise|timerlat)/[0-9]+\]?$'
# user threads
pgrep -P $rtla_pid | grep -v "^$shell_pid$"
}
@@ -0,0 +1,118 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source tests/engine.sh
test_begin
set_timeout 2m
timerlat_sample_event='/sys/kernel/tracing/events/osnoise/timerlat_sample'
if ldd $RTLA | grep libbpf >/dev/null && [ -d "$timerlat_sample_event" ]
then
# rtla build with BPF and system supports BPF mode
no_bpf_options='0 1'
else
no_bpf_options='1'
fi
# Do every test with and without BPF
for option in $no_bpf_options
do
export RTLA_NO_BPF=$option
# Basic tests
check "verify help page" \
"timerlat --help" 129 "timerlat version"
check_top_hist "verify help page" \
"timerlat TOOL --help" 129 "rtla timerlat"
check_top_hist "verify -s/--stack" \
"timerlat TOOL -s 3 -T 10 -t" 2 "Blocking thread stack trace"
check_top_hist "test in nanoseconds" \
"timerlat TOOL -i 2 -c 0 -n -d 10s" 2 "ns"
check_top_hist "set the automatic trace mode" \
"timerlat TOOL -a 5" 2 "analyzing it"
check_top_hist "dump tasks" \
"timerlat TOOL -a 5 --dump-tasks" 2 "Printing CPU tasks"
check "verify --aa-only stop on threshold" \
"timerlat top --aa-only 5" 2 "analyzing it" "Timer Latency"
check "verify --aa-only max latency" \
"timerlat top --aa-only 2000000 -d 1s" 0 "^ Max latency was" "Timer Latency"
check_top_hist "disable auto-analysis" \
"timerlat TOOL -s 3 -T 10 -t --no-aa" 2 "" "analyzing it"
# Thread tests
check_top_hist "verify -P/--priority" \
"timerlat TOOL -P F:1 -c 0 -d 10s -T 1 --on-threshold shell,command=\"$testdir/scripts/check-priority.sh SCHED_FIFO 1\"" \
2 "Priorities are set correctly"
check_top_hist "verify -C/--cgroup" \
"timerlat TOOL -k -C -c 0 -d 10s -T 1 --on-threshold shell,command=\"$testdir/scripts/check-cgroup-match.sh\"" \
2 "cgroup matches for all workload PIDs"
check_top_q_hist "verify -c/--cpus" \
"timerlat TOOL -c 0 -d 10s -T 1 --on-threshold shell,command=$testdir/scripts/check-cpus.sh" 2 "^Affinity of threads: 0$"
check_top_q_hist "verify -H/--house-keeping" \
"timerlat TOOL -H 0 -d 10s -T 1 --on-threshold shell,command=$testdir/scripts/check-housekeeping-cpus.sh" 2 "^Affinity of threads: 0$"
check_top_q_hist "verify -k/--kernel-threads" \
"timerlat TOOL -k -c 0 -d 10s -T 1 --on-threshold shell,command=$testdir/scripts/check-user-kernel-threads.sh" 2 "1 kernel threads, 0 user threads"
check_top_q_hist "verify -u/--user-threads" \
"timerlat TOOL -u -c 0 -d 10s -T 1 --on-threshold shell,command=$testdir/scripts/check-user-kernel-threads.sh" 2 "0 kernel threads, 1 user threads"
# Histogram tests
check "hist with -b/--bucket-size" \
"timerlat hist -b 1 -d 1s"
check "hist with -E/--entries" \
"timerlat hist -E 10 -d 1s"
check "hist with -E/--entries out of range" \
"timerlat hist -E 1 -d 1s" 1 "^Entries must be > 10 and < 10000000$"
check "hist with --no-header" \
"timerlat hist --no-header -d 1s" 0 "" "RTLA timerlat histogram"
check "hist with --with-zeros" \
"timerlat hist --with-zeros -b 100000 -E 21 -d 1s" 0 '^2000000\s+0\s+'
check "hist with --no-index" \
"timerlat hist --no-index --with-zeros -d 1s" 0 "" "^count:"
check "hist with --no-summary" \
"timerlat hist --no-summary -d 1s" 0 "" "^ALL:"
check "hist with --no-irq" \
"timerlat hist --no-irq -d 1s" 0 "" "IRQ-"
check "hist with --no-thread" \
"timerlat hist --no-thread -d 1s" 0 "" "Thr-"
# Actions tests
check_top_q_hist "trace output through -t" \
"timerlat TOOL -T 2 -t" 2 "^ Saving trace to timerlat_trace.txt$"
check_top_q_hist "trace output through -t with custom filename" \
"timerlat TOOL -T 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check_top_q_hist "trace output through --on-threshold trace" \
"timerlat TOOL -T 2 --on-threshold trace" 2 "^ Saving trace to timerlat_trace.txt$"
check_top_q_hist "trace output through --on-threshold trace with custom filename" \
"timerlat TOOL -T 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check_top_q_hist "exec command" \
"timerlat TOOL -T 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
check_top_q_hist "multiple actions" \
"timerlat TOOL -T 2 --on-threshold shell,command='echo -n 1' --on-threshold shell,command='echo 2'" 2 "^12$"
check "hist stop at failed action" \
"timerlat hist -T 2 --on-threshold shell,command='echo -n 1; false' --on-threshold shell,command='echo -n 2'" 2 "^1# RTLA timerlat histogram$"
check "top stop at failed action" \
"timerlat top -T 2 --on-threshold shell,command='echo -n abc; false' --on-threshold shell,command='echo -n defgh'" 2 "^abc" "defgh"
check_top_q_hist "with continue" \
"timerlat TOOL -T 2 -d 5s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
check_top_q_hist "with conditional continue" \
"timerlat TOOL -T 2 --on-threshold shell,command='if [ -f a ]; then echo 2; exit 1; else echo -n 1; touch a; fi' --on-threshold continue" 2 "^12$" "^2$"
check_top_hist "with trace output at end" \
"timerlat TOOL -d 1s --on-end trace" 0 "^ Saving trace to timerlat_trace.txt$"
# BPF action program tests
if [ "$option" -eq 0 ]
then
# Test BPF action program properly in BPF mode
[ -z "$BPFTOOL" ] && BPFTOOL=bpftool
check_top_q_hist "with BPF action program (BPF mode)" \
"timerlat TOOL -T 2 --bpf-action $testdir/bpf/bpf_action_map.o --on-threshold shell,command='$BPFTOOL map dump name rtla_test_map'" \
2 '"value": 42'
else
# Test BPF action program failure in non-BPF mode
check_top_q_hist "with BPF action program (non-BPF mode)" \
"timerlat TOOL -T 2 --bpf-action $testdir/bpf/bpf_action_map.o" \
1 "BPF actions are not supported in tracefs-only mode"
fi
done
test_end
@@ -0,0 +1,8 @@
unit_tests-y += utils.o
unit_tests-y += actions.o
unit_tests-y += unit_tests.o
unit_tests-y += osnoise_top_cli.o
unit_tests-y += osnoise_hist_cli.o
unit_tests-y += timerlat_top_cli.o
unit_tests-y += timerlat_hist_cli.o
unit_tests-y += cli_opt_callback.o
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-only
UNIT_TESTS := $(OUTPUT)unit_tests
UNIT_TESTS_IN := $(UNIT_TESTS)-in.o
$(UNIT_TESTS): $(UNIT_TESTS_IN) $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R)
$(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $^ $(EXTLIBS) -lcheck
$(UNIT_TESTS_IN): fixdep $(LIBSUBCMD_INCLUDES)
make $(build)=unit_tests
unit-tests: FORCE
$(Q)if [ "$(feature-libcheck)" = "1" ]; then \
$(MAKE) $(UNIT_TESTS) && $(UNIT_TESTS); \
else \
echo "libcheck is missing, skipping unit tests. Please install check-devel/check"; \
fi
@@ -0,0 +1,393 @@
// 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
START_TEST(test_actions_perform_continue_unset_flag)
{
actions_fixture.continue_flag = true;
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);
tcase_add_test(tc, test_actions_perform_continue_unset_flag);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,716 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <stdio.h>
#include <check.h>
#define RTLA_ALLOW_CLI_P_H
#include "../../src/cli_p.h"
#include "cli_params_assert.h"
#define TEST_CALLBACK(value, cb) OPT_CALLBACK('t', "test", value, "test value", "test help", cb)
START_TEST(test_opt_llong_callback_simple)
{
long long test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
ck_assert_int_eq(test_value, 1234567890);
}
END_TEST
START_TEST(test_opt_llong_callback_max)
{
long long test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
ck_assert_int_eq(opt_llong_callback(&opt, "9223372036854775807", 0), 0);
ck_assert_int_eq(test_value, 9223372036854775807LL);
}
END_TEST
START_TEST(test_opt_llong_callback_min)
{
long long test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
ck_assert_int_eq(opt_llong_callback(&opt, "-9223372036854775808", 0), 0);
ck_assert_int_eq(test_value, ~9223372036854775807LL);
}
END_TEST
START_TEST(test_opt_int_callback_simple)
{
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
ck_assert_int_eq(test_value, 1234567890);
}
END_TEST
START_TEST(test_opt_int_callback_max)
{
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
ck_assert_int_eq(opt_int_callback(&opt, "2147483647", 0), 0);
ck_assert_int_eq(test_value, 2147483647);
}
END_TEST
START_TEST(test_opt_int_callback_min)
{
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
ck_assert_int_eq(opt_int_callback(&opt, "-2147483648", 0), 0);
ck_assert_int_eq(test_value, -2147483648);
}
END_TEST
START_TEST(test_opt_int_callback_non_numeric)
{
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
ck_assert_int_eq(opt_int_callback(&opt, "abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_int_callback_non_numeric_suffix)
{
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
ck_assert_int_eq(opt_int_callback(&opt, "1234567890abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_cpus_cb)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_cpus_cb);
nr_cpus = 4;
ck_assert_int_eq(opt_cpus_cb(&opt, "0-3", 0), 0);
ck_assert_str_eq(params.cpus, "0-3");
}
END_TEST
START_TEST(test_opt_cpus_cb_invalid)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_cpus_cb);
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
opt_cpus_cb(&opt, "0-3,5", 0);
}
END_TEST
START_TEST(test_opt_cgroup_cb)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
ck_assert_int_eq(opt_cgroup_cb(&opt, "cgroup", 0), 0);
ck_assert_int_eq(params.cgroup, 1);
ck_assert_str_eq(params.cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_opt_cgroup_cb_equals)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
ck_assert_int_eq(opt_cgroup_cb(&opt, "=cgroup", 0), 0);
ck_assert_int_eq(params.cgroup, 1);
ck_assert_str_eq(params.cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_opt_duration_cb)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
ck_assert_int_eq(opt_duration_cb(&opt, "1m", 0), 0);
ck_assert_int_eq(params.duration, 60);
}
END_TEST
START_TEST(test_opt_duration_cb_invalid)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
assert(freopen("/dev/null", "w", stderr));
opt_duration_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_event_cb)
{
struct trace_events *events = NULL;
const struct option opt = TEST_CALLBACK(&events, opt_event_cb);
ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_switch", 0), 0);
ck_assert_str_eq(events->system, "sched");
ck_assert_str_eq(events->event, "sched_switch");
ck_assert_ptr_eq(events->next, NULL);
}
END_TEST
START_TEST(test_opt_event_cb_multiple)
{
struct trace_events *events = NULL;
const struct option opt = TEST_CALLBACK(&events, opt_event_cb);
ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_switch", 0), 0);
ck_assert_int_eq(opt_event_cb(&opt, "sched:sched_wakeup", 0), 0);
ck_assert_str_eq(events->system, "sched");
ck_assert_str_eq(events->event, "sched_wakeup");
ck_assert_str_eq(events->next->system, "sched");
ck_assert_str_eq(events->next->event, "sched_switch");
ck_assert_ptr_eq(events->next->next, NULL);
}
END_TEST
START_TEST(test_opt_housekeeping_cb)
{
struct common_params __params = {0};
struct common_params *params = &__params;
const struct option opt = TEST_CALLBACK(params, opt_housekeeping_cb);
nr_cpus = 4;
ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3", 0), 0);
ck_assert_int_eq(params->hk_cpus, 1);
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 2, 3);
}
END_TEST
START_TEST(test_opt_housekeeping_cb_invalid)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_housekeeping_cb);
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
opt_housekeeping_cb(&opt, "0-3,5", 0);
}
END_TEST
START_TEST(test_opt_priority_cb)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
ck_assert_int_eq(opt_priority_cb(&opt, "f:95", 0), 0);
ck_assert_int_eq(params.sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params.sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_opt_priority_cb_invalid)
{
struct common_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
assert(freopen("/dev/null", "w", stderr));
opt_priority_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_trigger_cb)
{
struct trace_events *events = trace_event_alloc("sched:sched_switch");
const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
ck_assert_int_eq(opt_trigger_cb(&opt, "stacktrace", 0), 0);
ck_assert_str_eq(events->trigger, "stacktrace");
}
END_TEST
START_TEST(test_opt_trigger_cb_no_event)
{
struct trace_events *events = NULL;
const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
assert(freopen("/dev/null", "w", stderr));
opt_trigger_cb(&opt, "stacktrace", 0);
}
END_TEST
START_TEST(test_opt_filter_cb)
{
struct trace_events *events = trace_event_alloc("sched:sched_switch");
const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
ck_assert_int_eq(opt_filter_cb(&opt, "comm ~ \"rtla\"", 0), 0);
ck_assert_str_eq(events->filter, "comm ~ \"rtla\"");
}
END_TEST
START_TEST(test_opt_filter_cb_no_event)
{
struct trace_events *events = NULL;
const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
assert(freopen("/dev/null", "w", stderr));
opt_filter_cb(&opt, "comm ~ \"rtla\"", 0);
}
END_TEST
START_TEST(test_opt_osnoise_auto_cb)
{
struct osnoise_params params = {0};
struct osnoise_cb_data cb_data = {&params};
const struct option opt = TEST_CALLBACK(&cb_data, opt_osnoise_auto_cb);
ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
ck_assert_int_eq(params.common.stop_us, 10);
ck_assert_int_eq(params.threshold, 1);
ck_assert_str_eq(cb_data.trace_output, "osnoise_trace.txt");
}
END_TEST
START_TEST(test_opt_osnoise_period_cb)
{
unsigned long long period = 0;
const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_cb);
ck_assert_int_eq(opt_osnoise_period_cb(&opt, "1000000", 0), 0);
ck_assert_int_eq(period, 1000000);
}
END_TEST
START_TEST(test_opt_osnoise_period_cb_invalid)
{
unsigned long long period = 0;
const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_cb);
assert(freopen("/dev/null", "w", stderr));
opt_osnoise_period_cb(&opt, "10000001", 0);
}
END_TEST
START_TEST(test_opt_osnoise_runtime_cb)
{
unsigned long long runtime = 0;
const struct option opt = TEST_CALLBACK(&runtime, opt_osnoise_runtime_cb);
ck_assert_int_eq(opt_osnoise_runtime_cb(&opt, "900000", 0), 0);
ck_assert_int_eq(runtime, 900000);
}
END_TEST
START_TEST(test_opt_osnoise_runtime_cb_invalid)
{
unsigned long long runtime = 0;
const struct option opt = TEST_CALLBACK(&runtime, opt_osnoise_runtime_cb);
assert(freopen("/dev/null", "w", stderr));
opt_osnoise_runtime_cb(&opt, "99", 0);
}
END_TEST
START_TEST(test_opt_osnoise_trace_output_cb)
{
const char *trace_output = NULL;
const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, "trace.txt", 0), 0);
ck_assert_str_eq(trace_output, "trace.txt");
}
END_TEST
START_TEST(test_opt_osnoise_trace_output_cb_noarg)
{
const char *trace_output = NULL;
const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 0), 0);
ck_assert_str_eq(trace_output, "osnoise_trace.txt");
}
END_TEST
START_TEST(test_opt_osnoise_on_threshold_cb)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_threshold_cb);
ck_assert_int_eq(opt_osnoise_on_threshold_cb(&opt, "trace", 0), 0);
ck_assert_int_eq(actions.len, 1);
ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
ck_assert_str_eq(actions.list[0].trace_output, "osnoise_trace.txt");
}
END_TEST
START_TEST(test_opt_osnoise_on_threshold_cb_invalid)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_threshold_cb);
assert(freopen("/dev/null", "w", stderr));
opt_osnoise_on_threshold_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_osnoise_on_end_cb)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_end_cb);
ck_assert_int_eq(opt_osnoise_on_end_cb(&opt, "trace", 0), 0);
ck_assert_int_eq(actions.len, 1);
ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
ck_assert_str_eq(actions.list[0].trace_output, "osnoise_trace.txt");
}
END_TEST
START_TEST(test_opt_osnoise_on_end_cb_invalid)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_end_cb);
assert(freopen("/dev/null", "w", stderr));
opt_osnoise_on_end_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_timerlat_period_cb)
{
long long period = 0;
const struct option opt = TEST_CALLBACK(&period, opt_timerlat_period_cb);
ck_assert_int_eq(opt_timerlat_period_cb(&opt, "1000", 0), 0);
ck_assert_int_eq(period, 1000);
}
END_TEST
START_TEST(test_opt_timerlat_period_cb_invalid)
{
long long period = 0;
const struct option opt = TEST_CALLBACK(&period, opt_timerlat_period_cb);
assert(freopen("/dev/null", "w", stderr));
opt_timerlat_period_cb(&opt, "1000001", 0);
}
END_TEST
START_TEST(test_opt_timerlat_auto_cb)
{
struct timerlat_params params = {0};
struct timerlat_cb_data cb_data = {&params};
const struct option opt = TEST_CALLBACK(&cb_data, opt_timerlat_auto_cb);
ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
ck_assert_int_eq(params.common.stop_us, 10);
ck_assert_int_eq(params.common.stop_total_us, 10);
ck_assert_int_eq(params.print_stack, 10);
ck_assert_str_eq(cb_data.trace_output, "timerlat_trace.txt");
}
END_TEST
START_TEST(test_opt_dma_latency_cb)
{
int dma_latency = 0;
const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
ck_assert_int_eq(opt_dma_latency_cb(&opt, "1000", 0), 0);
ck_assert_int_eq(dma_latency, 1000);
}
END_TEST
START_TEST(test_opt_dma_latency_cb_min)
{
int dma_latency = 0;
const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
assert(freopen("/dev/null", "w", stderr));
opt_dma_latency_cb(&opt, "-1", 0);
}
END_TEST
START_TEST(test_opt_dma_latency_cb_max)
{
int dma_latency = 0;
const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
assert(freopen("/dev/null", "w", stderr));
opt_dma_latency_cb(&opt, "10001", 0);
}
END_TEST
START_TEST(test_opt_aa_only_cb)
{
struct timerlat_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_aa_only_cb);
ck_assert_int_eq(opt_aa_only_cb(&opt, "10", 0), 0);
ck_assert_int_eq(params.common.stop_us, 10);
ck_assert_int_eq(params.common.stop_total_us, 10);
ck_assert_int_eq(params.print_stack, 10);
ck_assert_int_eq(params.common.aa_only, 1);
}
END_TEST
START_TEST(test_opt_timerlat_trace_output_cb)
{
const char *trace_output = NULL;
const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, "trace.txt", 0), 0);
ck_assert_str_eq(trace_output, "trace.txt");
}
END_TEST
START_TEST(test_opt_timerlat_trace_output_cb_noarg)
{
const char *trace_output = NULL;
const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 0), 0);
ck_assert_str_eq(trace_output, "timerlat_trace.txt");
}
END_TEST
START_TEST(test_opt_timerlat_on_threshold_cb)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_threshold_cb);
ck_assert_int_eq(opt_timerlat_on_threshold_cb(&opt, "trace", 0), 0);
ck_assert_int_eq(actions.len, 1);
ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
ck_assert_str_eq(actions.list[0].trace_output, "timerlat_trace.txt");
}
END_TEST
START_TEST(test_opt_timerlat_on_threshold_cb_invalid)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_threshold_cb);
assert(freopen("/dev/null", "w", stderr));
opt_timerlat_on_threshold_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_timerlat_on_end_cb)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_end_cb);
ck_assert_int_eq(opt_timerlat_on_end_cb(&opt, "trace", 0), 0);
ck_assert_int_eq(actions.len, 1);
ck_assert_int_eq(actions.list[0].type, ACTION_TRACE_OUTPUT);
ck_assert_str_eq(actions.list[0].trace_output, "timerlat_trace.txt");
}
END_TEST
START_TEST(test_opt_timerlat_on_end_cb_invalid)
{
struct actions actions = {0};
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_end_cb);
assert(freopen("/dev/null", "w", stderr));
opt_timerlat_on_end_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_user_threads_cb)
{
struct timerlat_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_user_threads_cb);
ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 0), 0);
ck_assert_int_eq(params.common.user_workload, 1);
ck_assert_int_eq(params.common.user_data, 1);
}
END_TEST
START_TEST(test_opt_nano_cb)
{
struct timerlat_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
ck_assert_int_eq(params.common.output_divisor, 1);
}
END_TEST
START_TEST(test_opt_timerlat_align_cb)
{
struct timerlat_params params = {0};
const struct option opt = TEST_CALLBACK(&params, opt_timerlat_align_cb);
ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
ck_assert(params.timerlat_align);
ck_assert_int_eq(params.timerlat_align_us, 500);
}
END_TEST
START_TEST(test_opt_stack_format_cb)
{
int stack_format = 0;
const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
ck_assert_int_eq(stack_format, STACK_FORMAT_FULL);
}
END_TEST
START_TEST(test_opt_stack_format_cb_invalid)
{
int stack_format = 0;
const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
assert(freopen("/dev/null", "w", stderr));
opt_stack_format_cb(&opt, "abc", 0);
}
END_TEST
START_TEST(test_opt_bucket_size_cb)
{
int bucket_size = 0;
const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
ck_assert_int_eq(opt_bucket_size_cb(&opt, "100", 0), 0);
ck_assert_int_eq(bucket_size, 100);
}
END_TEST
START_TEST(test_opt_bucket_size_min)
{
int bucket_size = 0;
const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
assert(freopen("/dev/null", "w", stderr));
opt_bucket_size_cb(&opt, "0", 0);
}
END_TEST
START_TEST(test_opt_bucket_size_max)
{
int bucket_size = 0;
const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
assert(freopen("/dev/null", "w", stderr));
opt_bucket_size_cb(&opt, "1000001", 0);
}
END_TEST
START_TEST(test_opt_entries_cb)
{
int entries = 0;
const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
ck_assert_int_eq(opt_entries_cb(&opt, "100", 0), 0);
ck_assert_int_eq(entries, 100);
}
END_TEST
START_TEST(test_opt_entries_min)
{
int entries = 0;
const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
assert(freopen("/dev/null", "w", stderr));
opt_entries_cb(&opt, "9", 0);
}
END_TEST
START_TEST(test_opt_entries_max)
{
int entries = 0;
const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
assert(freopen("/dev/null", "w", stderr));
opt_entries_cb(&opt, "10000000", 0);
}
END_TEST
Suite *cli_opt_callback_suite(void)
{
Suite *s = suite_create("cli_opt_callback");
TCase *tc;
tc = tcase_create("common");
tcase_add_test(tc, test_opt_llong_callback_simple);
tcase_add_test(tc, test_opt_llong_callback_max);
tcase_add_test(tc, test_opt_llong_callback_min);
tcase_add_test(tc, test_opt_int_callback_simple);
tcase_add_test(tc, test_opt_int_callback_max);
tcase_add_test(tc, test_opt_int_callback_min);
tcase_add_test(tc, test_opt_int_callback_non_numeric);
tcase_add_test(tc, test_opt_int_callback_non_numeric_suffix);
tcase_add_test(tc, test_opt_cpus_cb);
tcase_add_exit_test(tc, test_opt_cpus_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_cgroup_cb);
tcase_add_test(tc, test_opt_cgroup_cb_equals);
tcase_add_test(tc, test_opt_duration_cb);
tcase_add_exit_test(tc, test_opt_duration_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_event_cb);
tcase_add_test(tc, test_opt_event_cb_multiple);
tcase_add_test(tc, test_opt_housekeeping_cb);
tcase_add_exit_test(tc, test_opt_housekeeping_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_priority_cb);
tcase_add_exit_test(tc, test_opt_priority_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_trigger_cb);
tcase_add_exit_test(tc, test_opt_trigger_cb_no_event, EXIT_FAILURE);
tcase_add_test(tc, test_opt_filter_cb);
tcase_add_exit_test(tc, test_opt_filter_cb_no_event, EXIT_FAILURE);
suite_add_tcase(s, tc);
tc = tcase_create("osnoise");
tcase_add_test(tc, test_opt_osnoise_auto_cb);
tcase_add_test(tc, test_opt_osnoise_period_cb);
tcase_add_exit_test(tc, test_opt_osnoise_period_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_osnoise_runtime_cb);
tcase_add_exit_test(tc, test_opt_osnoise_runtime_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_osnoise_trace_output_cb);
tcase_add_test(tc, test_opt_osnoise_trace_output_cb_noarg);
tcase_add_test(tc, test_opt_osnoise_on_threshold_cb);
tcase_add_exit_test(tc, test_opt_osnoise_on_threshold_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_osnoise_on_end_cb);
tcase_add_exit_test(tc, test_opt_osnoise_on_end_cb_invalid, EXIT_FAILURE);
suite_add_tcase(s, tc);
tc = tcase_create("timerlat");
tcase_add_test(tc, test_opt_timerlat_period_cb);
tcase_add_exit_test(tc, test_opt_timerlat_period_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_timerlat_auto_cb);
tcase_add_test(tc, test_opt_dma_latency_cb);
tcase_add_exit_test(tc, test_opt_dma_latency_cb_min, EXIT_FAILURE);
tcase_add_exit_test(tc, test_opt_dma_latency_cb_max, EXIT_FAILURE);
tcase_add_test(tc, test_opt_aa_only_cb);
tcase_add_test(tc, test_opt_timerlat_trace_output_cb);
tcase_add_test(tc, test_opt_timerlat_trace_output_cb_noarg);
tcase_add_test(tc, test_opt_timerlat_on_threshold_cb);
tcase_add_exit_test(tc, test_opt_timerlat_on_threshold_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_timerlat_on_end_cb);
tcase_add_exit_test(tc, test_opt_timerlat_on_end_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_user_threads_cb);
tcase_add_test(tc, test_opt_nano_cb);
tcase_add_test(tc, test_opt_stack_format_cb);
tcase_add_exit_test(tc, test_opt_stack_format_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_timerlat_align_cb);
suite_add_tcase(s, tc);
tc = tcase_create("histogram");
tcase_add_test(tc, test_opt_bucket_size_cb);
tcase_add_exit_test(tc, test_opt_bucket_size_min, EXIT_FAILURE);
tcase_add_exit_test(tc, test_opt_bucket_size_max, EXIT_FAILURE);
tcase_add_test(tc, test_opt_entries_cb);
tcase_add_exit_test(tc, test_opt_entries_min, EXIT_FAILURE);
tcase_add_exit_test(tc, test_opt_entries_max, EXIT_FAILURE);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0 */
#pragma once
#include "../../src/timerlat.h"
/* Tracing Options */
#define CLI_ASSERT_SINGLE_EVENT(_system, _event) do {\
ck_assert_ptr_nonnull(params->events);\
ck_assert_str_eq(params->events->system, _system);\
ck_assert_str_eq(params->events->event, _event);\
ck_assert_ptr_null(params->events->next);\
} while (0)
#define CLI_ASSERT_SINGLE_FILTER(_filter) do {\
ck_assert_ptr_nonnull(params->events);\
ck_assert_str_eq(params->events->filter, _filter);\
ck_assert_ptr_null(params->events->next);\
} while (0)
#define CLI_ASSERT_SINGLE_TRIGGER(_trigger) do {\
ck_assert_ptr_nonnull(params->events);\
ck_assert_str_eq(params->events->trigger, _trigger);\
ck_assert_ptr_null(params->events->next);\
} while (0)
/* CPU Configuration */
#define CLI_ASSERT_CPUSET(_field, ...) do {\
int n;\
int cpus[] = { __VA_ARGS__ };\
for (n = 0; n < sizeof(cpus) / sizeof(int); n++)\
ck_assert(CPU_ISSET(cpus[n], &params->_field));\
ck_assert_int_eq(CPU_COUNT(&params->_field), n);\
} while (0)
/* Auto Analysis and Actions */
#define CLI_OSNOISE_ASSERT_AUTO(_stop) do {\
ck_assert_int_eq(params->stop_us, _stop);\
ck_assert_int_eq(osn_params->threshold, 1);\
ck_assert_int_eq(params->threshold_actions.len, 1);\
ck_assert_int_eq(params->threshold_actions.list[0].type, ACTION_TRACE_OUTPUT);\
ck_assert_str_eq(params->threshold_actions.list[0].trace_output, "osnoise_trace.txt");\
} while (0)
#define CLI_TIMERLAT_ASSERT_AUTO(_threshold) do {\
ck_assert_int_eq(params->stop_us, _threshold);\
ck_assert_int_eq(params->stop_total_us, _threshold);\
ck_assert_int_eq(tlat_params->print_stack, _threshold);\
ck_assert_int_eq(params->threshold_actions.len, 1);\
ck_assert_int_eq(params->threshold_actions.list[0].type, ACTION_TRACE_OUTPUT);\
ck_assert_str_eq(params->threshold_actions.list[0].trace_output, "timerlat_trace.txt");\
} while (0)
#define CLI_TIMERLAT_ASSERT_AA_ONLY(_threshold) do {\
ck_assert_int_eq(params->stop_us, _threshold);\
ck_assert_int_eq(params->stop_total_us, _threshold);\
ck_assert_int_eq(tlat_params->print_stack, _threshold);\
ck_assert_int_eq(params->threshold_actions.len, 0);\
ck_assert(params->aa_only);\
} while (0)
#define CLI_ASSERT_SINGLE_ACTION(_actions, _type, _arg, _valtype, _value) do {\
ck_assert_int_eq(params->_actions.len, 1);\
ck_assert_int_eq(params->_actions.list[0].type, _type);\
ck_assert_##_valtype##_eq(params->_actions.list[0]._arg, _value);\
} while (0)
@@ -0,0 +1,557 @@
// 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 "cli_params_assert.h"
#include "../../src/cli.h"
#define PARSE_ARGS(...) char *argv[] = { __VA_ARGS__, NULL };\
int argc = sizeof(argv) / sizeof(char *) - 1;\
struct common_params *params =\
osnoise_hist_parse_args(argc, argv);\
struct osnoise_params *osn_params __maybe_unused =\
to_osnoise_params(params)
/* Tracing Options */
START_TEST(test_period_short)
{
PARSE_ARGS("osnoise", "hist", "-p", "100000");
ck_assert_int_eq(osn_params->period, 100000);
}
END_TEST
START_TEST(test_period_long)
{
PARSE_ARGS("osnoise", "hist", "--period", "100000");
ck_assert_int_eq(osn_params->period, 100000);
}
END_TEST
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "hist", "-r", "95000");
ck_assert_int_eq(osn_params->runtime, 95000);
}
END_TEST
START_TEST(test_runtime_long)
{
PARSE_ARGS("osnoise", "hist", "--runtime", "95000");
ck_assert_int_eq(osn_params->runtime, 95000);
}
END_TEST
START_TEST(test_stop_short)
{
PARSE_ARGS("osnoise", "hist", "-s", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_stop_long)
{
PARSE_ARGS("osnoise", "hist", "--stop", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_stop_total_short)
{
PARSE_ARGS("osnoise", "hist", "-S", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_stop_total_long)
{
PARSE_ARGS("osnoise", "hist", "--stop-total", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_threshold_short)
{
PARSE_ARGS("osnoise", "hist", "-T", "5");
ck_assert_int_eq(osn_params->threshold, 5);
}
END_TEST
START_TEST(test_threshold_long)
{
PARSE_ARGS("osnoise", "hist", "--threshold", "5");
ck_assert_int_eq(osn_params->threshold, 5);
}
END_TEST
START_TEST(test_trace_short_noarg)
{
PARSE_ARGS("osnoise", "hist", "-t");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_trace_short_followarg)
{
PARSE_ARGS("osnoise", "hist", "-t", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_short_space)
{
PARSE_ARGS("osnoise", "hist", "-t", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_short_equals)
{
PARSE_ARGS("osnoise", "hist", "-t=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_noarg)
{
PARSE_ARGS("osnoise", "hist", "--trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_trace_long_followarg)
{
PARSE_ARGS("osnoise", "hist", "--trace", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_long_space)
{
PARSE_ARGS("osnoise", "hist", "--trace", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_equals)
{
PARSE_ARGS("osnoise", "hist", "--trace=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
/* Event Configuration */
START_TEST(test_event_short)
{
PARSE_ARGS("osnoise", "hist", "-e", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_event_long)
{
PARSE_ARGS("osnoise", "hist", "--event", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_filter)
{
PARSE_ARGS("osnoise", "hist", "-e", "system:event", "--filter", "filter");
CLI_ASSERT_SINGLE_FILTER("filter");
}
END_TEST
START_TEST(test_trigger)
{
PARSE_ARGS("osnoise", "hist", "-e", "system:event", "--trigger", "trigger");
CLI_ASSERT_SINGLE_TRIGGER("trigger");
}
END_TEST
/* CPU Configuration */
START_TEST(test_cpus_short)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "hist", "-c", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_cpus_long)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "hist", "--cpus", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_short)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "hist", "-H", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_long)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "hist", "--house-keeping", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
/* Thread Configuration */
START_TEST(test_cgroup_short_noarg)
{
PARSE_ARGS("osnoise", "hist", "-C");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_short_space)
{
PARSE_ARGS("osnoise", "hist", "-C", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_short_equals)
{
PARSE_ARGS("osnoise", "hist", "-C=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_noarg)
{
PARSE_ARGS("osnoise", "hist", "--cgroup");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_long_space)
{
PARSE_ARGS("osnoise", "hist", "--cgroup", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_equals)
{
PARSE_ARGS("osnoise", "hist", "--cgroup=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_priority_short)
{
PARSE_ARGS("osnoise", "hist", "-P", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_priority_long)
{
PARSE_ARGS("osnoise", "hist", "--priority", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
/* Histogram Options */
START_TEST(test_bucket_size_short)
{
PARSE_ARGS("osnoise", "hist", "-b", "2");
ck_assert_int_eq(params->hist.bucket_size, 2);
}
END_TEST
START_TEST(test_bucket_size_long)
{
PARSE_ARGS("osnoise", "hist", "--bucket-size", "2");
ck_assert_int_eq(params->hist.bucket_size, 2);
}
END_TEST
START_TEST(test_entries_short)
{
PARSE_ARGS("osnoise", "hist", "-E", "512");
ck_assert_int_eq(params->hist.entries, 512);
}
END_TEST
START_TEST(test_entries_long)
{
PARSE_ARGS("osnoise", "hist", "--entries", "512");
ck_assert_int_eq(params->hist.entries, 512);
}
END_TEST
START_TEST(test_no_header)
{
PARSE_ARGS("osnoise", "hist", "--no-header");
ck_assert(params->hist.no_header);
}
END_TEST
START_TEST(test_no_index)
{
PARSE_ARGS("osnoise", "hist", "--with-zeros", "--no-index");
ck_assert(params->hist.no_index);
}
END_TEST
START_TEST(test_no_summary)
{
PARSE_ARGS("osnoise", "hist", "--no-summary");
ck_assert(params->hist.no_summary);
}
END_TEST
START_TEST(test_with_zeros)
{
PARSE_ARGS("osnoise", "hist", "--with-zeros");
ck_assert(params->hist.with_zeros);
}
END_TEST
/* System Tuning */
START_TEST(test_trace_buffer_size)
{
PARSE_ARGS("osnoise", "hist", "--trace-buffer-size", "200");
ck_assert_int_eq(params->buffer_size, 200);
}
END_TEST
START_TEST(test_warm_up)
{
PARSE_ARGS("osnoise", "hist", "--warm-up", "5");
ck_assert_int_eq(params->warmup, 5);
}
END_TEST
/* Auto Analysis and Actions */
START_TEST(test_auto)
{
PARSE_ARGS("osnoise", "hist", "-a", "20");
CLI_OSNOISE_ASSERT_AUTO(20);
}
END_TEST
START_TEST(test_on_end)
{
PARSE_ARGS("osnoise", "hist", "--on-end", "trace");
CLI_ASSERT_SINGLE_ACTION(end_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_on_threshold)
{
PARSE_ARGS("osnoise", "hist", "--on-threshold", "trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
/* General */
START_TEST(test_debug_short)
{
PARSE_ARGS("osnoise", "hist", "-D");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_debug_long)
{
PARSE_ARGS("osnoise", "hist", "--debug");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_duration_short)
{
PARSE_ARGS("osnoise", "hist", "-d", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
START_TEST(test_duration_long)
{
PARSE_ARGS("osnoise", "hist", "--duration", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
Suite *osnoise_hist_cli_suite(void)
{
Suite *s = suite_create("osnoise_hist_cli");
TCase *tc;
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);
tcase_add_test(tc, test_stop_long);
tcase_add_test(tc, test_stop_total_short);
tcase_add_test(tc, test_stop_total_long);
tcase_add_test(tc, test_threshold_short);
tcase_add_test(tc, test_threshold_long);
tcase_add_test(tc, test_trace_short_noarg);
tcase_add_test(tc, test_trace_short_followarg);
tcase_add_test(tc, test_trace_short_space);
tcase_add_test(tc, test_trace_short_equals);
tcase_add_test(tc, test_trace_long_noarg);
tcase_add_test(tc, test_trace_long_followarg);
tcase_add_test(tc, test_trace_long_space);
tcase_add_test(tc, test_trace_long_equals);
suite_add_tcase(s, tc);
tc = tcase_create("event_configuration");
tcase_add_test(tc, test_event_short);
tcase_add_test(tc, test_event_long);
tcase_add_test(tc, test_filter);
tcase_add_test(tc, test_trigger);
suite_add_tcase(s, tc);
tc = tcase_create("cpu_configuration");
tcase_add_test(tc, test_cpus_short);
tcase_add_test(tc, test_cpus_long);
tcase_add_test(tc, test_housekeeping_short);
tcase_add_test(tc, test_housekeeping_long);
suite_add_tcase(s, tc);
tc = tcase_create("thread_configuration");
tcase_add_test(tc, test_cgroup_short_noarg);
tcase_add_test(tc, test_cgroup_short_space);
tcase_add_test(tc, test_cgroup_short_equals);
tcase_add_test(tc, test_cgroup_long_noarg);
tcase_add_test(tc, test_cgroup_long_space);
tcase_add_test(tc, test_cgroup_long_equals);
tcase_add_test(tc, test_priority_short);
tcase_add_test(tc, test_priority_long);
suite_add_tcase(s, tc);
tc = tcase_create("histogram_options");
tcase_add_test(tc, test_bucket_size_short);
tcase_add_test(tc, test_bucket_size_long);
tcase_add_test(tc, test_entries_short);
tcase_add_test(tc, test_entries_long);
tcase_add_test(tc, test_no_header);
tcase_add_test(tc, test_no_index);
tcase_add_test(tc, test_no_summary);
tcase_add_test(tc, test_with_zeros);
suite_add_tcase(s, tc);
tc = tcase_create("system_tuning");
tcase_add_test(tc, test_trace_buffer_size);
tcase_add_test(tc, test_warm_up);
suite_add_tcase(s, tc);
tc = tcase_create("aa_actions");
tcase_add_test(tc, test_auto);
tcase_add_test(tc, test_on_end);
tcase_add_test(tc, test_on_threshold);
suite_add_tcase(s, tc);
tc = tcase_create("general");
tcase_add_test(tc, test_debug_short);
tcase_add_test(tc, test_debug_long);
tcase_add_test(tc, test_duration_short);
tcase_add_test(tc, test_duration_long);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,503 @@
// 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 "cli_params_assert.h"
#include "../../src/cli.h"
#define PARSE_ARGS(...) char *argv[] = { __VA_ARGS__, NULL };\
int argc = sizeof(argv) / sizeof(char *) - 1;\
struct common_params *params =\
osnoise_top_parse_args(argc, argv);\
struct osnoise_params *osn_params __maybe_unused =\
to_osnoise_params(params)
/* Tracing Options */
START_TEST(test_period_short)
{
PARSE_ARGS("osnoise", "top", "-p", "100000");
ck_assert_int_eq(osn_params->period, 100000);
}
END_TEST
START_TEST(test_period_long)
{
PARSE_ARGS("osnoise", "top", "--period", "100000");
ck_assert_int_eq(osn_params->period, 100000);
}
END_TEST
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "top", "-r", "95000");
ck_assert_int_eq(osn_params->runtime, 95000);
}
END_TEST
START_TEST(test_runtime_long)
{
PARSE_ARGS("osnoise", "top", "--runtime", "95000");
ck_assert_int_eq(osn_params->runtime, 95000);
}
END_TEST
START_TEST(test_stop_short)
{
PARSE_ARGS("osnoise", "top", "-s", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_stop_long)
{
PARSE_ARGS("osnoise", "top", "--stop", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_stop_total_short)
{
PARSE_ARGS("osnoise", "top", "-S", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_stop_total_long)
{
PARSE_ARGS("osnoise", "top", "--stop-total", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_threshold_short)
{
PARSE_ARGS("osnoise", "top", "-T", "5");
ck_assert_int_eq(osn_params->threshold, 5);
}
END_TEST
START_TEST(test_threshold_long)
{
PARSE_ARGS("osnoise", "top", "--threshold", "5");
ck_assert_int_eq(osn_params->threshold, 5);
}
END_TEST
START_TEST(test_trace_short_noarg)
{
PARSE_ARGS("osnoise", "top", "-t");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_trace_short_followarg)
{
PARSE_ARGS("osnoise", "top", "-t", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_short_space)
{
PARSE_ARGS("osnoise", "top", "-t", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_short_equals)
{
PARSE_ARGS("osnoise", "top", "-t=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_noarg)
{
PARSE_ARGS("osnoise", "top", "--trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_trace_long_followarg)
{
PARSE_ARGS("osnoise", "top", "--trace", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_long_space)
{
PARSE_ARGS("osnoise", "top", "--trace", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_equals)
{
PARSE_ARGS("osnoise", "top", "--trace=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
/* Event Configuration */
START_TEST(test_event_short)
{
PARSE_ARGS("osnoise", "top", "-e", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_event_long)
{
PARSE_ARGS("osnoise", "top", "--event", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_filter)
{
PARSE_ARGS("osnoise", "top", "-e", "system:event", "--filter", "filter");
CLI_ASSERT_SINGLE_FILTER("filter");
}
END_TEST
START_TEST(test_trigger)
{
PARSE_ARGS("osnoise", "top", "-e", "system:event", "--trigger", "trigger");
CLI_ASSERT_SINGLE_TRIGGER("trigger");
}
END_TEST
/* CPU Configuration */
START_TEST(test_cpus_short)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "top", "-c", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_cpus_long)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "top", "--cpus", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_short)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "top", "-H", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_long)
{
nr_cpus = 4;
PARSE_ARGS("osnoise", "top", "--house-keeping", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
/* Thread Configuration */
START_TEST(test_cgroup_short_noarg)
{
PARSE_ARGS("osnoise", "top", "-C");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_short_space)
{
PARSE_ARGS("osnoise", "top", "-C", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_short_equals)
{
PARSE_ARGS("osnoise", "top", "-C=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_noarg)
{
PARSE_ARGS("osnoise", "top", "--cgroup");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_long_space)
{
PARSE_ARGS("osnoise", "top", "--cgroup", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_equals)
{
PARSE_ARGS("osnoise", "top", "--cgroup=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_priority_short)
{
PARSE_ARGS("osnoise", "top", "-P", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_priority_long)
{
PARSE_ARGS("osnoise", "top", "--priority", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
/* Output */
START_TEST(test_quiet_short)
{
PARSE_ARGS("osnoise", "top", "-q");
ck_assert(params->quiet);
}
END_TEST
START_TEST(test_quiet_long)
{
PARSE_ARGS("osnoise", "top", "--quiet");
ck_assert(params->quiet);
}
END_TEST
/* Auto Analysis and Actions */
START_TEST(test_auto)
{
PARSE_ARGS("osnoise", "top", "-a", "20");
CLI_OSNOISE_ASSERT_AUTO(20);
}
END_TEST
START_TEST(test_on_end)
{
PARSE_ARGS("osnoise", "top", "--on-end", "trace");
CLI_ASSERT_SINGLE_ACTION(end_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
START_TEST(test_on_threshold)
{
PARSE_ARGS("osnoise", "top", "--on-threshold", "trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"osnoise_trace.txt");
}
END_TEST
/* System Tuning */
START_TEST(test_trace_buffer_size)
{
PARSE_ARGS("osnoise", "top", "--trace-buffer-size", "200");
ck_assert_int_eq(params->buffer_size, 200);
}
END_TEST
START_TEST(test_warm_up)
{
PARSE_ARGS("osnoise", "top", "--warm-up", "5");
ck_assert_int_eq(params->warmup, 5);
}
END_TEST
/* General */
START_TEST(test_debug_short)
{
PARSE_ARGS("osnoise", "top", "-D");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_debug_long)
{
PARSE_ARGS("osnoise", "top", "--debug");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_duration_short)
{
PARSE_ARGS("osnoise", "top", "-d", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
START_TEST(test_duration_long)
{
PARSE_ARGS("osnoise", "top", "--duration", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
Suite *osnoise_top_cli_suite(void)
{
Suite *s = suite_create("osnoise_top_cli");
TCase *tc;
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);
tcase_add_test(tc, test_stop_long);
tcase_add_test(tc, test_stop_total_short);
tcase_add_test(tc, test_stop_total_long);
tcase_add_test(tc, test_threshold_short);
tcase_add_test(tc, test_threshold_long);
tcase_add_test(tc, test_trace_short_noarg);
tcase_add_test(tc, test_trace_short_followarg);
tcase_add_test(tc, test_trace_short_space);
tcase_add_test(tc, test_trace_short_equals);
tcase_add_test(tc, test_trace_long_noarg);
tcase_add_test(tc, test_trace_long_followarg);
tcase_add_test(tc, test_trace_long_space);
tcase_add_test(tc, test_trace_long_equals);
suite_add_tcase(s, tc);
tc = tcase_create("event_configuration");
tcase_add_test(tc, test_event_short);
tcase_add_test(tc, test_event_long);
tcase_add_test(tc, test_filter);
tcase_add_test(tc, test_trigger);
suite_add_tcase(s, tc);
tc = tcase_create("cpu_configuration");
tcase_add_test(tc, test_cpus_short);
tcase_add_test(tc, test_cpus_long);
tcase_add_test(tc, test_housekeeping_short);
tcase_add_test(tc, test_housekeeping_long);
suite_add_tcase(s, tc);
tc = tcase_create("thread_configuration");
tcase_add_test(tc, test_cgroup_short_noarg);
tcase_add_test(tc, test_cgroup_short_space);
tcase_add_test(tc, test_cgroup_short_equals);
tcase_add_test(tc, test_cgroup_long_noarg);
tcase_add_test(tc, test_cgroup_long_space);
tcase_add_test(tc, test_cgroup_long_equals);
tcase_add_test(tc, test_priority_short);
tcase_add_test(tc, test_priority_long);
suite_add_tcase(s, tc);
tc = tcase_create("output");
tcase_add_test(tc, test_quiet_short);
tcase_add_test(tc, test_quiet_long);
suite_add_tcase(s, tc);
tc = tcase_create("system_tuning");
tcase_add_test(tc, test_trace_buffer_size);
tcase_add_test(tc, test_warm_up);
suite_add_tcase(s, tc);
tc = tcase_create("aa_actions");
tcase_add_test(tc, test_auto);
tcase_add_test(tc, test_on_end);
tcase_add_test(tc, test_on_threshold);
suite_add_tcase(s, tc);
tc = tcase_create("general");
tcase_add_test(tc, test_debug_short);
tcase_add_test(tc, test_debug_long);
tcase_add_test(tc, test_duration_short);
tcase_add_test(tc, test_duration_long);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,722 @@
// 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 <linux/container_of.h>
#include "cli_params_assert.h"
#include "../../src/cli.h"
#define PARSE_ARGS(...) char *argv[] = { __VA_ARGS__, NULL };\
int argc = sizeof(argv) / sizeof(char *) - 1;\
struct common_params *params =\
timerlat_hist_parse_args(argc, argv);\
struct timerlat_params *tlat_params __maybe_unused =\
to_timerlat_params(params)
/* Tracing Options */
START_TEST(test_irq_short)
{
PARSE_ARGS("timerlat", "hist", "-i", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_irq_long)
{
PARSE_ARGS("timerlat", "hist", "--irq", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_period_short)
{
PARSE_ARGS("timerlat", "hist", "-p", "200");
ck_assert_int_eq(tlat_params->timerlat_period_us, 200);
}
END_TEST
START_TEST(test_period_long)
{
PARSE_ARGS("timerlat", "hist", "--period", "200");
ck_assert_int_eq(tlat_params->timerlat_period_us, 200);
}
END_TEST
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "hist", "-s", "20");
ck_assert_int_eq(tlat_params->print_stack, 20);
}
END_TEST
START_TEST(test_stack_long)
{
PARSE_ARGS("timerlat", "hist", "--stack", "20");
ck_assert_int_eq(tlat_params->print_stack, 20);
}
END_TEST
START_TEST(test_thread_short)
{
PARSE_ARGS("timerlat", "hist", "-T", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_thread_long)
{
PARSE_ARGS("timerlat", "hist", "--thread", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_trace_short_noarg)
{
PARSE_ARGS("timerlat", "hist", "-t");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_trace_short_followarg)
{
PARSE_ARGS("timerlat", "hist", "-t", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_short_space)
{
PARSE_ARGS("timerlat", "hist", "-t", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_short_equals)
{
PARSE_ARGS("timerlat", "hist", "-t=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_noarg)
{
PARSE_ARGS("timerlat", "hist", "--trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_trace_long_followarg)
{
PARSE_ARGS("timerlat", "hist", "--trace", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_long_space)
{
PARSE_ARGS("timerlat", "hist", "--trace", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_equals)
{
PARSE_ARGS("timerlat", "hist", "--trace=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
/* Event Configuration */
START_TEST(test_event_short)
{
PARSE_ARGS("timerlat", "hist", "-e", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_event_long)
{
PARSE_ARGS("timerlat", "hist", "--event", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_filter)
{
PARSE_ARGS("timerlat", "hist", "-e", "system:event", "--filter", "filter");
CLI_ASSERT_SINGLE_FILTER("filter");
}
END_TEST
START_TEST(test_trigger)
{
PARSE_ARGS("timerlat", "hist", "-e", "system:event", "--trigger", "trigger");
CLI_ASSERT_SINGLE_TRIGGER("trigger");
}
END_TEST
/* CPU Configuration */
START_TEST(test_cpus_short)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "hist", "-c", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_cpus_long)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "hist", "--cpus", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_short)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "hist", "-H", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_long)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "hist", "--house-keeping", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
/* Thread Configuration */
START_TEST(test_cgroup_short_noarg)
{
PARSE_ARGS("timerlat", "hist", "-C");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_short_space)
{
PARSE_ARGS("timerlat", "hist", "-C", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_short_equals)
{
PARSE_ARGS("timerlat", "hist", "-C=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_noarg)
{
PARSE_ARGS("timerlat", "hist", "--cgroup");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_long_space)
{
PARSE_ARGS("timerlat", "hist", "--cgroup", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_equals)
{
PARSE_ARGS("timerlat", "hist", "--cgroup=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_kernel_threads_short)
{
PARSE_ARGS("timerlat", "hist", "-k");
ck_assert(params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(!params->user_data);
}
END_TEST
START_TEST(test_kernel_threads_long)
{
PARSE_ARGS("timerlat", "hist", "--kernel-threads");
ck_assert(params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(!params->user_data);
}
END_TEST
START_TEST(test_priority_short)
{
PARSE_ARGS("timerlat", "hist", "-P", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_priority_long)
{
PARSE_ARGS("timerlat", "hist", "--priority", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_user_load_short)
{
PARSE_ARGS("timerlat", "hist", "-U");
ck_assert(!params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_load_long)
{
PARSE_ARGS("timerlat", "hist", "--user-load");
ck_assert(!params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_threads_short)
{
PARSE_ARGS("timerlat", "hist", "-u");
ck_assert(!params->kernel_workload);
ck_assert(params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_threads_long)
{
PARSE_ARGS("timerlat", "hist", "--user-threads");
ck_assert(!params->kernel_workload);
ck_assert(params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_aligned_short)
{
PARSE_ARGS("timerlat", "hist", "-A", "500");
ck_assert(tlat_params->timerlat_align);
ck_assert_int_eq(tlat_params->timerlat_align_us, 500);
}
END_TEST
START_TEST(test_aligned_long)
{
PARSE_ARGS("timerlat", "hist", "--aligned", "500");
ck_assert(tlat_params->timerlat_align);
ck_assert_int_eq(tlat_params->timerlat_align_us, 500);
}
END_TEST
/* Histogram Options */
START_TEST(test_bucket_size_short)
{
PARSE_ARGS("timerlat", "hist", "-b", "2");
ck_assert_int_eq(params->hist.bucket_size, 2);
}
END_TEST
START_TEST(test_bucket_size_long)
{
PARSE_ARGS("timerlat", "hist", "--bucket-size", "2");
ck_assert_int_eq(params->hist.bucket_size, 2);
}
END_TEST
START_TEST(test_entries_short)
{
PARSE_ARGS("timerlat", "hist", "-E", "512");
ck_assert_int_eq(params->hist.entries, 512);
}
END_TEST
START_TEST(test_entries_long)
{
PARSE_ARGS("timerlat", "hist", "--entries", "512");
ck_assert_int_eq(params->hist.entries, 512);
}
END_TEST
START_TEST(test_no_header)
{
PARSE_ARGS("timerlat", "hist", "--no-header");
ck_assert(params->hist.no_header);
}
END_TEST
START_TEST(test_no_index)
{
PARSE_ARGS("timerlat", "hist", "--with-zeros", "--no-index");
ck_assert(params->hist.no_index);
}
END_TEST
START_TEST(test_no_irq)
{
PARSE_ARGS("timerlat", "hist", "--no-irq");
ck_assert(params->hist.no_irq);
}
END_TEST
START_TEST(test_no_summary)
{
PARSE_ARGS("timerlat", "hist", "--no-summary");
ck_assert(params->hist.no_summary);
}
END_TEST
START_TEST(test_no_thread)
{
PARSE_ARGS("timerlat", "hist", "--no-thread");
ck_assert(params->hist.no_thread);
}
END_TEST
START_TEST(test_with_zeros)
{
PARSE_ARGS("timerlat", "hist", "--with-zeros");
ck_assert(params->hist.with_zeros);
}
END_TEST
/* Output */
START_TEST(test_nano_short)
{
PARSE_ARGS("timerlat", "hist", "-n");
ck_assert_int_eq(params->output_divisor, 1);
}
END_TEST
START_TEST(test_nano_long)
{
PARSE_ARGS("timerlat", "hist", "--nano");
ck_assert_int_eq(params->output_divisor, 1);
}
END_TEST
/* System Tuning */
START_TEST(test_deepest_idle_state)
{
PARSE_ARGS("timerlat", "hist", "--deepest-idle-state", "1");
ck_assert_int_eq(tlat_params->deepest_idle_state, 1);
}
END_TEST
START_TEST(test_dma_latency)
{
PARSE_ARGS("timerlat", "hist", "--dma-latency", "10");
ck_assert_int_eq(tlat_params->dma_latency, 10);
}
END_TEST
START_TEST(test_trace_buffer_size)
{
PARSE_ARGS("timerlat", "hist", "--trace-buffer-size", "200");
ck_assert_int_eq(params->buffer_size, 200);
}
END_TEST
START_TEST(test_warm_up)
{
PARSE_ARGS("timerlat", "hist", "--warm-up", "5");
ck_assert_int_eq(params->warmup, 5);
}
END_TEST
/* Auto Analysis and Actions */
START_TEST(test_auto)
{
PARSE_ARGS("timerlat", "hist", "-a", "20");
CLI_TIMERLAT_ASSERT_AUTO(20);
}
END_TEST
START_TEST(test_bpf_action)
{
PARSE_ARGS("timerlat", "hist", "--bpf-action", "program");
ck_assert_str_eq(tlat_params->bpf_action_program, "program");
}
END_TEST
START_TEST(test_dump_tasks)
{
PARSE_ARGS("timerlat", "hist", "--dump-tasks");
ck_assert(tlat_params->dump_tasks);
}
END_TEST
START_TEST(test_no_aa)
{
PARSE_ARGS("timerlat", "hist", "--no-aa");
ck_assert(tlat_params->no_aa);
}
END_TEST
START_TEST(test_on_end)
{
PARSE_ARGS("timerlat", "hist", "--on-end", "trace");
CLI_ASSERT_SINGLE_ACTION(end_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_on_threshold)
{
PARSE_ARGS("timerlat", "hist", "--on-threshold", "trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_stack_format)
{
PARSE_ARGS("timerlat", "hist", "--stack-format", "truncate");
ck_assert_int_eq(tlat_params->stack_format, STACK_FORMAT_TRUNCATE);
}
END_TEST
/* General */
START_TEST(test_debug_short)
{
PARSE_ARGS("timerlat", "hist", "-D");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_debug_long)
{
PARSE_ARGS("timerlat", "hist", "--debug");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_duration_short)
{
PARSE_ARGS("timerlat", "hist", "-d", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
START_TEST(test_duration_long)
{
PARSE_ARGS("timerlat", "hist", "--duration", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
Suite *timerlat_hist_cli_suite(void)
{
Suite *s = suite_create("timerlat_hist_cli");
TCase *tc;
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_irq_short);
tcase_add_test(tc, test_irq_long);
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);
tcase_add_test(tc, test_thread_long);
tcase_add_test(tc, test_trace_short_noarg);
tcase_add_test(tc, test_trace_short_followarg);
tcase_add_test(tc, test_trace_short_space);
tcase_add_test(tc, test_trace_short_equals);
tcase_add_test(tc, test_trace_long_noarg);
tcase_add_test(tc, test_trace_long_followarg);
tcase_add_test(tc, test_trace_long_space);
tcase_add_test(tc, test_trace_long_equals);
suite_add_tcase(s, tc);
tc = tcase_create("event_configuration");
tcase_add_test(tc, test_event_short);
tcase_add_test(tc, test_event_long);
tcase_add_test(tc, test_filter);
tcase_add_test(tc, test_trigger);
suite_add_tcase(s, tc);
tc = tcase_create("cpu_configuration");
tcase_add_test(tc, test_cpus_short);
tcase_add_test(tc, test_cpus_long);
tcase_add_test(tc, test_housekeeping_short);
tcase_add_test(tc, test_housekeeping_long);
suite_add_tcase(s, tc);
tc = tcase_create("thread_configuration");
tcase_add_test(tc, test_cgroup_short_noarg);
tcase_add_test(tc, test_cgroup_short_space);
tcase_add_test(tc, test_cgroup_short_equals);
tcase_add_test(tc, test_cgroup_long_noarg);
tcase_add_test(tc, test_cgroup_long_space);
tcase_add_test(tc, test_cgroup_long_equals);
tcase_add_test(tc, test_kernel_threads_short);
tcase_add_test(tc, test_kernel_threads_long);
tcase_add_test(tc, test_priority_short);
tcase_add_test(tc, test_priority_long);
tcase_add_test(tc, test_user_load_short);
tcase_add_test(tc, test_user_load_long);
tcase_add_test(tc, test_user_threads_short);
tcase_add_test(tc, test_user_threads_long);
tcase_add_test(tc, test_aligned_short);
tcase_add_test(tc, test_aligned_long);
suite_add_tcase(s, tc);
tc = tcase_create("histogram_options");
tcase_add_test(tc, test_bucket_size_short);
tcase_add_test(tc, test_bucket_size_long);
tcase_add_test(tc, test_entries_short);
tcase_add_test(tc, test_entries_long);
tcase_add_test(tc, test_no_header);
tcase_add_test(tc, test_no_index);
tcase_add_test(tc, test_no_irq);
tcase_add_test(tc, test_no_summary);
tcase_add_test(tc, test_no_thread);
tcase_add_test(tc, test_with_zeros);
suite_add_tcase(s, tc);
tc = tcase_create("output");
tcase_add_test(tc, test_nano_short);
tcase_add_test(tc, test_nano_long);
suite_add_tcase(s, tc);
tc = tcase_create("system_tuning");
tcase_add_test(tc, test_deepest_idle_state);
tcase_add_test(tc, test_dma_latency);
tcase_add_test(tc, test_trace_buffer_size);
tcase_add_test(tc, test_warm_up);
suite_add_tcase(s, tc);
tc = tcase_create("aa_actions");
tcase_add_test(tc, test_auto);
tcase_add_test(tc, test_bpf_action);
tcase_add_test(tc, test_dump_tasks);
tcase_add_test(tc, test_no_aa);
tcase_add_test(tc, test_on_end);
tcase_add_test(tc, test_on_threshold);
tcase_add_test(tc, test_stack_format);
suite_add_tcase(s, tc);
tc = tcase_create("general");
tcase_add_test(tc, test_debug_short);
tcase_add_test(tc, test_debug_long);
tcase_add_test(tc, test_duration_short);
tcase_add_test(tc, test_duration_long);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,654 @@
// 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 <linux/container_of.h>
#include "cli_params_assert.h"
#include "../../src/cli.h"
#define PARSE_ARGS(...) char *argv[] = { __VA_ARGS__, NULL };\
int argc = sizeof(argv) / sizeof(char *) - 1;\
struct common_params *params =\
timerlat_top_parse_args(argc, argv);\
struct timerlat_params *tlat_params __maybe_unused =\
to_timerlat_params(params)
/* Tracing Options */
START_TEST(test_irq_short)
{
PARSE_ARGS("timerlat", "top", "-i", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_irq_long)
{
PARSE_ARGS("timerlat", "top", "--irq", "20");
ck_assert_int_eq(params->stop_us, 20);
}
END_TEST
START_TEST(test_period_short)
{
PARSE_ARGS("timerlat", "top", "-p", "200");
ck_assert_int_eq(tlat_params->timerlat_period_us, 200);
}
END_TEST
START_TEST(test_period_long)
{
PARSE_ARGS("timerlat", "top", "--period", "200");
ck_assert_int_eq(tlat_params->timerlat_period_us, 200);
}
END_TEST
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "top", "-s", "20");
ck_assert_int_eq(tlat_params->print_stack, 20);
}
END_TEST
START_TEST(test_stack_long)
{
PARSE_ARGS("timerlat", "top", "--stack", "20");
ck_assert_int_eq(tlat_params->print_stack, 20);
}
END_TEST
START_TEST(test_thread_short)
{
PARSE_ARGS("timerlat", "top", "-T", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
START_TEST(test_thread_long)
{
PARSE_ARGS("timerlat", "top", "--thread", "20");
ck_assert_int_eq(params->stop_total_us, 20);
}
END_TEST
/* Event Configuration */
START_TEST(test_event_short)
{
PARSE_ARGS("timerlat", "top", "-e", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_event_long)
{
PARSE_ARGS("timerlat", "top", "--event", "system:event");
CLI_ASSERT_SINGLE_EVENT("system", "event");
}
END_TEST
START_TEST(test_filter)
{
PARSE_ARGS("timerlat", "top", "-e", "system:event", "--filter", "filter");
CLI_ASSERT_SINGLE_FILTER("filter");
}
END_TEST
START_TEST(test_trigger)
{
PARSE_ARGS("timerlat", "top", "-e", "system:event", "--trigger", "trigger");
CLI_ASSERT_SINGLE_TRIGGER("trigger");
}
END_TEST
START_TEST(test_trace_short_noarg)
{
PARSE_ARGS("timerlat", "top", "-t");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_trace_short_followarg)
{
PARSE_ARGS("timerlat", "top", "-t", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_short_space)
{
PARSE_ARGS("timerlat", "top", "-t", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_short_equals)
{
PARSE_ARGS("timerlat", "top", "-t=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_noarg)
{
PARSE_ARGS("timerlat", "top", "--trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_trace_long_followarg)
{
PARSE_ARGS("timerlat", "top", "--trace", "-d", "20");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
ck_assert_int_eq(params->duration, 20); /* check if next argument is read correctly */
}
END_TEST
START_TEST(test_trace_long_space)
{
PARSE_ARGS("timerlat", "top", "--trace", "tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
START_TEST(test_trace_long_equals)
{
PARSE_ARGS("timerlat", "top", "--trace=tracefile");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"tracefile");
}
END_TEST
/* CPU Configuration */
START_TEST(test_cpus_short)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "top", "-c", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_cpus_long)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "top", "--cpus", "0-1,3");
ck_assert_str_eq(params->cpus, "0-1,3");
CLI_ASSERT_CPUSET(monitored_cpus, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_short)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "top", "-H", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
START_TEST(test_housekeeping_long)
{
nr_cpus = 4;
PARSE_ARGS("timerlat", "top", "--house-keeping", "0-1,3");
CLI_ASSERT_CPUSET(hk_cpu_set, 0, 1, 3);
}
END_TEST
/* Thread Configuration */
START_TEST(test_cgroup_short_noarg)
{
PARSE_ARGS("timerlat", "top", "-C");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_short_space)
{
PARSE_ARGS("timerlat", "top", "-C", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_short_equals)
{
PARSE_ARGS("timerlat", "top", "-C=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_noarg)
{
PARSE_ARGS("timerlat", "top", "--cgroup");
ck_assert(params->cgroup);
ck_assert_ptr_null(params->cgroup_name);
}
END_TEST
START_TEST(test_cgroup_long_space)
{
PARSE_ARGS("timerlat", "top", "--cgroup", "cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_cgroup_long_equals)
{
PARSE_ARGS("timerlat", "top", "--cgroup=cgroup");
ck_assert(params->cgroup);
ck_assert_str_eq(params->cgroup_name, "cgroup");
}
END_TEST
START_TEST(test_kernel_threads_short)
{
PARSE_ARGS("timerlat", "top", "-k");
ck_assert(params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(!params->user_data);
}
END_TEST
START_TEST(test_kernel_threads_long)
{
PARSE_ARGS("timerlat", "top", "--kernel-threads");
ck_assert(params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(!params->user_data);
}
END_TEST
START_TEST(test_priority_short)
{
PARSE_ARGS("timerlat", "top", "-P", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_priority_long)
{
PARSE_ARGS("timerlat", "top", "--priority", "f:95");
ck_assert_int_eq(params->sched_param.sched_policy, SCHED_FIFO);
ck_assert_int_eq(params->sched_param.sched_priority, 95);
}
END_TEST
START_TEST(test_user_load_short)
{
PARSE_ARGS("timerlat", "top", "-U");
ck_assert(!params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_load_long)
{
PARSE_ARGS("timerlat", "top", "--user-load");
ck_assert(!params->kernel_workload);
ck_assert(!params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_threads_short)
{
PARSE_ARGS("timerlat", "top", "-u");
ck_assert(!params->kernel_workload);
ck_assert(params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_user_threads_long)
{
PARSE_ARGS("timerlat", "top", "--user-threads");
ck_assert(!params->kernel_workload);
ck_assert(params->user_workload);
ck_assert(params->user_data);
}
END_TEST
START_TEST(test_aligned_short)
{
PARSE_ARGS("timerlat", "top", "-A", "500");
ck_assert(tlat_params->timerlat_align);
ck_assert_int_eq(tlat_params->timerlat_align_us, 500);
}
END_TEST
START_TEST(test_aligned_long)
{
PARSE_ARGS("timerlat", "top", "--aligned", "500");
ck_assert(tlat_params->timerlat_align);
ck_assert_int_eq(tlat_params->timerlat_align_us, 500);
}
END_TEST
/* Output */
START_TEST(test_nano_short)
{
PARSE_ARGS("timerlat", "top", "-n");
ck_assert_int_eq(params->output_divisor, 1);
}
END_TEST
START_TEST(test_nano_long)
{
PARSE_ARGS("timerlat", "top", "--nano");
ck_assert_int_eq(params->output_divisor, 1);
}
END_TEST
START_TEST(test_quiet_short)
{
PARSE_ARGS("timerlat", "top", "-q");
ck_assert(params->quiet);
}
END_TEST
START_TEST(test_quiet_long)
{
PARSE_ARGS("timerlat", "top", "--quiet");
ck_assert(params->quiet);
}
END_TEST
/* System Tuning */
START_TEST(test_deepest_idle_state)
{
PARSE_ARGS("timerlat", "top", "--deepest-idle-state", "1");
ck_assert_int_eq(tlat_params->deepest_idle_state, 1);
}
END_TEST
START_TEST(test_dma_latency)
{
PARSE_ARGS("timerlat", "top", "--dma-latency", "10");
ck_assert_int_eq(tlat_params->dma_latency, 10);
}
END_TEST
START_TEST(test_trace_buffer_size)
{
PARSE_ARGS("timerlat", "top", "--trace-buffer-size", "200");
ck_assert_int_eq(params->buffer_size, 200);
}
END_TEST
START_TEST(test_warm_up)
{
PARSE_ARGS("timerlat", "top", "--warm-up", "5");
ck_assert_int_eq(params->warmup, 5);
}
END_TEST
/* Auto Analysis and Actions */
START_TEST(test_auto)
{
PARSE_ARGS("timerlat", "top", "-a", "20");
CLI_TIMERLAT_ASSERT_AUTO(20);
}
END_TEST
START_TEST(test_aa_only)
{
PARSE_ARGS("timerlat", "top", "--aa-only", "20");
CLI_TIMERLAT_ASSERT_AA_ONLY(20);
}
END_TEST
START_TEST(test_bpf_action)
{
PARSE_ARGS("timerlat", "top", "--bpf-action", "program");
ck_assert_str_eq(tlat_params->bpf_action_program, "program");
}
END_TEST
START_TEST(test_dump_tasks)
{
PARSE_ARGS("timerlat", "top", "--dump-tasks");
ck_assert(tlat_params->dump_tasks);
}
END_TEST
START_TEST(test_no_aa)
{
PARSE_ARGS("timerlat", "top", "--no-aa");
ck_assert(tlat_params->no_aa);
}
END_TEST
START_TEST(test_on_end)
{
PARSE_ARGS("timerlat", "top", "--on-end", "trace");
CLI_ASSERT_SINGLE_ACTION(end_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_on_threshold)
{
PARSE_ARGS("timerlat", "top", "--on-threshold", "trace");
CLI_ASSERT_SINGLE_ACTION(threshold_actions, ACTION_TRACE_OUTPUT, trace_output, str,
"timerlat_trace.txt");
}
END_TEST
START_TEST(test_stack_format)
{
PARSE_ARGS("timerlat", "top", "--stack-format", "truncate");
ck_assert_int_eq(tlat_params->stack_format, STACK_FORMAT_TRUNCATE);
}
END_TEST
/* General */
START_TEST(test_debug_short)
{
PARSE_ARGS("timerlat", "top", "-D");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_debug_long)
{
PARSE_ARGS("timerlat", "top", "--debug");
ck_assert(config_debug);
}
END_TEST
START_TEST(test_duration_short)
{
PARSE_ARGS("timerlat", "top", "-d", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
START_TEST(test_duration_long)
{
PARSE_ARGS("timerlat", "top", "--duration", "1m");
ck_assert_int_eq(params->duration, 60);
}
END_TEST
Suite *timerlat_top_cli_suite(void)
{
Suite *s = suite_create("timerlat_top_cli");
TCase *tc;
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_irq_short);
tcase_add_test(tc, test_irq_long);
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);
tcase_add_test(tc, test_thread_long);
tcase_add_test(tc, test_trace_short_noarg);
tcase_add_test(tc, test_trace_short_followarg);
tcase_add_test(tc, test_trace_short_space);
tcase_add_test(tc, test_trace_short_equals);
tcase_add_test(tc, test_trace_long_noarg);
tcase_add_test(tc, test_trace_long_followarg);
tcase_add_test(tc, test_trace_long_space);
tcase_add_test(tc, test_trace_long_equals);
suite_add_tcase(s, tc);
tc = tcase_create("event_configuration");
tcase_add_test(tc, test_event_short);
tcase_add_test(tc, test_event_long);
tcase_add_test(tc, test_filter);
tcase_add_test(tc, test_trigger);
suite_add_tcase(s, tc);
tc = tcase_create("cpu_configuration");
tcase_add_test(tc, test_cpus_short);
tcase_add_test(tc, test_cpus_long);
tcase_add_test(tc, test_housekeeping_short);
tcase_add_test(tc, test_housekeeping_long);
suite_add_tcase(s, tc);
tc = tcase_create("thread_configuration");
tcase_add_test(tc, test_cgroup_short_noarg);
tcase_add_test(tc, test_cgroup_short_space);
tcase_add_test(tc, test_cgroup_short_equals);
tcase_add_test(tc, test_cgroup_long_noarg);
tcase_add_test(tc, test_cgroup_long_space);
tcase_add_test(tc, test_cgroup_long_equals);
tcase_add_test(tc, test_kernel_threads_short);
tcase_add_test(tc, test_kernel_threads_long);
tcase_add_test(tc, test_priority_short);
tcase_add_test(tc, test_priority_long);
tcase_add_test(tc, test_user_load_short);
tcase_add_test(tc, test_user_load_long);
tcase_add_test(tc, test_user_threads_short);
tcase_add_test(tc, test_user_threads_long);
tcase_add_test(tc, test_aligned_short);
tcase_add_test(tc, test_aligned_long);
suite_add_tcase(s, tc);
tc = tcase_create("output");
tcase_add_test(tc, test_nano_short);
tcase_add_test(tc, test_nano_long);
tcase_add_test(tc, test_quiet_short);
tcase_add_test(tc, test_quiet_long);
suite_add_tcase(s, tc);
tc = tcase_create("system_tuning");
tcase_add_test(tc, test_deepest_idle_state);
tcase_add_test(tc, test_dma_latency);
tcase_add_test(tc, test_trace_buffer_size);
tcase_add_test(tc, test_warm_up);
suite_add_tcase(s, tc);
tc = tcase_create("aa_actions");
tcase_add_test(tc, test_auto);
tcase_add_test(tc, test_aa_only);
tcase_add_test(tc, test_bpf_action);
tcase_add_test(tc, test_dump_tasks);
tcase_add_test(tc, test_no_aa);
tcase_add_test(tc, test_on_end);
tcase_add_test(tc, test_on_threshold);
tcase_add_test(tc, test_stack_format);
suite_add_tcase(s, tc);
tc = tcase_create("general");
tcase_add_test(tc, test_debug_short);
tcase_add_test(tc, test_debug_long);
tcase_add_test(tc, test_duration_short);
tcase_add_test(tc, test_duration_long);
suite_add_tcase(s, tc);
return s;
}
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <check.h>
#include <stdbool.h>
#include "../../src/utils.h"
#include "../../src/cli.h"
Suite *utils_suite(void);
Suite *actions_suite(void);
Suite *osnoise_top_cli_suite(void);
Suite *osnoise_hist_cli_suite(void);
Suite *timerlat_top_cli_suite(void);
Suite *timerlat_hist_cli_suite(void);
Suite *cli_opt_callback_suite(void);
int main(int argc, char *argv[])
{
int num_failed;
SRunner *sr;
in_unit_test = true;
sr = srunner_create(utils_suite());
srunner_add_suite(sr, cli_opt_callback_suite());
srunner_add_suite(sr, actions_suite());
srunner_add_suite(sr, osnoise_top_cli_suite());
srunner_add_suite(sr, osnoise_hist_cli_suite());
srunner_add_suite(sr, timerlat_top_cli_suite());
srunner_add_suite(sr, timerlat_hist_cli_suite());
srunner_run_all(sr, CK_VERBOSE);
num_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (num_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
@@ -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;
}