GSettings: New schema source from path, bytes and resource

This commit is contained in:
Zipdox
2022-12-21 23:55:07 +01:00
committed by Matthias Clasen
parent 913a1bfd85
commit 4162307173
7 changed files with 689 additions and 37 deletions

View File

@@ -21,6 +21,7 @@
#include "config.h"
#include "glib-private.h"
#include "gresource.h"
#include "gsettingsschema-internal.h"
#include "gsettings.h"
@@ -156,6 +157,20 @@ struct _GSettingsSchema
gint ref_count;
};
/*
* @G_SETTINGS_SCHEMA_SOURCE_FILE: The schema source was created from a path or directory
* @G_SETTINGS_SCHEMA_SOURCE_RESOURCE: The schema source was created from a resource
* @G_SETTINGS_SCHEMA_SOURCE_BYTES: The schema source was created from #GBytes
*
* Type of a #GSettingsSchemaSource. It indicates how the source was created.
*/
typedef enum
{
G_SETTINGS_SCHEMA_SOURCE_FILE,
G_SETTINGS_SCHEMA_SOURCE_RESOURCE,
G_SETTINGS_SCHEMA_SOURCE_BYTES
} GSettingsSchemaSourceType;
/**
* G_TYPE_SETTINGS_SCHEMA_SOURCE:
*
@@ -184,7 +199,18 @@ G_DEFINE_BOXED_TYPE (GSettingsSchema, g_settings_schema, g_settings_schema_ref,
struct _GSettingsSchemaSource
{
GSettingsSchemaSource *parent;
gchar *directory;
GSettingsSchemaSourceType type;
union {
struct {
char *directory;
} file;
struct {
char *path;
GResourceLookupFlags lookup_flags;
} resource;
} type_data;
GvdbTable *table;
GHashTable **text_tables;
@@ -230,7 +256,18 @@ g_settings_schema_source_unref (GSettingsSchemaSource *source)
if (source->parent)
g_settings_schema_source_unref (source->parent);
gvdb_table_free (source->table);
g_free (source->directory);
switch (source->type)
{
case G_SETTINGS_SCHEMA_SOURCE_FILE:
g_free (source->type_data.file.directory);
break;
case G_SETTINGS_SCHEMA_SOURCE_RESOURCE:
g_free(source->type_data.resource.path);
break;
default:
break;
}
if (source->text_tables)
{
@@ -282,6 +319,8 @@ g_settings_schema_source_unref (GSettingsSchemaSource *source)
* @parent should probably be given as the default schema source, as
* returned by g_settings_schema_source_get_default().
*
* Returns: (transfer full): a new #GSettingsSchemaSource, or %NULL
*
* Since: 2.32
**/
GSettingsSchemaSource *
@@ -291,22 +330,158 @@ g_settings_schema_source_new_from_directory (const gchar *directory,
GError **error)
{
GSettingsSchemaSource *source;
GvdbTable *table;
gchar *filename;
filename = g_build_filename (directory, "gschemas.compiled", NULL);
table = gvdb_table_new (filename, trusted, error);
source = g_settings_schema_source_new_from_path (filename, parent, trusted, error);
g_free (filename);
return source;
}
/**
* g_settings_schema_source_new_from_path:
* @path: (type filename): the filename of a compiled schema source
* @parent: (nullable): a #GSettingsSchemaSource, or %NULL
* @trusted: %TRUE, if the directory is trusted
* @error: a pointer to a #GError pointer set to %NULL, or %NULL
*
* Almost identical to g_settings_schema_source_new_from_directory() but
* takes a path to a compiled schema file directly instead of to the
* directory it is in.
*
* Returns: (transfer full): a new #GSettingsSchemaSource, or %NULL
*
* Since: 2.78
**/
GSettingsSchemaSource *
g_settings_schema_source_new_from_path (const gchar *path,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error)
{
GSettingsSchemaSource *source;
GvdbTable *table;
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
table = gvdb_table_new (path, trusted, error);
if (table == NULL)
return NULL;
source = g_slice_new (GSettingsSchemaSource);
source->directory = g_strdup (directory);
source = g_slice_new0 (GSettingsSchemaSource);
source->parent = parent ? g_settings_schema_source_ref (parent) : NULL;
source->text_tables = NULL;
source->table = table;
source->ref_count = 1;
source->type = G_SETTINGS_SCHEMA_SOURCE_FILE;
source->type_data.file.directory = g_path_get_dirname (path);
return source;
}
/**
* g_settings_schema_source_new_from_bytes:
* @bytes: a #GBytes
* @parent: (nullable): a #GSettingsSchemaSource, or %NULL
* @trusted: %TRUE, if the data is trusted
* @error: a pointer to a #GError pointer set to %NULL, or %NULL
*
* Attempts to create a new schema source corresponding to the contents
* of @bytes, which should contain the data as produced by the
* [glib-compile-schemas][glib-compile-schemas] tool.
*
* This should only be used in standalone applications and should not
* be used in situations where settings are shared with other applications.
*
* Note that g_settings_schema_key_get_summary() and
* g_settings_schema_key_get_description() will always return %NULL for
* a #GSettingsSchemaKey belonging to a #GSettingsSchema created from a
* schema source returned by this function.
*
* See g_settings_schema_source_new_from_directory() for more information.
*
* Returns: (transfer full) (nullable): a new #GSettingsSchemaSource, or %NULL
*
* Since: 2.78
**/
GSettingsSchemaSource *
g_settings_schema_source_new_from_bytes (GBytes *bytes,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error)
{
GSettingsSchemaSource *source;
GvdbTable *table;
g_return_val_if_fail (bytes != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
table = gvdb_table_new_from_bytes (bytes, trusted, error);
if (table == NULL)
return NULL;
source = g_slice_new0 (GSettingsSchemaSource);
source->parent = parent ? g_settings_schema_source_ref (parent) : NULL;
source->table = table;
source->ref_count = 1;
source->type = G_SETTINGS_SCHEMA_SOURCE_BYTES;
return source;
}
/**
* g_settings_schema_source_new_from_resource:
* @path: the resource path
* @lookup_flags: A #GResourceLookupFlags
* @parent: (nullable): a #GSettingsSchemaSource, or %NULL
* @trusted: %TRUE, if the resource is trusted
* @error: a pointer to a #GError pointer set to %NULL, or %NULL
*
* Attempts to create a new schema source corresponding to the contents
* of the given resource, which should contain the data as produced by the
* [glib-compile-schemas][glib-compile-schemas] tool.
*
* This should only be used in standalone applications and should not
* be used in situations where settings are shared with other applications.
*
* Note that for g_settings_schema_key_get_summary() and
* g_settings_schema_key_get_description() to work, an XML schema resource
* $path.xml must be present.
*
* See g_settings_schema_source_new_from_directory() for more information.
*
* Returns: (transfer full): a new #GSettingsSchemaSource, or %NULL
*
* Since: 2.78
**/
GSettingsSchemaSource *
g_settings_schema_source_new_from_resource (const gchar *path,
GResourceLookupFlags lookup_flags,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error)
{
GSettingsSchemaSource *source;
GBytes *bytes;
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
bytes = g_resources_lookup_data (path, lookup_flags, error);
if (bytes == NULL)
return NULL;
source = g_settings_schema_source_new_from_bytes (bytes, parent, trusted, error);
if (source == NULL) {
g_bytes_unref (bytes);
return NULL;
}
g_bytes_unref (bytes);
source->type = G_SETTINGS_SCHEMA_SOURCE_RESOURCE;
source->type_data.resource.path = g_strdup (path);
source->type_data.resource.lookup_flags = lookup_flags;
return source;
}
@@ -680,12 +855,35 @@ text (GMarkupParseContext *context,
}
static void
parse_into_text_tables (const gchar *directory,
parse_into_text_tables (const char *data,
gsize size,
GHashTable *summaries,
GHashTable *descriptions)
{
GMarkupParser parser = { start_element, end_element, text, NULL, NULL };
TextTableParseInfo info = { summaries, descriptions, NULL, NULL, NULL, NULL };
GMarkupParseContext *context;
context = g_markup_parse_context_new (&parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &info, NULL);
/* Ignore errors here, this is best effort only. */
if (g_markup_parse_context_parse (context, data, size, NULL))
(void) g_markup_parse_context_end_parse (context, NULL);
g_markup_parse_context_free (context);
/* Clean up dangling stuff in case there was an error. */
g_slist_free_full (info.gettext_domain, g_free);
g_slist_free_full (info.schema_id, g_free);
g_slist_free_full (info.key_name, g_free);
if (info.string)
g_string_free (info.string, TRUE);
}
static void
parse_into_text_tables_directory (const gchar *directory,
GHashTable *summaries,
GHashTable *descriptions)
{
const gchar *basename;
GDir *dir;
@@ -699,29 +897,7 @@ parse_into_text_tables (const gchar *directory,
filename = g_build_filename (directory, basename, NULL);
if (g_file_get_contents (filename, &contents, &size, NULL))
{
GMarkupParseContext *context;
context = g_markup_parse_context_new (&parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &info, NULL);
/* Ignore errors here, this is best effort only. */
if (g_markup_parse_context_parse (context, contents, size, NULL))
(void) g_markup_parse_context_end_parse (context, NULL);
g_markup_parse_context_free (context);
/* Clean up dangling stuff in case there was an error. */
g_slist_free_full (info.gettext_domain, g_free);
g_slist_free_full (info.schema_id, g_free);
g_slist_free_full (info.key_name, g_free);
info.gettext_domain = NULL;
info.schema_id = NULL;
info.key_name = NULL;
if (info.string)
{
g_string_free (info.string, TRUE);
info.string = NULL;
}
parse_into_text_tables (contents, size, summaries, descriptions);
g_free (contents);
}
@@ -731,6 +907,68 @@ parse_into_text_tables (const gchar *directory,
g_dir_close (dir);
}
static void
parse_into_text_tables_resource (const char *path,
GResourceLookupFlags lookup_flags,
GHashTable *summaries,
GHashTable *descriptions)
{
char *xml_path;
GError *error = NULL;
GBytes *bytes;
const char *data;
gsize size, i;
char **resources;
/* First try loading the XML schema data from @path + '.xml'. */
xml_path = g_strdup_printf ("%s.xml", path);
bytes = g_resources_lookup_data (xml_path, lookup_flags, &error);
g_free (xml_path);
if (bytes)
{
data = g_bytes_get_data (bytes, &size);
parse_into_text_tables (data, size, summaries, descriptions);
g_bytes_unref (bytes);
return;
}
if (!g_error_matches (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
{
g_error_free (error);
return;
}
g_error_free (error);
/* If there is no singular @path + '.xml' resource, try to load all
* resources from under the @path + '.xml/' path.
*/
xml_path = g_strdup_printf ("%s.xml/", path);
resources = g_resources_enumerate_children (xml_path, lookup_flags, NULL);
if (!resources)
{
g_free (xml_path);
return;
}
for (i = 0; resources[i] != NULL; i++)
{
char *child_path;
child_path = g_strconcat (xml_path, resources[i], NULL);
bytes = g_resources_lookup_data (child_path, lookup_flags, NULL);
g_free (child_path);
if (!bytes)
continue;
data = g_bytes_get_data (bytes, &size);
parse_into_text_tables (data, size, summaries, descriptions);
g_bytes_unref (bytes);
}
g_free (xml_path);
g_strfreev (resources);
}
static GHashTable **
g_settings_schema_source_get_text_tables (GSettingsSchemaSource *source)
{
@@ -742,8 +980,19 @@ g_settings_schema_source_get_text_tables (GSettingsSchemaSource *source)
text_tables[0] = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_unref);
text_tables[1] = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_unref);
if (source->directory)
parse_into_text_tables (source->directory, text_tables[0], text_tables[1]);
if (source->type == G_SETTINGS_SCHEMA_SOURCE_FILE)
{
parse_into_text_tables_directory (source->type_data.file.directory, text_tables[0], text_tables[1]);
}
else if (source->type == G_SETTINGS_SCHEMA_SOURCE_RESOURCE)
{
parse_into_text_tables_resource (source->type_data.resource.path, source->type_data.resource.lookup_flags,
text_tables[0], text_tables[1]);
}
else if (source->type == G_SETTINGS_SCHEMA_SOURCE_BYTES)
{
/* Nothing to do in this case. */
}
g_once_init_leave_pointer (&source->text_tables, text_tables);
}
@@ -1704,6 +1953,12 @@ g_settings_schema_key_get_name (GSettingsSchemaKey *key)
* If no summary has been provided in the schema for @key, returns
* %NULL.
*
* This function only works on keys belonging to a #GSettingsSchema
* created from a #GSettingsSchemaSource created with
* g_settings_schema_source_new_from_directory() or
* g_settings_schema_source_new_from_path(), and requires the source
* XML file to be present in the same directory as the compiled schema.
*
* The summary is a short description of the purpose of the key; usually
* one short sentence. Summaries can be translated and the value
* returned from this function is is the current locale.
@@ -1738,6 +1993,12 @@ g_settings_schema_key_get_summary (GSettingsSchemaKey *key)
* If no description has been provided in the schema for @key, returns
* %NULL.
*
* This function only works on keys belonging to a #GSettingsSchema
* created from a #GSettingsSchemaSource created with
* g_settings_schema_source_new_from_directory() or
* g_settings_schema_source_new_from_path(), and requires the source
* XML file to be present in the same directory as the compiled schema.
*
* The description can be one sentence to several paragraphs in length.
* Paragraphs are delimited with a double newline. Descriptions can be
* translated and the value returned from this function is is the

View File

@@ -23,6 +23,7 @@
#include <glib-object.h>
#include <gio/gio-visibility.h>
#include <gio/gioenums.h>
G_BEGIN_DECLS
@@ -47,6 +48,25 @@ GSettingsSchemaSource * g_settings_schema_source_new_from_directory (const g
gboolean trusted,
GError **error);
GIO_AVAILABLE_IN_2_78
GSettingsSchemaSource * g_settings_schema_source_new_from_path (const gchar *path,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error);
GIO_AVAILABLE_IN_2_78
GSettingsSchemaSource * g_settings_schema_source_new_from_bytes (GBytes *bytes,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error);
GIO_AVAILABLE_IN_2_78
GSettingsSchemaSource * g_settings_schema_source_new_from_resource (const gchar *path,
GResourceLookupFlags lookup_flags,
GSettingsSchemaSource *parent,
gboolean trusted,
GError **error);
GIO_AVAILABLE_IN_2_32
GSettingsSchema * g_settings_schema_source_lookup (GSettingsSchemaSource *source,
const gchar *schema_id,

View File

@@ -2811,7 +2811,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
}
static void
test_schema_source (void)
test_schema_source_directory (void)
{
GSettingsSchemaSource *parent;
GSettingsSchemaSource *source;
@@ -2910,6 +2910,325 @@ test_schema_source (void)
g_object_unref (backend);
}
static void
test_schema_source_path (void)
{
GSettingsSchemaSource *parent;
GSettingsSchemaSource *source;
GSettingsBackend *backend;
GSettingsSchema *schema;
GError *error = NULL;
GSettings *settings, *child;
gboolean enabled;
backend = g_settings_backend_get_default ();
/* make sure it fails properly */
parent = g_settings_schema_source_get_default ();
source = g_settings_schema_source_new_from_path ("/path/that/does/not/exist/gschemas.compiled", parent, TRUE, &error);
g_assert_null (source);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
g_clear_error (&error);
/* Test error handling of corrupt compiled files. */
source = g_settings_schema_source_new_from_path ("schema-source-corrupt/gschemas.compiled", parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* Test error handling of empty compiled files. */
source = g_settings_schema_source_new_from_path ("schema-source-empty/gschemas.compiled", parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* create a source with the parent */
source = g_settings_schema_source_new_from_path ("schema-source/gschemas.compiled", parent, TRUE, &error);
g_assert_no_error (error);
g_assert_nonnull (source);
/* check recursive lookups are working */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive lookups for non-existent schemas */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
g_assert_null (schema);
/* check non-recursive for schema that only exists in lower layers */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
/* check non-recursive lookup for non-existent */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
g_assert_null (schema);
/* check non-recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
/* try to use it for something */
settings = g_settings_new_full (schema, backend, "/test/");
g_settings_schema_unref (schema);
enabled = FALSE;
g_settings_get (settings, "enabled", "b", &enabled);
g_assert_true (enabled);
/* Check that child schemas are resolved from the correct schema source, see glib#1884 */
child = g_settings_get_child (settings, "child");
g_settings_get (settings, "enabled", "b", &enabled);
g_object_unref (child);
g_object_unref (settings);
g_settings_schema_source_unref (source);
/* try again, but with no parent */
source = g_settings_schema_source_new_from_path ("schema-source/gschemas.compiled", NULL, FALSE, NULL);
g_assert_nonnull (source);
/* should not find it this time, even if recursive... */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_null (schema);
/* should still find our own... */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
g_settings_schema_source_unref (source);
g_object_unref (backend);
}
static void
test_schema_source_bytes (void)
{
GSettingsSchemaSource *parent;
GSettingsSchemaSource *source;
GSettingsBackend *backend;
GSettingsSchema *schema;
GError *error = NULL;
GSettings *settings, *child;
gboolean enabled;
GFile *corrupt_schema_file, *empty_schema_file, *normal_schema_file;
GBytes *corrupt_schema_bytes, *empty_schema_bytes, *normal_schema_bytes;
backend = g_settings_backend_get_default ();
parent = g_settings_schema_source_get_default ();
/* Read the schemas into bytes */
corrupt_schema_file = g_file_new_for_path("schema-source-corrupt/gschemas.compiled");
corrupt_schema_bytes = g_file_load_bytes(corrupt_schema_file, NULL, NULL, NULL);
empty_schema_file = g_file_new_for_path("schema-source-empty/gschemas.compiled");
empty_schema_bytes = g_file_load_bytes(empty_schema_file, NULL, NULL, NULL);
normal_schema_file = g_file_new_for_path("schema-source/gschemas.compiled");
normal_schema_bytes = g_file_load_bytes(normal_schema_file, NULL, NULL, NULL);
/* Test error handling of corrupt compiled files. */
source = g_settings_schema_source_new_from_bytes (corrupt_schema_bytes, parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* Test error handling of empty compiled files. */
source = g_settings_schema_source_new_from_bytes (empty_schema_bytes, parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* create a source with the parent */
source = g_settings_schema_source_new_from_bytes (normal_schema_bytes, parent, TRUE, &error);
g_assert_no_error (error);
g_assert_nonnull (source);
/* check recursive lookups are working */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive lookups for non-existent schemas */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
g_assert_null (schema);
/* check non-recursive for schema that only exists in lower layers */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
/* check non-recursive lookup for non-existent */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
g_assert_null (schema);
/* check non-recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
/* try to use it for something */
settings = g_settings_new_full (schema, backend, "/test/");
g_settings_schema_unref (schema);
enabled = FALSE;
g_settings_get (settings, "enabled", "b", &enabled);
g_assert_true (enabled);
/* Check that child schemas are resolved from the correct schema source, see glib#1884 */
child = g_settings_get_child (settings, "child");
g_settings_get (settings, "enabled", "b", &enabled);
g_object_unref (child);
g_object_unref (settings);
g_settings_schema_source_unref (source);
g_bytes_unref(empty_schema_bytes);
g_object_unref(empty_schema_file);
g_bytes_unref(corrupt_schema_bytes);
g_object_unref(corrupt_schema_file);
/* try again, but with no parent */
source = g_settings_schema_source_new_from_bytes (normal_schema_bytes, NULL, FALSE, NULL);
g_assert_nonnull (source);
/* should not find it this time, even if recursive... */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_null (schema);
/* should still find our own... */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
g_settings_schema_source_unref (source);
g_bytes_unref(normal_schema_bytes);
g_object_unref(normal_schema_file);
g_object_unref (backend);
}
static void
test_schema_source_resource (void)
{
GSettingsSchemaSource *parent;
GSettingsSchemaSource *source;
GSettingsBackend *backend;
GSettingsSchema *schema;
GSettingsSchemaKey *key;
GError *error = NULL;
GSettings *settings, *child;
gboolean enabled;
backend = g_settings_backend_get_default ();
parent = g_settings_schema_source_get_default ();
/* Test error handling of corrupt compiled files. */
source = g_settings_schema_source_new_from_resource ("/schema-source-corrupt/gschemas.compiled", G_RESOURCE_LOOKUP_FLAGS_NONE, parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* Test error handling of empty compiled files. */
source = g_settings_schema_source_new_from_resource ("/schema-source-empty/gschemas.compiled", G_RESOURCE_LOOKUP_FLAGS_NONE, parent, TRUE, &error);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
g_assert_null (source);
g_clear_error (&error);
/* create a source with the parent */
source = g_settings_schema_source_new_from_resource ("/schema-source/gschemas.compiled", G_RESOURCE_LOOKUP_FLAGS_NONE, parent, TRUE, &error);
g_assert_no_error (error);
g_assert_nonnull (source);
/* check recursive lookups are working */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive lookups for non-existent schemas */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
g_assert_null (schema);
/* check non-recursive for schema that only exists in lower layers */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
/* check non-recursive lookup for non-existent */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
g_assert_null (schema);
/* check non-recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
/* check summary and description lookup */
key = g_settings_schema_get_key (schema, "enabled");
g_assert_cmpstr (g_settings_schema_key_get_summary (key), ==, "Boolean setting test");
g_assert_cmpstr (g_settings_schema_key_get_description (key), ==, "Setting to test boolean settings");
g_settings_schema_key_unref (key);
key = g_settings_schema_get_key (schema, "nosummary");
g_assert_null (g_settings_schema_key_get_summary (key));
g_assert_null (g_settings_schema_key_get_description (key));
g_settings_schema_key_unref (key);
/* try to use it for something */
settings = g_settings_new_full (schema, backend, "/test/");
g_settings_schema_unref (schema);
enabled = FALSE;
g_settings_get (settings, "enabled", "b", &enabled);
g_assert_true (enabled);
/* Check that child schemas are resolved from the correct schema source, see glib#1884 */
child = g_settings_get_child (settings, "child");
g_settings_get (settings, "enabled", "b", &enabled);
g_object_unref (child);
g_object_unref (settings);
g_settings_schema_source_unref (source);
/* try again, but with no parent */
source = g_settings_schema_source_new_from_resource ("/schema-source/gschemas.compiled", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, TRUE, &error);
g_assert_nonnull (source);
/* should not find it this time, even if recursive... */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
g_assert_null (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
g_assert_null (schema);
/* should still find our own... */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
g_assert_nonnull (schema);
g_settings_schema_unref (schema);
g_settings_schema_source_unref (source);
g_object_unref (backend);
}
static void
test_schema_list_keys (void)
{
@@ -3269,6 +3588,7 @@ main (int argc, char *argv[])
gchar *schema_text;
gchar *override_text;
gchar *enums;
GResource *loaded_resource;
gint result;
const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" };
const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" };
@@ -3296,6 +3616,7 @@ main (int argc, char *argv[])
GError *local_error = NULL;
char *subprocess_stdout = NULL;
gboolean rv;
/* A GVDB header is 6 guint32s, and requires a magic number in the first
* two guint32s. A set of zero bytes of a greater length is considered
* corrupt. */
@@ -3329,6 +3650,10 @@ main (int argc, char *argv[])
g_assert_true (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
g_free (override_text);
g_assert_true (g_file_get_contents (SRCDIR "/schema_from_resource_test.gresource.xml", &override_text, NULL, NULL));
g_assert_true (g_file_set_contents ("schema_from_resource_test.gresource.xml", override_text, -1, NULL));
g_free (override_text);
g_remove ("gschemas.compiled");
/* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
@@ -3342,6 +3667,7 @@ main (int argc, char *argv[])
g_assert_cmpint (result, ==, 0);
g_remove ("schema-source/gschemas.compiled");
g_remove ("schema-source/org.gtk.schemasourcecheck.gschema.xml");
g_mkdir ("schema-source", 0777);
g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
"--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
@@ -3351,6 +3677,10 @@ main (int argc, char *argv[])
g_clear_pointer (&subprocess_stdout, g_free);
g_assert_cmpint (result, ==, 0);
g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.schemasourcecheck.gschema.xml", &override_text, NULL, NULL));
g_assert_true (g_file_set_contents ("schema-source/org.gtk.schemasourcecheck.gschema.xml", override_text, -1, NULL));
g_free (override_text);
g_remove ("schema-source-corrupt/gschemas.compiled");
g_mkdir ("schema-source-corrupt", 0777);
g_file_set_contents ("schema-source-corrupt/gschemas.compiled",
@@ -3365,6 +3695,23 @@ main (int argc, char *argv[])
"", 0,
&local_error);
g_assert_no_error (local_error);
/* #GLIB_COMPILE_RESOURCES is defined in meson.build */
rv = g_spawn_command_line_sync (GLIB_COMPILE_RESOURCES
" schema_from_resource_test.gresource.xml "
"--target=schema_from_resource_test.gresource",
NULL, NULL, &result, &local_error);
g_assert_no_error (local_error);
g_assert_true (rv);
rv = g_spawn_check_wait_status (result, &local_error);
g_assert_no_error (local_error);
g_assert_true (rv);
g_remove ("schema_from_resource_test.gresource.xml");
loaded_resource = g_resource_load ("schema_from_resource_test.gresource", &local_error);
g_remove ("schema_from_resource_test.gresource");
g_assert_no_error (local_error);
g_resources_register (loaded_resource);
}
g_test_add_func ("/gsettings/basic", test_basic);
@@ -3437,7 +3784,10 @@ main (int argc, char *argv[])
g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
g_test_add_func ("/gsettings/mapped", test_get_mapped);
g_test_add_func ("/gsettings/get-range", test_get_range);
g_test_add_func ("/gsettings/schema-source", test_schema_source);
g_test_add_func ("/gsettings/schema-source/directory", test_schema_source_directory);
g_test_add_func ("/gsettings/schema-source/path", test_schema_source_path);
g_test_add_func ("/gsettings/schema-source/bytes", test_schema_source_bytes);
g_test_add_func ("/gsettings/schema-source/resource", test_schema_source_resource);
g_test_add_func ("/gsettings/schema-list-keys", test_schema_list_keys);
g_test_add_func ("/gsettings/actions", test_actions);
g_test_add_func ("/gsettings/null-backend", test_null_backend);

View File

@@ -9,6 +9,7 @@ test_c_args = [
'-DG_LOG_DOMAIN="GLib-GIO"',
'-DGLIB_MKENUMS="@0@"'.format(glib_mkenums.full_path()),
'-DGLIB_COMPILE_SCHEMAS="@0@"'.format(glib_compile_schemas.full_path()),
'-DGLIB_COMPILE_RESOURCES="@0@"'.format(glib_compile_resources.full_path()),
'-UG_DISABLE_ASSERT',
]
@@ -631,7 +632,7 @@ if host_machine.system() != 'windows'
'c_args' : ['-DSRCDIR="@0@"'.format(meson.current_source_dir()),
'-DTEST_LOCALE_PATH="@0@"'.format(test_mo_dir)],
'install' : false,
'depends' : glib_compile_schemas,
'depends' : [glib_compile_schemas, glib_compile_resources],
# FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/3148
'can_fail' : host_system == 'gnu',
},

View File

@@ -2,6 +2,13 @@
<schema id="org.gtk.schemasourcecheck">
<key name="enabled" type="b">
<default>true</default>
<summary>Boolean setting test</summary>
<description>
Setting to test boolean settings
</description>
</key>
<key name="nosummary" type="b">
<default>true</default>
</key>
<child name="child" schema="org.gtk.schemasourcecheck" />
</schema>

View File

@@ -0,0 +1,14 @@
<gresources>
<gresource>
<file>schema-source-corrupt/gschemas.compiled</file>
</gresource>
<gresource>
<file>schema-source-empty/gschemas.compiled</file>
</gresource>
<gresource>
<file>schema-source/gschemas.compiled</file>
</gresource>
<gresource>
<file alias="schema-source/gschemas.compiled.xml">schema-source/org.gtk.schemasourcecheck.gschema.xml</file>
</gresource>
</gresources>

Submodule subprojects/gvdb deleted from 2b42fc75f0