diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index bf07f719dcc4bf15ea1dfa108ee656634825cbde..0b6179d1cee47b8d71c0c5e01977c7956611312c 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -75,7 +75,10 @@ struct _SrtSystemInfo
 {
   /*< private >*/
   GObject parent;
+  /* "" if we have tried and failed to auto-detect */
   gchar *expectations;
+  /* Fake environment variables, or %NULL to use the real environment */
+  gchar **env;
   Tristate can_write_uinput;
   /* (element-type Abi) */
   GPtrArray *abis;
@@ -199,6 +202,7 @@ srt_system_info_finalize (GObject *object)
 
   g_clear_pointer (&self->abis, g_ptr_array_unref);
   g_free (self->expectations);
+  g_strfreev (self->env);
 
   G_OBJECT_CLASS (srt_system_info_parent_class)->finalize (object);
 }
@@ -347,6 +351,43 @@ library_compare (SrtLibrary *a, SrtLibrary *b)
   return g_strcmp0 (srt_library_get_soname (a), srt_library_get_soname (b));
 }
 
+static gchar **
+get_environ (SrtSystemInfo *self)
+{
+  if (self->env != NULL)
+    return self->env;
+  else
+    return environ;
+}
+
+static gboolean
+ensure_expectations (SrtSystemInfo *self)
+{
+  if (self->expectations == NULL)
+    {
+      const char *runtime;
+      const char *sysroot = "/";
+      gchar *def;
+
+      runtime = g_environ_getenv (get_environ (self), "STEAM_RUNTIME");
+
+      if (runtime != NULL && runtime[0] == '/')
+        sysroot = runtime;
+
+      def = g_build_filename (sysroot, "usr", "lib", "steamrt",
+                              "expectations", NULL);
+
+      if (g_file_test (def, G_FILE_TEST_IS_DIR))
+        self->expectations = g_steal_pointer (&def);
+      else
+        self->expectations = g_strdup ("");
+
+      g_free (def);
+    }
+
+  return self->expectations[0] != '\0';
+}
+
 /**
  * srt_system_info_check_libraries:
  * @self: The #SrtSystemInfo object to use.
@@ -384,7 +425,7 @@ srt_system_info_check_libraries (SrtSystemInfo *self,
   g_return_val_if_fail (libraries_out == NULL || *libraries_out == NULL,
                         SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
 
-  if (self->expectations == NULL)
+  if (!ensure_expectations (self))
     {
       /* We don't know which libraries to check. */
       return SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS;
@@ -538,7 +579,7 @@ srt_system_info_check_library (SrtSystemInfo *self,
       return srt_library_get_issues (library);
     }
 
-  if (self->expectations != NULL)
+  if (ensure_expectations (self))
     {
       dir_path = g_build_filename (self->expectations, multiarch_tuple, NULL);
       dir = g_dir_open (dir_path, 0, &error);
@@ -628,3 +669,43 @@ srt_system_info_check_library (SrtSystemInfo *self,
 
     return ret;
 }
+
+/*
+ * Forget whether we can load libraries.
+ */
+static void
+forget_libraries (SrtSystemInfo *self)
+{
+  gsize i;
+
+  for (i = 0; i < self->abis->len; i++)
+    {
+      Abi *abi = g_ptr_array_index (self->abis, i);
+
+      g_hash_table_remove_all (abi->cached_results);
+      abi->cached_combined_issues = SRT_LIBRARY_ISSUES_NONE;
+      abi->libraries_cache_available = FALSE;
+    }
+}
+
+/**
+ * srt_system_info_set_environ:
+ * @self: The #SrtSystemInfo
+ * @env: (nullable) (array zero-terminated=1) (element-type filename) (transfer none): An
+ *  array of environment variables
+ *
+ * Use @env instead of the real environment variable block `environ`
+ * when locating the Steam Runtime.
+ *
+ * If @env is %NULL, go back to using the real environment variables.
+ */
+void
+srt_system_info_set_environ (SrtSystemInfo *self,
+                             gchar * const *env)
+{
+  g_return_if_fail (SRT_IS_SYSTEM_INFO (self));
+
+  forget_libraries (self);
+  g_strfreev (self->env);
+  self->env = g_strdupv ((gchar **) env);
+}
diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h
index 6213b2d145bda9146f5867ce94e6721f57bbffd1..33b6132b3b25235e320bfd201b54b85dafd5bcdd 100644
--- a/steam-runtime-tools/system-info.h
+++ b/steam-runtime-tools/system-info.h
@@ -58,3 +58,6 @@ SrtLibraryIssues srt_system_info_check_library (SrtSystemInfo *self,
                                                 const gchar *multiarch_tuple,
                                                 const gchar *soname,
                                                 SrtLibrary **more_details_out);
+
+void srt_system_info_set_environ (SrtSystemInfo *self,
+                                  gchar * const *env);
diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols
new file mode 100644
index 0000000000000000000000000000000000000000..17fc854ac6138920c30c24ddbc20ce719c88917f
--- /dev/null
+++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols
@@ -0,0 +1,11 @@
+# Cut-down version of libglib2.0-0:amd64.symbols, to illustrate what we expect
+# to find here
+libgio-2.0.so.0 libglib2.0-0 #MINVER#
+* Build-Depends-Package: libglib2.0-dev
+ g_action_activate@Base 2.28.0
+ g_action_change_state@Base 2.30.0
+libglib-2.0.so.0 libglib2.0-0 #MINVER#
+* Build-Depends-Package: libglib2.0-dev
+ g_access@Base 2.12.0
+ g_allocator_free@Base 2.12.0
+ g_allocator_new@Base 2.12.0
diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols
new file mode 100644
index 0000000000000000000000000000000000000000..63be790e3612555c3aae70b905be7b349964ee34
--- /dev/null
+++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols
@@ -0,0 +1,4 @@
+# Cut-down version of zlib1g:amd64.symbols, to illustrate what we expect
+# to find here
+libz.so.1 zlib1g #MINVER#
+ adler32@Base 1:1.1.4
diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols
new file mode 100644
index 0000000000000000000000000000000000000000..17fc854ac6138920c30c24ddbc20ce719c88917f
--- /dev/null
+++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols
@@ -0,0 +1,11 @@
+# Cut-down version of libglib2.0-0:amd64.symbols, to illustrate what we expect
+# to find here
+libgio-2.0.so.0 libglib2.0-0 #MINVER#
+* Build-Depends-Package: libglib2.0-dev
+ g_action_activate@Base 2.28.0
+ g_action_change_state@Base 2.30.0
+libglib-2.0.so.0 libglib2.0-0 #MINVER#
+* Build-Depends-Package: libglib2.0-dev
+ g_access@Base 2.12.0
+ g_allocator_free@Base 2.12.0
+ g_allocator_new@Base 2.12.0
diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols
new file mode 100644
index 0000000000000000000000000000000000000000..63be790e3612555c3aae70b905be7b349964ee34
--- /dev/null
+++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols
@@ -0,0 +1,4 @@
+# Cut-down version of zlib1g:amd64.symbols, to illustrate what we expect
+# to find here
+libz.so.1 zlib1g #MINVER#
+ adler32@Base 1:1.1.4
diff --git a/tests/meson.build b/tests/meson.build
index de2c93df2b67e2029951d62e3cb5d9314750aea7..53a323a8aaf07477412fdbcad6ae68cad1947451 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -47,6 +47,7 @@ tests_metadir = join_paths(
 
 install_subdir('expectations', install_dir : tests_dir)
 install_subdir('expectations_with_missings', install_dir : tests_dir)
+install_subdir('fake-steam-runtime', install_dir : tests_dir)
 
 foreach test_name : tests
   exe = executable(
diff --git a/tests/system-info.c b/tests/system-info.c
index 8edd66108331dca32c78c64596beb8cd71c1289c..afe4d58b1c1a9da6bc8c40b04630d6eb941dcda9 100644
--- a/tests/system-info.c
+++ b/tests/system-info.c
@@ -286,6 +286,44 @@ libraries_presence (Fixture *f,
   g_object_unref (info);
 }
 
+/*
+ * Check that the expectations can be auto-detected from the
+ * `STEAM_RUNTIME` environment variable.
+ */
+static void
+auto_expectations (Fixture *f,
+                   gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar *steam_runtime = NULL;
+  GList *libraries = NULL;
+  SrtLibraryIssues issues;
+  gchar **env;
+
+  if (strcmp (_SRT_MULTIARCH, "") == 0)
+    {
+      g_test_skip ("Unsupported architecture");
+      return;
+    }
+
+  env = g_get_environ ();
+  steam_runtime = g_build_filename (f->srcdir, "fake-steam-runtime", NULL);
+  env = g_environ_setenv (env, "STEAM_RUNTIME", steam_runtime, TRUE);
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, env);
+  issues = srt_system_info_check_libraries (info,
+                                            _SRT_MULTIARCH,
+                                            &libraries);
+  g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_NONE);
+  check_libraries_result (libraries);
+  g_list_free_full (libraries, g_object_unref);
+
+  g_object_unref (info);
+  g_strfreev (env);
+  g_free (steam_runtime);
+}
+
 static void
 check_library_result (SrtLibrary *library)
 {
@@ -623,9 +661,9 @@ wrong_expectations (Fixture *f,
       return;
     }
 
-  /* Set the expectations folder to NULL.
-   * We expect the library checks to fail. */
-  info = srt_system_info_new (NULL);
+  /* Set the expectations folder to one that does not contain the
+   * necessary files. We expect the library checks to fail. */
+  info = srt_system_info_new ("/dev");
 
   issues = srt_system_info_check_libraries (info,
                                             _SRT_MULTIARCH,
@@ -652,6 +690,8 @@ main (int argc,
               setup, test_object, teardown);
   g_test_add ("/system-info/libraries_presence", Fixture, NULL,
               setup, libraries_presence, teardown);
+  g_test_add ("/system-info/auto_expectations", Fixture, NULL,
+              setup, auto_expectations, teardown);
   g_test_add ("/system-info/library_presence", Fixture, NULL,
               setup, library_presence, teardown);
   g_test_add ("/system-info/libraries_missing", Fixture, NULL,