diff --git a/DOCS/build-system-differences.md b/DOCS/build-system-differences.md index 7b1a5e5bfd..ba430a219d 100644 --- a/DOCS/build-system-differences.md +++ b/DOCS/build-system-differences.md @@ -27,6 +27,7 @@ that you get for free. In some cases, these overlapped with custom waf options. supported in the meson build. Instead, pass the generic pkg-config values such as ``lua52``, ``lua5.2``, etc. * ``--lgpl`` was changed to ``gpl``. If ``gpl`` is false, the build is LGPL2.1+. +* ``--tests`` was removed since unit tests now explictly require meson to run ### Boolean Options diff --git a/meson.build b/meson.build index b57ce9d3c0..36bcf19f60 100644 --- a/meson.build +++ b/meson.build @@ -393,10 +393,11 @@ if features['cocoa'] endif if posix - sources += files('input/ipc-unix.c', - 'osdep/path-unix.c', + path_source = files('osdep/path-unix.c') + subprocess_source = files('osdep/subprocess-posix.c') + sources += path_source + subprocess_source + \ + files('input/ipc-unix.c', 'osdep/polldev.c', - 'osdep/subprocess-posix.c', 'osdep/terminal-unix.c', 'sub/filter_regex.c') endif @@ -479,10 +480,11 @@ if features['win32-desktop'] cc.find_library('version'), cc.find_library('winmm')] dependencies += win32_desktop_libs - sources += files('input/ipc-win.c', + path_source = files('osdep/path-win.c') + subprocess_source = files('osdep/subprocess-win.c') + sources += path_source + subprocess_source + \ + files('input/ipc-win.c', 'osdep/main-fn-win.c', - 'osdep/path-win.c', - 'osdep/subprocess-win.c', 'osdep/terminal-win.c', 'video/out/w32_common.c', 'video/out/win32/displayconfig.c', @@ -490,9 +492,8 @@ if features['win32-desktop'] endif if not posix and not features['win32-desktop'] - sources += files('input/ipc-dummy.c', - 'osdep/subprocess-dummy.c', - 'osdep/terminal-dummy.c') + subprocess_source = files('osdep/subprocess-dummy.c') + sources += subprocess_source + files('input/ipc-dummy.c') endif features += {'glob-posix': cc.has_function('glob', prefix: '#include ')} @@ -1685,9 +1686,6 @@ if get_option('libmpv') headers = ['libmpv/client.h', 'libmpv/render.h', 'libmpv/render_gl.h', 'libmpv/stream_cb.h'] install_headers(headers, subdir: 'mpv') - - libmpv_test = executable('libmpv-test', 'libmpv/test.c', link_with: [libmpv]) - test('libmpv', libmpv_test) endif if get_option('cplayer') @@ -1718,8 +1716,12 @@ if get_option('cplayer') rename: 'mpv.svg') install_data('etc/mpv-symbolic.svg', install_dir: join_paths(hicolor_dir, 'symbolic', 'apps')) - executable('mpv', objects: libmpv.extract_all_objects(recursive: true), dependencies: dependencies, - win_subsystem: 'windows,6.0', include_directories: includedir, install: true) + mpv = executable('mpv', objects: libmpv.extract_all_objects(recursive: true), dependencies: dependencies, + win_subsystem: 'windows,6.0', include_directories: includedir, install: true) +endif + +if get_option('tests') + subdir('test') endif summary({'d3d11': features['d3d11'], diff --git a/meson_options.txt b/meson_options.txt index 27af048c37..6e9269ffb4 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,7 +3,7 @@ option('gpl', type: 'boolean', value: true, description: 'GPL (version 2 or late option('cplayer', type: 'boolean', value: true, description: 'mpv CLI player') option('libmpv', type: 'boolean', value: false, description: 'libmpv library') option('build-date', type: 'boolean', value: true, description: 'whether to include binary compile time') -option('tests', type: 'boolean', value: false, description: 'unit tests (development only)') +option('tests', type: 'boolean', value: false, description: 'meson unit tests') # Reminder: normally always built, but enabled by MPV_LEAK_REPORT. # Building it can be disabled only by defining NDEBUG through CFLAGS. option('ta-leak-report', type: 'boolean', value: false, description: 'enable ta leak report by default (development only)') diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 78ce773822..8ed104fdf8 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -840,6 +840,14 @@ struct mp_draw_sub_cache *mp_draw_sub_alloc(void *ta_parent, struct mpv_global * return c; } +// For tests. +struct mp_draw_sub_cache *mp_draw_sub_alloc_test(struct mp_image *dst) +{ + struct mp_draw_sub_cache *c = talloc_zero(NULL, struct mp_draw_sub_cache); + reinit_to_video(c); + return c; +} + bool mp_draw_sub_bitmaps(struct mp_draw_sub_cache *p, struct mp_image *dst, struct sub_bitmap_list *sbs_list) { diff --git a/sub/draw_bmp.h b/sub/draw_bmp.h index e9560e1ca5..fda7797c9e 100644 --- a/sub/draw_bmp.h +++ b/sub/draw_bmp.h @@ -10,6 +10,9 @@ struct mp_draw_sub_cache; struct mp_draw_sub_cache *mp_draw_sub_alloc(void *ta_parent, struct mpv_global *g); +// Only for use in tests. +struct mp_draw_sub_cache *mp_draw_sub_alloc_test(struct mp_image *dst); + // Render the sub-bitmaps in sbs_list to dst. sbs_list must have been rendered // for an OSD resolution equivalent to dst's size (UB if not). // Warning: if dst is a format with alpha, and dst is not set to MP_ALPHA_PREMUL diff --git a/test/chmap.c b/test/chmap.c index 4515a329ee..48af822e72 100644 --- a/test/chmap.c +++ b/test/chmap.c @@ -1,8 +1,11 @@ #include "audio/chmap.h" -#include "audio/chmap_avchannel.h" #include "audio/chmap_sel.h" -#include "common/msg.h" -#include "tests.h" +#include "config.h" +#include "test_utils.h" + +#if HAVE_AV_CHANNEL_LAYOUT +#include "audio/chmap_avchannel.h" +#endif #define LAYOUTS(...) (char*[]){__VA_ARGS__, NULL} @@ -65,13 +68,13 @@ static bool layout_matches(const AVChannelLayout *av_layout, return true; } -static void test_mp_chmap_to_av_channel_layout(const struct test_ctx *ctx) +static void test_mp_chmap_to_av_channel_layout(void) { mp_ch_layout_tuple *mapping_array = NULL; void *iter = NULL; bool anything_failed = false; - MP_VERBOSE(ctx, "Testing mp_chmap -> AVChannelLayout conversions\n"); + printf("Testing mp_chmap -> AVChannelLayout conversions\n"); while ((mapping_array = mp_iterate_builtin_layouts(&iter))) { const char *mapping_name = (*mapping_array)[0]; @@ -93,8 +96,7 @@ static void test_mp_chmap_to_av_channel_layout(const struct test_ctx *ctx) if (!success) anything_failed = true; - MP_MSG(ctx, success ? MSGL_V : MSGL_FATAL, - "%s: %s (%s) -> %s\n", + printf("%s: %s (%s) -> %s\n", success ? "Success" : "Failure", mapping_str, mapping_name, layout_desc); @@ -104,13 +106,13 @@ static void test_mp_chmap_to_av_channel_layout(const struct test_ctx *ctx) assert_false(anything_failed); } -static void test_av_channel_layout_to_mp_chmap(const struct test_ctx *ctx) +static void test_av_channel_layout_to_mp_chmap(void) { const AVChannelLayout *av_layout = NULL; void *iter = NULL; bool anything_failed = false; - MP_VERBOSE(ctx, "Testing AVChannelLayout -> mp_chmap conversions\n"); + printf("Testing AVChannelLayout -> mp_chmap conversions\n"); while ((av_layout = av_channel_layout_standard(&iter))) { struct mp_chmap mp_layout = { 0 }; @@ -123,12 +125,11 @@ static void test_av_channel_layout_to_mp_chmap(const struct test_ctx *ctx) if (!ret) { bool too_many_channels = av_layout->nb_channels > MP_NUM_CHANNELS; - MP_MSG(ctx, too_many_channels ? MSGL_V : MSGL_FATAL, - "Conversion from '%s' to mp_chmap failed (%s)!\n", - layout_desc, - too_many_channels ? - "channel count was over max, ignoring" : - "unexpected, failing"); + printf("Conversion from '%s' to mp_chmap failed (%s)!\n", + layout_desc, + too_many_channels ? + "channel count was over max, ignoring" : + "unexpected, failing"); // we should for now only fail with things such as 22.2 // due to mp_chmap being currently limited to 16 channels @@ -143,8 +144,7 @@ static void test_av_channel_layout_to_mp_chmap(const struct test_ctx *ctx) if (!success) anything_failed = true; - MP_MSG(ctx, success ? MSGL_V : MSGL_FATAL, - "%s: %s -> %s\n", + printf("%s: %s -> %s\n", success ? "Success" : "Failure", layout_desc, mp_chmap_to_str(&mp_layout)); } @@ -154,7 +154,7 @@ static void test_av_channel_layout_to_mp_chmap(const struct test_ctx *ctx) #endif -static void run(struct test_ctx *ctx) +int main(void) { struct mp_chmap a; struct mp_chmap b; @@ -211,12 +211,8 @@ static void run(struct test_ctx *ctx) assert_int_equal(mp_chmap_diffn(&b, &a), 3); #if HAVE_AV_CHANNEL_LAYOUT - test_av_channel_layout_to_mp_chmap(ctx); - test_mp_chmap_to_av_channel_layout(ctx); + test_av_channel_layout_to_mp_chmap(); + test_mp_chmap_to_av_channel_layout(); #endif + return 0; } - -const struct unittest test_chmap = { - .name = "chmap", - .run = run, -}; diff --git a/test/gl_video.c b/test/gl_video.c index af1f082a40..a2bdda43a3 100644 --- a/test/gl_video.c +++ b/test/gl_video.c @@ -1,7 +1,7 @@ -#include "tests.h" -#include "video/out/gpu/video.h" +#include "test_utils.h" +#include "video/out/gpu/utils.h" -static void run(struct test_ctx *ctx) +int main(void) { float x; @@ -21,9 +21,5 @@ static void run(struct test_ctx *ctx) 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); + return 0; } - -const struct unittest test_gl_video = { - .name = "gl_video", - .run = run, -}; diff --git a/test/img_format.c b/test/img_format.c index 8c4a7d45e5..3cc8ff5fe0 100644 --- a/test/img_format.c +++ b/test/img_format.c @@ -1,55 +1,16 @@ #include #include -#include "tests.h" +#include "img_utils.h" +#include "options/path.h" +#include "test_utils.h" #include "video/fmt-conversion.h" #include "video/img_format.h" #include "video/mp_image.h" #include "video/sws_utils.h" -int imgfmts[IMGFMT_AVPIXFMT_END - IMGFMT_AVPIXFMT_START + 100]; -int num_imgfmts; - static enum AVPixelFormat pixfmt_unsup[100]; static int num_pixfmt_unsup; -static bool imgfmts_initialized; - -static int cmp_imgfmt_name(const void *a, const void *b) -{ - char *name_a = mp_imgfmt_to_name(*(int *)a); - char *name_b = mp_imgfmt_to_name(*(int *)b); - - return strcmp(name_a, name_b); -} - -void init_imgfmts_list(void) -{ - if (imgfmts_initialized) - return; - - const AVPixFmtDescriptor *avd = av_pix_fmt_desc_next(NULL); - for (; avd; avd = av_pix_fmt_desc_next(avd)) { - enum AVPixelFormat fmt = av_pix_fmt_desc_get_id(avd); - int mpfmt = pixfmt2imgfmt(fmt); - if (!mpfmt) { - assert(num_pixfmt_unsup < MP_ARRAY_SIZE(pixfmt_unsup)); - pixfmt_unsup[num_pixfmt_unsup++] = fmt; - } - } - - for (int fmt = IMGFMT_START; fmt <= IMGFMT_END; fmt++) { - struct mp_imgfmt_desc d = mp_imgfmt_get_desc(fmt); - enum AVPixelFormat pixfmt = imgfmt2pixfmt(fmt); - if (d.id || pixfmt != AV_PIX_FMT_NONE) { - assert(num_imgfmts < MP_ARRAY_SIZE(imgfmts)); // enlarge that array - imgfmts[num_imgfmts++] = fmt; - } - } - - qsort(imgfmts, num_imgfmts, sizeof(imgfmts[0]), cmp_imgfmt_name); - - imgfmts_initialized = true; -} static const char *comp_type(enum mp_component_type type) { @@ -60,11 +21,13 @@ static const char *comp_type(enum mp_component_type type) } } -static void run(struct test_ctx *ctx) +int main(int argc, char *argv[]) { init_imgfmts_list(); + const char *refdir = argv[1]; + const char *outdir = argv[2]; - FILE *f = test_open_out(ctx, "img_formats.txt"); + FILE *f = test_open_out(outdir, "img_formats.txt"); for (int z = 0; z < num_imgfmts; z++) { int mpfmt = imgfmts[z]; @@ -248,11 +211,7 @@ static void run(struct test_ctx *ctx) fclose(f); - assert_text_files_equal(ctx, "img_formats.txt", "img_formats.txt", + assert_text_files_equal(refdir, outdir, "img_formats.txt", "This can fail if FFmpeg adds new formats or flags."); + return 0; } - -const struct unittest test_img_format = { - .name = "img_format", - .run = run, -}; diff --git a/test/img_utils.c b/test/img_utils.c new file mode 100644 index 0000000000..71764f304f --- /dev/null +++ b/test/img_utils.c @@ -0,0 +1,63 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include + +#include "common/common.h" +#include "img_utils.h" +#include "video/img_format.h" +#include "video/fmt-conversion.h" + +int imgfmts[IMGFMT_AVPIXFMT_END - IMGFMT_AVPIXFMT_START + 100]; +int num_imgfmts; + +static enum AVPixelFormat pixfmt_unsup[100]; +static int num_pixfmt_unsup; + +static int cmp_imgfmt_name(const void *a, const void *b) +{ + char *name_a = mp_imgfmt_to_name(*(int *)a); + char *name_b = mp_imgfmt_to_name(*(int *)b); + + return strcmp(name_a, name_b); +} + +void init_imgfmts_list(void) +{ + const AVPixFmtDescriptor *avd = av_pix_fmt_desc_next(NULL); + for (; avd; avd = av_pix_fmt_desc_next(avd)) { + enum AVPixelFormat fmt = av_pix_fmt_desc_get_id(avd); + int mpfmt = pixfmt2imgfmt(fmt); + if (!mpfmt) { + assert(num_pixfmt_unsup < MP_ARRAY_SIZE(pixfmt_unsup)); + pixfmt_unsup[num_pixfmt_unsup++] = fmt; + } + } + + for (int fmt = IMGFMT_START; fmt <= IMGFMT_END; fmt++) { + struct mp_imgfmt_desc d = mp_imgfmt_get_desc(fmt); + enum AVPixelFormat pixfmt = imgfmt2pixfmt(fmt); + if (d.id || pixfmt != AV_PIX_FMT_NONE) { + assert(num_imgfmts < MP_ARRAY_SIZE(imgfmts)); // enlarge that array + imgfmts[num_imgfmts++] = fmt; + } + } + + qsort(imgfmts, num_imgfmts, sizeof(imgfmts[0]), cmp_imgfmt_name); +} diff --git a/test/img_utils.h b/test/img_utils.h new file mode 100644 index 0000000000..2c21bcd954 --- /dev/null +++ b/test/img_utils.h @@ -0,0 +1,24 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#pragma once + +// Sorted list of valid imgfmts. Call init_imgfmts_list() before use. +extern int imgfmts[]; +extern int num_imgfmts; + +void init_imgfmts_list(void); diff --git a/test/input-gamepad.conf b/test/input-gamepad.conf deleted file mode 100644 index ad79fb9973..0000000000 --- a/test/input-gamepad.conf +++ /dev/null @@ -1,4 +0,0 @@ -GAMEPAD_RIGHT_STICK_LEFT seek -10 -GAMEPAD_RIGHT_STICK_RIGHT seek 10 -GAMEPAD_LEFT_TRIGGER seek -1 -GAMEPAD_RIGHT_TRIGGER seek 1 diff --git a/test/json.c b/test/json.c index e95f88c972..fb6633accf 100644 --- a/test/json.c +++ b/test/json.c @@ -1,7 +1,6 @@ -#include "common/common.h" #include "misc/json.h" #include "misc/node.h" -#include "tests.h" +#include "test_utils.h" struct entry { const char *src; @@ -66,7 +65,7 @@ static const struct entry entries[] = { #define MAX_DEPTH 10 -static void run(struct test_ctx *ctx) +int main(void) { for (int n = 0; n < MP_ARRAY_SIZE(entries); n++) { const struct entry *e = &entries[n]; @@ -86,9 +85,5 @@ static void run(struct test_ctx *ctx) assert_true(equal_mpv_node(&e->out_data, &res)); talloc_free(tmp); } + return 0; } - -const struct unittest test_json = { - .name = "json", - .run = run, -}; diff --git a/libmpv/test.c b/test/libmpv_test.c similarity index 100% rename from libmpv/test.c rename to test/libmpv_test.c diff --git a/test/linked_list.c b/test/linked_list.c index c9fbf9639e..691de3534b 100644 --- a/test/linked_list.c +++ b/test/linked_list.c @@ -1,6 +1,6 @@ #include "common/common.h" #include "misc/linked_list.h" -#include "tests.h" +#include "test_utils.h" struct list_item { int v; @@ -55,7 +55,7 @@ static bool do_check_list(struct the_list *lst, int *c, int num_c) return true; } -static void run(struct test_ctx *ctx) +int main(void) { struct the_list lst = {0}; struct list_item e1 = {1}; @@ -156,9 +156,5 @@ static void run(struct test_ctx *ctx) LL_INSERT_AFTER(list_node, &lst, STUPID_SHIT(&e1), &e6); check_list(3, 4, 5, 2, 1, 6); + return 0; } - -const struct unittest test_linked_list = { - .name = "linked_list", - .run = run, -}; diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000000..61cd514c89 --- /dev/null +++ b/test/meson.build @@ -0,0 +1,135 @@ +# So we don't have to reorganize the entire directory tree. +incdir = include_directories('../') +outdir = join_paths(build_root, 'test', 'out') +refdir = join_paths(source_root, 'test', 'ref') + +# Convenient testing libraries. An adhoc collection of +# mpv objects that test_utils.c needs. Paths and subprocesses +# are required in order to run a diff command when comparing +# different files. Stuff will probably break if core things are +# carelessly moved around. +test_utils_args = [] +test_utils_files = [ + 'audio/chmap.c', + 'audio/format.c', + 'common/common.c', + 'misc/bstr.c', + 'misc/dispatch.c', + 'misc/json.c', + 'misc/node.c', + 'misc/random.c', + 'misc/thread_tools.c', + 'options/m_config_core.c', + 'options/m_config_frontend.c', + 'options/m_option.c', + 'options/path.c', + 'osdep/io.c', + 'osdep/subprocess.c', + path_source, + subprocess_source, + 'ta/ta.c', + 'ta/ta_talloc.c', + 'ta/ta_utils.c' +] +# The zimg code requires using threads. On windows, threads +# also requires timer code so this is added. +if features['win32-internal-pthreads'] + test_utils_args += '-DWIN32_TESTS' + test_utils_files += ['osdep/timer.c', + 'osdep/timer-win2.c', + 'osdep/win32/pthread.c', + 'osdep/windows_utils.c'] +endif + +test_utils_deps = [libavutil, libm, pthreads] +if features['win32-desktop'] + test_utils_deps += cc.find_library('winmm') +endif +test_utils_objects = libmpv.extract_objects(test_utils_files) +test_utils = static_library('test-utils', 'test_utils.c', include_directories: incdir, + c_args: test_utils_args, objects: test_utils_objects, + dependencies: test_utils_deps) + +# For getting imgfmts and stuff. +img_utils_files = [ + 'misc/thread_pool.c', + 'osdep/threads.c', + 'video/csputils.c', + 'video/fmt-conversion.c', + 'video/img_format.c', + 'video/mp_image.c', + 'video/sws_utils.c' +] +if features['zimg'] + img_utils_files += ['video/repack.c', 'video/zimg.c'] +endif + +img_utils_objects = libmpv.extract_objects(img_utils_files) +img_utils = static_library('img-utils', 'img_utils.c', include_directories: incdir, + dependencies: [libavcodec], objects: img_utils_objects) + +# The actual tests. +chmap_files = [ + 'audio/chmap_sel.c' +] +if features['av-channel-layout'] + chmap_files += 'audio/chmap_avchannel.c' +endif +chmap_objects = libmpv.extract_objects(chmap_files) +chmap = executable('chmap', 'chmap.c', include_directories: incdir, + objects: chmap_objects, link_with: test_utils) +test('chmap', chmap) + +gl_video_objects = libmpv.extract_objects('video/out/gpu/ra.c', + 'video/out/gpu/utils.c') +gl_video = executable('gl-video', 'gl_video.c', objects: gl_video_objects, + include_directories: incdir, link_with: [img_utils, test_utils]) +test('gl-video', gl_video) + +json = executable('json', 'json.c', include_directories: incdir, link_with: test_utils) +test('json', json) + +linked_list = executable('linked-list', files('linked_list.c'), include_directories: incdir) +test('linked-list', linked_list) + +paths_objects = libmpv.extract_objects('options/path.c', path_source) +paths = executable('paths', 'paths.c', include_directories: incdir, + objects: paths_objects, link_with: test_utils) +test('paths', paths) + +if get_option('libmpv') + libmpv_test = executable('libmpv-test', 'libmpv_test.c', + include_directories: incdir, link_with: libmpv) + test('libmpv', libmpv_test) +endif + +# Minimum required libavutil version that works with these tests. +# Will need to be manually updated when ffmpeg adds/removes more formats in the future. +if libavutil.version().version_compare('>= 57.10.101') + +# The CI can randomly fail if libavutil isn't explictly linked again here. + img_format = executable('img-format', 'img_format.c', include_directories: incdir, + dependencies: libavutil, link_with: [img_utils, test_utils]) + test('img-format', img_format, args: [refdir, outdir], suite: 'ffmpeg') + + + scale_sws_objects = libmpv.extract_objects('video/image_writer.c', + 'video/repack.c') + scale_sws = executable('scale-sws', ['scale_sws.c', 'scale_test.c'], include_directories: incdir, + objects: scale_sws_objects, dependencies: [libswscale, jpeg, zimg], + link_with: [img_utils, test_utils]) + test('scale-sws', scale_sws, args: [refdir, outdir], suite: 'ffmpeg') + + if features['zimg'] + repack_objects = libmpv.extract_objects('sub/draw_bmp.c') + repack = executable('repack', 'repack.c', include_directories: incdir, objects: repack_objects, + dependencies: [libswscale, zimg], link_with: [img_utils, test_utils]) + test('repack', repack, args: [refdir, outdir], suite: 'ffmpeg') + + scale_zimg_objects = libmpv.extract_objects('video/image_writer.c') + scale_zimg = executable('scale-zimg', ['scale_test.c', 'scale_zimg.c'], include_directories: incdir, + objects: scale_zimg_objects, dependencies:[libswscale, jpeg, zimg], + link_with: [img_utils, test_utils]) + test('scale-zimg', scale_zimg, args: [refdir, outdir], suite: 'ffmpeg') + endif +endif diff --git a/test/paths.c b/test/paths.c index 66d4ee2e2d..aa610db437 100644 --- a/test/paths.c +++ b/test/paths.c @@ -1,7 +1,8 @@ #include "common/common.h" +#include "common/msg.h" #include "config.h" #include "options/path.h" -#include "tests.h" +#include "test_utils.h" static void test_join(char *file, int line, char *a, char *b, char *c) { @@ -29,7 +30,7 @@ static void test_abs(char *file, int line, bool abs, char *a) #define TEST_ABS(abs, a) \ test_abs(__FILE__, __LINE__, abs, a) -static void run(struct test_ctx *ctx) +int main(void) { TEST_ABS(true, "/ab"); TEST_ABS(false, "ab"); @@ -60,9 +61,5 @@ static void run(struct test_ctx *ctx) TEST_JOIN("c:a", "b", "c:a/b"); TEST_JOIN("c:", "b", "c:b"); #endif + return 0; } - -const struct unittest test_paths = { - .name = "paths", - .run = run, -}; diff --git a/test/repack.c b/test/repack.c index 29eadd3a50..a37559b705 100644 --- a/test/repack.c +++ b/test/repack.c @@ -3,10 +3,13 @@ #include #include "common/common.h" +#include "common/global.h" +#include "img_utils.h" #include "sub/draw_bmp.h" #include "sub/osd.h" -#include "tests.h" +#include "test_utils.h" #include "video/fmt-conversion.h" +#include "video/mp_image.h" #include "video/img_format.h" #include "video/repack.h" #include "video/sws_utils.h" @@ -185,8 +188,7 @@ static bool is_true_planar(int imgfmt) return true; } -static int try_repack(struct test_ctx *ctx, FILE *f, int imgfmt, int flags, - int not_if_fmt) +static int try_repack(FILE *f, int imgfmt, int flags, int not_if_fmt) { char *head = mp_tprintf(80, "%-15s =>", mp_imgfmt_to_name(imgfmt)); struct mp_repack *un = mp_repack_create_planar(imgfmt, false, flags); @@ -324,7 +326,7 @@ static int try_repack(struct test_ctx *ctx, FILE *f, int imgfmt, int flags, return b; } -static void check_float_repack(struct test_ctx *ctx, int imgfmt, enum mp_csp csp, +static void check_float_repack(int imgfmt, enum mp_csp csp, enum mp_csp_levels levels) { imgfmt = UNFUCK(imgfmt); @@ -339,10 +341,8 @@ static void check_float_repack(struct test_ctx *ctx, int imgfmt, enum mp_csp csp int w = 1 << (bpp * 8); if (w > ZIMG_IMAGE_DIMENSION_MAX) { - MP_WARN(ctx, - "Image dimension (%d) exceeded maximum allowed by zimg (%zu)." - " Skipping test...\n", - w, ZIMG_IMAGE_DIMENSION_MAX); + printf("Image dimension (%d) exceeded maximum allowed by zimg (%zu)." + " Skipping test...\n", w, ZIMG_IMAGE_DIMENSION_MAX); return; } @@ -433,7 +433,7 @@ static void check_float_repack(struct test_ctx *ctx, int imgfmt, enum mp_csp csp talloc_free(from_f); } -static bool try_draw_bmp(struct mpv_global *g, FILE *f, int imgfmt) +static bool try_draw_bmp(FILE *f, int imgfmt) { bool ok = false; @@ -465,7 +465,7 @@ static bool try_draw_bmp(struct mpv_global *g, FILE *f, int imgfmt) .num_items = 1, }; - struct mp_draw_sub_cache *c = mp_draw_sub_alloc(NULL, g); + struct mp_draw_sub_cache *c = mp_draw_sub_alloc_test(dst); if (mp_draw_sub_bitmaps(c, dst, &sbs_list)) { char *info = mp_draw_sub_get_dbg_info(c); fprintf(f, "%s\n", info); @@ -482,53 +482,51 @@ done: return ok; } -static void run(struct test_ctx *ctx) +int main(int argc, char *argv[]) { - FILE *f = test_open_out(ctx, "repack.txt"); + const char *refdir = argv[1]; + const char *outdir = argv[2]; + FILE *f = test_open_out(outdir, "repack.txt"); init_imgfmts_list(); for (int n = 0; n < num_imgfmts; n++) { int imgfmt = imgfmts[n]; - int other = try_repack(ctx, f, imgfmt, 0, 0); - try_repack(ctx, f, imgfmt, REPACK_CREATE_ROUND_DOWN, other); - try_repack(ctx, f, imgfmt, REPACK_CREATE_EXPAND_8BIT, other); - try_repack(ctx, f, imgfmt, REPACK_CREATE_PLANAR_F32, other); + int other = try_repack(f, imgfmt, 0, 0); + try_repack(f, imgfmt, REPACK_CREATE_ROUND_DOWN, other); + try_repack(f, imgfmt, REPACK_CREATE_EXPAND_8BIT, other); + try_repack(f, imgfmt, REPACK_CREATE_PLANAR_F32, other); } fclose(f); - assert_text_files_equal(ctx, "repack.txt", "repack.txt", - "This can fail if FFmpeg/libswscale adds or removes pixfmts."); + assert_text_files_equal(refdir, outdir, "repack.txt", + "This can fail if FFmpeg/libswscale adds or removes pixfmts."); - check_float_repack(ctx, -AV_PIX_FMT_GBRAP, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_GBRAP10, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_GBRAP16, MP_CSP_RGB, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_TV); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_TV); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_PC); - check_float_repack(ctx, -AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_TV); + check_float_repack(-AV_PIX_FMT_GBRAP, MP_CSP_RGB, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_GBRAP10, MP_CSP_RGB, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_GBRAP16, MP_CSP_RGB, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_YUVA444P, MP_CSP_BT_709, MP_CSP_LEVELS_TV); + check_float_repack(-AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_YUVA444P10, MP_CSP_BT_709, MP_CSP_LEVELS_TV); + check_float_repack(-AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_PC); + check_float_repack(-AV_PIX_FMT_YUVA444P16, MP_CSP_BT_709, MP_CSP_LEVELS_TV); // Determine the list of possible draw_bmp input formats. Do this here // because it mostly depends on repack and imgformat stuff. - f = test_open_out(ctx, "draw_bmp.txt"); + f = test_open_out(outdir, "draw_bmp.txt"); for (int n = 0; n < num_imgfmts; n++) { int imgfmt = imgfmts[n]; fprintf(f, "%-12s= ", mp_imgfmt_to_name(imgfmt)); - try_draw_bmp(ctx->global, f, imgfmt); + try_draw_bmp(f, imgfmt); } fclose(f); - assert_text_files_equal(ctx, "draw_bmp.txt", "draw_bmp.txt", - "This can fail if FFmpeg/libswscale adds or removes pixfmts."); + assert_text_files_equal(refdir, outdir, "draw_bmp.txt", + "This can fail if FFmpeg/libswscale adds or removes pixfmts."); + return 0; } - -const struct unittest test_repack = { - .name = "repack", - .run = run, -}; diff --git a/test/scale_sws.c b/test/scale_sws.c index bfc3bb93ae..c9f5e3176b 100644 --- a/test/scale_sws.c +++ b/test/scale_sws.c @@ -23,7 +23,7 @@ static const struct scale_test_fns fns = { .supports_fmts = supports_fmts, }; -static void run(struct test_ctx *ctx) +int main(int argc, char *argv[]) { struct mp_sws_context *sws = mp_sws_alloc(NULL); @@ -31,15 +31,12 @@ static void run(struct test_ctx *ctx) stest->fns = &fns; stest->fns_priv = sws; stest->test_name = "repack_sws"; - stest->ctx = ctx; + stest->refdir = talloc_strdup(stest, argv[1]); + stest->outdir = talloc_strdup(stest, argv[2]); repack_test_run(stest); talloc_free(stest); talloc_free(sws); + return 0; } - -const struct unittest test_repack_sws = { - .name = "repack_sws", - .run = run, -}; diff --git a/test/scale_test.c b/test/scale_test.c index ccd83c7658..f919dca1e2 100644 --- a/test/scale_test.c +++ b/test/scale_test.c @@ -55,13 +55,13 @@ static struct mp_image *gen_repack_test_img(int w, int h, int bytes, bool rgb, static void dump_image(struct scale_test *stest, const char *name, struct mp_image *img) { - char *path = mp_tprintf(4096, "%s/%s.png", stest->ctx->out_path, name); + char *path = mp_tprintf(4096, "%s/%s.png", stest->outdir, name); struct image_writer_opts opts = image_writer_opts_defaults; opts.format = AV_CODEC_ID_PNG; - if (!write_image(img, &opts, path, stest->ctx->global, stest->ctx->log)) { - MP_FATAL(stest->ctx, "Failed to write '%s'.\n", path); + if (!write_image(img, &opts, path, NULL, NULL)) { + printf("Failed to write '%s'.\n", path); abort(); } } @@ -102,7 +102,7 @@ static void assert_imgs_equal(struct scale_test *stest, FILE *f, void repack_test_run(struct scale_test *stest) { char *logname = mp_tprintf(80, "%s.log", stest->test_name); - FILE *f = test_open_out(stest->ctx, logname); + FILE *f = test_open_out(stest->outdir, logname); if (!stest->sws) { init_imgfmts_list(); @@ -187,6 +187,6 @@ void repack_test_run(struct scale_test *stest) fclose(f); - assert_text_files_equal(stest->ctx, logname, logname, + assert_text_files_equal(stest->refdir, stest->outdir, logname, "This can fail if FFmpeg adds or removes pixfmts."); } diff --git a/test/scale_test.h b/test/scale_test.h index f49b456ecb..5c83786ac2 100644 --- a/test/scale_test.h +++ b/test/scale_test.h @@ -1,6 +1,7 @@ #pragma once -#include "tests.h" +#include "img_utils.h" +#include "test_utils.h" #include "video/mp_image.h" struct scale_test_fns { @@ -13,7 +14,8 @@ struct scale_test { const struct scale_test_fns *fns; void *fns_priv; const char *test_name; - struct test_ctx *ctx; + const char *refdir; + const char *outdir; // Private. struct mp_image *img_repack_rgb8; diff --git a/test/scale_zimg.c b/test/scale_zimg.c index f5957067c2..57894bea67 100644 --- a/test/scale_zimg.c +++ b/test/scale_zimg.c @@ -21,7 +21,7 @@ static const struct scale_test_fns fns = { .supports_fmts = supports_fmts, }; -static void run(struct test_ctx *ctx) +int main(int argc, char *argv[]) { struct mp_zimg_context *zimg = mp_zimg_alloc(); zimg->opts.threads = 1; @@ -30,12 +30,12 @@ static void run(struct test_ctx *ctx) stest->fns = &fns; stest->fns_priv = zimg; stest->test_name = "repack_zimg"; - stest->ctx = ctx; + stest->refdir = talloc_strdup(stest, argv[1]); + stest->outdir = talloc_strdup(stest, argv[2]); repack_test_run(stest); - FILE *f = test_open_out(ctx, "zimg_formats.txt"); - init_imgfmts_list(); + FILE *f = test_open_out(stest->outdir, "zimg_formats.txt"); for (int n = 0; n < num_imgfmts; n++) { int imgfmt = imgfmts[n]; fprintf(f, "%15s%7s%7s%7s%8s |\n", mp_imgfmt_to_name(imgfmt), @@ -47,14 +47,10 @@ static void run(struct test_ctx *ctx) } fclose(f); - assert_text_files_equal(stest->ctx, "zimg_formats.txt", "zimg_formats.txt", + assert_text_files_equal(stest->refdir, stest->outdir, "zimg_formats.txt", "This can fail if FFmpeg/libswscale adds or removes pixfmts."); talloc_free(stest); talloc_free(zimg); + return 0; } - -const struct unittest test_repack_zimg = { - .name = "repack_zimg", - .run = run, -}; diff --git a/test/subtimes.js b/test/subtimes.js deleted file mode 100644 index be6940ad3b..0000000000 --- a/test/subtimes.js +++ /dev/null @@ -1,15 +0,0 @@ -function subtimes() { - mp.msg.info("sub-start: " + mp.get_property_number("sub-start")); - mp.msg.info("sub-end: " + mp.get_property_number("sub-end")); - mp.msg.info("sub-text: " + mp.get_property_native("sub-text")); -} - -mp.add_key_binding("t", "subtimes", subtimes); - -function secondary_subtimes() { - mp.msg.info("secondary-sub-start: " + mp.get_property_number("secondary-sub-start")); - mp.msg.info("secondary-sub-end: " + mp.get_property_number("secondary-sub-end")); - mp.msg.info("secondary-sub-text: " + mp.get_property_native("secondary-sub-text")); -} - -mp.add_key_binding("T", "secondary_subtimes", secondary_subtimes); \ No newline at end of file diff --git a/test/test_utils.c b/test/test_utils.c new file mode 100644 index 0000000000..a1ecfacfd7 --- /dev/null +++ b/test/test_utils.c @@ -0,0 +1,114 @@ +#include + +#include "options/m_option.h" +#include "options/path.h" +#include "osdep/subprocess.h" +#include "test_utils.h" + +#ifdef NDEBUG +static_assert(false, "don't define NDEBUG for tests"); +#endif + +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(); + } +} + +FILE *test_open_out(const char *outdir, const char *name) +{ + mp_mkdirp(outdir); + assert(mp_path_isdir(outdir)); + char *path = mp_tprintf(4096, "%s/%s", outdir, name); + FILE *f = fopen(path, "wb"); + if (!f) { + printf("Could not open '%s' for writing: %s\n", path, + mp_strerror(errno)); + abort(); + } + return f; +} + +void assert_text_files_equal_impl(const char *file, int line, + const char *refdir, const char *outdir, + const char *ref, const char *new, + const char *err) +{ + char *path_ref = mp_tprintf(4096, "%s/%s", refdir, ref); + char *path_new = mp_tprintf(4096, "%s/%s", outdir, new); + + struct mp_subprocess_opts opts = { + .exe = "diff", + .args = (char*[]){"diff", "-u", "--", path_ref, path_new, 0}, + .fds = { {0, .src_fd = 0}, {1, .src_fd = 1}, {2, .src_fd = 2} }, + .num_fds = 3, + }; + + struct mp_subprocess_result res; + mp_subprocess2(&opts, &res); + + if (res.error || res.exit_status) { + if (res.error) + printf("Note: %s\n", mp_subprocess_err_str(res.error)); + printf("Giving up.\n"); + abort(); + } +} + +static void hexdump(const uint8_t *d, size_t size) +{ + printf("|"); + while (size--) { + printf(" %02x", d[0]); + d++; + } + printf(" |\n"); +} + +void assert_memcmp_impl(const char *file, int line, + const void *a, const void *b, size_t size) +{ + if (memcmp(a, b, size) == 0) + return; + + printf("%s:%d: mismatching data:\n", file, line); + hexdump(a, size); + hexdump(b, size); + abort(); +} + +/* Stubs: see test_utils.h */ +struct mp_log *mp_null_log; +const char *mp_help_text; + +void mp_msg(struct mp_log *log, int lev, const char *format, ...) {}; +int mp_msg_find_level(const char *s) {return 0;}; +int mp_msg_level(struct mp_log *log) {return 0;}; +void mp_write_console_ansi(void) {}; + +#ifndef WIN32_TESTS +void mp_add_timeout(void) {}; +void mp_rel_time_to_timespec(void) {}; +void mp_time_us(void) {}; +void mp_time_us_to_timespec(void) {}; +#endif diff --git a/test/test_utils.h b/test/test_utils.h new file mode 100644 index 0000000000..7dcb32cc3b --- /dev/null +++ b/test/test_utils.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include + +#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)) + +// Assert that memcmp(a,b,s)==0, or hexdump output on failure. +#define assert_memcmp(a, b, s) \ + assert_memcmp_impl(__FILE__, __LINE__, (a), (b), (s)) + +// Require that the files "ref" and "new" are the same. The paths can be +// relative to ref_path and out_path respectively. If they're not the same, +// the output of "diff" is shown, the err message (if not NULL), and the test +// fails. +#define assert_text_files_equal(refdir, outdir, name, err) \ + assert_text_files_equal_impl(__FILE__, __LINE__, (refdir), (outdir), (name), (name), (err)) + +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); +void assert_text_files_equal_impl(const char *file, int line, + const char *refdir, const char *outdir, + const char *ref, const char *new, + const char *err); +void assert_memcmp_impl(const char *file, int line, + const void *a, const void *b, size_t size); + +// Open a new file in the build dir path. Always succeeds. +FILE *test_open_out(const char *outdir, const char *name); + +/* Stubs */ + +// Files commonly import common/msg.h which requires these to be +// defined. We don't actually need mpv's logging system here so +// just define these as stubs that do nothing. +struct mp_log; +void mp_msg(struct mp_log *log, int lev, const char *format, ...) + PRINTF_ATTRIBUTE(3, 4); +int mp_msg_find_level(const char *s); +int mp_msg_level(struct mp_log *log); +void mp_write_console_ansi(void); + +// Windows additionally requires timer related code so it will actually +// import the real versions of these functions and use them. On other +// platforms, these can just be stubs for simplicity. +#ifndef WIN32_TESTS +void mp_add_timeout(void); +void mp_rel_time_to_timespec(void); +void mp_time_us(void); +void mp_time_us_to_timespec(void); +#endif diff --git a/test/tests.c b/test/tests.c deleted file mode 100644 index eb55bb302b..0000000000 --- a/test/tests.c +++ /dev/null @@ -1,159 +0,0 @@ -#include "options/path.h" -#include "osdep/subprocess.h" -#include "player/core.h" -#include "tests.h" - -static const struct unittest *unittests[] = { - &test_chmap, - &test_gl_video, - &test_img_format, - &test_json, - &test_linked_list, - &test_paths, - &test_repack_sws, -#if HAVE_ZIMG - &test_repack, // zimg only due to cross-checking with zimg.c - &test_repack_zimg, -#endif - 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; - } - - struct test_ctx ctx = { - .global = mpctx->global, - .log = mpctx->log, - .ref_path = "test/ref", - .out_path = "test/out", - }; - - if (!mp_path_isdir(ctx.ref_path)) { - MP_FATAL(mpctx, "Must be run from git repo root dir.\n"); - abort(); - } - mp_mkdirp(ctx.out_path); - assert(mp_path_isdir(ctx.out_path)); - - 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 ? (1 << 1) : 0))); - - bool run = false; - run |= strcmp(sel, "all-simple") == 0 && !t->is_complex; - run |= strcmp(sel, t->name) == 0; - - if (run) { - if (t->run) - t->run(&ctx); - num_run++; - } - } - - MP_INFO(mpctx, "%d unittests successfully run.\n", num_run); - - return num_run > 0; // still error if none -} - -#ifdef NDEBUG -static_assert(false, "don't define NDEBUG for tests"); -#endif - -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(); - } -} - -FILE *test_open_out(struct test_ctx *ctx, const char *name) -{ - char *path = mp_tprintf(4096, "%s/%s", ctx->out_path, name); - FILE *f = fopen(path, "wb"); - if (!f) { - MP_FATAL(ctx, "Could not open '%s' for writing.\n", path); - abort(); - } - return f; -} - -void assert_text_files_equal_impl(const char *file, int line, - struct test_ctx *ctx, const char *ref, - const char *new, const char *err) -{ - char *path_ref = mp_tprintf(4096, "%s/%s", ctx->ref_path, ref); - char *path_new = mp_tprintf(4096, "%s/%s", ctx->out_path, new); - - struct mp_subprocess_opts opts = { - .exe = "diff", - .args = (char*[]){"diff", "-u", "--", path_ref, path_new, 0}, - .fds = { {0, .src_fd = 0}, {1, .src_fd = 1}, {2, .src_fd = 2} }, - .num_fds = 3, - }; - - struct mp_subprocess_result res; - mp_subprocess2(&opts, &res); - - if (res.error || res.exit_status) { - if (res.error) - MP_WARN(ctx, "Note: %s\n", mp_subprocess_err_str(res.error)); - MP_FATAL(ctx, "Giving up.\n"); - abort(); - } -} - -static void hexdump(const uint8_t *d, size_t size) -{ - printf("|"); - while (size--) { - printf(" %02x", d[0]); - d++; - } - printf(" |\n"); -} - -void assert_memcmp_impl(const char *file, int line, - const void *a, const void *b, size_t size) -{ - if (memcmp(a, b, size) == 0) - return; - - printf("%s:%d: mismatching data:\n", file, line); - hexdump(a, size); - hexdump(b, size); - abort(); -} diff --git a/test/tests.h b/test/tests.h deleted file mode 100644 index 8b2eb98174..0000000000 --- a/test/tests.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "common/common.h" - -struct MPContext; - -bool run_tests(struct MPContext *mpctx); - -struct test_ctx { - struct mpv_global *global; - struct mp_log *log; - - // Path for ref files, without trailing "/". - const char *ref_path; - - // Path for result files, without trailing "/". - const char *out_path; -}; - -struct unittest { - // This is used to select the test on command line with --unittest=. - const char *name; - - // Cannot run without additional arguments supplied. - bool is_complex; - - // Entrypoints. There are various for various purposes. Only 1 of them must - // be set. - - // Entrypoint for tests which have a simple dependency on the mpv core. The - // core is sufficiently initialized at this point. - void (*run)(struct test_ctx *ctx); -}; - -extern const struct unittest test_chmap; -extern const struct unittest test_gl_video; -extern const struct unittest test_img_format; -extern const struct unittest test_json; -extern const struct unittest test_linked_list; -extern const struct unittest test_repack_sws; -extern const struct unittest test_repack_zimg; -extern const struct unittest test_repack; -extern const struct unittest test_paths; - -#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)) - -// Assert that memcmp(a,b,s)==0, or hexdump output on failure. -#define assert_memcmp(a, b, s) \ - assert_memcmp_impl(__FILE__, __LINE__, (a), (b), (s)) - -// Require that the files "ref" and "new" are the same. The paths can be -// relative to ref_path and out_path respectively. If they're not the same, -// the output of "diff" is shown, the err message (if not NULL), and the test -// fails. -#define assert_text_files_equal(ctx, ref, new, err) \ - assert_text_files_equal_impl(__FILE__, __LINE__, (ctx), (ref), (new), (err)) - -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); -void assert_text_files_equal_impl(const char *file, int line, - struct test_ctx *ctx, const char *ref, - const char *new, const char *err); -void assert_memcmp_impl(const char *file, int line, - const void *a, const void *b, size_t size); - -// Open a new file in the out_path. Always succeeds. -FILE *test_open_out(struct test_ctx *ctx, const char *name); - -// Sorted list of valid imgfmts. Call init_imgfmts_list() before use. -extern int imgfmts[]; -extern int num_imgfmts; - -void init_imgfmts_list(void); diff --git a/video/out/gpu/utils.c b/video/out/gpu/utils.c index 2c625dc26a..8a1aacfff5 100644 --- a/video/out/gpu/utils.c +++ b/video/out/gpu/utils.c @@ -39,6 +39,21 @@ void gl_transform_ortho_fbo(struct gl_transform *t, struct ra_fbo fbo) gl_transform_ortho(t, 0, fbo.tex->params.w, 0, fbo.tex->params.h * y_dir); } +float gl_video_scale_ambient_lux(float lmin, float lmax, + float rmin, float rmax, float lux) +{ + assert(lmax > lmin); + + float num = (rmax - rmin) * (log10(lux) - log10(lmin)); + float den = log10(lmax) - log10(lmin); + float result = num / den + rmin; + + // clamp the result + float max = MPMAX(rmax, rmin); + float min = MPMIN(rmax, rmin); + return MPMAX(MPMIN(result, max), min); +} + void ra_buf_pool_uninit(struct ra *ra, struct ra_buf_pool *pool) { for (int i = 0; i < pool->num_buffers; i++) diff --git a/video/out/gpu/utils.h b/video/out/gpu/utils.h index ac0cbf28d7..215873eec8 100644 --- a/video/out/gpu/utils.h +++ b/video/out/gpu/utils.h @@ -65,6 +65,9 @@ void gl_transform_trans(struct gl_transform t, struct gl_transform *x); void gl_transform_ortho_fbo(struct gl_transform *t, struct ra_fbo fbo); +float gl_video_scale_ambient_lux(float lmin, float lmax, + float rmin, float rmax, float lux); + // A pool of buffers, which can grow as needed struct ra_buf_pool { struct ra_buf_params current_params; diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index df689b53c3..21e004cd43 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -4239,21 +4239,6 @@ static int validate_error_diffusion_opt(struct mp_log *log, const m_option_t *op return r; } -float gl_video_scale_ambient_lux(float lmin, float lmax, - float rmin, float rmax, float lux) -{ - assert(lmax > lmin); - - float num = (rmax - rmin) * (log10(lux) - log10(lmin)); - float den = log10(lmax) - log10(lmin); - float result = num / den + rmin; - - // clamp the result - float max = MPMAX(rmax, rmin); - float min = MPMIN(rmax, rmin); - return MPMAX(MPMIN(result, max), min); -} - void gl_video_set_ambient_lux(struct gl_video *p, int lux) { if (p->opts.gamma_auto) { diff --git a/video/sws_utils.c b/video/sws_utils.c index 0f1708af3f..5e9c35876a 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -213,6 +213,9 @@ struct mp_sws_context *mp_sws_alloc(void *talloc_ctx) // if the user changes any options. void mp_sws_enable_cmdline_opts(struct mp_sws_context *ctx, struct mpv_global *g) { + // Should only ever be NULL for tests. + if (!g) + return; if (ctx->opts_cache) return;