Skip to content
Snippets Groups Projects
Commit 986cd6d1 authored by Ryan Gonzalez's avatar Ryan Gonzalez
Browse files

tests: Add helpers for showing string diffs


`_srt_show_diff` will run an external diff tool on both of the given
strings, and `_srt_assert_streq_diff` is a lightweight macro to perform
assert equality but use `_srt_show_diff` on error.

This is largely based on the diff-ing code from
`tests/system-info-cli.c` (ad877aae),
with some changes:

- _srt_async_signal_safe_error is an internal function, so it uses
  `GSubprocessLauncher` to be able to redirect stdout to stderr instead.
- Supports reading the diff tool and options from `$SRT_DIFF` and
  `$SRT_DIFF_OPTS`, respectively, to make room for using alternate diff
  tools on hairier test failures.

Signed-off-by: default avatarRyan Gonzalez <ryan.gonzalez@collabora.com>
parent 6b90d459
No related branches found
No related tags found
1 merge request!803Add shareable code for diff'ing JSON in tests
......@@ -317,3 +317,85 @@ _srt_tests_skip_if_really_in_steam_runtime (void)
return FALSE;
}
/**
* Show a diff of both strings, additionally saving their contents to a
* temporary directory for later inspections. Performs a diff via `$SRT_DIFF`
* (defaults to `diff`) with the options in `$SRT_DIFF_OPTS` (defaults to `-u`
* if not given *and* `$SRT_DIFF` was unset).
*/
void
_srt_show_diff (const char *expected,
const char *actual)
{
g_autoptr(GPtrArray) diff_argv = g_ptr_array_new ();
g_autoptr(GSubprocessLauncher) launcher =
g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDERR_MERGE);
g_autoptr(GSubprocess) diff = NULL;
g_autoptr(GError) error = NULL;
g_auto(GStrv) diff_opts_split = NULL;
g_autofree gchar *tmpdir = NULL;
g_autofree gchar *expected_path = NULL;
g_autofree gchar *actual_path = NULL;
glnx_autofd int stderr_dup = -1;
const char *artifacts = g_getenv ("AUTOPKGTEST_ARTIFACTS");
const char *diff_exe = g_getenv ("SRT_DIFF");
const char *diff_opts = g_getenv ("SRT_DIFF_OPTS");
g_assert_no_errno ((stderr_dup = dup (STDERR_FILENO)));
g_subprocess_launcher_take_stdout_fd (launcher, glnx_steal_fd (&stderr_dup));
if (artifacts == NULL)
{
tmpdir = g_dir_make_tmp ("srt-tests-XXXXXX", &error);
g_assert_no_error (error);
artifacts = tmpdir;
}
expected_path = g_build_filename (artifacts, "expected", NULL);
g_file_set_contents (expected_path, expected, -1, &error);
g_assert_no_error (error);
actual_path = g_build_filename (artifacts, "actual", NULL);
g_file_set_contents (actual_path, actual, -1, &error);
g_assert_no_error (error);
g_ptr_array_add (diff_argv, (gpointer) (diff_exe ?: "diff"));
/* Only add custom diff opts if given; but otherwise, if no diff tool
was given, default to '-u' for easier-to-read unified diffs. */
if (diff_opts != NULL)
{
char **p;
if (!g_shell_parse_argv (diff_opts, NULL, &diff_opts_split, &error))
{
if (g_error_matches (error, G_SHELL_ERROR, G_SHELL_ERROR_EMPTY_STRING))
g_clear_error (&error);
else
g_error ("Parsing $SRT_DIFF_OPTS: %s", error->message);
}
for (p = diff_opts_split; p != NULL && *p != NULL; p++)
g_ptr_array_add (diff_argv, *p);
}
else if (diff_exe == NULL)
{
g_ptr_array_add (diff_argv, (gpointer) "-u");
}
g_ptr_array_add (diff_argv, expected_path);
g_ptr_array_add (diff_argv, actual_path);
g_ptr_array_add (diff_argv, NULL);
/* Ignore error from calling diff, if any: we're running it
* for its side-effect of producing output on our stderr. */
diff = g_subprocess_launcher_spawnv (launcher,
(const char * const *) diff_argv->pdata,
NULL);
if (diff != NULL)
g_subprocess_wait (diff, NULL, NULL);
g_test_message ("Files for comparison: %s %s",
expected_path, actual_path);
if (tmpdir != NULL)
_srt_rm_rf (tmpdir);
}
......@@ -51,3 +51,20 @@ gchar *_srt_global_setup_sysroots (const char *argv0);
gboolean _srt_global_teardown_sysroots (void);
gboolean _srt_tests_skip_if_really_in_steam_runtime (void);
void _srt_show_diff (const char *expected,
const char *actual);
/**
* Asserts two strings as equal, showing a line-based diff of their contents via
* _srt_show_diff() if they don't match.
*/
#define _srt_assert_streq_diff(a, b) \
G_STMT_START { \
const char *__a = (a), *__b = (b); \
if (!g_str_equal (__a, __b)) {\
_srt_show_diff (__a, __b); \
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC,\
"assertion failed (" #a " == " #b ")"); \
} \
} G_STMT_END
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment