Merge tag 'trace-tools-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull RTLA updates from Steven Rostedt:

 - Extend support for unsetting CLI options

   libsubcmd auto-generates "--no-<option>" to unset options, provided
   the option callback supports it. Implement this for RTLA CLI beyond
   boolean options, and document the few exceptions that are left out.

 - Test all tracer options in runtime tests

   Verify that RTLA sets osnoise/timerlat options correctly by reading
   them from tracefs during runtime tests.

 - Improve range validation for option arguments

   Make CLI range validation consistent with the kernel limits and unify
   implementation and error messages between options.

 - Improve invalid option argument parsing

   Consistently reject invalid values for numeric option arguments with
   a unified error message for all options.

* tag 'trace-tools-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  rtla/cli: Unify and improve handling of invalid option arguments
  rtla/cli: Unify and improve range validation logic
  rtla/tests: Test all tracer options in runtime tests
  Documentation/rtla: Document unsetting options
  rtla: Add unit tests for CLI with unset
  rtla: Add unit tests for unset in opt callbacks
  rtla: Allow unsetting non-list custom-callback CLI options
This commit is contained in:
Linus Torvalds
2026-08-19 14:00:15 -07:00
17 changed files with 952 additions and 387 deletions

View File

@@ -1,5 +1,22 @@
.. SPDX-License-Identifier: GPL-2.0
UNSETTING OPTIONS
=================
The effect of most command line options can be reverted by prepending "no-" to
the long variant of the option, for example:
$ rtla timerlat top -p 100 --no-period
resets the period back to the default value of 1000 us.
If a command line option sets multiple RTLA parameters at once, the inverted
option will revert all of them, even if they were not set by the particular
option. For example, since using "--auto" implies "--trace", specifying
"--trace --no-auto" will also disable trace output, just like if "--no-trace"
was specified.
SIGINT BEHAVIOR
===============

View File

@@ -22,10 +22,14 @@
Enable an event in the trace (**-t**) session. The argument can be a specific event, e.g., **-e** *sched:sched_switch*, or all events of a system group, e.g., **-e** *sched*. Multiple **-e** are allowed. It is only active when **-t** or **-a** are set.
This option cannot be unset.
**--filter** *<filter>*
Filter the previous **-e** *sys:event* event with *<filter>*. For further information about event filtering see https://www.kernel.org/doc/html/latest/trace/events.html#event-filtering.
This option cannot be unset.
**--trigger** *<trigger>*
Enable a trace event trigger to the previous **-e** *sys:event*.
If the *hist:* trigger is activated, the output histogram will be automatically saved to a file named *system_event_hist.txt*.
@@ -37,6 +41,8 @@
For further information about event trigger see https://www.kernel.org/doc/html/latest/trace/events.html#event-triggers.
This option cannot be unset.
**-P**, **--priority** *o:prio|r:prio|f:prio|d:runtime:period*
Set scheduling parameters to the |tool| tracer threads, the format to set the priority are:
@@ -78,7 +84,8 @@
Saves trace output, optionally taking a filename. Alternative to -t/--trace.
Note that unlike -t/--trace, specifying this multiple times will result in
the trace being saved multiple times.
the trace being saved multiple times, and --no-trace will not disable trace
output when enabled through this option.
- *signal,num=<sig>,pid=<pid>*
@@ -107,6 +114,8 @@
|actionsperf|
This option cannot be unset.
**--on-end** *action*
Defines an action to be executed at the end of tracing.
@@ -124,6 +133,8 @@
This runs rtla with the default options, and saves trace output at the end.
This option cannot be unset.
**-h**, **--help**
Print help menu.

View File

@@ -24,11 +24,15 @@
Stop the trace if a single sample is higher than the argument in microseconds.
If **-T** is set, it will also save the trace to the output.
This option cannot be unset.
**-S**, **--stop-total** *us*
Stop the trace if the total sample is higher than the argument in microseconds.
If **-T** is set, it will also save the trace to the output.
This option cannot be unset.
**-T**, **--threshold** *us*
Specify the minimum delta between two time reads to be considered noise.

View File

@@ -23,10 +23,14 @@
Stop trace if the *IRQ* latency is higher than the argument in us.
This option cannot be unset.
**-T**, **--thread** *us*
Stop trace if the *Thread* latency is higher than the argument in us.
This option cannot be unset.
**-s**, **--stack** *us*
Save the stack trace at the *IRQ* if a *Thread* latency is higher than the

View File

@@ -192,10 +192,10 @@ struct common_params *osnoise_hist_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
/* display data in microseconds */
params->common.output_divisor = 1000;
params->common.hist.bucket_size = 1;
params->common.hist.entries = 256;
/* set default values */
params->common.output_divisor = default_output_divisor;
params->common.hist.bucket_size = default_bucket_size;
params->common.hist.entries = default_entries;
argc = parse_options(argc, (const char **)argv,
osnoise_hist_options, osnoise_hist_usage,
@@ -280,19 +280,15 @@ struct common_params *timerlat_top_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
params->deepest_idle_state = -2;
/* display data in microseconds */
params->common.output_divisor = 1000;
/* set default values */
params->dma_latency = default_dma_latency;
params->deepest_idle_state = default_deepest_idle_state;
params->common.output_divisor = default_output_divisor;
params->stack_format = default_stack_format;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
/* default to truncate stack format */
params->stack_format = STACK_FORMAT_TRUNCATE;
argc = parse_options(argc, (const char **)argv,
timerlat_top_options, timerlat_top_usage,
common_parse_options_flags);
@@ -403,23 +399,17 @@ struct common_params *timerlat_hist_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
/* disabled by default */
params->deepest_idle_state = -2;
/* display data in microseconds */
params->common.output_divisor = 1000;
params->common.hist.bucket_size = 1;
params->common.hist.entries = 256;
/* set default values */
params->dma_latency = default_dma_latency;
params->deepest_idle_state = default_deepest_idle_state;
params->common.output_divisor = default_output_divisor;
params->common.hist.bucket_size = default_bucket_size;
params->common.hist.entries = default_entries;
params->stack_format = default_stack_format;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
/* default to truncate stack format */
params->stack_format = STACK_FORMAT_TRUNCATE;
argc = parse_options(argc, (const char **)argv,
timerlat_hist_options, timerlat_hist_usage,
common_parse_options_flags);

View File

@@ -5,6 +5,8 @@
#error "Private header file included outside of cli.c module"
#endif
#include <errno.h>
#include <limits.h>
#include <linux/kernel.h>
#include <subcmd/parse-options.h>
@@ -22,6 +24,111 @@ struct timerlat_cb_data {
char *trace_output;
};
/*
* Non-zero default values for parameters
*/
static const int default_dma_latency = -1; /* -1 = unset */
static const int default_deepest_idle_state = -2; /* -1 = disable all, -2 = unset */
static const int default_output_divisor = 1000;
static const int default_bucket_size = 1;
static const int default_entries = 256;
static const enum stack_format default_stack_format = STACK_FORMAT_TRUNCATE;
/*
* Range checking for long long and int option callbacks.
*
* Pass a pointer to a const struct as opt->data to enable range checking.
* If opt->data is NULL, no range check is performed.
*/
struct llong_range {
long long min;
long long max;
};
struct int_range {
int min;
int max;
};
#define LLONG_RANGE(lo, hi) \
(&(const struct llong_range){ .min = (lo), .max = (hi) })
#define INT_RANGE(lo, hi) \
(&(const struct int_range){ .min = (lo), .max = (hi) })
static int check_llong_range(const struct option *opt, long long value)
{
const struct llong_range *range = opt->data;
if (!range)
return 0;
if (value < range->min || value > range->max) {
fprintf(stderr, " Error: --%s value %lld is out of range [%lld, %lld]\n",
opt->long_name, value, range->min, range->max);
return -1;
}
return 0;
}
static int check_int_range(const struct option *opt, int value)
{
const struct int_range *range = opt->data;
if (!range)
return 0;
if (value < range->min || value > range->max) {
fprintf(stderr, " Error: --%s value %d is out of range [%d, %d]\n",
opt->long_name, value, range->min, range->max);
return -1;
}
return 0;
}
/*
* OPT_CALLBACK variant that populates .data (for range checking).
*/
#define RTLA_OPT_CALLBACK_DATA(s, l, v, a, h, f, d) \
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
.value = (v), .argh = (a), .help = (h), .callback = (f), \
.data = (void *)(d) }
#define RTLA_OPT_CALLBACK_DATA_DEFVAL(s, l, v, a, h, f, d, dv) \
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
.value = (v), .argh = (a), .help = (h), .callback = (f), \
.data = (void *)(d), .defval = (intptr_t)(dv) }
/*
* Shorthand macros for integer/long long command line options using
* opt_int_callback/opt_llong_callback, with variants that set defval
* and/or data (for range checking).
*
* Note: defval's type is intptr_t. opt_int_callback interprets it directly as
* an int, opt_llong_callback interprets it as a pointer to a long long, as
* long long does not fit into intptr_t on 32-bit architectures.
*/
#define RTLA_OPT_LLONG(s, l, v, a, h) \
OPT_CALLBACK(s, l, v, a, h, opt_llong_callback)
#define RTLA_OPT_LLONG_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
.help = (h), .callback = opt_llong_callback, .defval = (intptr_t)(d) }
#define RTLA_OPT_LLONG_DATA(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
.help = (h), .callback = opt_llong_callback, .data = (void *)(d) }
#define RTLA_OPT_INT(s, l, v, a, h) \
OPT_CALLBACK(s, l, v, a, h, opt_int_callback)
#define RTLA_OPT_INT_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
.help = (h), .callback = opt_int_callback, .defval = (intptr_t)(d) }
#define RTLA_OPT_INT_DATA_DEFVAL(s, l, v, a, h, d, dv) { .type = OPTION_CALLBACK, \
.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
.help = (h), .callback = opt_int_callback, \
.data = (void *)(d), .defval = (intptr_t)(dv) }
/*
* Macros for command line options common to all tools
*
@@ -108,14 +215,12 @@ struct timerlat_cb_data {
#define RTLA_OPT_QUIET OPT_BOOLEAN('q', "quiet", &params->common.quiet, \
"print only a summary at the end")
#define RTLA_OPT_TRACE_BUFFER_SIZE OPT_CALLBACK(0, "trace-buffer-size", \
#define RTLA_OPT_TRACE_BUFFER_SIZE RTLA_OPT_INT(0, "trace-buffer-size", \
&params->common.buffer_size, "kB", \
"set the per-cpu trace buffer size in kB", \
opt_int_callback)
"set the per-cpu trace buffer size in kB")
#define RTLA_OPT_WARM_UP OPT_CALLBACK(0, "warm-up", &params->common.warmup, "s", \
"let the workload run for s seconds before collecting data", \
opt_int_callback)
#define RTLA_OPT_WARM_UP RTLA_OPT_INT(0, "warm-up", &params->common.warmup, "s", \
"let the workload run for s seconds before collecting data")
#define RTLA_OPT_AUTO(cb) OPT_CALLBACK('a', "auto", &cb_data, "us", \
"set automatic trace mode, stopping the session if argument in us sample is hit", \
@@ -135,6 +240,41 @@ struct timerlat_cb_data {
#define RTLA_OPT_DEBUG OPT_BOOLEAN('D', "debug", &config_debug, \
"print debug info")
/*
* Helper functions for parsing numeric option arguments.
*/
static void opt_err(const struct option *opt, const char *arg, const char *msg)
{
fprintf(stderr, " Error: --%s: '%s' %s\n", opt->long_name, arg, msg);
}
static int strtoll_safe(const struct option *opt, const char *arg, long long *value)
{
long long tmp;
char *end;
errno = 0;
tmp = strtoll(arg, &end, 10);
if (errno || *end || end == arg) {
opt_err(opt, arg, "is not a valid number");
return -1;
}
*value = tmp;
return 0;
}
static int strtoi_safe(const struct option *opt, const char *arg, int *value)
{
int tmp;
if (strtoi(arg, &tmp)) {
opt_err(opt, arg, "is not a valid number");
return -1;
}
*value = tmp;
return 0;
}
/*
* Common callback functions for command line options
*/
@@ -143,10 +283,18 @@ static int opt_llong_callback(const struct option *opt, const char *arg, int uns
{
long long *value = opt->value;
if (unset || !arg)
if (unset) {
*value = opt->defval ? *(long long *)opt->defval : 0;
return 0;
}
if (!arg)
return -1;
*value = get_llong_from_str((char *)arg);
if (strtoll_safe(opt, arg, value))
return -1;
if (check_llong_range(opt, *value))
return -1;
return 0;
}
@@ -154,10 +302,17 @@ static int opt_int_callback(const struct option *opt, const char *arg, int unset
{
int *value = opt->value;
if (unset || !arg)
if (unset) {
*value = (int)opt->defval;
return 0;
}
if (!arg)
return -1;
if (strtoi(arg, value))
if (strtoi_safe(opt, arg, value))
return -1;
if (check_int_range(opt, *value))
return -1;
return 0;
@@ -168,12 +323,20 @@ static int opt_cpus_cb(const struct option *opt, const char *arg, int unset)
struct common_params *params = opt->value;
int retval;
if (unset || !arg)
if (unset) {
CPU_ZERO(&params->monitored_cpus);
params->cpus = NULL;
return 0;
}
if (!arg)
return -1;
retval = parse_cpu_set((char *)arg, &params->monitored_cpus);
if (retval)
fatal("Invalid -c cpu list");
if (retval) {
opt_err(opt, arg, "is not a valid cpu set");
return -1;
}
params->cpus = (char *)arg;
return 0;
@@ -183,8 +346,11 @@ static int opt_cgroup_cb(const struct option *opt, const char *arg, int unset)
{
struct common_params *params = opt->value;
if (unset)
return -1;
if (unset) {
params->cgroup = 0;
params->cgroup_name = NULL;
return 0;
}
params->cgroup = 1;
params->cgroup_name = (char *)arg;
@@ -199,12 +365,19 @@ static int opt_duration_cb(const struct option *opt, const char *arg, int unset)
{
struct common_params *params = opt->value;
if (unset || !arg)
if (unset) {
params->duration = 0;
return 0;
}
if (!arg)
return -1;
params->duration = parse_seconds_duration((char *)arg);
if (!params->duration)
fatal("Invalid -d duration");
if (!params->duration) {
opt_err(opt, arg, "is not a valid duration");
return -1;
}
return 0;
}
@@ -233,13 +406,21 @@ static int opt_housekeeping_cb(const struct option *opt, const char *arg, int un
struct common_params *params = opt->value;
int retval;
if (unset || !arg)
if (unset) {
params->hk_cpus = 0;
CPU_ZERO(&params->hk_cpu_set);
return 0;
}
if (!arg)
return -1;
params->hk_cpus = 1;
retval = parse_cpu_set((char *)arg, &params->hk_cpu_set);
if (retval)
fatal("Error parsing house keeping CPUs");
if (retval) {
opt_err(opt, arg, "is not a valid cpu set");
return -1;
}
return 0;
}
@@ -249,12 +430,20 @@ static int opt_priority_cb(const struct option *opt, const char *arg, int unset)
struct common_params *params = opt->value;
int retval;
if (unset || !arg)
if (unset) {
memset(&params->sched_param, 0, sizeof(params->sched_param));
params->set_sched = 0;
return 0;
}
if (!arg)
return -1;
retval = parse_prio((char *)arg, &params->sched_param);
if (retval == -1)
fatal("Invalid -P priority");
if (retval == -1) {
opt_err(opt, arg, "is not a valid priority");
return -1;
}
params->set_sched = 1;
return 0;
@@ -267,8 +456,10 @@ static int opt_trigger_cb(const struct option *opt, const char *arg, int unset)
if (unset || !arg)
return -1;
if (!*events)
fatal("--trigger requires a previous -e");
if (!*events) {
opt_err(opt, arg, "has no previous event to apply to");
return -1;
}
trace_event_add_trigger(*events, (char *)arg);
@@ -282,8 +473,10 @@ static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
if (unset || !arg)
return -1;
if (!*events)
fatal("--filter requires a previous -e");
if (!*events) {
opt_err(opt, arg, "has no previous event to apply to");
return -1;
}
trace_event_add_filter(*events, (char *)arg);
@@ -293,17 +486,16 @@ static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
/*
* Macros for command line options specific to osnoise
*/
#define OSNOISE_OPT_PERIOD OPT_CALLBACK('p', "period", &params->period, "us", \
#define OSNOISE_OPT_PERIOD RTLA_OPT_LLONG_DATA('p', "period", &params->period, "us", \
"osnoise period in us", \
opt_osnoise_period_cb)
LLONG_RANGE(1, 10000000))
#define OSNOISE_OPT_RUNTIME OPT_CALLBACK('r', "runtime", &params->runtime, "us", \
#define OSNOISE_OPT_RUNTIME RTLA_OPT_LLONG_DATA('r', "runtime", &params->runtime, "us", \
"osnoise runtime in us", \
opt_osnoise_runtime_cb)
LLONG_RANGE(100, LLONG_MAX))
#define OSNOISE_OPT_THRESHOLD OPT_CALLBACK('T', "threshold", &params->threshold, "us", \
"the minimum delta to be considered a noise", \
opt_llong_callback)
#define OSNOISE_OPT_THRESHOLD RTLA_OPT_LLONG('T', "threshold", &params->threshold, "us", \
"the minimum delta to be considered a noise")
/*
* Callback functions for command line options for osnoise tools
@@ -315,10 +507,18 @@ static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int un
struct osnoise_params *params = cb_data->params;
long long auto_thresh;
if (unset || !arg)
if (unset) {
params->common.stop_us = 0;
params->threshold = 0;
cb_data->trace_output = NULL;
return 0;
}
if (!arg)
return -1;
auto_thresh = get_llong_from_str((char *)arg);
if (strtoll_safe(opt, arg, &auto_thresh))
return -1;
params->common.stop_us = auto_thresh;
params->threshold = 1;
@@ -328,40 +528,14 @@ static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int un
return 0;
}
static int opt_osnoise_period_cb(const struct option *opt, const char *arg, int unset)
{
unsigned long long *period = opt->value;
if (unset || !arg)
return -1;
*period = get_llong_from_str((char *)arg);
if (*period > 10000000)
fatal("Period longer than 10 s");
return 0;
}
static int opt_osnoise_runtime_cb(const struct option *opt, const char *arg, int unset)
{
unsigned long long *runtime = opt->value;
if (unset || !arg)
return -1;
*runtime = get_llong_from_str((char *)arg);
if (*runtime < 100)
fatal("Runtime shorter than 100 us");
return 0;
}
static int opt_osnoise_trace_output_cb(const struct option *opt, const char *arg, int unset)
{
const char **trace_output = opt->value;
if (unset)
return -1;
if (unset) {
*trace_output = NULL;
return 0;
}
if (!arg) {
*trace_output = "osnoise_trace.txt";
@@ -384,8 +558,10 @@ static int opt_osnoise_on_threshold_cb(const struct option *opt, const char *arg
return -1;
retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
if (retval)
fatal("Invalid action %s", arg);
if (retval) {
opt_err(opt, arg, "is not a valid action");
return -1;
}
return 0;
}
@@ -399,8 +575,10 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
return -1;
retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
if (retval)
fatal("Invalid action %s", arg);
if (retval) {
opt_err(opt, arg, "is not a valid action");
return -1;
}
return 0;
}
@@ -408,26 +586,26 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
/*
* Macros for command line options specific to timerlat
*/
#define TIMERLAT_OPT_PERIOD OPT_CALLBACK('p', "period", &params->timerlat_period_us, "us", \
#define TIMERLAT_OPT_PERIOD RTLA_OPT_LLONG_DATA('p', "period", &params->timerlat_period_us, "us", \
"timerlat period in us", \
opt_timerlat_period_cb)
LLONG_RANGE(100, 1000000))
#define TIMERLAT_OPT_STACK OPT_CALLBACK('s', "stack", &params->print_stack, "us", \
"save the stack trace at the IRQ if a thread latency is higher than the argument in us", \
opt_llong_callback)
#define TIMERLAT_OPT_STACK RTLA_OPT_LLONG('s', "stack", &params->print_stack, "us", \
"save the stack trace at the IRQ if a thread latency is higher than the argument in us")
#define TIMERLAT_OPT_NANO OPT_CALLBACK_NOOPT('n', "nano", params, NULL, \
"display data in nanoseconds", \
opt_nano_cb)
#define TIMERLAT_OPT_DMA_LATENCY OPT_CALLBACK(0, "dma-latency", &params->dma_latency, "us", \
#define TIMERLAT_OPT_DMA_LATENCY RTLA_OPT_INT_DATA_DEFVAL(0, "dma-latency", \
&params->dma_latency, "us", \
"set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", \
opt_dma_latency_cb)
INT_RANGE(0, 10000), default_dma_latency)
#define TIMERLAT_OPT_DEEPEST_IDLE_STATE OPT_CALLBACK(0, "deepest-idle-state", \
#define TIMERLAT_OPT_DEEPEST_IDLE_STATE RTLA_OPT_INT_DATA_DEFVAL(0, "deepest-idle-state", \
&params->deepest_idle_state, "n", \
"only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", \
opt_int_callback)
INT_RANGE(-1, INT_MAX), default_deepest_idle_state)
#define TIMERLAT_OPT_AA_ONLY OPT_CALLBACK(0, "aa-only", params, "us", \
"stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)", \
@@ -447,38 +625,33 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
"set the stack format (truncate, skip, full)", \
opt_stack_format_cb)
#define TIMERLAT_OPT_ALIGNED OPT_CALLBACK('A', "aligned", params, "us", \
#define TIMERLAT_OPT_ALIGNED RTLA_OPT_CALLBACK_DATA('A', "aligned", params, "us", \
"align thread wakeups to a specific offset", \
opt_timerlat_align_cb)
opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX))
/*
* Callback functions for command line options for timerlat tools
*/
static int opt_timerlat_period_cb(const struct option *opt, const char *arg, int unset)
{
long long *period = opt->value;
if (unset || !arg)
return -1;
*period = get_llong_from_str((char *)arg);
if (*period > 1000000)
fatal("Period longer than 1 s");
return 0;
}
static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_cb_data *cb_data = opt->value;
struct timerlat_params *params = cb_data->params;
long long auto_thresh;
if (unset || !arg)
if (unset) {
params->common.stop_total_us = 0;
params->common.stop_us = 0;
params->print_stack = 0;
cb_data->trace_output = NULL;
return 0;
}
if (!arg)
return -1;
auto_thresh = get_llong_from_str((char *)arg);
if (strtoll_safe(opt, arg, &auto_thresh))
return -1;
params->common.stop_total_us = auto_thresh;
params->common.stop_us = auto_thresh;
params->print_stack = auto_thresh;
@@ -489,32 +662,24 @@ static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int u
return 0;
}
static int opt_dma_latency_cb(const struct option *opt, const char *arg, int unset)
{
int *dma_latency = opt->value;
int retval;
if (unset || !arg)
return -1;
retval = strtoi((char *)arg, dma_latency);
if (retval)
fatal("Invalid -dma-latency %s", arg);
if (*dma_latency < 0 || *dma_latency > 10000)
fatal("--dma-latency needs to be >= 0 and <= 10000");
return 0;
}
static int opt_aa_only_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
long long auto_thresh;
if (unset || !arg)
if (unset) {
params->common.stop_total_us = 0;
params->common.stop_us = 0;
params->print_stack = 0;
params->common.aa_only = 0;
return 0;
}
if (!arg)
return -1;
auto_thresh = get_llong_from_str((char *)arg);
if (strtoll_safe(opt, arg, &auto_thresh))
return -1;
params->common.stop_total_us = auto_thresh;
params->common.stop_us = auto_thresh;
params->print_stack = auto_thresh;
@@ -527,8 +692,10 @@ static int opt_timerlat_trace_output_cb(const struct option *opt, const char *ar
{
const char **trace_output = opt->value;
if (unset)
return -1;
if (unset) {
*trace_output = NULL;
return 0;
}
if (!arg) {
*trace_output = "timerlat_trace.txt";
@@ -551,8 +718,10 @@ static int opt_timerlat_on_threshold_cb(const struct option *opt, const char *ar
return -1;
retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
if (retval)
fatal("Invalid action %s", arg);
if (retval) {
opt_err(opt, arg, "is not a valid action");
return -1;
}
return 0;
}
@@ -566,8 +735,10 @@ static int opt_timerlat_on_end_cb(const struct option *opt, const char *arg, int
return -1;
retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
if (retval)
fatal("Invalid action %s", arg);
if (retval) {
opt_err(opt, arg, "is not a valid action");
return -1;
}
return 0;
}
@@ -576,8 +747,11 @@ static int opt_user_threads_cb(const struct option *opt, const char *arg, int un
{
struct timerlat_params *params = opt->value;
if (unset)
return -1;
if (unset) {
params->common.user_workload = false;
params->common.user_data = false;
return 0;
}
params->common.user_workload = true;
params->common.user_data = true;
@@ -589,8 +763,10 @@ static int opt_nano_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
if (unset)
return -1;
if (unset) {
params->common.output_divisor = default_output_divisor;
return 0;
}
params->common.output_divisor = 1;
@@ -601,13 +777,20 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
{
int *format = opt->value;
if (unset || !arg)
if (unset) {
*format = default_stack_format;
return 0;
}
if (!arg)
return -1;
*format = parse_stack_format((char *)arg);
if (*format == -1)
fatal("Invalid --stack-format option");
if (*format == -1) {
opt_err(opt, arg, "is not a valid stack format");
return -1;
}
return 0;
}
@@ -615,12 +798,24 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
long long val;
if (unset || !arg)
if (unset) {
params->timerlat_align = false;
params->timerlat_align_us = 0;
return 0;
}
if (!arg)
return -1;
if (strtoll_safe(opt, arg, &val))
return -1;
if (check_llong_range(opt, val))
return -1;
params->timerlat_align = true;
params->timerlat_align_us = get_llong_from_str((char *)arg);
params->timerlat_align_us = val;
return 0;
}
@@ -629,14 +824,15 @@ static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int
* Macros for command line options specific to histogram-based tools
*/
#define HIST_OPT_BUCKET_SIZE OPT_CALLBACK('b', "bucket-size", \
#define HIST_OPT_BUCKET_SIZE RTLA_OPT_INT_DATA_DEFVAL('b', "bucket-size", \
&params->common.hist.bucket_size, "N", \
"set the histogram bucket size (default 1)", \
opt_bucket_size_cb)
INT_RANGE(1, 999999), default_bucket_size)
#define HIST_OPT_ENTRIES OPT_CALLBACK('E', "entries", &params->common.hist.entries, "N", \
#define HIST_OPT_ENTRIES RTLA_OPT_INT_DATA_DEFVAL('E', "entries", \
&params->common.hist.entries, "N", \
"set the number of entries of the histogram (default 256)", \
opt_entries_cb)
INT_RANGE(10, 9999999), default_entries)
#define HIST_OPT_NO_IRQ OPT_BOOLEAN_FLAG(0, "no-irq", &params->common.hist.no_irq, \
"ignore IRQ latencies", PARSE_OPT_NOAUTONEG)
@@ -656,32 +852,3 @@ static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int
#define HIST_OPT_WITH_ZEROS OPT_BOOLEAN(0, "with-zeros", &params->common.hist.with_zeros, \
"print zero only entries")
/* Histogram-specific callbacks */
static int opt_bucket_size_cb(const struct option *opt, const char *arg, int unset)
{
int *bucket_size = opt->value;
if (unset || !arg)
return -1;
*bucket_size = get_llong_from_str((char *)arg);
if (*bucket_size == 0 || *bucket_size >= 1000000)
fatal("Bucket size needs to be > 0 and <= 1000000");
return 0;
}
static int opt_entries_cb(const struct option *opt, const char *arg, int unset)
{
int *entries = opt->value;
if (unset || !arg)
return -1;
*entries = get_llong_from_str((char *)arg);
if (*entries < 10 || *entries > 9999999)
fatal("Entries must be > 10 and < 10000000");
return 0;
}

View File

@@ -98,30 +98,37 @@ check() {
}
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
# Do the same as "check", but with pre-set tracefs options.
# Resets osnoise first, then writes the given tracefs option=value
# pairs before running the check with NO_RESET_OSNOISE=1.
# Arguments: test_name command exit_code expected_output [path=value ...]
# Each path is relative to /sys/kernel/tracing/
local arg1=$1
local arg2=$2
local arg3=$3
local arg4=$4
local opt option value
# Apply osnoise options (if not dry run)
# Apply tracefs options (if not dry run)
if [ -n "$TEST_COUNT" ]
then
[ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise
shift
shift
while shift
shift 4
for opt in "$@"
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
[ -z "$opt" ] && continue
option="${opt%%=*}"
value="${opt#*=}"
# Try to apply the option, ignore errors: when pre-setting fails
# (e.g. kernel does not know the option), the test itself will likely
# also fail.
# Throwing an error here would cause the test to be incorrectly
# skipped.
echo "$value" > "/sys/kernel/tracing/$option"
done
fi
NO_RESET_OSNOISE=1 check "$arg1" "$arg2" "$arg3"
NO_RESET_OSNOISE=1 check "$arg1" "$arg2" "$arg3" "$arg4"
}
check_top_hist() {

View File

@@ -18,5 +18,8 @@ check "stop the trace if a single sample is higher than 1 us" \
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"
check "verify OSNOISE_IRQ_DISABLE" \
"hwnoise -S 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh OSNOISE_IRQ_DISABLE\"" \
2 "^OSNOISE_IRQ_DISABLE=enabled$"
test_end

View File

@@ -32,7 +32,7 @@ check "hist with -b/--bucket-size" \
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$"
"osnoise hist -E 1 -d 1s" 129 "out of range \[10, 9999999\]"
check "hist with --no-header" \
"osnoise hist --no-header -d 1s" 0 "" "RTLA osnoise histogram"
check "hist with --with-zeros" \
@@ -42,11 +42,40 @@ check "hist with --no-index" \
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.
# Tracer option tests - verify that rtla correctly sets tracefs options
# Default tests: poison tracefs with wrong values, verify rtla resets to defaults
check_with_osnoise_options "apply default period" \
"osnoise hist -s 1" 2 period_us=600000000
"osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/period_us\"" \
2 "^osnoise/period_us=1000000$" osnoise/period_us=600000000
check_with_osnoise_options "apply default runtime" \
"osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/runtime_us\"" \
2 "^osnoise/runtime_us=1000000$" osnoise/runtime_us=100
check_with_osnoise_options "apply default tracing_thresh" \
"osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh tracing_thresh\"" \
2 "^tracing_thresh=0$" tracing_thresh=999999
check_with_osnoise_options "apply default stop_tracing_us" \
"osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
2 "^osnoise/stop_tracing_us=0$" osnoise/stop_tracing_us=999999
check_with_osnoise_options "apply default stop_tracing_total_us" \
"osnoise top -q -s 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
2 "^osnoise/stop_tracing_total_us=0$" osnoise/stop_tracing_total_us=999999
# Non-default tracer option tests: verify CLI options correctly set tracefs values
check_top_q_hist "verify -p sets period_us" \
"osnoise TOOL -p 2000000 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/period_us\"" \
2 "^osnoise/period_us=2000000$"
check_top_q_hist "verify -r sets runtime_us" \
"osnoise TOOL -r 500000 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/runtime_us\"" \
2 "^osnoise/runtime_us=500000$"
check_top_q_hist "verify -T sets tracing_thresh" \
"osnoise TOOL -T 5 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh tracing_thresh\"" \
2 "^tracing_thresh=5$"
check_top_q_hist "verify -s sets stop_tracing_us" \
"osnoise TOOL -s 30 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
2 "^osnoise/stop_tracing_us=30$"
check_top_q_hist "verify -S sets stop_tracing_total_us" \
"osnoise TOOL -S 100 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
2 "^osnoise/stop_tracing_total_us=100$"
# Actions tests
check_top_q_hist "trace output through -t with custom filename" \

View File

@@ -0,0 +1,16 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Check if osnoise options are enabled or disabled.
# Usage: check-osnoise-option.sh <OPTION1> [<OPTION2> ...]
# Output: one line per option in the format "OPTION=enabled" or "OPTION=disabled"
options=$(tr ' ' '\n' < /sys/kernel/tracing/osnoise/options)
for name in "$@"; do
if echo "$options" | grep -q "^NO_${name}$"; then
echo "$name=disabled"
elif echo "$options" | grep -q "^${name}$"; then
echo "$name=enabled"
else
echo "$name=unsupported"
fi
done

View File

@@ -0,0 +1,11 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Read tracefs values and print them.
# Usage: check-tracefs-value.sh <relative_path1> [<relative_path2> ...]
# Each path is relative to /sys/kernel/tracing/
# Output: one line per file in the format "path=value"
for file in "$@"; do
read value < "/sys/kernel/tracing/$file"
echo "$file=$value"
done

View File

@@ -55,13 +55,51 @@ check_top_q_hist "verify -k/--kernel-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"
# Tracer option tests - verify that rtla correctly sets tracefs options
# Default tests: poison tracefs with wrong values, verify rtla resets to defaults
check_with_osnoise_options "apply default timerlat_period_us" \
"timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_period_us\"" \
2 "^osnoise/timerlat_period_us=1000$" osnoise/timerlat_period_us=999999
check_with_osnoise_options "apply default print_stack" \
"timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/print_stack\"" \
2 "^osnoise/print_stack=0$" osnoise/print_stack=999999
check_with_osnoise_options "apply default stop_tracing_us" \
"timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
2 "^osnoise/stop_tracing_us=0$" osnoise/stop_tracing_us=999999
check_with_osnoise_options "apply default stop_tracing_total_us" \
"timerlat top -q -i 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
2 "^osnoise/stop_tracing_total_us=0$" osnoise/stop_tracing_total_us=999999
# Non-default tracer option tests: verify CLI options correctly set tracefs values
check_top_q_hist "verify -p sets timerlat_period_us" \
"timerlat TOOL -p 2000 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_period_us\"" \
2 "^osnoise/timerlat_period_us=2000$"
check_top_q_hist "verify -s sets print_stack" \
"timerlat TOOL -s 5 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/print_stack\"" \
2 "^osnoise/print_stack=5$"
check_top_q_hist "verify -i sets stop_tracing_us" \
"timerlat TOOL -i 2 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
2 "^osnoise/stop_tracing_us=2$"
check_top_q_hist "verify -T sets stop_tracing_total_us" \
"timerlat TOOL -T 2 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
2 "^osnoise/stop_tracing_total_us=2$"
check_with_osnoise_options "apply default TIMERLAT_ALIGN" \
"timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh TIMERLAT_ALIGN\"" \
2 "^TIMERLAT_ALIGN=disabled$" osnoise/options=TIMERLAT_ALIGN
check_top_q_hist "verify -A sets TIMERLAT_ALIGN" \
"timerlat TOOL -A 100 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh TIMERLAT_ALIGN\"" \
2 "^TIMERLAT_ALIGN=enabled$"
check_top_q_hist "verify -A sets timerlat_align_us" \
"timerlat TOOL -A 100 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_align_us\"" \
2 "^osnoise/timerlat_align_us=100$"
# 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$"
"timerlat hist -E 1 -d 1s" 129 "out of range \[10, 9999999\]"
check "hist with --no-header" \
"timerlat hist --no-header -d 1s" 0 "" "RTLA timerlat histogram"
check "hist with --with-zeros" \

View File

@@ -9,6 +9,12 @@
#include "cli_params_assert.h"
#define TEST_CALLBACK(value, cb) OPT_CALLBACK('t', "test", value, "test value", "test help", cb)
#define TEST_LLONG_RANGE(value, lo, hi) \
RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
opt_llong_callback, LLONG_RANGE(lo, hi))
#define TEST_INT_RANGE(value, lo, hi) \
RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
opt_int_callback, INT_RANGE(lo, hi))
START_TEST(test_opt_llong_callback_simple)
{
@@ -40,6 +46,52 @@ START_TEST(test_opt_llong_callback_min)
}
END_TEST
START_TEST(test_opt_llong_callback_non_numeric)
{
long long test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_llong_callback(&opt, "abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_llong_callback_non_numeric_suffix)
{
long long test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_llong_callback(&opt, "1234567890abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_llong_callback_unset)
{
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(opt_llong_callback(&opt, NULL, 1), 0);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_llong_callback_unset_defval)
{
long long test_value = 0;
const long long default_value = 42;
const struct option opt = RTLA_OPT_LLONG_DEFVAL('t', "test", &test_value, "test value",
"test help", &default_value);
ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
ck_assert_int_eq(test_value, default_value);
}
END_TEST
START_TEST(test_opt_int_callback_simple)
{
int test_value = 0;
@@ -75,6 +127,7 @@ START_TEST(test_opt_int_callback_non_numeric)
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
@@ -85,11 +138,119 @@ START_TEST(test_opt_int_callback_non_numeric_suffix)
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "1234567890abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_int_callback_unset)
{
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(opt_int_callback(&opt, NULL, 1), 0);
ck_assert_int_eq(test_value, 0);
}
END_TEST
START_TEST(test_opt_int_callback_unset_defval)
{
int test_value = 0;
const struct option opt = RTLA_OPT_INT_DEFVAL('t', "test", &test_value, "test value",
"test help", 42);
ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
ck_assert_int_eq(test_value, 42);
}
END_TEST
START_TEST(test_opt_llong_callback_range_in)
{
long long test_value = 0;
const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
ck_assert_int_eq(opt_llong_callback(&opt, "50", 0), 0);
ck_assert_int_eq(test_value, 50);
}
END_TEST
START_TEST(test_opt_llong_callback_range_below)
{
long long test_value = 0;
const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_llong_callback(&opt, "9", 0), -1);
}
END_TEST
START_TEST(test_opt_llong_callback_range_above)
{
long long test_value = 0;
const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_llong_callback(&opt, "101", 0), -1);
}
END_TEST
START_TEST(test_opt_llong_callback_range_boundary)
{
long long test_value = 0;
const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
ck_assert_int_eq(opt_llong_callback(&opt, "10", 0), 0);
ck_assert_int_eq(test_value, 10);
ck_assert_int_eq(opt_llong_callback(&opt, "100", 0), 0);
ck_assert_int_eq(test_value, 100);
}
END_TEST
START_TEST(test_opt_int_callback_range_in)
{
int test_value = 0;
const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
ck_assert_int_eq(opt_int_callback(&opt, "5000", 0), 0);
ck_assert_int_eq(test_value, 5000);
}
END_TEST
START_TEST(test_opt_int_callback_range_below)
{
int test_value = 0;
const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "-1", 0), -1);
}
END_TEST
START_TEST(test_opt_int_callback_range_above)
{
int test_value = 0;
const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "10001", 0), -1);
}
END_TEST
START_TEST(test_opt_int_callback_range_boundary)
{
int test_value = 0;
const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
ck_assert_int_eq(opt_int_callback(&opt, "0", 0), 0);
ck_assert_int_eq(test_value, 0);
ck_assert_int_eq(opt_int_callback(&opt, "10000", 0), 0);
ck_assert_int_eq(test_value, 10000);
}
END_TEST
START_TEST(test_opt_cpus_cb)
{
struct common_params params = {0};
@@ -108,7 +269,7 @@ START_TEST(test_opt_cpus_cb_invalid)
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
opt_cpus_cb(&opt, "0-3,5", 0);
ck_assert_int_eq(opt_cpus_cb(&opt, "0-3,5", 0), -1);
}
END_TEST
@@ -134,6 +295,18 @@ START_TEST(test_opt_cgroup_cb_equals)
}
END_TEST
START_TEST(test_opt_cgroup_cb_unset)
{
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(opt_cgroup_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.cgroup, 0);
ck_assert_ptr_null(params.cgroup_name);
}
END_TEST
START_TEST(test_opt_duration_cb)
{
struct common_params params = {0};
@@ -150,7 +323,18 @@ START_TEST(test_opt_duration_cb_invalid)
const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
assert(freopen("/dev/null", "w", stderr));
opt_duration_cb(&opt, "abc", 0);
ck_assert_int_eq(opt_duration_cb(&opt, "abc", 0), -1);
}
END_TEST
START_TEST(test_opt_duration_cb_unset)
{
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(opt_duration_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.duration, 0);
}
END_TEST
@@ -201,7 +385,20 @@ START_TEST(test_opt_housekeeping_cb_invalid)
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
opt_housekeeping_cb(&opt, "0-3,5", 0);
ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3,5", 0), -1);
}
END_TEST
START_TEST(test_opt_housekeeping_cb_unset)
{
struct common_params params = {0};
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(opt_housekeeping_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.hk_cpus, 0);
ck_assert_int_eq(CPU_COUNT(&params.hk_cpu_set), 0);
}
END_TEST
@@ -222,7 +419,19 @@ START_TEST(test_opt_priority_cb_invalid)
const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
assert(freopen("/dev/null", "w", stderr));
opt_priority_cb(&opt, "abc", 0);
ck_assert_int_eq(opt_priority_cb(&opt, "abc", 0), -1);
}
END_TEST
START_TEST(test_opt_priority_cb_unset)
{
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(opt_priority_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.sched_param.sched_policy, 0);
ck_assert_int_eq(params.sched_param.sched_priority, 0);
}
END_TEST
@@ -242,7 +451,7 @@ START_TEST(test_opt_trigger_cb_no_event)
const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
assert(freopen("/dev/null", "w", stderr));
opt_trigger_cb(&opt, "stacktrace", 0);
ck_assert_int_eq(opt_trigger_cb(&opt, "stacktrace", 0), -1);
}
END_TEST
@@ -262,7 +471,7 @@ START_TEST(test_opt_filter_cb_no_event)
const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
assert(freopen("/dev/null", "w", stderr));
opt_filter_cb(&opt, "comm ~ \"rtla\"", 0);
ck_assert_int_eq(opt_filter_cb(&opt, "comm ~ \"rtla\"", 0), -1);
}
END_TEST
@@ -279,45 +488,20 @@ START_TEST(test_opt_osnoise_auto_cb)
}
END_TEST
START_TEST(test_opt_osnoise_period_cb)
START_TEST(test_opt_osnoise_auto_cb_unset)
{
unsigned long long period = 0;
const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_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_period_cb(&opt, "1000000", 0), 0);
ck_assert_int_eq(period, 1000000);
ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
ck_assert_int_eq(opt_osnoise_auto_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.common.stop_us, 0);
ck_assert_int_eq(params.threshold, 0);
ck_assert_ptr_null(cb_data.trace_output);
}
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)
{
@@ -339,6 +523,17 @@ START_TEST(test_opt_osnoise_trace_output_cb_noarg)
}
END_TEST
START_TEST(test_opt_osnoise_trace_output_cb_unset)
{
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_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 1), 0);
ck_assert_ptr_null(trace_output);
}
END_TEST
START_TEST(test_opt_osnoise_on_threshold_cb)
{
struct actions actions = {0};
@@ -357,7 +552,7 @@ START_TEST(test_opt_osnoise_on_threshold_cb_invalid)
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);
ck_assert_int_eq(opt_osnoise_on_threshold_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -379,27 +574,7 @@ START_TEST(test_opt_osnoise_on_end_cb_invalid)
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);
ck_assert_int_eq(opt_osnoise_on_end_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -417,35 +592,21 @@ START_TEST(test_opt_timerlat_auto_cb)
}
END_TEST
START_TEST(test_opt_dma_latency_cb)
START_TEST(test_opt_timerlat_auto_cb_unset)
{
int dma_latency = 0;
const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_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_dma_latency_cb(&opt, "1000", 0), 0);
ck_assert_int_eq(dma_latency, 1000);
ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
ck_assert_int_eq(opt_timerlat_auto_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.common.stop_us, 0);
ck_assert_int_eq(params.common.stop_total_us, 0);
ck_assert_int_eq(params.print_stack, 0);
ck_assert_ptr_null(cb_data.trace_output);
}
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)
{
@@ -460,6 +621,20 @@ START_TEST(test_opt_aa_only_cb)
}
END_TEST
START_TEST(test_opt_aa_only_cb_unset)
{
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(opt_aa_only_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.common.stop_us, 0);
ck_assert_int_eq(params.common.stop_total_us, 0);
ck_assert_int_eq(params.print_stack, 0);
ck_assert_int_eq(params.common.aa_only, 0);
}
END_TEST
START_TEST(test_opt_timerlat_trace_output_cb)
{
const char *trace_output = NULL;
@@ -480,6 +655,17 @@ START_TEST(test_opt_timerlat_trace_output_cb_noarg)
}
END_TEST
START_TEST(test_opt_timerlat_trace_output_cb_unset)
{
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_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 1), 0);
ck_assert_ptr_null(trace_output);
}
END_TEST
START_TEST(test_opt_timerlat_on_threshold_cb)
{
struct actions actions = {0};
@@ -498,7 +684,7 @@ START_TEST(test_opt_timerlat_on_threshold_cb_invalid)
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);
ck_assert_int_eq(opt_timerlat_on_threshold_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -520,7 +706,7 @@ START_TEST(test_opt_timerlat_on_end_cb_invalid)
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);
ck_assert_int_eq(opt_timerlat_on_end_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -535,6 +721,18 @@ START_TEST(test_opt_user_threads_cb)
}
END_TEST
START_TEST(test_opt_user_threads_cb_unset)
{
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(opt_user_threads_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.common.user_workload, 0);
ck_assert_int_eq(params.common.user_data, 0);
}
END_TEST
START_TEST(test_opt_nano_cb)
{
struct timerlat_params params = {0};
@@ -545,10 +743,22 @@ START_TEST(test_opt_nano_cb)
}
END_TEST
START_TEST(test_opt_nano_cb_unset)
{
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(opt_nano_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.common.output_divisor, default_output_divisor);
}
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);
const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
ck_assert(params.timerlat_align);
@@ -556,6 +766,30 @@ START_TEST(test_opt_timerlat_align_cb)
}
END_TEST
START_TEST(test_opt_timerlat_align_cb_invalid)
{
struct timerlat_params params = {0};
const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_timerlat_align_cb(&opt, "-1", 0), -1);
}
END_TEST
START_TEST(test_opt_timerlat_align_cb_unset)
{
struct timerlat_params params = {0};
const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
"test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
ck_assert_int_eq(opt_timerlat_align_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(params.timerlat_align, 0);
ck_assert_int_eq(params.timerlat_align_us, 0);
}
END_TEST
START_TEST(test_opt_stack_format_cb)
{
int stack_format = 0;
@@ -572,69 +806,21 @@ START_TEST(test_opt_stack_format_cb_invalid)
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);
ck_assert_int_eq(opt_stack_format_cb(&opt, "abc", 0), -1);
}
END_TEST
START_TEST(test_opt_bucket_size_cb)
START_TEST(test_opt_stack_format_cb_unset)
{
int bucket_size = 0;
const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
int stack_format = 0;
const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
ck_assert_int_eq(opt_bucket_size_cb(&opt, "100", 0), 0);
ck_assert_int_eq(bucket_size, 100);
ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
ck_assert_int_eq(opt_stack_format_cb(&opt, NULL, 1), 0);
ck_assert_int_eq(stack_format, default_stack_format);
}
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)
{
@@ -645,71 +831,81 @@ Suite *cli_opt_callback_suite(void)
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_llong_callback_non_numeric);
tcase_add_test(tc, test_opt_llong_callback_non_numeric_suffix);
tcase_add_test(tc, test_opt_llong_callback_unset);
tcase_add_test(tc, test_opt_llong_callback_unset_defval);
tcase_add_test(tc, test_opt_llong_callback_range_in);
tcase_add_test(tc, test_opt_llong_callback_range_below);
tcase_add_test(tc, test_opt_llong_callback_range_above);
tcase_add_test(tc, test_opt_llong_callback_range_boundary);
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_int_callback_unset);
tcase_add_test(tc, test_opt_int_callback_unset_defval);
tcase_add_test(tc, test_opt_int_callback_range_in);
tcase_add_test(tc, test_opt_int_callback_range_below);
tcase_add_test(tc, test_opt_int_callback_range_above);
tcase_add_test(tc, test_opt_int_callback_range_boundary);
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_cpus_cb_invalid);
tcase_add_test(tc, test_opt_cgroup_cb);
tcase_add_test(tc, test_opt_cgroup_cb_equals);
tcase_add_test(tc, test_opt_cgroup_cb_unset);
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_duration_cb_unset);
tcase_add_test(tc, test_opt_duration_cb_invalid);
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_housekeeping_cb_invalid);
tcase_add_test(tc, test_opt_housekeeping_cb_unset);
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_priority_cb_invalid);
tcase_add_test(tc, test_opt_priority_cb_unset);
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_trigger_cb_no_event);
tcase_add_test(tc, test_opt_filter_cb);
tcase_add_exit_test(tc, test_opt_filter_cb_no_event, EXIT_FAILURE);
tcase_add_test(tc, test_opt_filter_cb_no_event);
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_auto_cb_unset);
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_trace_output_cb_unset);
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_threshold_cb_invalid);
tcase_add_test(tc, test_opt_osnoise_on_end_cb);
tcase_add_exit_test(tc, test_opt_osnoise_on_end_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_osnoise_on_end_cb_invalid);
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_timerlat_auto_cb_unset);
tcase_add_test(tc, test_opt_aa_only_cb);
tcase_add_test(tc, test_opt_aa_only_cb_unset);
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_trace_output_cb_unset);
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_threshold_cb_invalid);
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_timerlat_on_end_cb_invalid);
tcase_add_test(tc, test_opt_user_threads_cb);
tcase_add_test(tc, test_opt_user_threads_cb_unset);
tcase_add_test(tc, test_opt_nano_cb);
tcase_add_test(tc, test_opt_nano_cb_unset);
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_stack_format_cb_invalid);
tcase_add_test(tc, test_opt_stack_format_cb_unset);
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);
tcase_add_test(tc, test_opt_timerlat_align_cb_invalid);
tcase_add_test(tc, test_opt_timerlat_align_cb_unset);
suite_add_tcase(s, tc);
return s;

