Skip to content
Snippets Groups Projects
Commit 06f27e65 authored by Ludovico de Nittis's avatar Ludovico de Nittis :palm_tree:
Browse files

Add libraries check to SrtSystemInfo


This provides a high-level API to wrap SrtLibrary and check if the
current system has the expected libraries and symbols.

Signed-off-by: default avatarLudovico de Nittis <ludovico.denittis@collabora.com>
parent 20333a02
Branches
Tags
1 merge request!25Add libraries check to SrtSystemInfo
Pipeline #1325 passed
This commit is part of merge request !25. Comments created here will be created in the context of that merge request.
Showing with 865 additions and 3 deletions
...@@ -449,9 +449,10 @@ srt_check_library_presence (const char *soname, ...@@ -449,9 +449,10 @@ srt_check_library_presence (const char *soname,
GStrv dependencies = NULL; GStrv dependencies = NULL;
SrtLibraryIssues issues = SRT_LIBRARY_ISSUES_NONE; SrtLibraryIssues issues = SRT_LIBRARY_ISSUES_NONE;
g_return_val_if_fail (soname != NULL, SRT_LIBRARY_ISSUES_CANNOT_LOAD); g_return_val_if_fail (soname != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (multiarch != NULL, SRT_LIBRARY_ISSUES_CANNOT_LOAD); g_return_val_if_fail (multiarch != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (more_details_out == NULL || *more_details_out == NULL, SRT_LIBRARY_ISSUES_CANNOT_LOAD); g_return_val_if_fail (more_details_out == NULL || *more_details_out == NULL,
SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
switch (symbols_format) switch (symbols_format)
{ {
......
...@@ -52,6 +52,8 @@ GType srt_library_get_type (void); ...@@ -52,6 +52,8 @@ GType srt_library_get_type (void);
* were not present * were not present
* @SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS: Some of the expected symbols * @SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS: Some of the expected symbols
* were available with a different version * were available with a different version
* @SRT_LIBRARY_ISSUES_INTERNAL_ERROR: Generic internal error, for example
* a function has been called with a missing required parameter
* *
* A bitfield with flags representing problems with a library, or * A bitfield with flags representing problems with a library, or
* %SRT_LIBRARY_ISSUES_NONE (which is numerically zero) if no problems * %SRT_LIBRARY_ISSUES_NONE (which is numerically zero) if no problems
...@@ -64,6 +66,7 @@ typedef enum ...@@ -64,6 +66,7 @@ typedef enum
SRT_LIBRARY_ISSUES_CANNOT_LOAD = (1 << 0), SRT_LIBRARY_ISSUES_CANNOT_LOAD = (1 << 0),
SRT_LIBRARY_ISSUES_MISSING_SYMBOLS = (1 << 1), SRT_LIBRARY_ISSUES_MISSING_SYMBOLS = (1 << 1),
SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS = (1 << 2), SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS = (1 << 2),
SRT_LIBRARY_ISSUES_INTERNAL_ERROR = (1 << 3),
SRT_LIBRARY_ISSUES_NONE = 0 SRT_LIBRARY_ISSUES_NONE = 0
} SrtLibraryIssues; } SrtLibraryIssues;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
...@@ -85,6 +86,9 @@ typedef struct ...@@ -85,6 +86,9 @@ typedef struct
{ {
GQuark multiarch_tuple; GQuark multiarch_tuple;
Tristate can_run; Tristate can_run;
GHashTable *cached_results;
SrtLibraryIssues cached_combined_issues;
gboolean libraries_cache_available;
} Abi; } Abi;
static Abi * static Abi *
...@@ -108,6 +112,9 @@ ensure_abi (SrtSystemInfo *self, ...@@ -108,6 +112,9 @@ ensure_abi (SrtSystemInfo *self,
abi = g_slice_new0 (Abi); abi = g_slice_new0 (Abi);
abi->multiarch_tuple = quark; abi->multiarch_tuple = quark;
abi->can_run = TRI_MAYBE; abi->can_run = TRI_MAYBE;
abi->cached_results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
abi->cached_combined_issues = SRT_LIBRARY_ISSUES_NONE;
abi->libraries_cache_available = FALSE;
/* transfer ownership to self->abis */ /* transfer ownership to self->abis */
g_ptr_array_add (self->abis, abi); g_ptr_array_add (self->abis, abi);
return abi; return abi;
...@@ -116,6 +123,10 @@ ensure_abi (SrtSystemInfo *self, ...@@ -116,6 +123,10 @@ ensure_abi (SrtSystemInfo *self,
static void static void
abi_free (gpointer self) abi_free (gpointer self)
{ {
Abi *abi = self;
if (abi->cached_results != NULL)
g_hash_table_unref (abi->cached_results);
g_slice_free (Abi, self); g_slice_free (Abi, self);
} }
...@@ -260,3 +271,279 @@ srt_system_info_can_write_to_uinput (SrtSystemInfo *self) ...@@ -260,3 +271,279 @@ srt_system_info_can_write_to_uinput (SrtSystemInfo *self)
return (self->can_write_uinput == TRI_YES); return (self->can_write_uinput == TRI_YES);
} }
static gint
library_compare (SrtLibrary *a, SrtLibrary *b)
{
return g_strcmp0 (srt_library_get_soname (a), srt_library_get_soname (b));
}
/**
* srt_system_info_check_libraries:
* @self: The #SrtSystemInfo object to use.
* @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI.
* @libraries_out: (out) (optional) (element-type SrtLibrary) (transfer full):
* Used to return a #GList object where every element of said list is an
* #SrtLibrary object, representing every `SONAME` found from the expectations
* folder. Free with `g_list_free_full(libraries, g_object_unref)`.
*
* Check if the running system has all the expected libraries, and related symbols,
* as listed in the `deb-symbols(5)` files `*.symbols` in the @multiarch
* subdirectory of #SrtSystemInfo:expectations.
*
* Returns: A bitfield containing problems, or %SRT_LIBRARY_ISSUES_NONE
* if no problems were found.
*/
SrtLibraryIssues
srt_system_info_check_libraries (SrtSystemInfo *self,
const gchar *multiarch_tuple,
GList **libraries_out)
{
Abi *abi = NULL;
gchar *dir_path = NULL;
const gchar *filename = NULL;
gchar *symbols_file = NULL;
size_t len = 0;
ssize_t chars;
GDir *dir = NULL;
FILE *fp = NULL;
GError *error = NULL;
SrtLibraryIssues ret = SRT_LIBRARY_ISSUES_INTERNAL_ERROR;
g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (multiarch_tuple != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (libraries_out == NULL || *libraries_out == NULL,
SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
abi = ensure_abi (self, multiarch_tuple);
/* If we cached already the result, we return it */
if (abi->libraries_cache_available)
{
if (libraries_out != NULL)
{
*libraries_out = g_list_sort (g_hash_table_get_values (abi->cached_results),
(GCompareFunc) library_compare);
g_list_foreach (*libraries_out, (GFunc) G_CALLBACK (g_object_ref), NULL);
}
return abi->cached_combined_issues;
}
dir_path = g_build_filename (self->expectations, multiarch_tuple, NULL);
dir = g_dir_open (dir_path, 0, &error);
if (error)
{
g_debug ("An error occurred while opening the symbols directory: %s", error->message);
g_clear_error (&error);
goto out;
}
while ((filename = g_dir_read_name (dir)))
{
char *line = NULL;
if (!g_str_has_suffix (filename, ".symbols"))
continue;
symbols_file = g_build_filename (dir_path, filename, NULL);
fp = fopen(symbols_file, "r");
if (fp == NULL)
{
int saved_errno = errno;
g_debug ("Error reading \"%s\": %s\n", symbols_file, strerror (saved_errno));
goto out;
}
while ((chars = getline(&line, &len, fp)) != -1)
{
char *pointer_into_line = line;
if (line[chars - 1] == '\n')
line[chars - 1] = '\0';
if (line[0] == '\0')
continue;
if (line[0] != '#' && line[0] != '*' && line[0] != '|' && line[0] != ' ')
{
/* This line introduces a new SONAME. We extract it and call
* `srt_check_library_presence` with the symbols file where we
* found it, as an argument. */
SrtLibrary *library = NULL;
char *soname = g_strdup (strsep (&pointer_into_line, " \t"));
abi->cached_combined_issues |= srt_check_library_presence (soname,
multiarch_tuple,
symbols_file,
SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
&library);
g_hash_table_insert (abi->cached_results, soname, library);
}
}
free (line);
g_clear_pointer (&symbols_file, g_free);
g_clear_pointer (&fp, fclose);
}
abi->libraries_cache_available = TRUE;
if (libraries_out != NULL)
{
*libraries_out = g_list_sort (g_hash_table_get_values (abi->cached_results),
(GCompareFunc) library_compare);
g_list_foreach (*libraries_out, (GFunc) G_CALLBACK (g_object_ref), NULL);
}
ret = abi->cached_combined_issues;
out:
g_clear_pointer (&symbols_file, g_free);
g_clear_pointer (&dir_path, g_free);
if (fp != NULL)
g_clear_pointer (&fp, fclose);
if (dir != NULL)
g_dir_close (dir);
return ret;
}
/**
* srt_system_info_check_library:
* @self: The #SrtSystemInfo object to use.
* @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI.
* @soname: (type filename): The `SONAME` of a shared library, for example `libjpeg.so.62`.
* @more_details_out: (out) (optional) (transfer full): Used to return an
* #SrtLibrary object representing the shared library provided by @soname.
* Free with `g_object_unref()`.
*
* Check if @soname is available in the running system and whether it conforms
* to the `deb-symbols(5)` files `*.symbols` in the @multiarch
* subdirectory of #SrtSystemInfo:expectations.
*
* Returns: A bitfield containing problems, or %SRT_LIBRARY_ISSUES_NONE
* if no problems were found.
*/
SrtLibraryIssues
srt_system_info_check_library (SrtSystemInfo *self,
const gchar *multiarch_tuple,
const gchar *soname,
SrtLibrary **more_details_out)
{
Abi *abi = NULL;
SrtLibrary *library = NULL;
const gchar *filename = NULL;
gchar *symbols_file = NULL;
gchar *dir_path = NULL;
gchar *line = NULL;
size_t len = 0;
ssize_t chars;
FILE *fp = NULL;
SrtLibraryIssues issues;
GDir *dir;
GError *error = NULL;
SrtLibraryIssues ret = SRT_LIBRARY_ISSUES_INTERNAL_ERROR;
g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (multiarch_tuple != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (soname != NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_return_val_if_fail (more_details_out == NULL || *more_details_out == NULL,
SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
abi = ensure_abi (self, multiarch_tuple);
/* If we have the result already in cache, we return it */
library = g_hash_table_lookup (abi->cached_results, soname);
if (library != NULL)
{
if (more_details_out != NULL)
*more_details_out = g_object_ref (library);
return srt_library_get_issues (library);
}
dir_path = g_build_filename (self->expectations, multiarch_tuple, NULL);
dir = g_dir_open (dir_path, 0, &error);
if (error)
{
g_debug ("An error occurred while opening the symbols directory: %s", error->message);
g_clear_error (&error);
goto out;
}
while ((filename = g_dir_read_name (dir)))
{
if (!g_str_has_suffix (filename, ".symbols"))
continue;
symbols_file = g_build_filename (dir_path, filename, NULL);
fp = fopen(symbols_file, "r");
if (fp == NULL)
{
int saved_errno = errno;
g_debug ("Error reading \"%s\": %s\n", symbols_file, strerror (saved_errno));
goto out;
}
while ((chars = getline(&line, &len, fp)) != -1)
{
char *pointer_into_line = line;
if (line[chars - 1] == '\n')
line[chars - 1] = '\0';
if (line[0] == '\0')
continue;
if (line[0] != '#' && line[0] != '*' && line[0] != '|' && line[0] != ' ')
{
/* This line introduces a new SONAME, which might
* be the one we are interested in. */
char *soname_found = g_strdup (strsep (&pointer_into_line, " \t"));
if (g_strcmp0 (soname_found, soname) == 0)
{
issues = srt_check_library_presence (soname_found,
multiarch_tuple,
symbols_file,
SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
&library);
g_hash_table_insert (abi->cached_results, soname_found, library);
abi->cached_combined_issues |= issues;
if (more_details_out != NULL)
*more_details_out = g_object_ref (library);
free (line);
ret = issues;
goto out;
}
free (soname_found);
}
}
g_clear_pointer (&symbols_file, g_free);
g_clear_pointer (&line, g_free);
g_clear_pointer (&fp, fclose);
}
/* The SONAME's symbols file is not available.
* We do instead a simple absence/presence check. */
issues = srt_check_library_presence (soname,
multiarch_tuple,
NULL,
SRT_LIBRARY_SYMBOLS_FORMAT_DEB_SYMBOLS,
&library);
g_hash_table_insert (abi->cached_results, g_strdup (soname), library);
abi->cached_combined_issues |= issues;
if (more_details_out != NULL)
*more_details_out = g_object_ref (library);
ret = issues;
out:
g_clear_pointer (&symbols_file, g_free);
g_clear_pointer (&dir_path, g_free);
if (fp != NULL)
g_clear_pointer (&fp, fclose);
if (dir != NULL)
g_dir_close (dir);
return ret;
}
...@@ -51,3 +51,10 @@ SrtSystemInfo *srt_system_info_new (const char *expectations); ...@@ -51,3 +51,10 @@ SrtSystemInfo *srt_system_info_new (const char *expectations);
gboolean srt_system_info_can_run (SrtSystemInfo *self, gboolean srt_system_info_can_run (SrtSystemInfo *self,
const char *multiarch_tuple); const char *multiarch_tuple);
gboolean srt_system_info_can_write_to_uinput (SrtSystemInfo *self); gboolean srt_system_info_can_write_to_uinput (SrtSystemInfo *self);
SrtLibraryIssues srt_system_info_check_libraries (SrtSystemInfo *self,
const gchar *multiarch_tuple,
GList **libraries_out);
SrtLibraryIssues srt_system_info_check_library (SrtSystemInfo *self,
const gchar *multiarch_tuple,
const gchar *soname,
SrtLibrary **more_details_out);
# 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
# 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
# Cut-down version of libglib2.0-0:amd64.symbols.
# Also libgio-2.0.so.0 has been renamed to libgio-MISSING-2.0.so.0
# In this way we can simulate a missing library.
libgio-MISSING-2.0.so.0 libglib2.0-0 #MINVER#
* Build-Depends-Package: libglib2.0-dev
g_action_activate@Base 2.28.0
libglib-2.0.so.0 libglib2.0-0 #MINVER#
* Build-Depends-Package: libglib2.0-dev
g_access@Base 2.12.0
# Cut-down version of zlib1g:amd64.symbols.
# It has been appended also a missing symbol `missing@NotAvailable`
# In this way we can simulate an available library with a missing symbol
libz.so.1 zlib1g #MINVER#
adler32@Base 1:1.1.4
crc32@WRONG_VERSION 1:1.1.4
missing@NotAvailable 1:1.1.4
# Cut-down version of libglib2.0-0:amd64.symbols.
# Also libgio-2.0.so.0 has been renamed to libgio-MISSING-2.0.so.0
# In this way we can simulate a missing library.
libgio-MISSING-2.0.so.0 libglib2.0-0 #MINVER#
* Build-Depends-Package: libglib2.0-dev
g_action_activate@Base 2.28.0
libglib-2.0.so.0 libglib2.0-0 #MINVER#
* Build-Depends-Package: libglib2.0-dev
g_access@Base 2.12.0
# Cut-down version of zlib1g:amd64.symbols.
# It has been appended also a missing symbol `missing@NotAvailable`
# In this way we can simulate an available library with a missing symbol
libz.so.1 zlib1g #MINVER#
adler32@Base 1:1.1.4
crc32@WRONG_VERSION 1:1.1.4
missing@NotAvailable 1:1.1.4
...@@ -44,6 +44,7 @@ tests_metadir = join_paths( ...@@ -44,6 +44,7 @@ tests_metadir = join_paths(
) )
install_subdir('expectations', install_dir : tests_dir) install_subdir('expectations', install_dir : tests_dir)
install_subdir('expectations_with_missings', install_dir : tests_dir)
foreach test_name : tests foreach test_name : tests
exe = executable( exe = executable(
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <steam-runtime-tools/steam-runtime-tools.h> #include <steam-runtime-tools/steam-runtime-tools.h>
#include <steam-runtime-tools/glib-compat.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
...@@ -137,6 +139,503 @@ test_object (Fixture *f, ...@@ -137,6 +139,503 @@ test_object (Fixture *f,
g_object_unref (info); g_object_unref (info);
} }
static void
check_libraries_result (GList *libraries)
{
SrtLibrary *library = NULL;
const char * const *missing_symbols;
const char * const *misversioned_symbols;
const char * const *dependencies;
gboolean seen_libc;
GList *l;
g_assert_nonnull (libraries);
l = libraries;
/* Test first library. Alphabetical order is an API guarantee, so we know
* which one it should be. */
library = l->data;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libgio-2.0.so.0");
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_NONE);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
seen_libc = FALSE;
for (gsize i = 0; dependencies[i] != NULL; i++)
{
g_debug ("libgio-2.0.so.0 depends on %s", dependencies[i]);
if (strstr (dependencies[i], "/libc.so.") != NULL)
seen_libc = TRUE;
}
g_assert_true (seen_libc);
/* Test second library */
l = g_list_next (l);
library = l->data;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libglib-2.0.so.0");
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_NONE);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
seen_libc = FALSE;
for (gsize i = 0; dependencies[i] != NULL; i++)
{
g_debug ("libglib-2.0.so.0 depends on %s", dependencies[i]);
if (strstr (dependencies[i], "/libc.so.") != NULL)
seen_libc = TRUE;
}
g_assert_true (seen_libc);
/* Test last library */
l = g_list_next (l);
library = l->data;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libz.so.1");
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_NONE);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
seen_libc = FALSE;
for (gsize i = 0; dependencies[i] != NULL; i++)
{
g_debug ("libz.so.1 depends on %s", dependencies[i]);
if (strstr (dependencies[i], "/libc.so.") != NULL)
seen_libc = TRUE;
}
g_assert_true (seen_libc);
g_assert_null (g_list_next (l));
}
/*
* Test if the expected libraries are available in the
* running system.
*/
static void
libraries_presence (Fixture *f,
gconstpointer context)
{
SrtSystemInfo *info;
gchar *expectations_in = NULL;
GList *libraries = NULL;
SrtLibraryIssues issues;
if (strcmp (_SRT_MULTIARCH, "") == 0)
{
g_test_skip ("Unsupported architecture");
return;
}
expectations_in = g_build_filename (f->srcdir, "expectations", NULL);
info = srt_system_info_new (expectations_in);
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);
libraries = NULL;
/* Do the check again, this time using the cache */
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_free (expectations_in);
g_object_unref (info);
}
static void
check_library_result (SrtLibrary *library)
{
const char * const *missing_symbols;
const char * const *misversioned_symbols;
const char * const *dependencies;
gboolean seen_libc;
g_assert_cmpstr (srt_library_get_soname (library), ==, "libz.so.1");
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
seen_libc = FALSE;
for (gsize i = 0; dependencies[i] != NULL; i++)
{
g_debug ("libz.so.1 depends on %s", dependencies[i]);
if (strstr (dependencies[i], "/libc.so.") != NULL)
seen_libc = TRUE;
}
g_assert_true (seen_libc);
}
/*
* Test if `libz.so.1` is available in the running system and
* if it has the expected symbols.
*/
static void
library_presence (Fixture *f,
gconstpointer context)
{
SrtSystemInfo *info;
gchar *expectations_in = NULL;
SrtLibrary *library = NULL;
SrtLibraryIssues issues;
if (strcmp (_SRT_MULTIARCH, "") == 0)
{
g_test_skip ("Unsupported architecture");
return;
}
expectations_in = g_build_filename (f->srcdir, "expectations", NULL);
info = srt_system_info_new (expectations_in);
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libz.so.1",
&library);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_NONE);
check_library_result (library);
g_clear_pointer (&library, g_object_unref);
/* Do the check again, this time using the cache */
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libz.so.1",
&library);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_NONE);
check_library_result (library);
g_object_unref (library);
g_free (expectations_in);
g_object_unref (info);
}
static void
check_library_libz_missing_sym_result (SrtLibrary *library)
{
const char * const *missing_symbols;
const char * const *misversioned_symbols;
const char * const *dependencies;
gboolean seen_libc;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libz.so.1");
g_debug ("path to libz.so.1 is %s", srt_library_get_absolute_path (library));
g_assert_true (srt_library_get_absolute_path (library)[0] == '/');
g_assert_true (g_file_test (srt_library_get_absolute_path (library), G_FILE_TEST_EXISTS));
g_assert_cmpint (srt_library_get_issues (library) & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0);
g_assert_cmpint (srt_library_get_issues (library) & SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS, !=, 0);
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, "missing@NotAvailable");
g_assert_cmpstr (missing_symbols[1], ==, NULL);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, "crc32@WRONG_VERSION");
g_assert_cmpstr (misversioned_symbols[1], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
seen_libc = FALSE;
for (gsize i = 0; dependencies[i] != NULL; i++)
{
g_debug ("libz.so.1 depends on %s", dependencies[i]);
if (strstr (dependencies[i], "/libc.so.") != NULL)
seen_libc = TRUE;
}
g_assert_true (seen_libc);
}
static void
check_missing_libraries_result (GList *libraries)
{
SrtLibrary *library = NULL;
const char * const *missing_symbols;
const char * const *misversioned_symbols;
const char * const *dependencies;
GList *l;
g_assert_nonnull (libraries);
l = libraries;
/* Test first library. Alphabetical order is an API guarantee, so we know
* which one it should be. */
library = l->data;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libgio-MISSING-2.0.so.0");
g_assert_cmpstr (srt_library_get_absolute_path (library), ==, NULL);
g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_CANNOT_LOAD);
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], ==, NULL);
/* Test second library */
l = g_list_next (l);
library = l->data;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libglib-2.0.so.0");
g_debug ("path to libglib-2.0.so.0 is %s", srt_library_get_absolute_path (library));
g_assert_true (srt_library_get_absolute_path (library)[0] == '/');
g_assert_true (g_file_test (srt_library_get_absolute_path (library), G_FILE_TEST_EXISTS));
g_assert_cmpint (srt_library_get_issues (library), ==, SRT_LIBRARY_ISSUES_NONE);
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], !=, NULL);
/* Test last library */
l = g_list_next (l);
library = l->data;
check_library_libz_missing_sym_result (library);
}
/*
* Test libraries that are either not available or with missing and
* misversioned symbols.
*/
static void
libraries_missing (Fixture *f,
gconstpointer context)
{
SrtSystemInfo *info;
gchar *expectations_in = NULL;
GList *libraries = NULL;
SrtLibraryIssues issues;
if (strcmp (_SRT_MULTIARCH, "") == 0)
{
g_test_skip ("Unsupported architecture");
return;
}
expectations_in = g_build_filename (f->srcdir, "expectations_with_missings", NULL);
info = srt_system_info_new (expectations_in);
issues = srt_system_info_check_libraries (info,
_SRT_MULTIARCH,
&libraries);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_CANNOT_LOAD, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS, !=, 0);
check_missing_libraries_result (libraries);
g_list_free_full (libraries, g_object_unref);
libraries = NULL;
/* Do the check again, this time using the cache */
issues = srt_system_info_check_libraries (info,
_SRT_MULTIARCH,
&libraries);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_CANNOT_LOAD, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS, !=, 0);
check_missing_libraries_result (libraries);
g_list_free_full (libraries, g_object_unref);
g_free (expectations_in);
g_object_unref (info);
}
static void
check_library_missing_lib_result (SrtLibrary *library)
{
const char * const *missing_symbols;
const char * const *misversioned_symbols;
const char * const *dependencies;
g_assert_nonnull (library);
g_assert_cmpstr (srt_library_get_soname (library), ==, "libMISSING.so.62");
g_assert_cmpstr (srt_library_get_absolute_path (library), ==, NULL);
missing_symbols = srt_library_get_missing_symbols (library);
g_assert_nonnull (missing_symbols);
g_assert_cmpstr (missing_symbols[0], ==, NULL);
misversioned_symbols = srt_library_get_misversioned_symbols (library);
g_assert_nonnull (misversioned_symbols);
g_assert_cmpstr (misversioned_symbols[0], ==, NULL);
dependencies = srt_library_get_dependencies (library);
g_assert_nonnull (dependencies);
g_assert_cmpstr (dependencies[0], ==, NULL);
}
/*
* Test `libz.so.1` expecting missing and misversioned symbols.
* Then test the missing library `libMISSING.so.62`.
*/
static void
library_missing (Fixture *f,
gconstpointer context)
{
SrtSystemInfo *info;
gchar *expectations_in = NULL;
SrtLibrary *library = NULL;
SrtLibraryIssues issues;
if (strcmp (_SRT_MULTIARCH, "") == 0)
{
g_test_skip ("Unsupported architecture");
return;
}
expectations_in = g_build_filename (f->srcdir, "expectations_with_missings", NULL);
info = srt_system_info_new (expectations_in);
/* Check a present library that has a missing symbol */
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libz.so.1",
&library);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS, !=, 0);
check_library_libz_missing_sym_result (library);
g_clear_pointer (&library, g_object_unref);
/* Do the check again, this time using the cache */
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libz.so.1",
&library);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISSING_SYMBOLS, !=, 0);
g_assert_cmpint (issues & SRT_LIBRARY_ISSUES_MISVERSIONED_SYMBOLS, !=, 0);
check_library_libz_missing_sym_result (library);
g_clear_pointer (&library, g_object_unref);
/* Check for a library that isn't listed in any of the .symbols files */
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libMISSING.so.62",
&library);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_CANNOT_LOAD);
check_library_missing_lib_result (library);
g_clear_pointer (&library, g_object_unref);
/* Do the check again, this time using the cache */
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libMISSING.so.62",
&library);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_CANNOT_LOAD);
check_library_missing_lib_result (library);
g_object_unref (library);
g_free (expectations_in);
g_object_unref (info);
}
/*
* Test libraries with the expectations folder set to NULL.
*/
static void
wrong_expectations (Fixture *f,
gconstpointer context)
{
SrtSystemInfo *info;
SrtLibraryIssues issues;
if (strcmp (_SRT_MULTIARCH, "") == 0)
{
g_test_skip ("Unsupported architecture");
return;
}
/* Set the expectations folder to NULL.
* We expect the library checks to fail. */
info = srt_system_info_new (NULL);
issues = srt_system_info_check_libraries (info,
_SRT_MULTIARCH,
NULL);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
issues = srt_system_info_check_library (info,
_SRT_MULTIARCH,
"libz.so.1",
NULL);
g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_INTERNAL_ERROR);
g_object_unref (info);
}
int int
main (int argc, main (int argc,
char **argv) char **argv)
...@@ -146,6 +645,16 @@ main (int argc, ...@@ -146,6 +645,16 @@ main (int argc,
g_test_init (&argc, &argv, NULL); g_test_init (&argc, &argv, NULL);
g_test_add ("/system-info/object", Fixture, NULL, g_test_add ("/system-info/object", Fixture, NULL,
setup, test_object, teardown); setup, test_object, teardown);
g_test_add ("/system-info/libraries_presence", Fixture, NULL,
setup, libraries_presence, teardown);
g_test_add ("/system-info/library_presence", Fixture, NULL,
setup, library_presence, teardown);
g_test_add ("/system-info/libraries_missing", Fixture, NULL,
setup, libraries_missing, teardown);
g_test_add ("/system-info/library_missing", Fixture, NULL,
setup, library_missing, teardown);
g_test_add ("/system-info/wrong_expectations", Fixture, NULL,
setup, wrong_expectations, teardown);
return g_test_run (); return g_test_run ();
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment