From d228854f1d8decf03344256c6fb4d16d5276621c Mon Sep 17 00:00:00 2001
From: Ludovico de Nittis <ludovico.denittis@collabora.com>
Date: Fri, 17 Apr 2020 17:24:42 +0200
Subject: [PATCH] Add automated graphics verification for VDPAU

We use the automated VDPAU check to add an entry in the
steam-runtime-system-info report.
Also `check-vdpau` has a new option `--verbose` that prints additional
info about the driver in use.

Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com>
---
 bin/system-info.c                           |   6 +-
 bin/system-info.md                          |   3 +
 helpers/check-vdpau.c                       |  29 +++--
 steam-runtime-tools/graphics-test-defines.h |   4 +-
 steam-runtime-tools/graphics.c              |  54 ++++++++--
 steam-runtime-tools/graphics.h              |   4 +-
 steam-runtime-tools/system-info.c           |   9 +-
 tests/graphics.c                            | 112 +++++++++++++++++++-
 tests/meson.build                           |   2 +
 tests/mock-bad-check-vdpau.c                |  37 +++++++
 tests/mock-good-check-vdpau.c               |  36 +++++++
 11 files changed, 279 insertions(+), 17 deletions(-)
 create mode 100644 tests/mock-bad-check-vdpau.c
 create mode 100644 tests/mock-good-check-vdpau.c

diff --git a/bin/system-info.c b/bin/system-info.c
index 7bd36df9b..e198914d2 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -449,6 +449,7 @@ print_graphics_details(JsonBuilder *builder,
       gchar *parameters = srt_graphics_dup_parameters_string (g->data);
       const char *messages;
       SrtGraphicsLibraryVendor library_vendor;
+      SrtRenderingInterface rendering_interface;
 
       json_builder_set_member_name (builder, parameters);
       json_builder_begin_object (builder);
@@ -465,7 +466,10 @@ print_graphics_details(JsonBuilder *builder,
       json_builder_add_string_value (builder, srt_graphics_get_renderer_string (g->data));
       json_builder_set_member_name (builder, "version");
       json_builder_add_string_value (builder, srt_graphics_get_version_string (g->data));
-      if (srt_graphics_get_rendering_interface (g->data) != SRT_RENDERING_INTERFACE_VULKAN)
+
+      rendering_interface = srt_graphics_get_rendering_interface (g->data);
+      if (rendering_interface != SRT_RENDERING_INTERFACE_VULKAN &&
+          rendering_interface != SRT_RENDERING_INTERFACE_VDPAU)
         {
           json_builder_set_member_name (builder, "library-vendor");
           srt_graphics_library_is_vendor_neutral (g->data, &library_vendor);
diff --git a/bin/system-info.md b/bin/system-info.md
index 12a745421..a9d8a2593 100644
--- a/bin/system-info.md
+++ b/bin/system-info.md
@@ -411,6 +411,9 @@ keys:
         **vulkan**
         :   Vulkan
 
+        **vdpau**
+        :   VDPAU
+
         The values are objects with the following string keys:
 
         **renderer**
diff --git a/helpers/check-vdpau.c b/helpers/check-vdpau.c
index 9480f9433..8f9519a1b 100644
--- a/helpers/check-vdpau.c
+++ b/helpers/check-vdpau.c
@@ -27,6 +27,7 @@
  */
 
 #include <assert.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <getopt.h>
 #include <stdio.h>
@@ -37,6 +38,7 @@
 #include <vdpau/vdpau.h>
 #include <vdpau/vdpau_x11.h>
 
+static VdpGetInformationString *vdp_get_information_string;
 static VdpGetProcAddress *vdp_get_proc_address;
 static VdpDeviceDestroy *vdp_device_destroy;
 static VdpGetErrorString *vdp_get_error_string;
@@ -48,12 +50,14 @@ static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_sur
 enum
 {
   OPTION_HELP = 1,
+  OPTION_VERBOSE,
   OPTION_VERSION,
 };
 
 struct option long_options[] =
 {
   { "help", no_argument, NULL, OPTION_HELP },
+  { "verbose", no_argument, NULL, OPTION_VERBOSE },
   { "version", no_argument, NULL, OPTION_VERSION },
   { NULL, 0, NULL, 0 }
 };
@@ -103,12 +107,13 @@ load_vdpau (VdpDevice dev)
 {
 #define GET_POINTER(fid, fn) do_vdpau_or_exit (vdp_get_proc_address (dev, fid, (void**)&fn))
 
-   GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY,                       vdp_device_destroy);
-   GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING,                     vdp_get_error_string);
-   GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,                vdp_output_surface_create);
-   GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,       vdp_output_surface_get_bits_native);
-   GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE,       vdp_output_surface_put_bits_native);
-   GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface);
+  GET_POINTER(VDP_FUNC_ID_GET_INFORMATION_STRING,               vdp_get_information_string);
+  GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY,                       vdp_device_destroy);
+  GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING,                     vdp_get_error_string);
+  GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,                vdp_output_surface_create);
+  GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,       vdp_output_surface_get_bits_native);
+  GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE,       vdp_output_surface_put_bits_native);
+  GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface);
 }
 
 int
