diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c index bbbb5f8ad668f51cdf33ade52429e7cf36faaf40..e737424d4010f914a5a1280edcfef88f4a39a089 100644 --- a/steam-runtime-tools/graphics.c +++ b/steam-runtime-tools/graphics.c @@ -541,6 +541,46 @@ _argv_for_graphics_test (const char *helpers_path, return argv; } + +static GPtrArray * +_argv_for_check_vulkan (const char *helpers_path, + SrtTestFlags test_flags, + const char *multiarch_tuple) +{ + GPtrArray *argv = g_ptr_array_new_with_free_func (g_free); + + // Use timeout command to limit how long the helper can run + g_ptr_array_add (argv, g_strdup ("timeout")); + g_ptr_array_add (argv, g_strdup ("--signal=TERM")); + + if (test_flags & SRT_TEST_FLAGS_TIME_OUT_SOONER) + { + // Speed up the failing case in automated testing + g_ptr_array_add (argv, g_strdup ("--kill-after=1")); + g_ptr_array_add (argv, g_strdup ("1")); + } + else + { + // Kill the helper (if still running) 3 seconds after the TERM signal + g_ptr_array_add (argv, g_strdup ("--kill-after=3")); + // Send TERM signal after 10 seconds + g_ptr_array_add (argv, g_strdup ("10")); + } + + if (helpers_path != NULL) + { + g_ptr_array_add (argv, g_strdup_printf ("%s/%s-check-vulkan", helpers_path, multiarch_tuple)); + } + else + { + g_ptr_array_add (argv, g_strdup_printf ("%s-check-vulkan", multiarch_tuple)); + } + + g_ptr_array_add (argv, NULL); + + return argv; +} + /** * _srt_check_graphics: * @helpers_path: An optional path to find wflinfo helpers, PATH is used if null. @@ -565,6 +605,7 @@ _srt_check_graphics (const char *helpers_path, { gchar *output = NULL; gchar *child_stderr = NULL; + gchar *child_stderr2 = NULL; int exit_status = -1; JsonParser *parser = NULL; const gchar *version_string = NULL; @@ -657,6 +698,53 @@ _srt_check_graphics (const char *helpers_path, } /* Now perform *-check-vulkan drawing test */ + g_ptr_array_unref (argv); + g_clear_pointer (&output, g_free); + + argv = _argv_for_check_vulkan (helpers_path, + test_flags, + multiarch_tuple); + + g_return_val_if_fail (argv != NULL, SRT_GRAPHICS_ISSUES_INTERNAL_ERROR); + + /* Now run and report exit code/messages if failure */ + if (!g_spawn_sync (NULL, /* working directory */ + (gchar **) argv->pdata, + my_environ, /* envp */ + G_SPAWN_SEARCH_PATH, /* flags */ + NULL, /* child setup */ + NULL, /* user data */ + &output, /* stdout */ + &child_stderr2, + &exit_status, + &error)) + { + g_debug ("An error occurred calling the helper: %s", error->message); + issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD; + goto out; + } + + if (child_stderr2 != NULL && child_stderr2[0] != '\0') + { + gchar *tmp = g_strconcat (child_stderr, child_stderr2, NULL); + + g_free (child_stderr); + child_stderr = tmp; + } + g_free (child_stderr2); + + if (exit_status != 0) + { + g_debug ("... wait status %d", exit_status); + issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW; + + // TERM signal gives us 124 from timeout man page + if (WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 124) // timeout command killed the helper + { + g_debug ("helper killed by timeout command"); + issues |= SRT_GRAPHICS_ISSUES_TIMEOUT; + } + } } out: diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h index 799d35e221cd8d9ba02c36f145130e6c88b1d1a6..d241e6c9d370180ae8e77d15646cad5a1b9b3a1e 100644 --- a/steam-runtime-tools/graphics.h +++ b/steam-runtime-tools/graphics.h @@ -53,6 +53,7 @@ GType srt_graphics_get_type (void); * @SRT_GRAPHICS_ISSUES_TIMEOUT: The check for this graphics stack took * too long to run and was terminated. This is likely to indicate that * the graphics stack causes the process using it to hang. + * @SRT_GRAPHICS_ISSUES_CANNOT_DRAW: The drawing test failed * * A bitfield with flags representing problems with the graphics stack, or * %SRT_GRAPHICS_ISSUES_NONE (which is numerically zero) if no problems @@ -67,6 +68,7 @@ typedef enum SRT_GRAPHICS_ISSUES_CANNOT_LOAD = (1 << 1), SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING = (1 << 2), SRT_GRAPHICS_ISSUES_TIMEOUT = (1 << 3), + SRT_GRAPHICS_ISSUES_CANNOT_DRAW = (1 << 4) } SrtGraphicsIssues; /** diff --git a/tests/graphics.c b/tests/graphics.c index f94020b9cf00e3e7943047dddc99164b1737fc4c..556fc6ebca9f483b351b69bf6cdfea7836551588 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -509,6 +509,50 @@ test_bad_vulkan (Fixture *f, g_object_unref (info); } +/* + * Test a mock system with vulkan driver but check-vulkan failure + */ +static void +test_mixed_vulkan (Fixture *f, + gconstpointer context) +{ + SrtGraphics *graphics = NULL; + SrtGraphicsIssues issues; + gchar *tuple; + gchar *renderer; + gchar *version; + + SrtSystemInfo *info = srt_system_info_new (NULL); + srt_system_info_set_helpers_path (info, f->builddir); + + issues = srt_system_info_check_graphics (info, + "mock-mixed", + SRT_WINDOW_SYSTEM_X11, + SRT_RENDERING_INTERFACE_VULKAN, + &graphics); + g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_DRAW); + g_assert_cmpstr (srt_graphics_get_renderer_string (graphics), ==, + SRT_TEST_GOOD_GRAPHICS_RENDERER); + g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, + SRT_TEST_GOOD_VULKAN_VERSION); + g_object_get (graphics, + "multiarch-tuple", &tuple, + "issues", &issues, + "renderer-string", &renderer, + "version-string", &version, + NULL); + g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_DRAW); + g_assert_cmpstr (tuple, ==, "mock-mixed"); + g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_GRAPHICS_RENDERER); + g_assert_cmpstr (version, ==, SRT_TEST_GOOD_VULKAN_VERSION); + g_free (tuple); + g_free (renderer); + g_free (version); + + g_object_unref (graphics); + g_object_unref (info); +} + /* * Assert that @icd is internally consistent. */ @@ -1350,6 +1394,8 @@ main (int argc, setup, test_good_vulkan, teardown); g_test_add ("/vulkan-bad", Fixture, NULL, setup, test_bad_vulkan, teardown); + g_test_add ("/vulkan-mixed", Fixture, NULL, + setup, test_mixed_vulkan, teardown); g_test_add ("/icd/egl/basic", Fixture, NULL, setup, test_icd_egl, teardown); diff --git a/tests/meson.build b/tests/meson.build index 110f8687cf620085049bd65d7c0b1498fb27b5b3..784f33db5cbd11fc3bc1c65e9417ac43053b7af4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -185,5 +185,32 @@ executable( install_dir: tests_dir ) +executable( + 'mock-good-check-vulkan', + join_paths('..', 'helpers', 'true.c'), + install: true, + install_dir: tests_dir +) + +executable( + 'mock-bad-check-vulkan', + 'mock-bad-check-vulkan.c', + install: true, + install_dir: tests_dir +) + +executable( + 'mock-mixed-vulkaninfo', + 'mock-good-vulkaninfo.c', + install: true, + install_dir: tests_dir +) + +executable( + 'mock-mixed-check-vulkan', + 'mock-bad-check-vulkan.c', + install: true, + install_dir: tests_dir +) # vim:set sw=2 sts=2 et: diff --git a/tests/mock-bad-check-vulkan.c b/tests/mock-bad-check-vulkan.c new file mode 100644 index 0000000000000000000000000000000000000000..3e3fc6050282bc0680a9269f5e47c7dd6bc4283c --- /dev/null +++ b/tests/mock-bad-check-vulkan.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2019 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> + +int +main (int argc, + char **argv) +{ + // Give bad output + fprintf (stderr, "failed to create window surface!\n"); + return 1; +} +