PipeWire  0.3.52
Test Suite

pwtest is a test runner framework for PipeWire. More...

Files

file  pwtest.h
 /builds/pipewire/pipewire/test/pwtest.h
 

Data Structures

struct  pwtest_spa_plugin
 
struct  pwtest_context
 
struct  pwtest_suite
 
struct  pwtest_test
 

Macros

#define pwtest_fail()    _pwtest_fail_condition(PWTEST_FAIL, __FILE__, __LINE__, __func__, "aborting", "")
 Fail the current test. More...
 
#define pwtest_fail_if_reached()    _pwtest_fail_condition(PWTEST_FAIL, __FILE__, __LINE__, __func__, "This line is supposed to be unreachable", "")
 Same as above but more expressive in the code. More...
 
#define pwtest_fail_with_msg(...)
 Fail the current test with the given message. More...
 
#define pwtest_error_with_msg(...)
 Error out of the current test with the given message. More...
 
#define pwtest_errno_ok(r_)    pwtest_errno_check(r_, 0);
 Assert r is not -1 and if it is, print the errno. More...
 
#define pwtest_errno(r_, errno_)    pwtest_errno_check(r_, errno_);
 Assert r is -1 and the errno is the given one. More...
 
#define pwtest_neg_errno_ok(r_)    pwtest_neg_errno_check(r_, 0);
 Assert r is not < 0 and if it is assume it's a negative errno. More...
 
#define pwtest_neg_errno(r_, errno_)    pwtest_neg_errno_check(r_, errno_);
 Assert r is < 0 and the given negative errno. More...
 
#define pwtest_bool_eq(a_, b_)    pwtest_comparison_bool_(a_, ==, b_)
 Assert boolean (a == b) More...
 
#define pwtest_bool_ne(a_, b_)    pwtest_comparison_bool_(a_, !=, b_)
 Assert boolean (a != b) More...
 
#define pwtest_bool_true(cond_)    pwtest_comparison_bool_(cond_, ==, true)
 Assert cond to be true. More...
 
#define pwtest_bool_false(cond_)    pwtest_comparison_bool_(cond_, ==, false)
 Assert cond to be false. More...
 
#define pwtest_int_eq(a_, b_)    pwtest_comparison_int_(a_, ==, b_)
 Assert a == b
More...
 
#define pwtest_int_ne(a_, b_)    pwtest_comparison_int_(a_, !=, b_)
 Assert a != b
More...
 
#define pwtest_int_lt(a_, b_)    pwtest_comparison_int_(a_, <, b_)
 Assert a < b
More...
 
#define pwtest_int_le(a_, b_)    pwtest_comparison_int_(a_, <=, b_)
 Assert a <= b
More...
 
#define pwtest_int_ge(a_, b_)    pwtest_comparison_int_(a_, >=, b_)
 Assert a >= b
More...
 
#define pwtest_int_gt(a_, b_)    pwtest_comparison_int_(a_, >, b_)
 Assert a > b
More...
 
#define pwtest_ptr_eq(a_, b_)    pwtest_comparison_ptr_(a_, ==, b_)
 Assert ptr1 == ptr2
More...
 
#define pwtest_ptr_ne(a_, b_)    pwtest_comparison_ptr_(a_, !=, b_)
 Assert ptr1 != ptr2
More...
 
#define pwtest_ptr_null(a_)    pwtest_comparison_ptr_(a_, ==, NULL)
 Assert ptr == NULL
More...
 
#define pwtest_ptr_notnull(a_)    pwtest_comparison_ptr_(a_, !=, NULL)
 Assert ptr != NULL
More...
 
#define pwtest_double_eq(a_, b_)    pwtest_comparison_double_((a_), ==, (b_))
 Assert a == b for a (hardcoded) epsilon. More...
 
#define pwtest_double_ne(a_, b_)    pwtest_comparison_double_((a_), !=, (b_))
 Assert a != b for a (hardcoded) epsilon. More...
 
