From e982bbd129543ce6bfce1e5e50416ecee27aedd0 Mon Sep 17 00:00:00 2001
From: Ludovico de Nittis <ludovico.denittis@collabora.com>
Date: Thu, 16 Apr 2020 11:21:15 +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                       |  22 +++++
 bin/system-info.md                      |  14 +++
 helpers/check-vdpau.c                   |  29 ++++--
 steam-runtime-tools/graphics-internal.h |   6 ++
 steam-runtime-tools/graphics.c          | 114 ++++++++++++++++++++++++
 steam-runtime-tools/system-info.c       |  91 ++++++++++++++++++-
 steam-runtime-tools/system-info.h       |   4 +
 tests/graphics.c                        |  35 +++++++-
 tests/meson.build                       |   2 +
 tests/mock-bad-check-vdpau.c            |  37 ++++++++
 tests/mock-good-check-vdpau.c           |  36 ++++++++
 tests/system-info-cli.c                 |   4 +
 12 files changed, 386 insertions(+), 8 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..fe89cbe38 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -1060,6 +1060,28 @@ main (int argc,
                                                 SRT_DRIVER_FLAGS_INCLUDE_ALL);
       print_glx_details (builder, glx_list);
 
+      json_builder_set_member_name (builder, "graphics-verification");
+      json_builder_begin_object (builder);
+        {
+          gboolean can_run_vdpau;
+          gchar *vdpau_additional_info = NULL;
+
+          can_run_vdpau = srt_system_info_can_run_vdpau (info, multiarch_tuples[i]);
+          vdpau_additional_info = srt_system_info_dup_vdpau_additional_info (info, multiarch_tuples[i]);
+          json_builder_set_member_name (builder, "vdpau");
+          json_builder_begin_object (builder);
+          json_builder_set_member_name (builder, "can-run");
+          json_builder_add_boolean_value (builder, can_run_vdpau);
+          if (vdpau_additional_info != NULL)
+            {
+              json_builder_set_member_name (builder, "additional-info");
+              json_builder_add_string_value (builder, vdpau_additional_info);
+            }
+          json_builder_end_object (builder);
+          g_free (vdpau_additional_info);
+        }
+      json_builder_end_object (builder);
+
       json_builder_end_object (builder); // End multiarch_tuple object
       g_list_free_full (libraries, g_object_unref);
       g_list_free_full (graphics_list, g_object_unref);
diff --git a/bin/system-info.md b/bin/system-info.md
index 12a745421..58ddd5d5d 100644
--- a/bin/system-info.md
+++ b/bin/system-info.md
@@ -516,6 +516,20 @@ keys:
         **library_path**
         :   Absolute path to the library that imlements the **library_soname**.
 
+    **graphics-verification**
+    :   An object describing the ability to use a specific graphics module.
+        At the moment the only available key is **vdpau**.
+        The values are objects with the following keys:
+
+        **can-run**
+        :   A boolean value indicating whether we are able to successfully use
+            this graphics module.
+
+        **additional-info**
+        :   Any additional information that we were able to gather about this
+            graphics module. For example it can contain information about the
+            driver in use or any eventual error message.
+
 **locale-issues**
 :   An array of strings indicating locale-related issues.
     The array is empty if no problems were detected.
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-internal.h b/steam-runtime-tools/graphics-internal.h
index 6b31220ca..81f8a8cbc 100644
--- a/steam-runtime-tools/graphics-internal.h
+++ b/steam-runtime-tools/graphics-internal.h
@@ -174,3 +174,9 @@ GList *_srt_list_graphics_modules (const gchar *sysroot,
                                    const char *helpers_path,
                                    const char *multiarch_tuple,
                                    SrtGraphicsModule which);
+
+G_GNUC_INTERNAL
+gboolean _srt_graphics_can_run (const char *helpers_path,
+                                const char *multiarch_tuple,
+                                SrtGraphicsModule which,
+                                gchar **info_out);
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index ab90bbec2..310106ee7 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -3523,6 +3523,120 @@ _srt_list_graphics_modules (const char *sysroot,
   return g_list_reverse (drivers);
 }
 
