xmlconfig: Add unit tests for recent bugs in the driconf rewrite.
authorEric Anholt <eric@anholt.net>
Wed, 7 Oct 2020 16:59:43 +0000 (09:59 -0700)
committerMarge Bot <eric+marge@anholt.net>
Fri, 4 Dec 2020 21:32:17 +0000 (21:32 +0000)
This covers:
7fb4ab9ec122 ("driconf: Restore the ability to override driconf with the environment.")
2b977adff805 ("xmlconfig: fix scandir_filter")

and touches a bit more of drirc logic while I'm here.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7048>

src/util/meson.build
src/util/tests/drirc_configdir/00-test.conf [new file with mode: 0644]
src/util/tests/drirc_configdir/01-unused [new file with mode: 0644]
src/util/tests/drirc_home/.drirc [new file with mode: 0644]
src/util/tests/xmlconfig.cpp
src/util/xmlconfig.c
src/util/xmlconfig.h

index f9f9fee..705de9c 100644 (file)
@@ -243,6 +243,10 @@ if with_tests
         cpp_args: ['-Wno-write-strings']
       ),
       suite : ['util'],
+      env: ['HOME=' + join_paths(meson.current_source_dir(),
+                                 'tests', 'drirc_home'),
+            'DRIRC_CONFIGDIR=' + join_paths(meson.current_source_dir(),
+                                            'tests', 'drirc_configdir')]
         )
   endif
 
diff --git a/src/util/tests/drirc_configdir/00-test.conf b/src/util/tests/drirc_configdir/00-test.conf
new file mode 100644 (file)
index 0000000..fcc7208
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE driconf [
+   <!ELEMENT driconf      (device+)>
+   <!ELEMENT device       (application | engine)+>
+   <!ATTLIST device       driver CDATA #IMPLIED>
+   <!ELEMENT application  (option+)>
+   <!ATTLIST application  name CDATA #REQUIRED
+                          executable CDATA #IMPLIED
+                          sha1 CDATA #IMPLIED
+                          application_name_match CDATA #IMPLIED
+                          application_versions CDATA #IMPLIED>
+   <!ELEMENT engine       (option+)>
+
+   <!-- engine_name_match: A regexp matching the engine name -->
+   <!-- engine_versions: A version in range format
+             (version 1 to 4 : "1:4") -->
+
+   <!ATTLIST engine       engine_name_match CDATA #REQUIRED
+                          engine_versions CDATA #REQUIRED>
+
+   <!ELEMENT option       EMPTY>
+   <!ATTLIST option       name CDATA #REQUIRED
+                          value CDATA #REQUIRED>
+]>
+
+<driconf>
+    <device>
+        <application name="Application 1" executable="app1">
+            <option name="mesa_drirc_option" value="1" />
+        </application>
+
+        <application name="Application 2" executable="app2">
+            <option name="mesa_drirc_option" value="2" />
+        </application>
+
+        <application name="Application 2" application_name_match="Versioned App.*" application_versions="0:1">
+            <option name="mesa_drirc_option" value="3" />
+        </application>
+
+        <application name="Application 2" application_name_match="Versioned App.*" application_versions="2:3">
+            <option name="mesa_drirc_option" value="4" />
+        </application>
+
+        <engine engine_name_match="Versioned Engine.*" engine_versions="0:1">
+            <option name="mesa_drirc_option" value="5" />
+        </engine>
+        <engine engine_name_match="Versioned Engine.*" engine_versions="2:3">
+            <option name="mesa_drirc_option" value="6" />
+        </engine>
+    </device>
+</driconf>
diff --git a/src/util/tests/drirc_configdir/01-unused b/src/util/tests/drirc_configdir/01-unused
new file mode 100644 (file)
index 0000000..dfdc4eb
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE driconf [
+   <!ELEMENT driconf      (device+)>
+   <!ELEMENT device       (application | engine)+>
+   <!ATTLIST device       driver CDATA #IMPLIED>
+   <!ELEMENT application  (option+)>
+   <!ATTLIST application  name CDATA #REQUIRED
+                          executable CDATA #IMPLIED
+                          sha1 CDATA #IMPLIED
+                          application_name_match CDATA #IMPLIED
+                          application_versions CDATA #IMPLIED>
+   <!ELEMENT engine       (option+)>
+
+   <!-- engine_name_match: A regexp matching the engine name -->
+   <!-- engine_versions: A version in range format
+             (version 1 to 4 : "1:4") -->
+
+   <!ATTLIST engine       engine_name_match CDATA #REQUIRED
+                          engine_versions CDATA #REQUIRED>
+
+   <!ELEMENT option       EMPTY>
+   <!ATTLIST option       name CDATA #REQUIRED
+                          value CDATA #REQUIRED>
+]>
+
+<!-- since this file lacks its extension, it shouldn't be parsed. -->
+
+<driconf>
+    <device>
+        <application name="Application 1" executable="app1">
+            <option name="mesa_drirc_option" value="100" />
+        </application>
+    </device>
+</driconf>
diff --git a/src/util/tests/drirc_home/.drirc b/src/util/tests/drirc_home/.drirc
new file mode 100644 (file)
index 0000000..695fe0e
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE driconf [
+   <!ELEMENT driconf      (device+)>
+   <!ELEMENT device       (application | engine)+>
+   <!ATTLIST device       driver CDATA #IMPLIED>
+   <!ELEMENT application  (option+)>
+   <!ATTLIST application  name CDATA #REQUIRED
+                          executable CDATA #IMPLIED
+                          sha1 CDATA #IMPLIED
+                          application_name_match CDATA #IMPLIED
+                          application_versions CDATA #IMPLIED>
+   <!ELEMENT engine       (option+)>
+
+   <!-- engine_name_match: A regexp matching the engine name -->
+   <!-- engine_versions: A version in range format
+             (version 1 to 4 : "1:4") -->
+
+   <!ATTLIST engine       engine_name_match CDATA #REQUIRED
+                          engine_versions CDATA #REQUIRED>
+
+   <!ELEMENT option       EMPTY>
+   <!ATTLIST option       name CDATA #REQUIRED
+                          value CDATA #REQUIRED>
+]>
+
+<driconf>
+    <device>
+        <application name="Application 3" executable="app3">
+            <option name="mesa_drirc_option" value="10" />
+        </application>
+    </device>
+</driconf>
index ad9af36..42bb101 100644 (file)
@@ -30,6 +30,11 @@ protected:
    xmlconfig_test();
    ~xmlconfig_test();
 
+   driOptionCache drirc_init(const char *driver, const char *drm,
+                             const char *exec_name,
+                             const char *app, int appver,
+                             const char *engine, int enginever);
+
    driOptionCache options;
 };
 
@@ -153,3 +158,93 @@ TEST_F(xmlconfig_test, copy_cache)
 
    driDestroyOptionCache(&cache);
 }
+
+driOptionCache
+xmlconfig_test::drirc_init(const char *driver, const char *drm,
+                           const char *exec_name,
+                           const char *app, int appver,
+                           const char *engine, int enginever)
+{
+   /* Make the parser look in the directory of config files for the test,
+    * passed in by meson.build.
+    */
+   driInjectDataDir(getenv("DRIRC_CONFIGDIR"));
+
+   driInjectExecName(exec_name);
+
+   driOptionDescription driconf[] = {
+      DRI_CONF_SECTION_MISCELLANEOUS
+      DRI_CONF_OPT_I(mesa_drirc_option, 0, 0, 200, "description")
+   };
+   driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
+
+   driOptionCache cache;
+
+   /* This should parse the "user" drirc files under ./tests/drirc_test/,
+    * based on the setting of $HOME by meson.build.
+    */
+   driParseConfigFiles(&cache, &options,
+                       0, driver, drm,
+                       app, appver,
+                       engine, enginever);
+
+   return cache;
+}
+
+TEST_F(xmlconfig_test, drirc_app)
+{
+   driOptionCache cache = drirc_init("driver", "drm",
+                                     "app1",
+                                     NULL, 0,
+                                     NULL, 0);
+#if WITH_XMLCONFIG
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 1);
+#else
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 0);
+#endif
+}
+
+TEST_F(xmlconfig_test, drirc_user_app)
+{
+   driOptionCache cache = drirc_init("driver", "drm",
+                                     "app3",
+                                     NULL, 0,
+                                     NULL, 0);
+#if WITH_XMLCONFIG
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 10);
+#else
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 0);
+#endif
+}
+
+TEST_F(xmlconfig_test, drirc_env_override)
+{
+   setenv("mesa_drirc_option", "7", 1);
+   driOptionCache cache = drirc_init("driver", "drm",
+                                     "app1",
+                                     NULL, 0,
+                                     NULL, 0);
+   /* env var takes precedence over config files */
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 7);
+   unsetenv("mesa_drirc_option");
+}
+
+#if WITH_XMLCONFIG
+TEST_F(xmlconfig_test, drirc_app_versioned)
+{
+   driOptionCache cache = drirc_init("driver", "drm",
+                                     NULL,
+                                     "Versioned App Name", 1,
+                                     NULL, 0);
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 3);
+}
+
+TEST_F(xmlconfig_test, drirc_engine_versioned)
+{
+   driOptionCache cache = drirc_init("driver", "drm",
+                                     NULL,
+                                     "unknownapp", 0,
+                                     "Versioned Engine Name", 1);
+   EXPECT_EQ(driQueryOptioni(&cache, "mesa_drirc_option"), 5);
+}
+#endif
index 0245f8f..170e1b5 100644 (file)
  * \author Felix Kuehling
  */
 
-#if defined(ANDROID) || defined(_WIN32)
-#define WITH_XMLCONFIG 0
-#else
-#define WITH_XMLCONFIG 1
-#endif
-
+#include "xmlconfig.h"
 #include <limits.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -52,7 +47,6 @@
 #include <fcntl.h>
 #include <math.h>
 #include "strndup.h"
-#include "xmlconfig.h"
 #include "u_process.h"
 #include "os_file.h"
 
@@ -1036,6 +1030,21 @@ initOptionCache(driOptionCache *cache, const driOptionCache *info)
 #define DATADIR "/usr/share"
 #endif
 
+static const char *datadir = DATADIR "/drirc.d";
+static const char *execname;
+
+void
+driInjectDataDir(const char *dir)
+{
+   datadir = dir;
+}
+
+void
+driInjectExecName(const char *exec)
+{
+   execname = exec;
+}
+
 void
 driParseConfigFiles(driOptionCache *cache, const driOptionCache *info,
                     int screenNum, const char *driverName,
@@ -1057,9 +1066,9 @@ driParseConfigFiles(driOptionCache *cache, const driOptionCache *info,
    userData.applicationVersion = applicationVersion;
    userData.engineName = engineName ? engineName : "";
    userData.engineVersion = engineVersion;
-   userData.execName = util_get_process_name();
+   userData.execName = execname ?: util_get_process_name();
 
-   parseConfigDir(&userData, DATADIR "/drirc.d");
+   parseConfigDir(&userData, datadir);
    parseOneConfigFile(&userData, SYSCONFDIR "/drirc");
 
    if ((home = getenv("HOME"))) {
index 130de09..d0bb0b3 100644 (file)
 extern "C" {
 #endif
 
+#ifdef ANDROID
+#define WITH_XMLCONFIG 0
+#else
+#define WITH_XMLCONFIG 1
+#endif
+
 #define STRING_CONF_MAXLEN 1024
 
 /** \brief Option data types */
@@ -157,6 +163,10 @@ float driQueryOptionf(const driOptionCache *cache, const char *name);
 /** \brief Query a string option value */
 char *driQueryOptionstr(const driOptionCache *cache, const char *name);
 
+/* Overrides for the unit tests to control drirc parsing. */
+void driInjectDataDir(const char *dir);
+void driInjectExecName(const char *exec);
+
 /**
  * Returns a hash of the options for this application.
  */