@@ -119,8 +124,10 @@ main (int argc,
   VdpDevice device;
   VdpOutputSurface out_surface_1;
   VdpOutputSurface out_surface_2;
+  bool verbose = false;
   int screen;
   int opt;
+  const char* information = NULL;
 
   /* Arbitrarily declare two 4x4 source images */
   uint32_t black_box[] =
@@ -151,6 +158,10 @@ main (int argc,
             usage (0);
             break;
 
+          case OPTION_VERBOSE:
+            verbose = true;
+            break;
+
           case OPTION_VERSION:
             /* Output version number as YAML for machine-readability,
              * inspired by `ostree --version` and `docker version` */
@@ -180,6 +191,12 @@ main (int argc,
 
   load_vdpau (device);
 
+  if (verbose)
+    {
+      do_vdpau_or_exit (vdp_get_information_string (&information));
+      printf ("%s\n", information);
+    }
+
   do_vdpau_or_exit (vdp_output_surface_create (device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_1));
   do_vdpau_or_exit (vdp_output_surface_create (device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_2));
 
diff --git a/steam-runtime-tools/graphics-test-defines.h b/steam-runtime-tools/graphics-test-defines.h
index 83832ad50..e0cbaf6fb 100644
--- a/steam-runtime-tools/graphics-test-defines.h
+++ b/steam-runtime-tools/graphics-test-defines.h
@@ -33,4 +33,6 @@
 #define SRT_TEST_SOFTWARE_GRAPHICS_VERSION "3.1 Mesa 19.1.3"
 #define SRT_TEST_GOOD_VULKAN_DRIVER_VERSION "79695877"
 #define SRT_TEST_GOOD_VULKAN_VERSION "1.1.102 (device 8086:0412) (driver 19.1.5)"
-
+#define SRT_TEST_GOOD_VDPAU_RENDERER "G3DVL VDPAU Driver Shared Library version 1.0\n"
+#define SRT_TEST_BAD_VDPAU_MESSAGES "Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n\
+vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n"
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index 256d70988..acd24513a 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -504,6 +504,7 @@ _argv_for_graphics_test (const char *helpers_path,
 
           case SRT_RENDERING_INTERFACE_GLESV2:
           case SRT_RENDERING_INTERFACE_VULKAN:
+          case SRT_RENDERING_INTERFACE_VDPAU:
           default:
             g_critical ("GLX window system only makes sense with GL "
                         "rendering interface, not %d",
@@ -527,6 +528,7 @@ _argv_for_graphics_test (const char *helpers_path,
             break;
 
           case SRT_RENDERING_INTERFACE_VULKAN:
+          case SRT_RENDERING_INTERFACE_VDPAU:
             /* They don't set platformstring, just set argv later. */
             break;
 
@@ -544,6 +546,7 @@ _argv_for_graphics_test (const char *helpers_path,
             break;
 
           case SRT_RENDERING_INTERFACE_VULKAN:
+          case SRT_RENDERING_INTERFACE_VDPAU:
           default:
             g_critical ("EGL window system only makes sense with a GL-based "
                         "rendering interface, not %d",
@@ -589,6 +592,16 @@ _argv_for_graphics_test (const char *helpers_path,
         g_ptr_array_add (argv, g_strdup ("-j"));
         break;
 
+      case SRT_RENDERING_INTERFACE_VDPAU:
+        argv = _srt_get_helper (helpers_path, multiarch_tuple, "check-vdpau",
+                                flags, error);
+
+        if (argv == NULL)
+          goto out;
+
+        g_ptr_array_add (argv, g_strdup ("--verbose"));
+        break;
+
       default:
         g_return_val_if_reached (NULL);
         break;
@@ -782,9 +795,10 @@ _srt_check_library_vendor (const char *multiarch_tuple,
   SrtLibraryIssues issues;
   const char * const *dependencies;
 
-  /* Vulkan is always vendor-neutral, so it doesn't make sense to check it. We simply return
-   * SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN */
-  if (rendering_interface == SRT_RENDERING_INTERFACE_VULKAN)
+  /* Vulkan and VDPAU are always vendor-neutral, so it doesn't make sense to check it.
+   * We simply return SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN */
+  if (rendering_interface == SRT_RENDERING_INTERFACE_VULKAN ||
+      rendering_interface == SRT_RENDERING_INTERFACE_VDPAU)
     goto out;
 
   switch (window_system)
@@ -954,6 +968,7 @@ _srt_check_graphics (const char *helpers_path,
   const gchar *renderer_string = NULL;
   GError *error = NULL;
   SrtGraphicsIssues issues = SRT_GRAPHICS_ISSUES_NONE;
+  SrtGraphicsIssues non_zero_wait_status_issue = SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
   GStrv my_environ = NULL;
   const gchar *ld_preload;
   gchar *filtered_preload = NULL;
@@ -989,6 +1004,23 @@ _srt_check_graphics (const char *helpers_path,
 
   library_vendor = _srt_check_library_vendor (multiarch_tuple, window_system, rendering_interface);
 
+  switch (rendering_interface)
+    {
+      case SRT_RENDERING_INTERFACE_GL:
+      case SRT_RENDERING_INTERFACE_GLESV2:
+      case SRT_RENDERING_INTERFACE_VULKAN:
+        non_zero_wait_status_issue = SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
+        break;
+
+      case SRT_RENDERING_INTERFACE_VDPAU:
+        /* The test here tries to draw an offscreen X11 window */
+        non_zero_wait_status_issue = SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
+        break;
+
+      default:
+        g_return_val_if_reached (SRT_GRAPHICS_ISSUES_INTERNAL_ERROR);
+    }
+
   issues |= _srt_run_helper (&my_environ,
                              &output,
                              &child_stderr,
@@ -997,7 +1029,7 @@ _srt_check_graphics (const char *helpers_path,
                              &exit_status,
                              &terminating_signal,
                              FALSE,
-                             SRT_GRAPHICS_ISSUES_CANNOT_LOAD);
+                             non_zero_wait_status_issue);
 
   if (issues != SRT_GRAPHICS_ISSUES_NONE)
     {
@@ -1010,7 +1042,7 @@ _srt_check_graphics (const char *helpers_path,
                                  &exit_status,
                                  &terminating_signal,
                                  TRUE,
-                                 SRT_GRAPHICS_ISSUES_CANNOT_LOAD);
+                                 non_zero_wait_status_issue);
 
       goto out;
     }
@@ -1044,6 +1076,10 @@ _srt_check_graphics (const char *helpers_path,
           }
         break;
 
+      case SRT_RENDERING_INTERFACE_VDPAU:
+        /* The output is in plan text, nothing to do here */
+        break;
+
       default:
         g_return_val_if_reached (SRT_GRAPHICS_ISSUES_INTERNAL_ERROR);
     }
@@ -1151,6 +1187,11 @@ _srt_check_graphics (const char *helpers_path,
                                    SRT_GRAPHICS_ISSUES_CANNOT_DRAW);
         break;
 
+      case SRT_RENDERING_INTERFACE_VDPAU:
+        if (output != NULL)
+          renderer_string = output;
+        break;
+
       default:
         g_return_val_if_reached (SRT_GRAPHICS_ISSUES_INTERNAL_ERROR);
     }
@@ -1217,7 +1258,7 @@ srt_graphics_get_issues (SrtGraphics *self)
  *  or vendor-specific, and if vendor-specific, attempt to guess the vendor
  *
  * Return whether the entry-point library for this graphics stack is vendor-neutral or vendor-specific.
- * Vulkan is always vendor-neutral, so this function will always return %TRUE for it.
+ * Vulkan and VDPAU are always vendor-neutral, so this function will always return %TRUE for them.
  *
  * Returns: %TRUE if the graphics library is vendor-neutral, %FALSE otherwise.
  */
@@ -1231,6 +1272,7 @@ srt_graphics_library_is_vendor_neutral (SrtGraphics *self,
     *vendor_out = self->library_vendor;
 
   return (self->rendering_interface == SRT_RENDERING_INTERFACE_VULKAN ||
+          self->rendering_interface == SRT_RENDERING_INTERFACE_VDPAU ||
           self->library_vendor == SRT_GRAPHICS_LIBRARY_VENDOR_GLVND);
 }
 
diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h
index 3f30c60eb..e74c20786 100644
--- a/steam-runtime-tools/graphics.h
+++ b/steam-runtime-tools/graphics.h
@@ -109,16 +109,18 @@ typedef enum
  * @SRT_RENDERING_INTERFACE_GL: GL rendering interface
  * @SRT_RENDERING_INTERFACE_GLESV2: GLESv2 rendering interfaces
  * @SRT_RENDERING_INTERFACE_VULKAN: Vulkan rendering interface
+ * @SRT_RENDERING_INTERFACE_VDPAU: VDPAU rendering interface
  */
 typedef enum
 {
   SRT_RENDERING_INTERFACE_GL,
   SRT_RENDERING_INTERFACE_GLESV2,
   SRT_RENDERING_INTERFACE_VULKAN,
+  SRT_RENDERING_INTERFACE_VDPAU,
   /* ... possible future additions: GLESV1, GLESV3? */
 } SrtRenderingInterface;
 
-#define SRT_N_RENDERING_INTERFACES (SRT_RENDERING_INTERFACE_VULKAN + 1)
+#define SRT_N_RENDERING_INTERFACES (SRT_RENDERING_INTERFACE_VDPAU + 1)
 
 const char *srt_graphics_get_multiarch_tuple (SrtGraphics *self);
 SrtGraphicsIssues srt_graphics_get_issues (SrtGraphics *self);
diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index 19c5208e7..93b4c7f01 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -1538,7 +1538,7 @@ GList * srt_system_info_check_all_graphics (SrtSystemInfo *self,
       return list;
     }
 
-  // Try each of glx and gles
+  // Try each rendering interface
   // Try each window system
 
   abi->cached_combined_issues |=
@@ -1569,6 +1569,13 @@ GList * srt_system_info_check_all_graphics (SrtSystemInfo *self,
                                     SRT_RENDERING_INTERFACE_VULKAN,
                                     NULL);
 
+  abi->cached_combined_issues |=
+    srt_system_info_check_graphics (self,
+                                    multiarch_tuple,
+                                    SRT_WINDOW_SYSTEM_X11,
+                                    SRT_RENDERING_INTERFACE_VDPAU,
+                                    NULL);
+
   abi->graphics_cache_available = TRUE;
 
   list = g_list_sort (g_hash_table_get_values (abi->cached_graphics_results),
diff --git a/tests/graphics.c b/tests/graphics.c
index 4087d294e..544642855 100644
--- a/tests/graphics.c
+++ b/tests/graphics.c
@@ -2493,6 +2493,112 @@ test_vdpau (Fixture *f,
     }
 }
 
+static void
+test_good_vdpau (Fixture *f,
+                 gconstpointer context)
+{
+  SrtGraphics *graphics = NULL;
+  SrtGraphicsIssues issues;
+  gchar *tuple;
+  gchar *renderer;
+  gchar *version;
+  gchar *messages;
+  int exit_status;
+  int terminating_signal;
+
+  SrtSystemInfo *info = srt_system_info_new (NULL);
+  srt_system_info_set_helpers_path (info, f->builddir);
+
+  issues = srt_system_info_check_graphics (info,
+                                           "mock-good",
+                                           SRT_WINDOW_SYSTEM_X11,
+                                           SRT_RENDERING_INTERFACE_VDPAU,
+                                           &graphics);
+  g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_NONE);
+  g_assert_cmpstr (srt_graphics_get_renderer_string (graphics), ==, SRT_TEST_GOOD_VDPAU_RENDERER);
+  g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, NULL);
+  g_assert_cmpstr (srt_graphics_get_messages (graphics), ==, NULL);
+  g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 0);
+  g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0);
+
+  g_object_get (graphics,
+                "multiarch-tuple", &tuple,
+                "issues", &issues,
+                "renderer-string", &renderer,
+                "version-string", &version,
+                "messages", &messages,
+                "exit-status", &exit_status,
+                "terminating-signal", &terminating_signal,
+                NULL);
+  g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_NONE);
+  g_assert_cmpstr (tuple, ==, "mock-good");
+  g_assert_cmpstr (renderer, ==, SRT_TEST_GOOD_VDPAU_RENDERER);
+  g_assert_cmpstr (version, ==, NULL);
+  g_assert_cmpstr (messages, ==, NULL);
+  g_assert_cmpint (exit_status, ==, 0);
+  g_assert_cmpint (terminating_signal, ==, 0);
+  g_free (tuple);
+  g_free (renderer);
+  g_free (version);
+  g_free (messages);
+
+  g_object_unref (graphics);
+  g_object_unref (info);
+}
+
+static void
+test_bad_vdpau (Fixture *f,
+                gconstpointer context)
+{
+  SrtGraphics *graphics = NULL;
+  SrtGraphicsIssues issues;
+  gchar *tuple;
+  gchar *renderer;
+  gchar *version;
+  gchar *messages;
+  int exit_status;
+  int terminating_signal;
+
+  SrtSystemInfo *info = srt_system_info_new (NULL);
+  srt_system_info_set_helpers_path (info, f->builddir);
+
+  issues = srt_system_info_check_graphics (info,
+                                           "mock-bad",
+                                           SRT_WINDOW_SYSTEM_X11,
+                                           SRT_RENDERING_INTERFACE_VDPAU,
+                                           &graphics);
+  g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_DRAW);
+  g_assert_cmpstr (srt_graphics_get_renderer_string (graphics), ==, NULL);
+  g_assert_cmpstr (srt_graphics_get_version_string (graphics), ==, NULL);
+  g_assert_cmpstr (srt_graphics_get_messages (graphics), ==, SRT_TEST_BAD_VDPAU_MESSAGES);
+  g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, 1);
+  g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0);
+
+  g_object_get (graphics,
+                "multiarch-tuple", &tuple,
+                "issues", &issues,
+                "renderer-string", &renderer,
+                "version-string", &version,
+                "messages", &messages,
+                "exit-status", &exit_status,
+                "terminating-signal", &terminating_signal,
+                NULL);
+  g_assert_cmpint (issues, ==, SRT_GRAPHICS_ISSUES_CANNOT_DRAW);
+  g_assert_cmpstr (tuple, ==, "mock-bad");
+  g_assert_cmpstr (renderer, ==, NULL);
+  g_assert_cmpstr (version, ==, NULL);
+  g_assert_cmpstr (messages, ==, SRT_TEST_BAD_VDPAU_MESSAGES);
+  g_assert_cmpint (exit_status, ==, 1);
+  g_assert_cmpint (terminating_signal, ==, 0);
+  g_free (tuple);
+  g_free (renderer);
+  g_free (version);
+  g_free (messages);
+
+  g_object_unref (graphics);
+  g_object_unref (info);
+}
+
 static gint
 glx_icd_compare (SrtGlxIcd *a, SrtGlxIcd *b)
 {
@@ -2670,8 +2776,12 @@ main (int argc,
   g_test_add ("/graphics/dri/flatpak", Fixture, NULL,
               setup, test_dri_flatpak, teardown);
 
-  g_test_add ("/graphics/vdpau", Fixture, NULL,
+  g_test_add ("/graphics/vdpau/basic", Fixture, NULL,
               setup, test_vdpau, teardown);
+  g_test_add ("/graphics/vdpau/good", Fixture, NULL,
+              setup, test_good_vdpau, teardown);
+  g_test_add ("/graphics/vdpau/bad", Fixture, NULL,
+              setup, test_bad_vdpau, teardown);
 
   g_test_add ("/graphics/glx/debian", Fixture, NULL,
               setup, test_glx_debian, teardown);
diff --git a/tests/meson.build b/tests/meson.build
index 7e2e59a8d..260adff8f 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -179,8 +179,10 @@ executable(
 # Helpers with no dependencies and one source file of the same name
 # as the helper itself.
 foreach helper : [
+  'mock-bad-check-vdpau',
   'mock-bad-check-vulkan',
   'mock-bad-vulkaninfo',
+  'mock-good-check-vdpau',
   'mock-good-vulkaninfo',
   'mock-hanging-wflinfo',
   'mock-sigusr-wflinfo',
diff --git a/tests/mock-bad-check-vdpau.c b/tests/mock-bad-check-vdpau.c
new file mode 100644
index 000000000..d9904229b
--- /dev/null
+++ b/tests/mock-bad-check-vdpau.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2020 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 open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n");
+  fprintf (stderr, "vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n");
+  return 1;
+}
+
diff --git a/tests/mock-good-check-vdpau.c b/tests/mock-good-check-vdpau.c
new file mode 100644
index 000000000..ebc90fc5d
--- /dev/null
+++ b/tests/mock-good-check-vdpau.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2020 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 good output
+  printf ("G3DVL VDPAU Driver Shared Library version 1.0\n");
+  return 0;
+}
+
-- 
GitLab