+/**
+ * _srt_graphics_can_run:
+ * @helpers_path: (nullable): An optional path to find the graphics check helpers,
+ *  PATH is used if %NULL
+ * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple
+ *  such as %SRT_ABI_X86_64
+ * @which: Graphics modules to look for
+ * @info_out: (out) (type utf8) (transfer full) (optional): Used to return
+ *  additional information gathered from the graphics helper.
+ *
+ * After running the @which graphics helper, its stdout and stderr will be combined
+ * and stored in @info_out (if provided). So it usually contains additional
+ * information like the graphics driver in use or any eventual error message.
+ *
+ * Returns: %TRUE if we are able to use the @which graphics module.
+ */
+gboolean
+_srt_graphics_can_run (const char *helpers_path,
+                       const char *multiarch_tuple,
+                       SrtGraphicsModule which,
+                       gchar **info_out)
+{
+  GPtrArray *argv;
+  int exit_status = -1;
+  gboolean can_run = FALSE;
+  GStrv my_environ = NULL;
+  gchar *filtered_preload = NULL;
+  gchar *output = NULL;
+  gchar *child_stderr = NULL;
+  const gchar *helper = NULL;
+  const gchar *ld_preload;
+  GError *error = NULL;
+
+  g_return_val_if_fail (multiarch_tuple != NULL, FALSE);
+  g_return_val_if_fail (info_out == NULL || *info_out == NULL, FALSE);
+
+  switch (which)
+    {
+      case SRT_GRAPHICS_VDPAU_MODULE:
+        helper = "check-vdpau";
+        break;
+
+      case SRT_GRAPHICS_VAAPI_MODULE:
+      case SRT_GRAPHICS_DRI_MODULE:
+      case SRT_GRAPHICS_GLX_MODULE:
+      case NUM_SRT_GRAPHICS_MODULES:
+      default:
+        g_return_val_if_reached (FALSE);
+    }
+
+  argv = _srt_get_helper (helpers_path, multiarch_tuple, helper,
+                          SRT_HELPER_FLAGS_NONE, &error);
+
+  if (argv == NULL)
+    {
+      /* Put the error message in the additional info */
+      if (info_out != NULL)
+        *info_out = g_strdup (error->message);
+      goto out;
+    }
+
+  g_ptr_array_add (argv, g_strdup ("--verbose"));
+  g_ptr_array_add (argv, NULL);
+
+  my_environ = g_get_environ ();
+  ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD");
+  if (ld_preload != NULL)
+    {
+      filtered_preload = _srt_filter_gameoverlayrenderer (ld_preload);
+      my_environ = g_environ_setenv (my_environ, "LD_PRELOAD", filtered_preload, TRUE);
+    }
+
+  if (!g_spawn_sync (NULL,    /* working directory */
+                     (gchar **) argv->pdata,
+                     my_environ,    /* envp */
+                     G_SPAWN_SEARCH_PATH,       /* flags */
+                     _srt_child_setup_unblock_signals,
+                     NULL,    /* user data */
+                     &output, /* stdout */
+                     &child_stderr,
+                     &exit_status,
+                     &error))
+    {
+      g_debug ("An error occurred calling the helper: %s", error->message);
+      if (info_out != NULL)
+        *info_out = g_strdup (error->message);
+      goto out;
+    }
+
+  if (exit_status != 0)
+    g_debug ("... wait status %d", exit_status);
+  else
+    can_run = TRUE;
+
+  if (info_out != NULL)
+    {
+      if (output == NULL)
+        *info_out = g_strdup (child_stderr);
+      else if (child_stderr == NULL)
+        *info_out = g_strdup (output);
+      else
+        *info_out = g_strconcat (output, child_stderr, NULL);
+    }
+
+out:
+  g_clear_pointer (&argv, g_ptr_array_unref);
+  g_free (filtered_preload);
+  g_free (output);
+  g_free (child_stderr);
+  g_strfreev (my_environ);
+  g_clear_error (&error);
+  return can_run;
+}
+
 /**
  * SrtVaApiDriver:
  *
diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index 19c5208e7..bca0deb6c 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -228,6 +228,8 @@ typedef struct
 {
   GList *modules;
   gboolean available;
+  Tristate can_run;
+  gchar *additional_info;
 } ModuleList;
 
 typedef struct
@@ -276,6 +278,8 @@ ensure_abi (SrtSystemInfo *self,
     {
       abi->graphics_modules[i].modules = NULL;
       abi->graphics_modules[i].available = FALSE;
+      abi->graphics_modules[i].can_run = TRI_MAYBE;
+      abi->graphics_modules[i].additional_info = NULL;
     }
 
   /* transfer ownership to self->abis */
@@ -296,7 +300,10 @@ abi_free (gpointer self)
     g_hash_table_unref (abi->cached_graphics_results);
 
   for (i = 0; i < G_N_ELEMENTS (abi->graphics_modules); i++)
-    g_list_free_full (abi->graphics_modules[i].modules, g_object_unref);
+    {
+      g_list_free_full (abi->graphics_modules[i].modules, g_object_unref);
+      g_free (abi->graphics_modules[i].additional_info);
+    }
 
   g_slice_free (Abi, self);
 }
@@ -3087,3 +3094,85 @@ srt_system_info_get_x86_features (SrtSystemInfo *self)
 
   return self->cpu_features.x86_features;
 }
+
+static void
+ensure_can_run_graphics_cached (SrtSystemInfo *self,
+                                Abi *abi,
+                                SrtGraphicsModule which)
+{
+  g_return_if_fail (SRT_IS_SYSTEM_INFO (self));
+  g_return_if_fail (abi != NULL);
+  /* We can do this check only for VDPAU */
+  g_return_if_fail (which == SRT_GRAPHICS_VDPAU_MODULE);
+
+  if (abi->graphics_modules[which].can_run != TRI_MAYBE)
+    return;
+
+  g_assert (abi->graphics_modules[which].additional_info == NULL);
+
+  if (_srt_graphics_can_run (self->helpers_path,
+                             g_quark_to_string (abi->multiarch_tuple),
+                             which,
+                             &(abi->graphics_modules[which].additional_info)))
+    {
+      abi->graphics_modules[which].can_run = TRI_YES;
+    }
+  else
+    {
+      abi->graphics_modules[which].can_run = TRI_NO;
+    }
+}
+
+/**
+ * srt_system_info_can_run_vdpau:
+ * @self: A #SrtSystemInfo object
+ * @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI.
+ *
+ * Check whether VDPAU for the given ABI can be run successfully.
+ *
+ * Returns: %TRUE if we are able to use VDPAU for the provided @multiarch_tuple
+ */
+gboolean
+srt_system_info_can_run_vdpau (SrtSystemInfo *self,
+                               const char *multiarch_tuple)
+{
+  Abi *abi = NULL;
+
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), FALSE);
+  g_return_val_if_fail (multiarch_tuple != NULL, FALSE);
+
+  abi = ensure_abi (self, multiarch_tuple);
+
+  ensure_can_run_graphics_cached (self, abi, SRT_GRAPHICS_VDPAU_MODULE);
+
+  return (abi->graphics_modules[SRT_GRAPHICS_VDPAU_MODULE].can_run == TRI_YES);
+}
+
+/**
+ * srt_system_info_dup_vdpau_additional_info:
+ * @self: A #SrtSystemInfo object
+ * @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI.
+ *
+ * Return addtional information gathered from the VDPAU graphics helper.
+ * Usually the returned string will contain either information about the graphics
+ * driver in use or any eventual error message encountered running the helper.
+ *
+ * Returns: (type utf8) (transfer full) (nullable): Any additional information
+ *  gathered from the graphics helper for the provided @multiarch_tuple, or %NULL
+ *  if no information is available.
+ */
+gchar *
+srt_system_info_dup_vdpau_additional_info (SrtSystemInfo *self,
+                                           const char *multiarch_tuple)
+{
+  Abi *abi = NULL;
+
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), FALSE);
+  g_return_val_if_fail (multiarch_tuple != NULL, FALSE);
+
+  abi = ensure_abi (self, multiarch_tuple);
+
+  ensure_can_run_graphics_cached (self, abi, SRT_GRAPHICS_VDPAU_MODULE);
+
+  return g_strdup (abi->graphics_modules[SRT_GRAPHICS_VDPAU_MODULE].additional_info);
+}
diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h
index 08ecca115..ccf1ca541 100644
--- a/steam-runtime-tools/system-info.h
+++ b/steam-runtime-tools/system-info.h
@@ -200,6 +200,10 @@ GList *srt_system_info_list_desktop_entries (SrtSystemInfo *self);
 
 SrtX86FeatureFlags srt_system_info_get_x86_features (SrtSystemInfo *self);
 
