This is a variant of `g_test_trap_subprocess()` which allows the
environment for the child process to be specified. This is quite useful
when you want to test code which reads environment variables, as it’s
not safe to set those after the start of `main()`.
This will be useful within and outwith GLib for testing such code.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: #1618
g_option_context_parse()/g_application_run()/g_test_init() for
convenience also call g_set_prgname(), when the prgname is unset at this
point. This was racy.
Fix the race by using an atomic compare-and-exchange and only reset the
value, if it is unset still.
This should not result in any functional changes, but will eventually
allow glib to be functional on CHERI-enabled systems such as Morello.
Helps: https://gitlab.gnome.org/GNOME/glib/-/issues/2842
Prompted by #3071, this clarifies that `g_test_trap_subprocess()` uses
`g_child_watch_source_new()` internally, so it will not work if any of
the preconditions for using that API are not met. In particular, if
`SIGCHLD` is ignored, things will break.
This documentation is not meant to be an API guarantee which constrains
the implementation of `g_test_trap_subprocess()` in future, just a tip
to people currently using the API.
Signed-off-by: Philip Withnall <philip@tecnocode.co.uk>
Helps: #3071
Otherwise, crashing tests like assert-msg-test will still report to
pipe-based crash reporting frameworks like systemd-coredump, even though
the RLIMIT_CORE limit is zero.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Displaying the execution time will aid developers in understanding which
test cases are responsible for slow execution times. The test code is
already measuring the execution time for every test case, but is not
reporting that data anywhere accessible to developers running the tests.
The new code will print a TAP comment:
# slow test /the/test/path executed in NN.NN secs
for any test taking longer than 0.5 seconds to run.
Example new output format:
$ ./build/glib/tests/unix
TAP version 13
# random seed: R02S690dc3c7a04866e4890501eedc7f8eef
1..13
# Start of glib-unix tests
ok 1 /glib-unix/pipe
# /glib-unix/pipe-stdio-overwrite summary: Test that g_unix_open_pipe() will use the first available FD, even if it?s stdin/stdout/stderr
# Bug Reference: https://gitlab.gnome.org/GNOME/glib/-/issues/2795
ok 2 /glib-unix/pipe-stdio-overwrite
ok 3 /glib-unix/error
ok 4 /glib-unix/nonblocking
ok 5 /glib-unix/sighup
# slow test /glib-unix/sighup executed in 0.50 secs
ok 6 /glib-unix/sigterm
# slow test /glib-unix/sigterm executed in 0.50 secs
ok 7 /glib-unix/sighup_again
# slow test /glib-unix/sighup_again executed in 0.50 secs
ok 8 /glib-unix/sighup_add_remove
ok 9 /glib-unix/sighup_nested
ok 10 /glib-unix/callback_after_signal
# slow test /glib-unix/callback_after_signal took 2.00 secs
ok 11 /glib-unix/child-wait
# Start of get-passwd-entry tests
# /glib-unix/get-passwd-entry/root summary: Tests that g_unix_get_passwd_entry() works for a known-existing username.
ok 12 /glib-unix/get-passwd-entry/root
# /glib-unix/get-passwd-entry/nonexistent summary: Tests that g_unix_get_passwd_entry() returns an error for a nonexistent username.
ok 13 /glib-unix/get-passwd-entry/nonexistent
# End of get-passwd-entry tests
# End of glib-unix tests
As a practical usage example, the meson log can be queried to find
slow tests project-wide:
$ grep 'slow test' build/meson-logs/testlog.txt | sort -n -k 7 -r | head
# slow test /threadpool/basics executed in 36.04 secs
# slow test /gobject/refcount/properties-3 executed in 30.00 secs
# slow test /gio/io-basics executed in 12.54 secs
# slow test /timeout/rounding executed in 10.60 secs
# slow test /GObject/threaded-weak-ref executed in 10.42 secs
# slow test /thread/rerun-all executed in 9.84 secs
# slow test /gobject/refcount/object-advanced executed in 5.46 secs
# slow test /thread/static-rw-lock executed in 5.00 secs
# slow test /gobject/refcount/signals executed in 5.00 secs
# slow test /gobject/refcount/signals executed in 5.00 secs
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Use more modern styling to the code added in the previous patch:
- split 'label: stmt; stmt;' into multiple lines
- add default: label with g_assert_not_reached() [yes, it's a bit
weird adding an assertion inside code that handles assertions, but
we should be okay since g_assertion_message_* are not public
functions and should only be used by our macros]
- use <inttypes.h> for shorter format strings
Note, however, that using uint64_t in gtestutils.h is not feasible,
since it would require adding an '#include <stdint.h>' with potential
unintended namespace pollution to older clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
While x86_64 has enough precision in long double to do a round trip
from guint64 to long double and back, this is platform-specific, and
is a disservice to users trying to debug failing unit tests on other
architectures where it loses precision for g_assert_cmp{int,uint,hex}.
See also https://bugzilla.gnome.org/show_bug.cgi?id=788385 which
mentions having to add casts to specifically silence the compiler on
platforms where the precision loss occurs.
Meanwhile, g_assert_cmpuint() does an unsigned comparison, but outputs
signed values if the comparison fails, which is confusing.
Fix both issues by introducing a new g_assertion_message_cmpint()
function with a new 'u' numtype. For backwards compatibility, the
macros still call into the older g_assertion_message_cmpnum() when not
targetting 2.78, and that function still works when passed 'i' and 'x'
types even though code compiled for 2.78 and later will never invoke
it with numtype anything other than 'f'. Note that g_assert_cmpmem
can also take advantage of the new code, even though in practice,
comparison between two size_t values representing array lengths that
can actually be compiled is unlikely to have ever hit the precision
loss. The macros in signals.c test code does not have to worry about
versioning, since it is not part of the glib library proper.
Closes#2997
Signed-off-by: Eric Blake <eblake@redhat.com>
Apparently 3 hashes is too many, and as a result this line is not
displayed properly in the HTML documentation. 2 hashes seems to be
just right, as can be seen with:
$ git grep '^ \* ##' | wc -l
65
$ git grep '^ \* ###' | wc -l
1
We don't want to update this function in case some crusty old third party
code might be relying on its current behavior.
Also, it is deprecated anyway and no code should be using it.
Although unlikely, apparently `message` may be `NULL` (the rest of the
code checks for it), so the code to convert newlines to spaces should
probably also check for `NULL`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Coverity CID: #1504054
When we've a failure our TAP reporting just bails out without that is clear
what is the test that has failed.
So in this case, expose a "not ok" message if the test name is known, and
use it to report the error message too if available.
Otherwise just use the same Bail out! strategy.
This is something that a base test should decide, so if a subtest fails it's
up to the caller to decide whether to bail out the whole suite or just the
subtest.
When using verbose logging, all the printing and the glib info and debug
logs may end up being written in standard out, making meson TAP parser to be
confused and to fail with TAP parsing errors.
So, in such case write the subprocess output all at once using the the gtest
printer so that we add proper formatting.
Also do not write any gtest result message for subprocesses
When using TAP output in gtest, all the printed strings should be commented
not to break the spec, so enforce this at GTest level, by ensuring that
all the lines written via g_print() will be in the commented form and will
respect the subtest indentation.
As per this we can remove some custom code in g_test_log() as now there are
very few cases in which we need to use the default print handler which is
now private when testing.
Only use g_test_log() because it will prepend `#` to log messages when
using TAP protocol. Meson >=1.0 rightfully prints a warning when using
TAP protocol and stdout contains non-comment unknown TAP command.
Sadly meson 60 doesn't support parsing TAP 14 subtests properly, so it would
fail.
So temporary go back to the previous logic in a simple way so that this
commit can be reverted quickly when we can use a newer meson version.
Instead of just commenting all the output of sub-processes we can just use
the TAP 14 syntax for subtests, by using 4-spaces to indent the subtests
output.
This may not work perfectly when there are sub-process that may write
output mixed with the parent, but it should be enough to expose the
hierarchy.
If a gtest process is run as a child of another process, we should not print
the TAP output in plain mode or we'll break the parent results.
We can instead just comment their output so that it gets ignored by TAP
parsers.
Extra lines must be prepended with `#` which g_test_message() does for
us. Note that lines after "Bail out" are ignored, so we print
stdout/stderr before.
Do not write it in multiple lines, to ensure it's going to be written
all together, and nothing else could be written in the middle.
Also optimize a bit the code.
We used to send the test log to stderr in pieces, but this could be
problematic when running multiple tests in parallel, so let's just prepare
the string in pieces and write it all at once.
In some cases if verbose output was enabled we were using wrong output
format in TAP mode, so let's fix these cases and run the 'testing' test
case in --verbose mode to ensure we won't regress.
When running multiple tests in parallel using meson, the output could be
mixed and if we write the TAP reports in multiple steps the output could
be mangled together with other results.
An example is: https://gitlab.gnome.org/3v1n0/glib/-/jobs/2507620
Where we have:
ok 5 /cancellable/poll-fd# GLib-GIO-DEBUG: Collecting capable appnames: 0ms
# Allocating hashtables:...... 0ms
# Reading capable apps: 63ms
# Reading URL associations:... 0ms
# Reading extension assocs: 78ms
# Reading exe-only apps:...... 47ms
# Reading classes: 312ms
# Reading UWP apps: 47ms
# Postprocessing:..............16ms
# TOTAL: 563ms
# SKIP Platform not supported
Leading to a clear TAP parsing error
This is not required, but meson may warn about in future versions, so it's
safer to define it.
However, we must be sure that we only expose it once and in the root binary
if a test file launches another subprocess test file.
To avoid this, we set an environment variable at test init, so that it can
be inherited by children.
It's not the best solution, but for sure the best-effort one without having
to change gtest arguments and called binaries.
Non mentioning a version was considered as assuming we were using TAP
version 12, while no version earlier than 13 can be specified
explicitly so let's use it.
See: https://testanything.org/tap-specification.html
And: https://testanything.org/tap-version-13-specification.html
During tests in which we are isolating directories, we may still create
temporary files in the global temporary directory without cleaning them
because the value returned by g_get_tmp_dir() is cached when we isolate
the tests directory to the global TMPDIR.
To ensure that we're always isolating the temporary directories, let's
unset the cached temporary directory once we've defined $G_TEST_TMPDIR
so that the returned value of g_get_tmpdir() can be recomputed using the
test isolated temporary directory.
Using `test_run_name` in the path for the isolated dir tree for a test
is fine on Unix, because the `/` separator from GTest paths is suitable
as a file system separator.
On Windows, however, it doesn‘t work when mixed and concatenated with
paths which use backslashes. In particular, byte-by-byte path
comparisons don’t work. There are likely also issues if running on a
system with non-UTF-8 file system encoding.
Fix that by storing a file system path version of `test_run_name`
separately, and using the correct `G_DIR_SEPARATOR` for the host OS.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Add SPDX license (but not copyright) headers to all files which follow a
certain pattern in their existing non-machine-readable header comment.
This commit was entirely generated using the command:
```
git ls-files glib/*.[ch] | xargs perl -0777 -pi -e 's/\n \*\n \* This library is free software; you can redistribute it and\/or\n \* modify it under the terms of the GNU Lesser General Public/\n \*\n \* SPDX-License-Identifier: LGPL-2.1-or-later\n \*\n \* This library is free software; you can redistribute it and\/or\n \* modify it under the terms of the GNU Lesser General Public/igs'
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1415
This can happen if a caller (ab)uses `execve()` to execute a gtest
process with an empty `argv` array. `g_test_init()` has to gracefully
handle such a situation.
Fix a few problem areas in the code, and add a simple test which checks
that `g_test_init()` doesn’t crash when called with an empty `argv`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Some test suites try to call g_test_build_filename() after g_test_run()
has returned. In the installed-tests use-case where G_TEST_BUILDDIR and
G_TEST_SRCDIR are unset, that call uses test_argv0_dirname, which
is freed in test_cleanup(). Defer test_cleanup() using atexit() so it
isn't freed until after we return from main().
Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2563
Signed-off-by: Simon McVittie <smcv@collabora.com>
Many UCRT (and msvcrt/msvcxx) functions open dialog boxes
by default for .... some reason. This is a problem because a test runner
waiting on a process to exit won't see it exit unless someone actually
clicks away the box, which won't happen on a CI machine.
Additionally g_abort unconditionally raises a debugging exception,
which, if uncaught, will cause windows error reporting to pop a dialog
Resolve the first problem by calling platform specific (but documented)
functions to change the CRT's behavior in g_test_init
Resolve the second by only throwing a debug exception if we're under
debugging, and just calling abort() otherwise.
This reduces the number of popups triggerd by `meson test` from
over 10 to about three on my machine, mostly in the spawn test code.
This allows a pattern like
g_test_message ("cannot reticulate splines: %s", error->message);
g_test_fail ();
to be replaced by the simpler
g_test_fail_printf ("cannot reticulate splines: %s", error->message);
with the secondary benefit of making the message available to TAP
consumers as part of the "not ok" message.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Forming the g_test_skip() message from printf-style arguments seems
common enough to deserve a convenience function.
g_test_incomplete() is mechanically almost equivalent to g_test_skip()
(the semantics are different but the implementation is very similar),
so give it a similar mechanism for symmetry.
Signed-off-by: Simon McVittie <smcv@collabora.com>