#define pwtest_double_lt(a_, b_)    pwtest_comparison_double_((a_), <, (b_))
 Assert a < b for a (hardcoded) epsilon. More...
 
#define pwtest_double_le(a_, b_)    pwtest_comparison_double_((a_), <=, (b_))
 Assert a <= b for a (hardcoded) epsilon. More...
 
#define pwtest_double_ge(a_, b_)    pwtest_comparison_double_((a_), >=, (b_))
 Assert a >= b for a (hardcoded) epsilon. More...
 
#define pwtest_double_gt(a_, b_)    pwtest_comparison_double_((a_), >, (b_))
 Assert a > b for a (hardcoded) epsilon. More...
 
#define pwtest_int(a_, op_, b_)    pwtest_comparison_int_(a_, op_, b_)
 
#define pwtest_str_eq(a_, b_)
 Assert str1 is equal to str2. More...
 
#define pwtest_str_eq_n(a_, b_, l_)
 Assert str1 is equal to str2 for l characters. More...
 
#define pwtest_str_ne(a_, b_)
 Assert str1 is not equal to str2. More...
 
#define pwtest_str_ne_n(a_, b_, l_)
 Assert str1 is not equal to str2 for l characters. More...
 
#define pwtest_str_contains(haystack_, needle_)
 Assert haystack contains needle. More...
 
#define pwtest_add(func_, ...)    _pwtest_add(ctx, suite, #func_, func_, __VA_ARGS__, NULL)
 Add function func_ to the current test suite. More...
 
#define PWTEST(tname)    static enum pwtest_result tname(struct pwtest_test *current_test)
 Declare a test case. More...
 
#define PWTEST_SUITE(cname)
 Initialize a test suite. More...
 

Enumerations

enum  pwtest_result {
  PWTEST_PASS = 75 , PWTEST_FAIL = 76 , PWTEST_SKIP = 77 , PWTEST_TIMEOUT = 78 ,
  PWTEST_SYSTEM_ERROR = 79
}
 Result returned from tests or suites. More...
 
enum  pwtest_arg {
  PWTEST_NOARG = 0 , PWTEST_ARG_SIGNAL , PWTEST_ARG_RANGE , PWTEST_ARG_PROP ,
  PWTEST_ARG_ENV , PWTEST_ARG_DAEMON
}
 

Functions

int pwtest_get_iteration (struct pwtest_test *t)
 If the test was added with a range (see PWTEST_ARG_RANGE), this function returns the current iteration within that range. More...
 
struct pw_propertiespwtest_get_props (struct pwtest_test *t)
 If the test had properties set (see PWTEST_ARG_PROP), this function returns the Properties. More...
 
struct pwtest_contextpwtest_get_context (struct pwtest_test *t)
 
struct pwtest_spa_pluginpwtest_spa_plugin_new (void)
 
void pwtest_spa_plugin_destroy (struct pwtest_spa_plugin *plugin)
 
void * pwtest_spa_plugin_load_interface (struct pwtest_spa_plugin *plugin, const char *libname, const char *factory_name, const char *interface_name, const struct spa_dict *info)
 Identical to pwtest_spa_plugin_try_load_interface() but returns the interface and fails if the interface is NULL. More...
 
int pwtest_spa_plugin_try_load_interface (struct pwtest_spa_plugin *plugin, void **iface_return, const char *libname, const char *factory_name, const char *interface_name, const struct spa_dict *info)
 Load interface_name from the factory in libname. More...
 
void pwtest_mkstemp (char path[PATH_MAX])
 Create a temporary file and copy its full path to path. More...
 
int pwtest_spawn (const char *file, char *const argv[])
 Run a command and wait for it to return. More...
 

Detailed Description

pwtest is a test runner framework for PipeWire.

It's modelled after other test suites like check and draws a lot of inspiration from the libinput test suite.

pwtest captures logs from the tests (and the pipewire daemon, if applicable) and collects the output into YAML files printed to stderr.

Tests

A pwtest test is declared with the PWTEST() macro and must return one of the pwtest status codes. Those codes are:

#include "pwtest.h"
PWTEST(some_test)
{
int var = 10;
const char *str = "foo";
if (access("/", R_OK))
pwtest_error_with_message("Oh dear, no root directory?");
if (today_is_monday)
return PWTEST_SKIP;
pwtest_int_lt(var, 20);
pwtest_str_ne(str, "bar");
return PWTEST_PASS;
}
...
#define pwtest_ptr_notnull(a_)
Assert ptr != NULL
Definition: pwtest.h:285
#define pwtest_str_ne(a_, b_)
Assert str1 is not equal to str2.
Definition: pwtest.h:337
#define pwtest_int_lt(a_, b_)
Assert a < b
Definition: pwtest.h:257
#define PWTEST(tname)
Declare a test case.
Definition: pwtest.h:493
@ PWTEST_PASS
test successful
Definition: pwtest.h:175
@ PWTEST_SKIP
test was skipped
Definition: pwtest.h:178
/builds/pipewire/pipewire/test/pwtest.h

pwtest provides comparison macros for most basic data types with the lt, le, eq, gt, ge suffixes (<, <=, ==, >, >=). Tests usually should not return PWTEST_FAIL directly, use the pwtest_fail() macros if .

By default, a test runs in a forked process, any changes to the process'environment, etc. are discarded in the next test.

Suites

Tests are grouped into suites and declared with the PWTEST_SUITE() macro. Each test must be added with the required arguments, it is acceptable to add the same test multiple times with different arguments.

...
PWTEST_SUITE(misc)
{
if (today_is_monday)
return PWTEST_SKIP;
// simple test
pwtest_add(some_test, PWTEST_NOARG);
// starts with its own pipewire daemon instance
return PWTEST_SUCCESS;
}
#define pwtest_add(func_,...)
Add function func_ to the current test suite.
Definition: pwtest.h:465
@ PWTEST_ARG_DAEMON
Takes no extra arguments.
Definition: pwtest.h:442
@ PWTEST_NOARG
Definition: pwtest.h:370

For a list of potential arguments, see pwtest_arg and the test-examples.c file in the source directory.

Suites are auto-discovered, they do not have to be manually added to a test run.

Running tests

The pwtest framework is built into each test binary, so just execute the matching binary. See the --help output for the full argument list.

The most useful arguments when running the test suite:

Debugging test-case failures

To debug a single test, disable forking and run the test through gdb:

$ gdb path/to/test
(gdb) break test_function_name
Breakpoint 1 at 0xfffffffffffff: file ../test/test-file.c, line 123
(gdb) r --no-fork --filter-test=test_function_name

Disabling forking makes it easy to debug but should always be used with --filter-test. Any test that modifies its environment will affect subsequent tests and may invalidate the test results.

Where a test has multiple iterations, use --filter-iteration to only run one single iteration.

Macro Definition Documentation

◆ pwtest_fail

#define pwtest_fail ( )     _pwtest_fail_condition(PWTEST_FAIL, __FILE__, __LINE__, __func__, "aborting", "")

Fail the current test.

◆ pwtest_fail_if_reached

#define pwtest_fail_if_reached ( )     _pwtest_fail_condition(PWTEST_FAIL, __FILE__, __LINE__, __func__, "This line is supposed to be unreachable", "")

Same as above but more expressive in the code.

◆ pwtest_fail_with_msg

#define pwtest_fail_with_msg (   ...)

Fail the current test with the given message.

◆ pwtest_error_with_msg

#define pwtest_error_with_msg (   ...)

Error out of the current test with the given message.

◆ pwtest_errno_ok

#define pwtest_errno_ok (   r_)     pwtest_errno_check(r_, 0);

Assert r is not -1 and if it is, print the errno.

◆ pwtest_errno

#define pwtest_errno (   r_,
  errno_ 
)     pwtest_errno_check(r_, errno_);

Assert r is -1 and the errno is the given one.

◆ pwtest_neg_errno_ok

#define pwtest_neg_errno_ok (   r_)     pwtest_neg_errno_check(r_, 0);

Assert r is not < 0 and if it is assume it's a negative errno.

◆ pwtest_neg_errno

#define pwtest_neg_errno (   r_,
  errno_ 
)     pwtest_neg_errno_check(r_, errno_);

Assert r is < 0 and the given negative errno.

◆ pwtest_bool_eq

#define pwtest_bool_eq (   a_,
  b_ 
)     pwtest_comparison_bool_(a_, ==, b_)

Assert boolean (a == b)

◆ pwtest_bool_ne

#define pwtest_bool_ne (   a_,
  b_ 
)     pwtest_comparison_bool_(a_, !=, b_)

Assert boolean (a != b)

◆ pwtest_bool_true

#define pwtest_bool_true (   cond_)     pwtest_comparison_bool_(cond_, ==, true)

Assert cond to be true.

Convenience wrapper for readability

◆ pwtest_bool_false

#define pwtest_bool_false (   cond_)     pwtest_comparison_bool_(cond_, ==, false)

Assert cond to be false.

Convenience wrapper for readability

◆ pwtest_int_eq

#define pwtest_int_eq (   a_,
  b_ 
)     pwtest_comparison_int_(a_, ==, b_)

Assert a == b

◆ pwtest_int_ne

#define pwtest_int_ne (   a_,
  b_ 
)     pwtest_comparison_int_(a_, !=, b_)

Assert a != b

◆ pwtest_int_lt

#define pwtest_int_lt (   a_,
  b_ 
)     pwtest_comparison_int_(a_, <, b_)

Assert a < b

◆ pwtest_int_le

#define pwtest_int_le (   a_,
  b_ 
)     pwtest_comparison_int_(a_, <=, b_)

Assert a <= b

◆ pwtest_int_ge

#define pwtest_int_ge (   a_,
  b_ 
)     pwtest_comparison_int_(a_, >=, b_)

Assert a >= b

◆ pwtest_int_gt

#define pwtest_int_gt (   a_,
  b_ 
)     pwtest_comparison_int_(a_, >, b_)

Assert a > b

◆ pwtest_ptr_eq

#define pwtest_ptr_eq (   a_,
  b_ 
)     pwtest_comparison_ptr_(a_, ==, b_)

Assert ptr1 == ptr2

◆ pwtest_ptr_ne

#define pwtest_ptr_ne (   a_,
  b_ 
)     pwtest_comparison_ptr_(a_, !=, b_)

Assert ptr1 != ptr2

◆ pwtest_ptr_null

#define pwtest_ptr_null (   a_)     pwtest_comparison_ptr_(a_, ==, NULL)

Assert ptr == NULL

◆ pwtest_ptr_notnull

#define pwtest_ptr_notnull (   a_)     pwtest_comparison_ptr_(a_, !=, NULL)

Assert ptr != NULL

◆ pwtest_double_eq

#define pwtest_double_eq (   a_,
  b_ 
)     pwtest_comparison_double_((a_), ==, (b_))

Assert a == b for a (hardcoded) epsilon.

◆ pwtest_double_ne

#define pwtest_double_ne (   a_,
  b_ 
)     pwtest_comparison_double_((a_), !=, (b_))

Assert a != b for a (hardcoded) epsilon.

◆ pwtest_double_lt

#define pwtest_double_lt (   a_,
  b_ 
)     pwtest_comparison_double_((a_), <, (b_))

Assert a < b for a (hardcoded) epsilon.

◆ pwtest_double_le

#define pwtest_double_le (   a_,
  b_ 
)     pwtest_comparison_double_((a_), <=, (b_))

Assert a <= b for a (hardcoded) epsilon.

◆ pwtest_double_ge

#define pwtest_double_ge (   a_,
  b_ 
)     pwtest_comparison_double_((a_), >=, (b_))

Assert a >= b for a (hardcoded) epsilon.

◆ pwtest_double_gt

#define pwtest_double_gt (   a_,
  b_ 
)     pwtest_comparison_double_((a_), >, (b_))

Assert a > b for a (hardcoded) epsilon.

◆ pwtest_int

#define pwtest_int (   a_,
  op_,
  b_ 
)     pwtest_comparison_int_(a_, op_, b_)

◆ pwtest_str_eq

#define pwtest_str_eq (   a_,
  b_ 
)

Assert str1 is equal to str2.

◆ pwtest_str_eq_n

#define pwtest_str_eq_n (   a_,
  b_,
  l_ 
)

Assert str1 is equal to str2 for l characters.

◆ pwtest_str_ne

#define pwtest_str_ne (   a_,
  b_ 
)

Assert str1 is not equal to str2.

◆ pwtest_str_ne_n

#define pwtest_str_ne_n (   a_,
  b_,
  l_ 
)

Assert str1 is not equal to str2 for l characters.

◆ pwtest_str_contains

#define pwtest_str_contains (   haystack_,
  needle_ 
)

Assert haystack contains needle.

◆ pwtest_add