+gboolean srt_system_info_can_run_vdpau (SrtSystemInfo *self,
+                                        const char *multiarch_tuple);
+gchar *srt_system_info_dup_vdpau_additional_info (SrtSystemInfo *self,
+                                                  const char *multiarch_tuple);
 #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtSystemInfo, g_object_unref)
 #endif
diff --git a/tests/graphics.c b/tests/graphics.c
index 4087d294e..c97543fe1 100644
--- a/tests/graphics.c
+++ b/tests/graphics.c
@@ -2493,6 +2493,37 @@ test_vdpau (Fixture *f,
     }
 }
 
+static void
+test_vdpau_can_run (Fixture *f,
+                    gconstpointer context)
+{
+  gboolean can_run;
+  gchar *additional_info;
+
+  SrtSystemInfo *info = srt_system_info_new (NULL);
+  srt_system_info_set_helpers_path (info, f->builddir);
+
+  can_run = srt_system_info_can_run_vdpau (info, "mock-good");
+  g_assert_true (can_run);
+
+  additional_info = srt_system_info_dup_vdpau_additional_info (info, "mock-good");
+  g_assert_cmpstr (additional_info, ==, "G3DVL VDPAU Driver Shared Library version 1.0\n");
+  g_free (additional_info);
+
+  const gchar *error_message =
+    "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";
+
+  can_run = srt_system_info_can_run_vdpau (info, "mock-bad");
+  g_assert_false (can_run);
+
+  additional_info = srt_system_info_dup_vdpau_additional_info (info, "mock-bad");
+  g_assert_cmpstr (additional_info, ==, error_message);
+  g_free (additional_info);
+
+  g_object_unref (info);
+}
+
 static gint
 glx_icd_compare (SrtGlxIcd *a, SrtGlxIcd *b)
 {
@@ -2670,8 +2701,10 @@ 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/can-run", Fixture, NULL,
+              setup, test_vdpau_can_run, 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;
+}
+
diff --git a/tests/system-info-cli.c b/tests/system-info-cli.c
index 974474784..64b833ead 100644
--- a/tests/system-info-cli.c
+++ b/tests/system-info-cli.c
@@ -156,6 +156,7 @@ libraries_presence (Fixture *f,
       g_assert_true (json_object_has_member (json_arch, "va-api_drivers"));
       g_assert_true (json_object_has_member (json_arch, "vdpau_drivers"));
       g_assert_true (json_object_has_member (json_arch, "glx_drivers"));
+      g_assert_true (json_object_has_member (json_arch, "graphics-verification"));
     }
 
   g_object_unref (parser);
@@ -280,6 +281,7 @@ libraries_missing (Fixture *f,
       g_assert_true (json_object_has_member (json_arch, "va-api_drivers"));
       g_assert_true (json_object_has_member (json_arch, "vdpau_drivers"));
       g_assert_true (json_object_has_member (json_arch, "glx_drivers"));
+      g_assert_true (json_object_has_member (json_arch, "graphics-verification"));
 
       check_libraries_missing (json_arch);
     }
@@ -401,6 +403,7 @@ libraries_presence_verbose (Fixture *f,
       g_assert_true (json_object_has_member (json_arch, "va-api_drivers"));
       g_assert_true (json_object_has_member (json_arch, "vdpau_drivers"));
       g_assert_true (json_object_has_member (json_arch, "glx_drivers"));
+      g_assert_true (json_object_has_member (json_arch, "graphics-verification"));
 
       check_libraries_verbose (json_arch);
     }
@@ -472,6 +475,7 @@ no_arguments (Fixture *f,
       g_assert_true (json_object_has_member (json_arch, "va-api_drivers"));
       g_assert_true (json_object_has_member (json_arch, "vdpau_drivers"));
       g_assert_true (json_object_has_member (json_arch, "glx_drivers"));
+      g_assert_true (json_object_has_member (json_arch, "graphics-verification"));
     }
 
   g_object_unref (parser);
-- 
GitLab