From cef772ac5ca3e4b771f8237cbfced5797fa6c1f7 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Wed, 31 Aug 2016 21:40:31 +0200 Subject: [PATCH] Fix cache (de)serialization for screenshots and suggestions This resolves #66 --- src/as-bundle.c | 22 +++---- src/as-bundle.h | 4 +- src/as-cache-file.c | 118 ++++++++++++++++++++++++++++--------- src/as-component-private.h | 1 + src/as-pool.c | 2 +- src/as-xmldata.c | 2 +- src/as-yamldata.c | 2 +- tests/test-pool.c | 72 ++++++++++++++++++++-- 8 files changed, 174 insertions(+), 49 deletions(-) diff --git a/src/as-bundle.c b/src/as-bundle.c index e9a538fac..5cd7d663e 100644 --- a/src/as-bundle.c +++ b/src/as-bundle.c @@ -44,42 +44,42 @@ G_DEFINE_TYPE_WITH_PRIVATE (AsBundle, as_bundle, G_TYPE_OBJECT) /** * as_bundle_kind_to_string: - * @bundle_kind: the %AsBundleKind. + * @kind: the %AsBundleKind. * * Converts the enumerated value to an text representation. * - * Returns: string version of @bundle_kind + * Returns: string version of @kind * * Since: 0.8.0 **/ const gchar* -as_bundle_kind_to_string (AsBundleKind bundle_kind) +as_bundle_kind_to_string (AsBundleKind kind) { - if (bundle_kind == AS_BUNDLE_KIND_PACKAGE) + if (kind == AS_BUNDLE_KIND_PACKAGE) return "package"; - if (bundle_kind == AS_BUNDLE_KIND_LIMBA) + if (kind == AS_BUNDLE_KIND_LIMBA) return "limba"; - if (bundle_kind == AS_BUNDLE_KIND_FLATPAK) + if (kind == AS_BUNDLE_KIND_FLATPAK) return "flatpak"; return "unknown"; } /** * as_bundle_kind_from_string: - * @bundle_kind: the string. + * @bundle_str: the string. * * Converts the text representation to an enumerated value. * * Returns: a #AsBundleKind or %AS_BUNDLE_KIND_UNKNOWN for unknown **/ AsBundleKind -as_bundle_kind_from_string (const gchar *bundle_kind) +as_bundle_kind_from_string (const gchar *bundle_str) { - if (g_strcmp0 (bundle_kind, "package") == 0) + if (g_strcmp0 (bundle_str, "package") == 0) return AS_BUNDLE_KIND_PACKAGE; - if (g_strcmp0 (bundle_kind, "limba") == 0) + if (g_strcmp0 (bundle_str, "limba") == 0) return AS_BUNDLE_KIND_LIMBA; - if (g_strcmp0 (bundle_kind, "flatpak") == 0) + if (g_strcmp0 (bundle_str, "flatpak") == 0) return AS_BUNDLE_KIND_FLATPAK; return AS_BUNDLE_KIND_UNKNOWN; } diff --git a/src/as-bundle.h b/src/as-bundle.h index 9b686208a..fc74c5bcc 100644 --- a/src/as-bundle.h +++ b/src/as-bundle.h @@ -62,8 +62,8 @@ typedef enum { AS_BUNDLE_KIND_LAST } AsBundleKind; -const gchar *as_bundle_kind_to_string (AsBundleKind bundle_kind); -AsBundleKind as_bundle_kind_from_string (const gchar *bundle_kind); +const gchar *as_bundle_kind_to_string (AsBundleKind kind); +AsBundleKind as_bundle_kind_from_string (const gchar *bundle_str); AsBundle *as_bundle_new (void); diff --git a/src/as-cache-file.c b/src/as-cache-file.c index b43d62125..8da5a71d3 100644 --- a/src/as-cache-file.c +++ b/src/as-cache-file.c @@ -95,11 +95,13 @@ as_string_ptrarray_to_variant (GPtrArray *strarray) static void as_bundle_array_to_variant_cb (AsBundle *bundle, GVariantBuilder *builder) { - GVariant *bundle_var; - bundle_var = g_variant_new_parsed ("({'type', %u},{'id', %s})", - as_bundle_get_kind (bundle), - as_bundle_get_id (bundle)); - g_variant_builder_add_value (builder, bundle_var); + GVariantBuilder bundle_b; + g_variant_builder_init (&bundle_b, G_VARIANT_TYPE_ARRAY); + + g_variant_builder_add_parsed (&bundle_b, "{'type', <%u>}", as_bundle_get_kind (bundle)); + g_variant_builder_add_parsed (&bundle_b, "{'id', <%s>}", as_bundle_get_id (bundle)); + + g_variant_builder_add_value (builder, g_variant_builder_end (&bundle_b)); } /** @@ -123,15 +125,17 @@ as_url_table_to_variant_cb (gpointer ukind_ptr, const gchar *value, GVariantBuil static void as_images_array_to_variant_cb (AsImage *img, GVariantBuilder *builder) { - GVariant *image_var; - - image_var = g_variant_new_parsed ("({'type', %u},{'url', %s},{'width', %i},{'height', %i},{'locale', %v})", - as_image_get_kind (img), - as_image_get_url (img), - as_image_get_width (img), - as_image_get_height (img), - as_variant_mstring_new (as_image_get_locale (img))); - g_variant_builder_add_value (builder, image_var); + GVariantBuilder image_b; + + g_variant_builder_init (&image_b, G_VARIANT_TYPE_ARRAY); + + g_variant_builder_add_parsed (&image_b, "{'type', <%u>}", as_image_get_kind (img)); + g_variant_builder_add_parsed (&image_b, "{'url', <%s>}", as_image_get_url (img)); + g_variant_builder_add_parsed (&image_b, "{'width', <%i>}", as_image_get_width (img)); + g_variant_builder_add_parsed (&image_b, "{'height', <%i>}", as_image_get_height (img)); + g_variant_builder_add_parsed (&image_b, "{'locale', %v}", as_variant_mstring_new (as_image_get_locale (img))); + + g_variant_builder_add_value (builder, g_variant_builder_end (&image_b)); } /** @@ -410,22 +414,24 @@ as_cache_file_save (const gchar *fname, const gchar *locale, GPtrArray *cpts, GE } } - locations_var = g_variant_new_maybe (G_VARIANT_TYPE_STRING_ARRAY, - as_string_ptrarray_to_variant (as_release_get_locations (rel))); - checksums_var = g_variant_new_maybe ((const GVariantType *) "a{us}", - checksums->len > 0? g_variant_builder_end (&checksum_b) : NULL); - sizes_var = g_variant_new_maybe ((const GVariantType *) "a{ut}", - have_sizes? g_variant_builder_end (&sizes_b) : NULL); - g_variant_builder_init (&rel_b, G_VARIANT_TYPE_ARRAY); g_variant_builder_add_parsed (&rel_b, "{'version', %v}", as_variant_mstring_new (as_release_get_version (rel))); g_variant_builder_add_parsed (&rel_b, "{'timestamp', <%t>}", as_release_get_timestamp (rel)); g_variant_builder_add_parsed (&rel_b, "{'urgency', <%u>}", as_release_get_urgency (rel)); - g_variant_builder_add_parsed (&rel_b, "{'locations', %v}", locations_var); - g_variant_builder_add_parsed (&rel_b, "{'checksums', %v}", checksums_var); - g_variant_builder_add_parsed (&rel_b, "{'sizes', %v}", sizes_var); g_variant_builder_add_parsed (&rel_b, "{'description', %v}", as_variant_mstring_new (as_release_get_description (rel))); + locations_var = as_string_ptrarray_to_variant (as_release_get_locations (rel)); + if (locations_var) + g_variant_builder_add_parsed (&rel_b, "{'locations', %v}", locations_var); + + checksums_var = checksums->len > 0? g_variant_builder_end (&checksum_b) : NULL; + if (checksums_var) + g_variant_builder_add_parsed (&rel_b, "{'checksums', %v}", checksums_var); + + sizes_var = have_sizes? g_variant_builder_end (&sizes_b) : NULL; + if (sizes_var) + g_variant_builder_add_parsed (&rel_b, "{'sizes', %v}", sizes_var); + g_variant_builder_add_value (&array_b, g_variant_builder_end (&rel_b)); } @@ -445,6 +451,24 @@ as_cache_file_save (const gchar *fname, const gchar *locale, GPtrArray *cpts, GE g_variant_builder_end (&dict_b)); } + /* suggestions */ + tmp_array_ref = as_component_get_suggested (cpt); + if (tmp_array_ref->len > 0) { + g_variant_builder_init (&array_b, G_VARIANT_TYPE_ARRAY); + for (i = 0; i < tmp_array_ref->len; i++) { + AsSuggested *suggested = AS_SUGGESTED (g_ptr_array_index (tmp_array_ref, i)); + GVariant *sug_var; + + sug_var = g_variant_new ("{uv}", + as_suggested_get_kind (suggested), + as_string_ptrarray_to_variant (as_suggested_get_ids (suggested))); + g_variant_builder_add_value (&array_b, sug_var); + } + + as_variant_builder_add_kv (&cb, "suggestions", + g_variant_builder_end (&array_b)); + } + /* search tokens */ as_component_create_token_cache (cpt); tmp_table_ref = as_component_get_token_cache_table (cpt); @@ -808,7 +832,7 @@ as_cache_file_read (const gchar *fname, GError **error) g_variant_unref (var); /* bundles */ - var = g_variant_dict_lookup_value (&dict, "bundles", G_VARIANT_TYPE_STRING_ARRAY); + var = g_variant_dict_lookup_value (&dict, "bundles", G_VARIANT_TYPE_ARRAY); if (var != NULL) { GVariant *child; @@ -985,7 +1009,7 @@ as_cache_file_read (const gchar *fname, GError **error) locale); g_variant_unref (tmp); - images_var = g_variant_dict_lookup_value (&idict, "images", G_VARIANT_TYPE_VARIANT); + images_var = g_variant_dict_lookup_value (&idict, "images", G_VARIANT_TYPE_ARRAY); if (images_var != NULL) { GVariant *img_child; g_variant_iter_init (&inner_iter, images_var); @@ -1035,8 +1059,13 @@ as_cache_file_read (const gchar *fname, GError **error) locale); g_variant_unref (tmp); + /* locations */ + as_variant_to_string_ptrarray_by_dict (&dict, + "locations", + as_release_get_locations (rel)); + /* sizes */ - tmp = g_variant_dict_lookup_value (&rdict, "sizes", G_VARIANT_TYPE_VARIANT); + tmp = g_variant_dict_lookup_value (&rdict, "sizes", G_VARIANT_TYPE_DICTIONARY); if (tmp != NULL) { g_variant_iter_init (&riter, tmp); while ((inner_child = g_variant_iter_next_value (&riter))) { @@ -1044,7 +1073,7 @@ as_cache_file_read (const gchar *fname, GError **error) guint64 size; g_variant_get (inner_child, "{ut}", &kind, &size); - as_release_set_size (rel, kind, size); + as_release_set_size (rel, size, kind); g_variant_unref (inner_child); } @@ -1052,7 +1081,7 @@ as_cache_file_read (const gchar *fname, GError **error) } /* checksums */ - tmp = g_variant_dict_lookup_value (&rdict, "checksums", G_VARIANT_TYPE_VARIANT); + tmp = g_variant_dict_lookup_value (&rdict, "checksums", G_VARIANT_TYPE_DICTIONARY); if (tmp != NULL) { g_variant_iter_init (&riter, var); while ((inner_child = g_variant_iter_next_value (&riter))) { @@ -1096,6 +1125,37 @@ as_cache_file_read (const gchar *fname, GError **error) g_variant_unref (var); } + /* suggestions */ + var = g_variant_dict_lookup_value (&dict, + "suggestions", + G_VARIANT_TYPE_ARRAY); + if (var != NULL) { + GVariant *child; + + g_variant_iter_init (&gvi, var); + while ((child = g_variant_iter_next_value (&gvi))) { + AsSuggestedKind kind; + GVariantIter inner_iter; + GVariant *id_child; + g_autoptr(GVariant) ids_var = NULL; + g_autoptr(AsSuggested) suggested = as_suggested_new (); + + g_variant_get (child, "{uv}", &kind, &ids_var); + as_suggested_set_kind (suggested, kind); + + g_variant_iter_init (&inner_iter, ids_var); + while ((id_child = g_variant_iter_next_value (&inner_iter))) { + as_suggested_add_id (suggested, + g_variant_get_string (id_child, NULL)); + g_variant_unref (id_child); + } + + as_component_add_suggested (cpt, suggested); + g_variant_unref (child); + } + g_variant_unref (var); + } + /* search tokens */ var = g_variant_dict_lookup_value (&dict, "tokens", diff --git a/src/as-component-private.h b/src/as-component-private.h index 2599287a4..c7b146fca 100644 --- a/src/as-component-private.h +++ b/src/as-component-private.h @@ -43,6 +43,7 @@ GHashTable *as_component_get_summary_table (AsComponent *cpt); GHashTable *as_component_get_description_table (AsComponent *cpt); GHashTable *as_component_get_developer_name_table (AsComponent *cpt); GHashTable *as_component_get_keywords_table (AsComponent *cpt); +AS_INTERNAL_VISIBLE GHashTable *as_component_get_languages_table (AsComponent *cpt); void as_component_set_bundles_array (AsComponent *cpt, diff --git a/src/as-pool.c b/src/as-pool.c index 1065a706c..17d04ce90 100644 --- a/src/as-pool.c +++ b/src/as-pool.c @@ -1033,7 +1033,7 @@ as_pool_build_search_terms (AsPool *pool, const gchar *search) /** * as_sort_components_by_score_cb: * - * helper method to sort result arrays by the #AsComponent match score. + * Helper method to sort result arrays by the #AsComponent match score. */ static gint as_sort_components_by_score_cb (gconstpointer a, gconstpointer b) diff --git a/src/as-xmldata.c b/src/as-xmldata.c index a2dc0c07e..7e847d158 100644 --- a/src/as-xmldata.c +++ b/src/as-xmldata.c @@ -1906,7 +1906,7 @@ as_xmldata_component_to_node (AsXMLData *xdt, AsComponent *cpt) (xmlChar*) as_bundle_get_id (bundle)); xmlNewProp (n, (xmlChar*) "type", - (xmlChar*) as_bundle_kind_to_string (i)); + (xmlChar*) as_bundle_kind_to_string (as_bundle_get_kind (bundle))); } /* translations */ diff --git a/src/as-yamldata.c b/src/as-yamldata.c index 3c12e91b1..aea7347c1 100644 --- a/src/as-yamldata.c +++ b/src/as-yamldata.c @@ -366,7 +366,7 @@ as_yaml_process_bundles (GNode *node, AsComponent *cpt) } else if (g_strcmp0 (key, "id") == 0) { as_bundle_set_id (bundle, value); } else { - as_yaml_print_unknown ("bundle", key); + as_yaml_print_unknown ("bundles", key); } } diff --git a/tests/test-pool.c b/tests/test-pool.c index bac774afb..1a679e72d 100644 --- a/tests/test-pool.c +++ b/tests/test-pool.c @@ -22,8 +22,10 @@ #include #include "appstream.h" -#include "../src/as-utils-private.h" #include "as-cache-file.h" +#include "as-test-utils.h" +#include "../src/as-utils-private.h" +#include "../src/as-component-private.h" static gchar *datadir = NULL; @@ -148,6 +150,69 @@ test_get_sampledata_pool (gboolean use_caches) return pool; } +/** + * as_sort_components_cb: + * + * Helper method to sort lists of #AsComponent + */ +static gint +as_sort_components_cb (gconstpointer a, gconstpointer b) +{ + AsComponent *cpt1 = *((AsComponent **) a); + AsComponent *cpt2 = *((AsComponent **) b); + + return g_strcmp0 (as_component_get_id (cpt1), + as_component_get_id (cpt2)); +} + +/** + * as_assert_component_lists_equal: + * + * Check if the components present in the two #GPtrArray are equal. + */ +static void +as_assert_component_lists_equal (GPtrArray *cpts_a, GPtrArray *cpts_b) +{ + guint i; + g_autofree gchar *cpts_a_xml = NULL; + g_autofree gchar *cpts_b_xml = NULL; + GError *error = NULL; + g_autoptr(AsMetadata) metad = as_metadata_new (); + + /* sort */ + g_ptr_array_sort (cpts_a, as_sort_components_cb); + g_ptr_array_sort (cpts_b, as_sort_components_cb); + + for (i = 0; i < cpts_a->len; i++) { + AsComponent *cpt = AS_COMPONENT (g_ptr_array_index (cpts_a, i)); + /* we ignore keywords for now */ + as_component_set_keywords (cpt, NULL, "C"); + /* FIXME: And languages, because their ordering on serialization is random. */ + g_hash_table_remove_all (as_component_get_languages_table (cpt)); + + as_metadata_add_component (metad, cpt); + } + + cpts_a_xml = as_metadata_components_to_collection (metad, AS_FORMAT_KIND_XML, &error); + g_assert_no_error (error); + + as_metadata_clear_components (metad); + for (i = 0; i < cpts_b->len; i++) { + AsComponent *cpt = AS_COMPONENT (g_ptr_array_index (cpts_b, i)); + /* we ignore keywords for now */ + as_component_set_keywords (cpt, NULL, "C"); + /* FIXME: And languages, because their ordering on serialization is random. */ + g_hash_table_remove_all (as_component_get_languages_table (cpt)); + + as_metadata_add_component (metad, cpt); + } + + cpts_b_xml = as_metadata_components_to_collection (metad, AS_FORMAT_KIND_XML, &error); + g_assert_no_error (error); + + g_assert (as_test_compare_lines (cpts_a_xml, cpts_b_xml)); +} + /** * test_cache_file: * @@ -173,10 +238,9 @@ test_cache_file () cpts = as_cache_file_read ("/tmp/as-unittest-dummy.gvz", &error); g_assert_no_error (error); - - /* TODO: Serialize components and check if they are equal to what we attempted to store in the cache */ - g_assert_cmpint (cpts->len, ==, 18); + + as_assert_component_lists_equal (cpts, cpts_prev); } /**