#define pwtest_add (   func_,
  ... 
)     _pwtest_add(ctx, suite, #func_, func_, __VA_ARGS__, NULL)

Add function func_ to the current test suite.

This macro should be used within PWTEST_SUITE() to register the test in that suite, for example:

PWTEST_SUITE(mysuite)
{
}
#define PWTEST_SUITE(cname)
Initialize a test suite.
Definition: pwtest.h:502
@ PWTEST_ARG_RANGE
The next two int arguments are the minimum (inclusive) and maximum (exclusive) range for this test.
Definition: pwtest.h:392

If the test matches the given filters and the suite is executed, the test will be executed with the parameters given to pwtest_add().

Arguments take a argument-dependent number of extra parameters, see see the pwtest_arg documentation for details.

◆ PWTEST

#define PWTEST (   tname)     static enum pwtest_result tname(struct pwtest_test *current_test)

Declare a test case.

To execute the test, add the test case name with pwtest_add().

This macro expands so each test has a struct pwtest_test variable named current_test available.

PWTEST(mytest)
{
struct pwtest_test *t = current_test;
... do stuff ...
return PWTEST_PASS;
}
PWTEST_SUITE(mysuite)
{
pwtest_add(mytest);
return PWTEST_PASS;
}
Definition: pwtest.h:164

◆ PWTEST_SUITE

#define PWTEST_SUITE (   cname)

Initialize a test suite.

A test suite is a group of related tests that filters and other conditions may apply to.

Test suites are automatically discovered at build-time.

Enumeration Type Documentation

◆ pwtest_result

Result returned from tests or suites.

Enumerator
PWTEST_PASS 

test successful

PWTEST_FAIL 

test failed.

Should not be returned directly, Use the pwtest_ macros instead

PWTEST_SKIP 

test was skipped

PWTEST_TIMEOUT 

test aborted after timeout

PWTEST_SYSTEM_ERROR 

unrelated error occurred

◆ pwtest_arg

enum pwtest_arg
Enumerator
PWTEST_NOARG 
PWTEST_ARG_SIGNAL 

The next argument is an int specifying the numerical signal number.

The test is expected to raise that signal. The test fails if none or any other signal is raised.

Example:

pwtest_add(mytest, PWTEST_ARG_SIGNAL, SIGABRT);
@ PWTEST_ARG_SIGNAL
The next argument is an int specifying the numerical signal number.
Definition: pwtest.h:381
PWTEST_ARG_RANGE 

The next two int arguments are the minimum (inclusive) and maximum (exclusive) range for this test.

Example:

pwtest_add(mytest, PWTEST_ARG_RANGE, -50, 50);

Use pwtest_get_iteration() in the test function to obtain the current iteration.

PWTEST_ARG_PROP 

The next two const char * arguments are the key and value for a property entry.

This argument may be specified multiple times to add multiple properties.

Use pwtest_get_props() to get the properties within the test function.

Example:

pwtest_add(mytest,
PWTEST_ARG_PROP, "key1", "value1",
PWTEST_ARG_PROP, "key2", "value2");
@ PWTEST_ARG_PROP
The next two const char * arguments are the key and value for a property entry.
Definition: pwtest.h:407
PWTEST_ARG_ENV 

The next two const char * arguments are the key and value for the environment variable to be set in the test.

This argument may be specified multiple times to add multiple environment variables.

Example:

pwtest_add(mytest,
PWTEST_ARG_ENV, "env1", "value1",
PWTEST_ARG_ENV, "env2", "value2");
@ PWTEST_ARG_ENV
The next two const char * arguments are the key and value for the environment variable to be set in t...
Definition: pwtest.h:426

These environment variables are only set for the test itself, a a pipewire daemon started with PWTEST_ARG_DAEMON does not share those variables.

PWTEST_ARG_DAEMON 

Takes no extra arguments.

If provided, the test case will start a pipewire daemon and stop the daemon when finished.

The PIPEWIRE_REMOTE environment variable will be set in the test to point to this daemon.

Example:

Environment variables specified with PWTEST_ARG_ENV are not available to the daemon, only to the test itself.

Function Documentation

◆ pwtest_get_iteration()

int pwtest_get_iteration ( struct pwtest_test t)

If the test was added with a range (see PWTEST_ARG_RANGE), this function returns the current iteration within that range.

Otherwise, this function returns zero.

◆ pwtest_get_props()

struct pw_properties* pwtest_get_props ( struct pwtest_test t)

If the test had properties set (see PWTEST_ARG_PROP), this function returns the Properties.

Otherwise, this function returns NULL.

◆ pwtest_get_context()

struct pwtest_context* pwtest_get_context ( struct pwtest_test t)

◆ pwtest_spa_plugin_new()

struct pwtest_spa_plugin* pwtest_spa_plugin_new ( void  )

◆ pwtest_spa_plugin_destroy()

void pwtest_spa_plugin_destroy ( struct pwtest_spa_plugin plugin)

◆ pwtest_spa_plugin_load_interface()

void* pwtest_spa_plugin_load_interface ( struct pwtest_spa_plugin plugin,
const char *  libname,
const char *  factory_name,
const char *  interface_name,
const struct spa_dict info 
)

Identical to pwtest_spa_plugin_try_load_interface() but returns the interface and fails if the interface is NULL.

◆ pwtest_spa_plugin_try_load_interface()

int pwtest_spa_plugin_try_load_interface ( struct pwtest_spa_plugin plugin,
void **  iface_return,
const char *  libname,
const char *  factory_name,
const char *  interface_name,
const struct spa_dict info 
)

Load interface_name from the factory in libname.

If successful, the interface is returned and added to plugin's support items, i.e. subsequent loads of an interface will be able to make use of previously loaded ones.

Returns
0 on success or a negative errno on error
Return values
-ENOENTlibname does not exist
-EINVALfactory_name does not exist in libname
-ENOSYSinterface_name does not exist in factory_name

◆ pwtest_mkstemp()

void pwtest_mkstemp ( char  path[PATH_MAX])

Create a temporary file and copy its full path to path.

Fails the test with PWTEST_SYSTEM_ERROR on error.

This file does not need to be removed by the test, the pwtest framework will take care of it on exit.

◆ pwtest_spawn()

int pwtest_spawn ( const char *  file,
char *const  argv[] 
)

Run a command and wait for it to return.