View File

@@ -37,6 +37,22 @@ START_TEST(test_period_long)
}
END_TEST
START_TEST(test_period_unset_short)
{
PARSE_ARGS("osnoise", "hist", "-p", "100000", "--no-period");
ck_assert_int_eq(osn_params->period, 0);
}
END_TEST
START_TEST(test_period_unset_long)
{
PARSE_ARGS("osnoise", "hist", "--period", "100000", "--no-period");
ck_assert_int_eq(osn_params->period, 0);
}
END_TEST
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "hist", "-r", "95000");
@@ -481,6 +497,8 @@ Suite *osnoise_hist_cli_suite(void)
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_period_unset_short);
tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);

View File

@@ -37,6 +37,22 @@ START_TEST(test_period_long)
}
END_TEST
START_TEST(test_period_unset_short)
{
PARSE_ARGS("osnoise", "top", "-p", "100000", "--no-period");
ck_assert_int_eq(osn_params->period, 0);
}
END_TEST
START_TEST(test_period_unset_long)
{
PARSE_ARGS("osnoise", "top", "--period", "100000", "--no-period");
ck_assert_int_eq(osn_params->period, 0);
}
END_TEST
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "top", "-r", "95000");
@@ -433,6 +449,8 @@ Suite *osnoise_top_cli_suite(void)
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
tcase_add_test(tc, test_period_unset_short);
tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);

View File

@@ -55,6 +55,22 @@ START_TEST(test_period_long)
}
END_TEST
START_TEST(test_period_unset_short)
{
PARSE_ARGS("timerlat", "hist", "-p", "200", "--no-period");
ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
}
END_TEST
START_TEST(test_period_unset_long)
{
PARSE_ARGS("timerlat", "hist", "--period", "200", "--no-period");
ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
}
END_TEST
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "hist", "-s", "20");
@@ -629,6 +645,8 @@ Suite *timerlat_hist_cli_suite(void)
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_period_unset_short);
tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);

View File

@@ -55,6 +55,22 @@ START_TEST(test_period_long)
}
END_TEST
START_TEST(test_period_unset_short)
{
PARSE_ARGS("timerlat", "top", "-p", "200", "--no-period");
ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
}
END_TEST
START_TEST(test_period_unset_long)
{
PARSE_ARGS("timerlat", "top", "--period", "200", "--no-period");
ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
}
END_TEST
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "top", "-s", "20");
@@ -571,6 +587,8 @@ Suite *timerlat_top_cli_suite(void)
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_period_unset_short);
tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);