summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-11-07 22:42:14 +0100
committerwm4 <wm4@nowhere>2019-11-08 00:26:37 +0100
commitfb568963199312c7970ebc3bd7f89ae85ea43648 (patch)
treecac54fb7ff53e2aeda9281f132823df5e7245dfa
parent17dde8eeb6516b8000248c3bcce293d695232865 (diff)
downloadmpv-fb568963199312c7970ebc3bd7f89ae85ea43648.tar.bz2
mpv-fb568963199312c7970ebc3bd7f89ae85ea43648.tar.xz
test: make tests part of the mpv binary
Until now, each .c file in test/ was built as separate, self-contained binary. Each binary could be run to execute the tests it contained. Change this and make them part of the normal mpv binary. Now the tests have to be invoked via the --unittest option. Do this for two reasons: - Tests now run within a "properly" initialized mpv instance, so all services are available. - Possibly simplifying the situation for future build systems. The first point is the main motivation. The mpv code is entangled with mp_log and the option system. It feels like a bad idea to duplicate some of the initialization of this just so you can call code using them. I'm also getting rid of cmocka. There wouldn't be any problem to keep it (it's a perfectly sane set of helpers), but NIH calls. I would have had to aggregate all tests into a CMUnitTest list, and I don't see how I'd get different types of entry points easily. Probably easily solvable, but since we made only pretty basic use of this library, NIH-ing this is actually easier (I needed a list of tests with custom metadata anyway, so all what was left was reimplement the assert_* helpers). Unit tests now don't output anything, and if they fail, they'll simply crash and leave a message that typically requires inspecting the test code to figure out what went wrong (and probably editing the test code to get more information). I even merged the various test functions into single ones. Sucks, but here you go. chmap_sel.c is merged into chmap.c, because I didn't see the point of this being separate. json.c drops the print_message() to go along with the new silent-by-default idea, also there's a memory leak fix unrelated to the rest of this commit. The new code is enabled with --enable-tests (--enable-test goes away). Due to waf's option parser, --enable-test still works, because it's a unique prefix to --enable-tests.
-rw-r--r--DOCS/man/options.rst17
-rw-r--r--options/options.c4
-rw-r--r--options/options.h1
-rw-r--r--player/main.c6
-rw-r--r--test/chmap.c86
-rw-r--r--test/chmap_sel.c136
-rw-r--r--test/gl_video.c28
-rw-r--r--test/index.c51
-rw-r--r--test/index.h29
-rw-r--r--test/json.c22
-rw-r--r--test/linked_list.c17
-rw-r--r--test/test_helpers.c29
-rw-r--r--test/test_helpers.h23
-rw-r--r--wscript10
-rw-r--r--wscript_build.py21
15 files changed, 271 insertions, 209 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 27b24d0e98..4c208fe025 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -6184,3 +6184,20 @@ Miscellaneous
See the FFmpeg libavfilter documentation for details on the available
filters.
+
+Debugging
+---------
+
+``--unittest=<name>``
+ Run an internal unit test. There are multiple, and the name specifies which.
+
+ The special value ``all-simple`` runs all tests which do not need further
+ setup (other arguments and such). Some tests may need additional arguments
+ to do anything useful.
+
+ On success, the player binary exits with exit status 0, otherwise it returns
+ with an undefined non-0 exit status (it may crash or abort itself on test
+ failures).
+
+ This is only enabled if built with ``--enable-tests``, and should normally
+ be enabled and used by developers only.
diff --git a/options/options.c b/options/options.c
index 79ae3ca5ab..53cf82abd8 100644
--- a/options/options.c
+++ b/options/options.c
@@ -347,6 +347,10 @@ const m_option_t mp_opts[] = {
OPT_PRINT("version", print_version),
OPT_PRINT("V", print_version),
+#if HAVE_TESTS
+ OPT_STRING("unittest", test_mode, CONF_NOCFG | M_OPT_FIXED | M_OPT_NOPROP),
+#endif
+
OPT_CHOICE("player-operation-mode", operation_mode,
M_OPT_FIXED | M_OPT_PRE_PARSE | M_OPT_NOPROP,
({"cplayer", 0}, {"pseudo-gui", 1})),
diff --git a/options/options.h b/options/options.h
index 7af86ab9fb..2f7e368446 100644
--- a/options/options.h
+++ b/options/options.h
@@ -123,6 +123,7 @@ typedef struct MPOpts {
int msg_time;
char *log_file;
+ char *test_mode;
int operation_mode;
char **reset_options;
diff --git a/player/main.c b/player/main.c
index 70697a2a6e..8894988e99 100644
--- a/player/main.c
+++ b/player/main.c
@@ -56,6 +56,7 @@
#include "demux/demux.h"
#include "misc/thread_tools.h"
#include "sub/osd.h"
+#include "test/index.h"
#include "video/out/vo.h"
#include "core.h"
@@ -427,6 +428,11 @@ int mp_initialize(struct MPContext *mpctx, char **options)
if (opts->force_vo == 2 && handle_force_window(mpctx, false) < 0)
return -1;
+#if HAVE_TESTS
+ if (opts->test_mode && opts->test_mode[0])
+ return run_tests(mpctx) ? 1 : -1;
+#endif
+
MP_STATS(mpctx, "end init");
return 0;
diff --git a/test/chmap.c b/test/chmap.c
index 395b716b74..6484698f4c 100644
--- a/test/chmap.c
+++ b/test/chmap.c
@@ -1,9 +1,81 @@
-#include "test_helpers.h"
#include "audio/chmap.h"
+#include "audio/chmap_sel.h"
+#include "index.h"
+#include "test_helpers.h"
+
+#define LAYOUTS(...) (char*[]){__VA_ARGS__, NULL}
+
+static void test_sel(const char *input, const char *expected_selection,
+ char **layouts)
+{
+ struct mp_chmap_sel s = {0};
+ struct mp_chmap input_map;
+ struct mp_chmap expected_map;
+
+ assert_true(mp_chmap_from_str(&input_map, bstr0(input)));
+ assert_true(mp_chmap_from_str(&expected_map, bstr0(expected_selection)));
+
+ for (int n = 0; layouts[n]; n++) {
+ struct mp_chmap tmp;
+ assert_true(mp_chmap_from_str(&tmp, bstr0(layouts[n])));
+ int count = s.num_chmaps;
+ mp_chmap_sel_add_map(&s, &tmp);
+ assert_true(s.num_chmaps > count); // assure validity and max. count
+ }
+
+ assert_true(mp_chmap_sel_fallback(&s, &input_map));
+ // We convert expected_map to a chmap and then back to a string to avoid
+ // problems with ambiguous layouts.
+ assert_string_equal(mp_chmap_to_str(&input_map),
+ mp_chmap_to_str(&expected_map));
+}
-static void test_mp_chmap_diff(void **state) {
+static void run(void)
+{
struct mp_chmap a;
struct mp_chmap b;
+ struct mp_chmap_sel s = {0};
+
+ test_sel("5.1", "7.1", LAYOUTS("7.1"));
+ test_sel("7.1", "5.1", LAYOUTS("5.1"));
+ test_sel("7.1(wide-side)", "7.1", LAYOUTS("7.1"));
+ test_sel("7.1(wide-side)", "5.1(side)", LAYOUTS("7.1", "5.1(side)"));
+ test_sel("3.1", "5.1", LAYOUTS("7.1", "5.1", "2.1", "stereo", "mono"));
+ test_sel("5.1", "7.1(rear)", LAYOUTS("7.1(rear)"));
+ test_sel("5.1(side)", "5.1", LAYOUTS("5.1", "7.1"));
+ test_sel("5.1", "7.1(alsa)", LAYOUTS("7.1(alsa)"));
+ test_sel("mono", "stereo", LAYOUTS("stereo", "5.1"));
+ test_sel("stereo", "stereo", LAYOUTS("stereo", "5.1"));
+ test_sel("5.1(side)", "7.1(rear)", LAYOUTS("stereo", "7.1(rear)"));
+ test_sel("7.1", "fl-fr-lfe-fc-bl-br-flc-frc",
+ LAYOUTS("fl-fr-lfe-fc-bl-br-flc-frc", "3.0(back)"));
+
+ mp_chmap_set_unknown(&a, 2);
+
+ mp_chmap_from_str(&b, bstr0("5.1"));
+
+ mp_chmap_sel_add_map(&s, &a);
+ assert_false(mp_chmap_sel_fallback(&s, &b));
+ assert_string_equal(mp_chmap_to_str(&b), "5.1");
+
+ test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "stereo"));
+ test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "7.0"));
+ test_sel("quad", "quad(side)", LAYOUTS("7.0", "quad(side)"));
+ test_sel("quad", "7.1(wide-side)", LAYOUTS("7.1(wide-side)", "stereo"));
+ test_sel("quad", "7.1(wide-side)", LAYOUTS("stereo", "7.1(wide-side)"));
+ test_sel("quad", "fl-fr-sl-sr",
+ LAYOUTS("fl-fr-fc-bl-br", "fl-fr-sl-sr"));
+ test_sel("quad", "fl-fr-bl-br-na-na-na-na",
+ LAYOUTS("fl-fr-bl-br-na-na-na-na", "quad(side)", "stereo"));
+ test_sel("quad", "fl-fr-bl-br-na-na-na-na",
+ LAYOUTS("stereo", "quad(side)", "fl-fr-bl-br-na-na-na-na"));
+ test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
+ LAYOUTS("fl-fr-lfe-fc-bl-br-na-na", "fl-fr-lfe-fc-bl-br-sdl-sdr"));
+ test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
+ LAYOUTS("fl-fr-lfe-fc-bl-br-sdl-sdr", "fl-fr-lfe-fc-bl-br-na-na"));
+
+ test_sel("na-fl-fr", "na-fl-fr", LAYOUTS("na-fl-fr-na", "fl-na-fr", "na-fl-fr",
+ "fl-fr-na-na", "na-na-fl-fr"));
mp_chmap_from_str(&a, bstr0("3.1"));
mp_chmap_from_str(&b, bstr0("2.1"));
@@ -15,9 +87,7 @@ static void test_mp_chmap_diff(void **state) {
assert_int_equal(mp_chmap_diffn(&b, &a), 3);
}
-int main(void) {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_mp_chmap_diff),
- };
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
+const struct unittest test_chmap = {
+ .name = "chmap",
+ .run_simple = run,
+};
diff --git a/test/chmap_sel.c b/test/chmap_sel.c
deleted file mode 100644
index 38a5254073..0000000000
--- a/test/chmap_sel.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "test_helpers.h"
-#include "audio/chmap_sel.h"
-
-#define LAYOUTS(...) (char*[]){__VA_ARGS__, NULL}
-
-static void test_sel(const char *input, const char *expected_selection,
- char **layouts)
-{
- struct mp_chmap_sel s = {0};
- struct mp_chmap input_map;
- struct mp_chmap expected_map;
-
- assert_true(mp_chmap_from_str(&input_map, bstr0(input)));
- assert_true(mp_chmap_from_str(&expected_map, bstr0(expected_selection)));
-
- for (int n = 0; layouts[n]; n++) {
- struct mp_chmap tmp;
- assert_true(mp_chmap_from_str(&tmp, bstr0(layouts[n])));
- int count = s.num_chmaps;
- mp_chmap_sel_add_map(&s, &tmp);
- assert_true(s.num_chmaps > count); // assure validity and max. count
- }
-
- assert_true(mp_chmap_sel_fallback(&s, &input_map));
- // We convert expected_map to a chmap and then back to a string to avoid
- // problems with ambiguous layouts.
- assert_string_equal(mp_chmap_to_str(&input_map),
- mp_chmap_to_str(&expected_map));
-}
-
-static void test_mp_chmap_sel_fallback_upmix(void **state) {
- test_sel("5.1", "7.1", LAYOUTS("7.1"));
-}
-
-static void test_mp_chmap_sel_fallback_downmix(void **state) {
- test_sel("7.1", "5.1", LAYOUTS("5.1"));
-}
-
-static void test_mp_chmap_sel_fallback_incompatible(void **state) {
- test_sel("7.1(wide-side)", "7.1", LAYOUTS("7.1"));
-}
-
-static void test_mp_chmap_sel_fallback_prefer_compatible(void **state) {
- test_sel("7.1(wide-side)", "5.1(side)", LAYOUTS("7.1", "5.1(side)"));
-}
-
-static void test_mp_chmap_sel_fallback_prefer_closest_upmix(void **state) {
- test_sel("3.1", "5.1", LAYOUTS("7.1", "5.1", "2.1", "stereo", "mono"));
-}
-
-static void test_mp_chmap_sel_fallback_use_replacements(void **state) {
- test_sel("5.1", "7.1(rear)", LAYOUTS("7.1(rear)"));
-}
-
-static void test_mp_chmap_sel_fallback_inexact_equivalent(void **state) {
- test_sel("5.1(side)", "5.1", LAYOUTS("5.1", "7.1"));
-}
-
-static void test_mp_chmap_sel_fallback_works_on_alsa_chmaps(void **state) {
- test_sel("5.1", "7.1(alsa)", LAYOUTS("7.1(alsa)"));
-}
-
-static void test_mp_chmap_sel_fallback_mono_to_stereo(void **state) {
- test_sel("mono", "stereo", LAYOUTS("stereo", "5.1"));
-}
-
-static void test_mp_chmap_sel_fallback_stereo_to_stereo(void **state) {
- test_sel("stereo", "stereo", LAYOUTS("stereo", "5.1"));
-}
-
-static void test_mp_chmap_sel_fallback_no_downmix(void **state) {
- test_sel("5.1(side)", "7.1(rear)", LAYOUTS("stereo", "7.1(rear)"));
-}
-
-static void test_mp_chmap_sel_fallback_minimal_downmix(void **state) {
- test_sel("7.1", "fl-fr-lfe-fc-bl-br-flc-frc",
- LAYOUTS("fl-fr-lfe-fc-bl-br-flc-frc", "3.0(back)"));
-}
-
-static void test_mp_chmap_sel_fallback_reject_unknown(void **state) {
- struct mp_chmap a;
- struct mp_chmap b;
- struct mp_chmap_sel s = {0};
-
- mp_chmap_set_unknown(&a, 2);
-
- mp_chmap_from_str(&b, bstr0("5.1"));
-
- mp_chmap_sel_add_map(&s, &a);
- assert_false(mp_chmap_sel_fallback(&s, &b));
- assert_string_equal(mp_chmap_to_str(&b), "5.1");
-}
-
-static void test_mp_chmap_sel_fallback_more_replacements(void **state) {
- test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "stereo"));
- test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "7.0"));
- test_sel("quad", "quad(side)", LAYOUTS("7.0", "quad(side)"));
- test_sel("quad", "7.1(wide-side)", LAYOUTS("7.1(wide-side)", "stereo"));
- test_sel("quad", "7.1(wide-side)", LAYOUTS("stereo", "7.1(wide-side)"));
- test_sel("quad", "fl-fr-sl-sr",
- LAYOUTS("fl-fr-fc-bl-br", "fl-fr-sl-sr"));
- test_sel("quad", "fl-fr-bl-br-na-na-na-na",
- LAYOUTS("fl-fr-bl-br-na-na-na-na", "quad(side)", "stereo"));
- test_sel("quad", "fl-fr-bl-br-na-na-na-na",
- LAYOUTS("stereo", "quad(side)", "fl-fr-bl-br-na-na-na-na"));
- test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
- LAYOUTS("fl-fr-lfe-fc-bl-br-na-na", "fl-fr-lfe-fc-bl-br-sdl-sdr"));
- test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
- LAYOUTS("fl-fr-lfe-fc-bl-br-sdl-sdr", "fl-fr-lfe-fc-bl-br-na-na"));
-}
-
-static void test_mp_chmap_sel_fallback_na_channels(void **state) {
- test_sel("na-fl-fr", "na-fl-fr", LAYOUTS("na-fl-fr-na", "fl-na-fr", "na-fl-fr",
- "fl-fr-na-na", "na-na-fl-fr"));
-}
-
-int main(void) {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_mp_chmap_sel_fallback_upmix),
- cmocka_unit_test(test_mp_chmap_sel_fallback_downmix),
- cmocka_unit_test(test_mp_chmap_sel_fallback_incompatible),
- cmocka_unit_test(test_mp_chmap_sel_fallback_prefer_compatible),
- cmocka_unit_test(test_mp_chmap_sel_fallback_prefer_closest_upmix),
- cmocka_unit_test(test_mp_chmap_sel_fallback_use_replacements),
- cmocka_unit_test(test_mp_chmap_sel_fallback_inexact_equivalent),
- cmocka_unit_test(test_mp_chmap_sel_fallback_works_on_alsa_chmaps),
- cmocka_unit_test(test_mp_chmap_sel_fallback_mono_to_stereo),
- cmocka_unit_test(test_mp_chmap_sel_fallback_stereo_to_stereo),
- cmocka_unit_test(test_mp_chmap_sel_fallback_no_downmix),
- cmocka_unit_test(test_mp_chmap_sel_fallback_minimal_downmix),
- cmocka_unit_test(test_mp_chmap_sel_fallback_reject_unknown),
- cmocka_unit_test(test_mp_chmap_sel_fallback_more_replacements),
- cmocka_unit_test(test_mp_chmap_sel_fallback_na_channels),
- };
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
diff --git a/test/gl_video.c b/test/gl_video.c
index 91271bd2d6..dd866c955c 100644
--- a/test/gl_video.c
+++ b/test/gl_video.c
@@ -1,42 +1,30 @@
+#include "index.h"
#include "test_helpers.h"
#include "video/out/gpu/video.h"
-static void test_scale_ambient_lux_limits(void **state) {
+static void run(void)
+{
float x;
+
x = gl_video_scale_ambient_lux(16.0, 64.0, 2.40, 1.961, 16.0);
assert_float_equal(x, 2.40f, FLT_EPSILON);
x = gl_video_scale_ambient_lux(16.0, 64.0, 2.40, 1.961, 64.0);
assert_float_equal(x, 1.961f, FLT_EPSILON);
-}
-static void test_scale_ambient_lux_sign(void **state) {
- float x;
x = gl_video_scale_ambient_lux(16.0, 64.0, 1.961, 2.40, 64.0);
assert_float_equal(x, 2.40f, FLT_EPSILON);
-}
-static void test_scale_ambient_lux_clamping(void **state) {
- float x;
x = gl_video_scale_ambient_lux(16.0, 64.0, 2.40, 1.961, 0.0);
assert_float_equal(x, 2.40f, FLT_EPSILON);
-}
-static void test_scale_ambient_lux_log10_midpoint(void **state) {
- float x;
// 32 corresponds to the the midpoint after converting lux to the log10 scale
x = gl_video_scale_ambient_lux(16.0, 64.0, 2.40, 1.961, 32.0);
float mid_gamma = (2.40 - 1.961) / 2 + 1.961;
assert_float_equal(x, mid_gamma, FLT_EPSILON);
}
-int main(void) {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_scale_ambient_lux_limits),
- cmocka_unit_test(test_scale_ambient_lux_sign),
- cmocka_unit_test(test_scale_ambient_lux_clamping),
- cmocka_unit_test(test_scale_ambient_lux_log10_midpoint),
- };
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
-
+const struct unittest test_gl_video = {
+ .name = "gl_video",
+ .run_simple = run,
+};
diff --git a/test/index.c b/test/index.c
new file mode 100644
index 0000000000..64f3f85344
--- /dev/null
+++ b/test/index.c
@@ -0,0 +1,51 @@
+#include "index.h"
+#include "player/core.h"
+
+static const struct unittest *unittests[] = {
+ &test_chmap,
+ &test_gl_video,
+ &test_json,
+ &test_linked_list,
+ NULL
+};
+
+bool run_tests(struct MPContext *mpctx)
+{
+ char *sel = mpctx->opts->test_mode;
+ assert(sel && sel[0]);
+
+ if (strcmp(sel, "help") == 0) {
+ MP_INFO(mpctx, "Available tests:\n");
+ for (int n = 0; unittests[n]; n++)
+ MP_INFO(mpctx, " %s\n", unittests[n]->name);
+ MP_INFO(mpctx, " all-simple\n");
+ return true;
+ }
+
+ int num_run = 0;
+
+ for (int n = 0; unittests[n]; n++) {
+ const struct unittest *t = unittests[n];
+
+ // Exactly 1 entrypoint please.
+ assert(MP_IS_POWER_OF_2(
+ (t->run_simple ? (1 << 0) : 0) |
+ (t->run ? (1 << 1) : 0)));
+
+ bool run = false;
+ run |= strcmp(sel, "all-simple") == 0 && !!t->run_simple;
+ run |= strcmp(sel, t->name);
+
+ if (run) {
+ if (t->run_simple)
+ t->run_simple();
+ if (t->run)
+ t->run(mpctx->global, mpctx->log);
+ num_run++;
+ }
+ }
+
+ MP_INFO(mpctx, "%d unittests successfully run.\n", num_run);
+
+ return num_run > 0; // still error if none
+}
diff --git a/test/index.h b/test/index.h
new file mode 100644
index 0000000000..6060eb699f
--- /dev/null
+++ b/test/index.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <stdbool.h>
+
+struct mpv_global;
+struct mp_log;
+struct MPContext;
+
+bool run_tests(struct MPContext *mpctx);
+
+struct unittest {
+ // This is used to select the test on command line with --unittest=<name>.
+ const char *name;
+
+ // Entrypoints. There are various for various purposes. Only 1 of them must
+ // be set.
+
+ // Entrypoint for tests which don't depend on the mpv core.
+ void (*run_simple)(void);
+
+ // Entrypoint for tests which have a simple dependency on the mpv core. The
+ // core is sufficiently initialized at this point.
+ void (*run)(struct mpv_global *global, struct mp_log *log);
+};
+
+extern const struct unittest test_chmap;
+extern const struct unittest test_gl_video;
+extern const struct unittest test_json;
+extern const struct unittest test_linked_list;
diff --git a/test/json.c b/test/json.c
index 0a4462bc21..e8499bee39 100644
--- a/test/json.c
+++ b/test/json.c
@@ -1,8 +1,8 @@
-#include "test_helpers.h"
-
#include "common/common.h"
+#include "index.h"
#include "misc/json.h"
#include "misc/node.h"
+#include "test_helpers.h"
struct entry {
const char *src;
@@ -67,19 +67,20 @@ static const struct entry entries[] = {
#define MAX_DEPTH 10
-static void test_json(void **state)
+static void run(void)
{
for (int n = 0; n < MP_ARRAY_SIZE(entries); n++) {
const struct entry *e = &entries[n];
- print_message("%d: %s\n", n, e->src);
void *tmp = talloc_new(NULL);
char *s = talloc_strdup(tmp, e->src);
json_skip_whitespace(&s);
struct mpv_node res;
bool ok = json_parse(tmp, &res, &s, MAX_DEPTH) >= 0;
assert_true(ok != e->expect_fail);
- if (!ok)
+ if (!ok) {
+ talloc_free(tmp);
continue;
+ }
char *d = talloc_strdup(tmp, "");
assert_true(json_write(&d, &res) >= 0);
assert_string_equal(e->out_txt, d);
@@ -88,10 +89,7 @@ static void test_json(void **state)
}
}
-int main(void) {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_json),
- };
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
-
+const struct unittest test_json = {
+ .name = "json",
+ .run_simple = run,
+};
diff --git a/test/linked_list.c b/test/linked_list.c
index a7b5b6b171..c679d8cc28 100644
--- a/test/linked_list.c
+++ b/test/linked_list.c
@@ -1,7 +1,7 @@
-#include "test_helpers.h"
-
#include "common/common.h"
+#include "index.h"
#include "misc/linked_list.h"
+#include "test_helpers.h"
struct list_item {
int v;
@@ -56,7 +56,7 @@ static bool do_check_list(struct the_list *lst, int *c, int num_c)
return true;
}
-static void test_linked_list(void **state)
+static void run(void)
{
struct the_list lst = {0};
struct list_item e1 = {1};
@@ -159,10 +159,7 @@ static void test_linked_list(void **state)
check_list(3, 4, 5, 2, 1, 6);
}
-int main(void) {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_linked_list),
- };
- return cmocka_run_group_tests(tests, NULL, NULL);
-}
-
+const struct unittest test_linked_list = {
+ .name = "linked_list",
+ .run_simple = run,
+};
diff --git a/test/test_helpers.c b/test/test_helpers.c
new file mode 100644
index 0000000000..187ff73c61
--- /dev/null
+++ b/test/test_helpers.c
@@ -0,0 +1,29 @@
+#include <inttypes.h>
+
+#include "test_helpers.h"
+
+void assert_int_equal_impl(const char *file, int line, int64_t a, int64_t b)
+{
+ if (a != b) {
+ printf("%s:%d: %"PRId64" != %"PRId64"\n", file, line, a, b);
+ abort();
+ }
+}
+
+void assert_string_equal_impl(const char *file, int line,
+ const char *a, const char *b)
+{
+ if (strcmp(a, b) != 0) {
+ printf("%s:%d: '%s' != '%s'\n", file, line, a, b);
+ abort();
+ }
+}
+
+void assert_float_equal_impl(const char *file, int line,
+ double a, double b, double tolerance)
+{
+ if (fabs(a - b) > tolerance) {
+ printf("%s:%d: %f != %f\n", file, line, a, b);
+ abort();
+ }
+}
diff --git a/test/test_helpers.h b/test/test_helpers.h
index 8a8669c624..6ca3cd99b3 100644
--- a/test/test_helpers.h
+++ b/test/test_helpers.h
@@ -1,13 +1,24 @@
#ifndef MP_TESTS_H
#define MP_TESTS_H
-#include <stdarg.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include <cmocka.h>
-
-#include <stdio.h>
#include <math.h>
#include <float.h>
+#include "common/common.h"
+
+#define assert_true(x) assert(x)
+#define assert_false(x) assert(!(x))
+#define assert_int_equal(a, b) \
+ assert_int_equal_impl(__FILE__, __LINE__, (a), (b))
+#define assert_string_equal(a, b) \
+ assert_string_equal_impl(__FILE__, __LINE__, (a), (b))
+#define assert_float_equal(a, b, tolerance) \
+ assert_float_equal_impl(__FILE__, __LINE__, (a), (b), (tolerance))
+
+void assert_int_equal_impl(const char *file, int line, int64_t a, int64_t b);
+void assert_string_equal_impl(const char *file, int line,
+ const char *a, const char *b);
+void assert_float_equal_impl(const char *file, int line,
+ double a, double b, double tolerance);
+
#endif
diff --git a/wscript b/wscript
index 0fae0c2941..aea318d2b6 100644
--- a/wscript
+++ b/wscript
@@ -81,6 +81,11 @@ build_options = [
'default': 'enable',
'func': check_true
}, {
+ 'name': '--tests',
+ 'desc': 'unit tests (development only)',
+ 'default': 'disable',
+ 'func': check_true
+ }, {
'name': '--manpage-build',
'desc': 'manpage generation',
'func': check_ctx_vars('RST2MAN')
@@ -110,11 +115,6 @@ build_options = [
'default': 'enable',
'func': check_true,
}, {
- 'name': '--test',
- 'desc': 'test suite (using cmocka)',
- 'func': check_pkg_config('cmocka', '>= 1.1.5'),
- 'default': 'disable',
- }, {
'name': '--clang-database',
'desc': 'generate a clang compilation database',
'func': check_true,
diff --git a/wscript_build.py b/wscript_build.py
index 951584ec9d..547d0968fe 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -394,6 +394,14 @@ def build(ctx):
( "sub/sd_ass.c", "libass" ),
( "sub/sd_lavc.c" ),
+ ## Tests
+ ( "test/chmap.c", "tests" ),
+ ( "test/gl_video.c", "tests" ),
+ ( "test/index.c", "tests" ),
+ ( "test/json.c", "tests" ),
+ ( "test/linked_list.c", "tests" ),
+ ( "test/test_helpers.c", "tests" ),
+
## Video
( "video/csputils.c" ),
( "video/d3d.c", "d3d-hwaccel" ),
@@ -581,7 +589,7 @@ def build(ctx):
ctx.path.find_node('osdep/mpv.rc'),
version)
- if ctx.dependency_satisfied('cplayer') or ctx.dependency_satisfied('test'):
+ if ctx.dependency_satisfied('cplayer'):
ctx(
target = "objects",
source = ctx.filtered_sources(sources),
@@ -628,17 +636,6 @@ def build(ctx):
wrapctx.env.CFLAGS = ctx.env.CFLAGS + wrapflags
wrapctx.env.LAST_LINKFLAGS = ctx.env.LAST_LINKFLAGS + wrapflags
- if ctx.dependency_satisfied('test'):
- for test in ctx.path.ant_glob("test/*.c"):
- ctx(
- target = os.path.splitext(test.srcpath())[0],
- source = test.srcpath(),
- use = ctx.dependencies_use() + ['objects'],
- includes = _all_includes(ctx),
- features = "c cprogram",
- install_path = None,
- )
-
build_shared = ctx.dependency_satisfied('libmpv-shared')
build_static = ctx.dependency_satisfied('libmpv-static')
if build_shared or build_static: