1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2014-2018 Richard Hughes <richard@hughsie.com>
4 * Copyright (C) 2019 Kalev Lember <klember@redhat.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1+
7 */
8
9 #include "config.h"
10
11 #include <glib.h>
12 #include <glib/gstdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "as-agreement-private.h"
17 #include "as-app-private.h"
18 #include "as-app-builder.h"
19 #include "as-bundle-private.h"
20 #include "as-translation-private.h"
21 #include "as-checksum-private.h"
22 #include "as-content-rating-private.h"
23 #include "as-enums.h"
24 #include "as-icon-private.h"
25 #include "as-image-private.h"
26 #include "as-require-private.h"
27 #include "as-review-private.h"
28 #include "as-markup.h"
29 #include "as-monitor.h"
30 #include "as-node-private.h"
31 #include "as-problem.h"
32 #include "as-launchable-private.h"
33 #include "as-provide-private.h"
34 #include "as-ref-string.h"
35 #include "as-release-private.h"
36 #include "as-suggest-private.h"
37 #include "as-screenshot-private.h"
38 #include "as-store.h"
39 #include "as-tag.h"
40 #include "as-utils-private.h"
41 #include "as-yaml.h"
42
43 #ifndef _WIN32
44 #include <fnmatch.h>
45 #else
46 #include <windows.h>
47 #endif
48
49 #define AS_TEST_WILDCARD_SHA1 "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?"
50
51 static gboolean
as_test_compare_lines(const gchar * txt1,const gchar * txt2,GError ** error)52 as_test_compare_lines (const gchar *txt1, const gchar *txt2, GError **error)
53 {
54 g_autofree gchar *output = NULL;
55
56 /* exactly the same */
57 if (g_strcmp0 (txt1, txt2) == 0)
58 return TRUE;
59
60 /* matches a pattern */
61 #ifdef _WIN32
62 if (g_strcmp0 (txt2, txt1) == 0)
63 return TRUE;
64 #else
65 if (fnmatch (txt2, txt1, FNM_NOESCAPE) == 0)
66 return TRUE;
67 #endif
68
69 /* save temp files and diff them */
70 if (!g_file_set_contents ("/tmp/a", txt1, -1, error))
71 return FALSE;
72 if (!g_file_set_contents ("/tmp/b", txt2, -1, error))
73 return FALSE;
74 if (!g_spawn_command_line_sync ("diff -urNp /tmp/b /tmp/a",
75 &output, NULL, NULL, error))
76 return FALSE;
77
78 /* just output the diff */
79 g_set_error_literal (error, 1, 0, output);
80 return FALSE;
81 }
82
83 static gchar *
as_test_get_filename(const gchar * filename)84 as_test_get_filename (const gchar *filename)
85 {
86 g_autofree gchar *path = NULL;
87
88 /* try the source then the destdir */
89 path = g_build_filename (TESTDIRSRC, filename, NULL);
90 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
91 g_free (path);
92 path = g_build_filename (TESTDIRBUILD, filename, NULL);
93 }
94 #ifdef _WIN32
95 {
96 char full_path[PATH_MAX];
97 if (_fullpath (full_path, path, PATH_MAX) == NULL)
98 return NULL;
99 if (!g_file_test (full_path, G_FILE_TEST_EXISTS))
100 return NULL;
101 return g_strdup (full_path);
102 }
103 #else
104 return realpath (path, NULL);
105 #endif
106 }
107
108 static GMainLoop *_test_loop = NULL;
109 static guint _test_loop_timeout_id = 0;
110
111 static gboolean
as_test_hang_check_cb(gpointer user_data)112 as_test_hang_check_cb (gpointer user_data)
113 {
114 g_main_loop_quit (_test_loop);
115 _test_loop_timeout_id = 0;
116 _test_loop = NULL;
117 return G_SOURCE_REMOVE;
118 }
119
120 static void
as_test_loop_run_with_timeout(guint timeout_ms)121 as_test_loop_run_with_timeout (guint timeout_ms)
122 {
123 g_assert (_test_loop_timeout_id == 0);
124 g_assert (_test_loop == NULL);
125 _test_loop = g_main_loop_new (NULL, FALSE);
126 _test_loop_timeout_id = g_timeout_add (timeout_ms, as_test_hang_check_cb, NULL);
127 g_main_loop_run (_test_loop);
128 }
129
130 static void
as_test_loop_quit(void)131 as_test_loop_quit (void)
132 {
133 if (_test_loop_timeout_id > 0) {
134 g_source_remove (_test_loop_timeout_id);
135 _test_loop_timeout_id = 0;
136 }
137 if (_test_loop != NULL) {
138 g_main_loop_quit (_test_loop);
139 g_main_loop_unref (_test_loop);
140 _test_loop = NULL;
141 }
142 }
143
144 static void
monitor_test_cb(AsMonitor * mon,const gchar * filename,guint * cnt)145 monitor_test_cb (AsMonitor *mon, const gchar *filename, guint *cnt)
146 {
147 (*cnt)++;
148 }
149
150 static void
as_test_monitor_dir_func(void)151 as_test_monitor_dir_func (void)
152 {
153 gboolean ret;
154 guint cnt_added = 0;
155 guint cnt_removed = 0;
156 guint cnt_changed = 0;
157 g_autoptr(AsMonitor) mon = NULL;
158 g_autoptr(GError) error = NULL;
159 const gchar *tmpdir = "/tmp/monitor-test/usr/share/app-info/xmls";
160 g_autofree gchar *tmpfile = NULL;
161 g_autofree gchar *tmpfile_new = NULL;
162 g_autofree gchar *cmd_touch = NULL;
163
164 tmpfile = g_build_filename (tmpdir, "test.txt", NULL);
165 tmpfile_new = g_build_filename (tmpdir, "newtest.txt", NULL);
166 g_unlink (tmpfile);
167 g_unlink (tmpfile_new);
168
169 mon = as_monitor_new ();
170 g_signal_connect (mon, "added",
171 G_CALLBACK (monitor_test_cb), &cnt_added);
172 g_signal_connect (mon, "removed",
173 G_CALLBACK (monitor_test_cb), &cnt_removed);
174 g_signal_connect (mon, "changed",
175 G_CALLBACK (monitor_test_cb), &cnt_changed);
176
177 /* add watch */
178 ret = as_monitor_add_directory (mon, tmpdir, NULL, &error);
179 g_assert_no_error (error);
180 g_assert (ret);
181
182 /* create directory */
183 g_mkdir_with_parents (tmpdir, 0700);
184
185 /* touch file */
186 cmd_touch = g_strdup_printf ("touch %s", tmpfile);
187 ret = g_spawn_command_line_sync (cmd_touch, NULL, NULL, NULL, &error);
188 g_assert_no_error (error);
189 g_assert (ret);
190 as_test_loop_run_with_timeout (2000);
191 as_test_loop_quit ();
192 g_assert_cmpint (cnt_added, ==, 1);
193 g_assert_cmpint (cnt_removed, ==, 0);
194 g_assert_cmpint (cnt_changed, ==, 0);
195
196 /* just change the mtime */
197 cnt_added = cnt_removed = cnt_changed = 0;
198 ret = g_spawn_command_line_sync (cmd_touch, NULL, NULL, NULL, &error);
199 g_assert_no_error (error);
200 g_assert (ret);
201 as_test_loop_run_with_timeout (2000);
202 as_test_loop_quit ();
203 g_assert_cmpint (cnt_added, ==, 0);
204 g_assert_cmpint (cnt_removed, ==, 0);
205 g_assert_cmpint (cnt_changed, ==, 1);
206
207 /* delete it */
208 cnt_added = cnt_removed = cnt_changed = 0;
209 g_unlink (tmpfile);
210 as_test_loop_run_with_timeout (2000);
211 as_test_loop_quit ();
212 g_assert_cmpint (cnt_added, ==, 0);
213 g_assert_cmpint (cnt_removed, ==, 1);
214 g_assert_cmpint (cnt_changed, ==, 0);
215
216 /* save a new file with temp copy */
217 cnt_added = cnt_removed = cnt_changed = 0;
218 ret = g_file_set_contents (tmpfile, "foo", -1, &error);
219 g_assert_no_error (error);
220 g_assert (ret);
221 as_test_loop_run_with_timeout (2000);
222 as_test_loop_quit ();
223 g_assert_cmpint (cnt_added, ==, 1);
224 g_assert_cmpint (cnt_removed, ==, 0);
225 g_assert_cmpint (cnt_changed, ==, 0);
226
227 /* modify file with temp copy */
228 cnt_added = cnt_removed = cnt_changed = 0;
229 ret = g_file_set_contents (tmpfile, "bar", -1, &error);
230 g_assert_no_error (error);
231 g_assert (ret);
232 as_test_loop_run_with_timeout (2000);
233 as_test_loop_quit ();
234 g_assert_cmpint (cnt_added, ==, 0);
235 g_assert_cmpint (cnt_removed, ==, 0);
236 g_assert_cmpint (cnt_changed, ==, 1);
237
238 /* rename the file */
239 cnt_added = cnt_removed = cnt_changed = 0;
240 g_assert_cmpint (g_rename (tmpfile, tmpfile_new), ==, 0);
241 as_test_loop_run_with_timeout (2000);
242 as_test_loop_quit ();
243 g_assert_cmpint (cnt_added, ==, 1);
244 g_assert_cmpint (cnt_removed, ==, 1);
245 g_assert_cmpint (cnt_changed, ==, 0);
246
247 g_unlink (tmpfile);
248 g_unlink (tmpfile_new);
249 }
250
251 static void
as_test_monitor_file_func(void)252 as_test_monitor_file_func (void)
253 {
254 gboolean ret;
255 guint cnt_added = 0;
256 guint cnt_removed = 0;
257 guint cnt_changed = 0;
258 g_autoptr(AsMonitor) mon = NULL;
259 g_autoptr(GError) error = NULL;
260 const gchar *tmpfile = "/tmp/one.txt";
261 const gchar *tmpfile_new = "/tmp/two.txt";
262 g_autofree gchar *cmd_touch = NULL;
263
264 g_unlink (tmpfile);
265 g_unlink (tmpfile_new);
266
267 mon = as_monitor_new ();
268 g_signal_connect (mon, "added",
269 G_CALLBACK (monitor_test_cb), &cnt_added);
270 g_signal_connect (mon, "removed",
271 G_CALLBACK (monitor_test_cb), &cnt_removed);
272 g_signal_connect (mon, "changed",
273 G_CALLBACK (monitor_test_cb), &cnt_changed);
274
275 /* add a single file */
276 ret = as_monitor_add_file (mon, tmpfile, NULL, &error);
277 g_assert_no_error (error);
278 g_assert (ret);
279
280 /* touch file */
281 cnt_added = cnt_removed = cnt_changed = 0;
282 cmd_touch = g_strdup_printf ("touch %s", tmpfile);
283 ret = g_spawn_command_line_sync (cmd_touch, NULL, NULL, NULL, &error);
284 g_assert_no_error (error);
285 g_assert (ret);
286 as_test_loop_run_with_timeout (2000);
287 as_test_loop_quit ();
288 g_assert_cmpint (cnt_added, ==, 1);
289 g_assert_cmpint (cnt_removed, ==, 0);
290 g_assert_cmpint (cnt_changed, ==, 0);
291
292 /* just change the mtime */
293 cnt_added = cnt_removed = cnt_changed = 0;
294 ret = g_spawn_command_line_sync (cmd_touch, NULL, NULL, NULL, &error);
295 g_assert_no_error (error);
296 g_assert (ret);
297 as_test_loop_run_with_timeout (2000);
298 as_test_loop_quit ();
299 g_assert_cmpint (cnt_added, ==, 0);
300 g_assert_cmpint (cnt_removed, ==, 0);
301 g_assert_cmpint (cnt_changed, ==, 1);
302
303 /* delete it */
304 cnt_added = cnt_removed = cnt_changed = 0;
305 g_unlink (tmpfile);
306 as_test_loop_run_with_timeout (2000);
307 as_test_loop_quit ();
308 g_assert_cmpint (cnt_added, ==, 0);
309 g_assert_cmpint (cnt_removed, ==, 1);
310 g_assert_cmpint (cnt_changed, ==, 0);
311
312 /* save a new file with temp copy */
313 cnt_added = cnt_removed = cnt_changed = 0;
314 ret = g_file_set_contents (tmpfile, "foo", -1, &error);
315 g_assert_no_error (error);
316 g_assert (ret);
317 as_test_loop_run_with_timeout (2000);
318 as_test_loop_quit ();
319 g_assert_cmpint (cnt_added, ==, 1);
320 g_assert_cmpint (cnt_removed, ==, 0);
321 g_assert_cmpint (cnt_changed, ==, 0);
322
323 /* modify file with temp copy */
324 cnt_added = cnt_removed = cnt_changed = 0;
325 ret = g_file_set_contents (tmpfile, "bar", -1, &error);
326 g_assert_no_error (error);
327 g_assert (ret);
328 as_test_loop_run_with_timeout (2000);
329 as_test_loop_quit ();
330 g_assert_cmpint (cnt_added, ==, 0);
331 g_assert_cmpint (cnt_removed, ==, 0);
332 g_assert_cmpint (cnt_changed, ==, 1);
333 }
334
335 static void
as_test_app_builder_gettext_func(void)336 as_test_app_builder_gettext_func (void)
337 {
338 GError *error = NULL;
339 gboolean ret;
340 guint i;
341 g_autofree gchar *fn = NULL;
342 g_autoptr(AsApp) app = NULL;
343 g_autoptr(GList) list = NULL;
344 const gchar *gettext_domains[] = { "app", "notgoingtoexist", NULL };
345
346 app = as_app_new ();
347 fn = as_test_get_filename ("usr");
348 g_assert (fn != NULL);
349 for (i = 0; gettext_domains[i] != NULL; i++) {
350 g_autoptr(AsTranslation) translation = NULL;
351 translation = as_translation_new ();
352 as_translation_set_kind (translation, AS_TRANSLATION_KIND_GETTEXT);
353 as_translation_set_id (translation, gettext_domains[i]);
354 as_app_add_translation (app, translation);
355 }
356 ret = as_app_builder_search_translations (app, fn, 25,
357 AS_APP_BUILDER_FLAG_NONE,
358 NULL, &error);
359 g_assert_no_error (error);
360 g_assert (ret);
361
362 /* check langs */
363 g_assert_cmpint (as_app_get_language (app, "en_GB"), ==, 100);
364 g_assert_cmpint (as_app_get_language (app, "ru"), ==, 33);
365 g_assert_cmpint (as_app_get_language (app, "fr_FR"), ==, -1);
366
367 /* check fallback */
368 g_assert_cmpint (as_app_get_language (app, "ru_RU"), ==, 33);
369
370 /* check size */
371 list = as_app_get_languages (app);
372 g_assert_cmpint (g_list_length (list), ==, 2);
373 }
374
375 static void
as_test_app_builder_gettext_nodomain_func(void)376 as_test_app_builder_gettext_nodomain_func (void)
377 {
378 GError *error = NULL;
379 gboolean ret;
380 g_autofree gchar *fn = NULL;
381 g_autoptr(AsApp) app = NULL;
382 g_autoptr(GList) list = NULL;
383
384 app = as_app_new ();
385 fn = as_test_get_filename ("usr");
386 ret = as_app_builder_search_translations (app, fn, 50,
387 AS_APP_BUILDER_FLAG_USE_FALLBACKS,
388 NULL, &error);
389 g_assert_no_error (error);
390 g_assert (ret);
391
392 /* check langs */
393 g_assert_cmpint (as_app_get_language (app, "en_GB"), ==, 100);
394 g_assert_cmpint (as_app_get_language (app, "ru"), ==, -1);
395 g_assert_cmpint (as_app_get_language (app, "fr_FR"), ==, -1);
396
397 /* check size */
398 list = as_app_get_languages (app);
399 g_assert_cmpint (g_list_length (list), ==, 1);
400 }
401
402 static void
as_test_app_builder_qt_func(void)403 as_test_app_builder_qt_func (void)
404 {
405 GError *error = NULL;
406 gboolean ret;
407 guint i;
408 g_autofree gchar *fn = NULL;
409 g_autoptr(AsApp) app = NULL;
410 g_autoptr(GList) list = NULL;
411 const gchar *gettext_domains[] = { "kdeapp", "notgoingtoexist", NULL };
412
413 app = as_app_new ();
414 fn = as_test_get_filename ("usr");
415 g_assert (fn != NULL);
416 for (i = 0; gettext_domains[i] != NULL; i++) {
417 g_autoptr(AsTranslation) translation = NULL;
418 translation = as_translation_new ();
419 as_translation_set_kind (translation, AS_TRANSLATION_KIND_QT);
420 as_translation_set_id (translation, gettext_domains[i]);
421 as_app_add_translation (app, translation);
422 }
423 ret = as_app_builder_search_translations (app, fn, 25,
424 AS_APP_BUILDER_FLAG_NONE,
425 NULL, &error);
426 g_assert_no_error (error);
427 g_assert (ret);
428
429 /* check langs */
430 g_assert_cmpint (as_app_get_language (app, "fr"), ==, 100);
431 g_assert_cmpint (as_app_get_language (app, "en_GB"), ==, -1);
432
433 /* check size */
434 list = as_app_get_languages (app);
435 g_assert_cmpint (g_list_length (list), ==, 1);
436 }
437
438 static void
as_test_app_builder_qt_subdir_func(void)439 as_test_app_builder_qt_subdir_func (void)
440 {
441 GError *error = NULL;
442 gboolean ret;
443 guint i;
444 g_autofree gchar *fn = NULL;
445 g_autoptr(AsApp) app = NULL;
446 g_autoptr(GList) list = NULL;
447 const gchar *gettext_domains[] = { "kdeapp2", "notgoingtoexist", NULL };
448
449 app = as_app_new ();
450 fn = as_test_get_filename ("usr");
451 g_assert (fn != NULL);
452 for (i = 0; gettext_domains[i] != NULL; i++) {
453 g_autoptr(AsTranslation) translation = NULL;
454 translation = as_translation_new ();
455 as_translation_set_kind (translation, AS_TRANSLATION_KIND_QT);
456 as_translation_set_id (translation, gettext_domains[i]);
457 as_app_add_translation (app, translation);
458 }
459 ret = as_app_builder_search_translations (app, fn, 25,
460 AS_APP_BUILDER_FLAG_NONE,
461 NULL, &error);
462 g_assert_no_error (error);
463 g_assert (ret);
464
465 /* check langs */
466 g_assert_cmpint (as_app_get_language (app, "fr"), ==, 100);
467 g_assert_cmpint (as_app_get_language (app, "en_GB"), ==, -1);
468
469 /* check size */
470 list = as_app_get_languages (app);
471 g_assert_cmpint (g_list_length (list), ==, 1);
472 }
473
474 static void
as_test_tag_func(void)475 as_test_tag_func (void)
476 {
477 guint i;
478
479 /* simple test */
480 g_assert_cmpstr (as_tag_to_string (AS_TAG_URL), ==, "url");
481 g_assert_cmpstr (as_tag_to_string (AS_TAG_UNKNOWN), ==, "unknown");
482 g_assert_cmpint (as_tag_from_string ("url"), ==, AS_TAG_URL);
483 g_assert_cmpint (as_tag_from_string ("xxx"), ==, AS_TAG_UNKNOWN);
484 g_assert_cmpint (as_tag_from_string (NULL), ==, AS_TAG_UNKNOWN);
485
486 /* deprecated names */
487 g_assert_cmpint (as_tag_from_string_full ("appcategories",
488 AS_TAG_FLAG_USE_FALLBACKS),
489 ==, AS_TAG_CATEGORIES);
490
491 /* test we can go back and forth */
492 for (i = 0; i < AS_TAG_LAST; i++)
493 g_assert_cmpint (as_tag_from_string (as_tag_to_string (i)), ==, i);
494 }
495
496 static void
as_test_release_func(void)497 as_test_release_func (void)
498 {
499 GError *error = NULL;
500 AsNode *n;
501 AsNode *root;
502 GString *xml;
503 const gchar *src = "<release type=\"stable\" install_duration=\"120\" "
504 "timestamp=\"123\" urgency=\"critical\" version=\"0.1.2\"/>";
505 gboolean ret;
506 g_autoptr(AsNodeContext) ctx = NULL;
507 g_autoptr(AsRelease) release = NULL;
508
509 release = as_release_new ();
510
511 /* to object */
512 root = as_node_from_xml (src, 0, &error);
513 g_assert_no_error (error);
514 g_assert (root != NULL);
515 n = as_node_find (root, "release");
516 g_assert (n != NULL);
517 ctx = as_node_context_new ();
518 ret = as_release_node_parse (release, n, ctx, &error);
519 g_assert_no_error (error);
520 g_assert (ret);
521 as_node_unref (root);
522
523 /* verify */
524 g_assert_cmpint ((gint32) as_release_get_timestamp (release), ==, 123);
525 g_assert_cmpint (as_release_get_urgency (release), ==, AS_URGENCY_KIND_CRITICAL);
526 g_assert_cmpint (as_release_get_state (release), ==, AS_RELEASE_STATE_UNKNOWN);
527 g_assert_cmpint (as_release_get_kind (release), ==, AS_RELEASE_KIND_STABLE);
528 g_assert_cmpstr (as_release_get_version (release), ==, "0.1.2");
529
530 /* state is not stored in the XML */
531 as_release_set_state (release, AS_RELEASE_STATE_INSTALLED);
532 g_assert_cmpint (as_release_get_state (release), ==, AS_RELEASE_STATE_INSTALLED);
533
534 /* back to node */
535 root = as_node_new ();
536 as_node_context_set_version (ctx, 0.4);
537 n = as_release_node_insert (release, root, ctx);
538 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
539 ret = as_test_compare_lines (xml->str, src, &error);
540 g_assert_no_error (error);
541 g_assert (ret);
542 g_string_free (xml, TRUE);
543 as_node_unref (root);
544 }
545
546 static void
as_test_release_date_func(void)547 as_test_release_date_func (void)
548 {
549 GError *error = NULL;
550 AsNode *n;
551 AsNode *root;
552 const gchar *src = "<release date=\"2016-01-18\"/>";
553 gboolean ret;
554 g_autoptr(AsNodeContext) ctx = NULL;
555 g_autoptr(AsRelease) release = NULL;
556
557 release = as_release_new ();
558
559 /* to object */
560 root = as_node_from_xml (src, 0, &error);
561 g_assert_no_error (error);
562 g_assert (root != NULL);
563 n = as_node_find (root, "release");
564 g_assert (n != NULL);
565 ctx = as_node_context_new ();
566 ret = as_release_node_parse (release, n, ctx, &error);
567 g_assert_no_error (error);
568 g_assert (ret);
569 as_node_unref (root);
570
571 /* verify */
572 g_assert_cmpint ((gint32) as_release_get_timestamp (release), ==, 1453075200);
573 }
574
575 static void
as_test_provide_func(void)576 as_test_provide_func (void)
577 {
578 GError *error = NULL;
579 AsNode *n;
580 AsNode *root;
581 GString *xml;
582 const gchar *src = "<binary>/usr/bin/gnome-shell</binary>";
583 gboolean ret;
584 g_autoptr(AsNodeContext) ctx = NULL;
585 g_autoptr(AsProvide) provide = NULL;
586
587 provide = as_provide_new ();
588
589 /* to object */
590 root = as_node_from_xml (src, 0, &error);
591 g_assert_no_error (error);
592 g_assert (root != NULL);
593 n = as_node_find (root, "binary");
594 g_assert (n != NULL);
595 ctx = as_node_context_new ();
596 ret = as_provide_node_parse (provide, n, ctx, &error);
597 g_assert_no_error (error);
598 g_assert (ret);
599 as_node_unref (root);
600
601 /* verify */
602 g_assert_cmpint (as_provide_get_kind (provide), ==, AS_PROVIDE_KIND_BINARY);
603 g_assert_cmpstr (as_provide_get_value (provide), ==, "/usr/bin/gnome-shell");
604
605 /* back to node */
606 root = as_node_new ();
607 as_node_context_set_version (ctx, 0.4);
608 n = as_provide_node_insert (provide, root, ctx);
609 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
610 ret = as_test_compare_lines (xml->str, src, &error);
611 g_assert_no_error (error);
612 g_assert (ret);
613 g_string_free (xml, TRUE);
614 as_node_unref (root);
615 }
616
617 static void
as_test_launchable_func(void)618 as_test_launchable_func (void)
619 {
620 GError *error = NULL;
621 AsNode *n;
622 AsNode *root;
623 GString *xml;
624 const gchar *src = "<launchable type=\"desktop-id\">gnome-software.desktop</launchable>";
625 gboolean ret;
626 g_autoptr(AsNodeContext) ctx = NULL;
627 g_autoptr(AsLaunchable) launchable = NULL;
628
629 launchable = as_launchable_new ();
630
631 /* to object */
632 root = as_node_from_xml (src, 0, &error);
633 g_assert_no_error (error);
634 g_assert (root != NULL);
635 n = as_node_find (root, "launchable");
636 g_assert (n != NULL);
637 ctx = as_node_context_new ();
638 ret = as_launchable_node_parse (launchable, n, ctx, &error);
639 g_assert_no_error (error);
640 g_assert (ret);
641 as_node_unref (root);
642
643 /* verify */
644 g_assert_cmpint (as_launchable_get_kind (launchable), ==, AS_LAUNCHABLE_KIND_DESKTOP_ID);
645 g_assert_cmpstr (as_launchable_get_value (launchable), ==, "gnome-software.desktop");
646
647 /* back to node */
648 root = as_node_new ();
649 as_node_context_set_version (ctx, 0.4);
650 n = as_launchable_node_insert (launchable, root, ctx);
651 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
652 ret = as_test_compare_lines (xml->str, src, &error);
653 g_assert_no_error (error);
654 g_assert (ret);
655 g_string_free (xml, TRUE);
656 as_node_unref (root);
657 }
658
659 static void
as_test_release_appstream_func(void)660 as_test_release_appstream_func (void)
661 {
662 const gchar *url;
663 AsChecksum *csum;
664 GError *error = NULL;
665 AsNode *n;
666 AsNode *root;
667 GString *xml;
668 gboolean ret;
669 guint64 sz;
670 const gchar *src =
671 "<release timestamp=\"123\" version=\"0.1.2\">\n"
672 "<location>http://foo.com/bar.zip</location>\n"
673 "<location>http://baz.com/bar.cab</location>\n"
674 "<checksum type=\"sha1\" filename=\"firmware.cab\" target=\"container\">12345</checksum>\n"
675 "<checksum type=\"md5\" filename=\"firmware.cab\" target=\"container\">deadbeef</checksum>\n"
676 "<url type=\"details\">http://foo.bar/</url>\n"
677 "<description><p>This is a new release</p><ul><li>Point</li></ul></description>\n"
678 "<description xml:lang=\"pl\"><p>Oprogramowanie</p></description>\n"
679 "<size type=\"installed\">123456</size>\n"
680 "<size type=\"download\">654321</size>\n"
681 "</release>\n";
682 g_autoptr(AsNodeContext) ctx = NULL;
683 g_autoptr(AsRelease) release = NULL;
684
685 release = as_release_new ();
686
687 /* to object */
688 root = as_node_from_xml (src, 0, &error);
689 g_assert_no_error (error);
690 g_assert (root != NULL);
691 n = as_node_find (root, "release");
692 g_assert (n != NULL);
693 ctx = as_node_context_new ();
694 ret = as_release_node_parse (release, n, ctx, &error);
695 g_assert_no_error (error);
696 g_assert (ret);
697 as_node_unref (root);
698
699 /* verify */
700 g_assert_cmpint ((gint32) as_release_get_timestamp (release), ==, 123);
701 g_assert_cmpstr (as_release_get_version (release), ==, "0.1.2");
702 g_assert_cmpstr (as_release_get_location_default (release), ==, "http://foo.com/bar.zip");
703 g_assert_cmpstr (as_release_get_description (release, "pl"), ==,
704 "<p>Oprogramowanie</p>");
705 g_assert_cmpstr (as_release_get_description (release, NULL), ==,
706 "<p>This is a new release</p><ul><li>Point</li></ul>");
707
708 /* checksum */
709 g_assert_cmpint (as_release_get_checksums(release)->len, ==, 2);
710 csum = as_release_get_checksum_by_fn (release, "firmware.inf");
711 g_assert (csum == NULL);
712 csum = as_release_get_checksum_by_fn (release, "firmware.cab");
713 g_assert (csum != NULL);
714 g_assert_cmpint (as_checksum_get_kind (csum), ==, G_CHECKSUM_SHA1);
715 g_assert_cmpint (as_checksum_get_target (csum), ==, AS_CHECKSUM_TARGET_CONTAINER);
716 g_assert_cmpstr (as_checksum_get_filename (csum), ==, "firmware.cab");
717 g_assert_cmpstr (as_checksum_get_value (csum), ==, "12345");
718
719 /* get by target type */
720 csum = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTENT);
721 g_assert (csum == NULL);
722 csum = as_release_get_checksum_by_target (release, AS_CHECKSUM_TARGET_CONTAINER);
723 g_assert (csum != NULL);
724 g_assert_cmpstr (as_checksum_get_value (csum), ==, "12345");
725
726 /* test size */
727 sz = as_release_get_size (release, AS_SIZE_KIND_INSTALLED);
728 g_assert_cmpuint (sz, ==, 123456);
729 sz = as_release_get_size (release, AS_SIZE_KIND_DOWNLOAD);
730 g_assert_cmpuint (sz, ==, 654321);
731
732 /* URL */
733 url = as_release_get_url (release, AS_URL_KIND_DETAILS);
734 g_assert_cmpstr (url, ==, "http://foo.bar/");
735 url = as_release_get_url (release, AS_URL_KIND_HOMEPAGE);
736 g_assert_null (url);
737
738 /* back to node */
739 root = as_node_new ();
740 as_node_context_set_version (ctx, 1.0);
741 as_node_context_set_format_kind (ctx, AS_FORMAT_KIND_APPSTREAM);
742 n = as_release_node_insert (release, root, ctx);
743 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
744 ret = as_test_compare_lines (xml->str, src, &error);
745 g_assert_no_error (error);
746 g_assert (ret);
747
748 g_string_free (xml, TRUE);
749 as_node_unref (root);
750 }
751
752 static void
as_test_release_appdata_func(void)753 as_test_release_appdata_func (void)
754 {
755 GError *error = NULL;
756 AsNode *n;
757 AsNode *root;
758 gboolean ret;
759 const gchar *src =
760 "<release version=\"0.1.2\" timestamp=\"123\">\n"
761 "<description>\n"
762 "<p>This is a new release</p>\n"
763 "<p xml:lang=\"pl\">Oprogramowanie</p>\n"
764 "</description>\n"
765 "</release>\n";
766 g_autoptr(AsNodeContext) ctx = NULL;
767 g_autoptr(AsRelease) release = NULL;
768
769 release = as_release_new ();
770
771 /* to object */
772 root = as_node_from_xml (src, 0, &error);
773 g_assert_no_error (error);
774 g_assert (root != NULL);
775 n = as_node_find (root, "release");
776 g_assert (n != NULL);
777 ctx = as_node_context_new ();
778 as_node_context_set_format_kind (ctx, AS_FORMAT_KIND_APPDATA);
779 ret = as_release_node_parse (release, n, ctx, &error);
780 g_assert_no_error (error);
781 g_assert (ret);
782 as_node_unref (root);
783
784 /* verify */
785 g_assert_cmpint ((gint32) as_release_get_timestamp (release), ==, 123);
786 g_assert_cmpstr (as_release_get_version (release), ==, "0.1.2");
787 g_assert_cmpstr (as_release_get_description (release, NULL), ==,
788 "<p>This is a new release</p>");
789 g_assert_cmpstr (as_release_get_description (release, "pl"), ==,
790 "<p>Oprogramowanie</p>");
791 }
792
793 typedef enum {
794 AS_TEST_RESIZE_NEAREST,
795 AS_TEST_RESIZE_TILES,
796 AS_TEST_RESIZE_BILINEAR,
797 AS_TEST_RESIZE_HYPER,
798 AS_TEST_RESIZE_BILINEAR_SHARP,
799 AS_TEST_RESIZE_HYPER_SHARP,
800 AS_TEST_RESIZE_LAST,
801 } AsTestResize;
802
803 static const gchar *
as_test_resize_to_string(AsTestResize rz)804 as_test_resize_to_string (AsTestResize rz)
805 {
806 if (rz == AS_TEST_RESIZE_NEAREST)
807 return "nearest";
808 if (rz == AS_TEST_RESIZE_TILES)
809 return "tiles";
810 if (rz == AS_TEST_RESIZE_BILINEAR)
811 return "bilinear";
812 if (rz == AS_TEST_RESIZE_HYPER)
813 return "hyper";
814 if (rz == AS_TEST_RESIZE_BILINEAR_SHARP)
815 return "bilinear-sharp";
816 if (rz == AS_TEST_RESIZE_HYPER_SHARP)
817 return "hyper-sharp";
818 return NULL;
819 }
820
821 static void
as_test_image_resize_filename(AsTestResize rz,const gchar * in,const gchar * out)822 as_test_image_resize_filename (AsTestResize rz, const gchar *in, const gchar *out)
823 {
824 gboolean ret;
825 g_autoptr(GdkPixbuf) pb = NULL;
826 g_autoptr(GdkPixbuf) pb2 = NULL;
827
828 pb = gdk_pixbuf_new_from_file (in, NULL);
829 g_assert (pb != NULL);
830
831 switch (rz) {
832 case AS_TEST_RESIZE_NEAREST:
833 pb2 = gdk_pixbuf_scale_simple (pb,
834 AS_IMAGE_LARGE_WIDTH,
835 AS_IMAGE_LARGE_HEIGHT,
836 GDK_INTERP_NEAREST);
837 break;
838 case AS_TEST_RESIZE_TILES:
839 pb2 = gdk_pixbuf_scale_simple (pb,
840 AS_IMAGE_LARGE_WIDTH,
841 AS_IMAGE_LARGE_HEIGHT,
842 GDK_INTERP_TILES);
843 break;
844 case AS_TEST_RESIZE_BILINEAR:
845 pb2 = gdk_pixbuf_scale_simple (pb,
846 AS_IMAGE_LARGE_WIDTH,
847 AS_IMAGE_LARGE_HEIGHT,
848 GDK_INTERP_BILINEAR);
849 break;
850 case AS_TEST_RESIZE_HYPER:
851 pb2 = gdk_pixbuf_scale_simple (pb,
852 AS_IMAGE_LARGE_WIDTH,
853 AS_IMAGE_LARGE_HEIGHT,
854 GDK_INTERP_HYPER);
855 break;
856 case AS_TEST_RESIZE_BILINEAR_SHARP:
857 pb2 = gdk_pixbuf_scale_simple (pb,
858 AS_IMAGE_LARGE_WIDTH,
859 AS_IMAGE_LARGE_HEIGHT,
860 GDK_INTERP_BILINEAR);
861 as_pixbuf_sharpen (pb2, 1, -0.5);
862 break;
863 case AS_TEST_RESIZE_HYPER_SHARP:
864 pb2 = gdk_pixbuf_scale_simple (pb,
865 AS_IMAGE_LARGE_WIDTH,
866 AS_IMAGE_LARGE_HEIGHT,
867 GDK_INTERP_HYPER);
868 as_pixbuf_sharpen (pb2, 1, -0.5);
869 break;
870 default:
871 g_assert_not_reached ();
872 }
873
874 ret = gdk_pixbuf_save (pb2, out, "png", NULL, NULL);
875 g_assert (ret);
876 }
877
878 static void
as_test_image_alpha_func(void)879 as_test_image_alpha_func (void)
880 {
881 gboolean ret;
882 g_autoptr(GError) error = NULL;
883 g_autofree gchar *fn_both = NULL;
884 g_autofree gchar *fn_horiz = NULL;
885 g_autofree gchar *fn_internal1 = NULL;
886 g_autofree gchar *fn_internal2 = NULL;
887 g_autofree gchar *fn_none = NULL;
888 g_autofree gchar *fn_vert = NULL;
889 g_autoptr(AsImage) im = NULL;
890
891 /* horiz */
892 fn_horiz = as_test_get_filename ("alpha-horiz.png");
893 im = as_image_new ();
894 ret = as_image_load_filename (im, fn_horiz, &error);
895 g_assert_no_error (error);
896 g_assert (ret);
897 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
898 AS_IMAGE_ALPHA_FLAG_LEFT |
899 AS_IMAGE_ALPHA_FLAG_RIGHT);
900
901 /* vert */
902 fn_vert = as_test_get_filename ("alpha-vert.png");
903 ret = as_image_load_filename (im, fn_vert, &error);
904 g_assert_no_error (error);
905 g_assert (ret);
906 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
907 AS_IMAGE_ALPHA_FLAG_TOP |
908 AS_IMAGE_ALPHA_FLAG_BOTTOM);
909
910 /* both */
911 fn_both = as_test_get_filename ("alpha-both.png");
912 ret = as_image_load_filename (im, fn_both, &error);
913 g_assert_no_error (error);
914 g_assert (ret);
915 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
916 AS_IMAGE_ALPHA_FLAG_LEFT |
917 AS_IMAGE_ALPHA_FLAG_RIGHT |
918 AS_IMAGE_ALPHA_FLAG_TOP |
919 AS_IMAGE_ALPHA_FLAG_BOTTOM);
920
921 /* internal */
922 fn_internal1 = as_test_get_filename ("alpha-internal1.png");
923 ret = as_image_load_filename (im, fn_internal1, &error);
924 g_assert_no_error (error);
925 g_assert (ret);
926 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
927 AS_IMAGE_ALPHA_FLAG_INTERNAL);
928
929 fn_internal2 = as_test_get_filename ("alpha-internal2.png");
930 ret = as_image_load_filename (im, fn_internal2, &error);
931 g_assert_no_error (error);
932 g_assert (ret);
933 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
934 AS_IMAGE_ALPHA_FLAG_INTERNAL);
935
936 fn_none = as_test_get_filename ("ss-small.png");
937 ret = as_image_load_filename (im, fn_none, &error);
938 g_assert_no_error (error);
939 g_assert (ret);
940 g_assert_cmpint (as_image_get_alpha_flags (im), ==,
941 AS_IMAGE_ALPHA_FLAG_NONE);
942 }
943
944 static void
as_test_image_resize_func(void)945 as_test_image_resize_func (void)
946 {
947 GError *error = NULL;
948 const gchar *tmp;
949 g_autoptr(GDir) dir = NULL;
950 g_autofree gchar *output_dir = NULL;
951
952 /* only do this test if an "output" directory exists */
953 output_dir = g_build_filename (TESTDIRSRC, "output", NULL);
954 if (!g_file_test (output_dir, G_FILE_TEST_EXISTS))
955 return;
956
957 /* look for test screenshots */
958 dir = g_dir_open (TESTDIRSRC, 0, &error);
959 g_assert_no_error (error);
960 g_assert (dir != NULL);
961 while ((tmp = g_dir_read_name (dir)) != NULL) {
962 guint i;
963 g_autofree gchar *path = NULL;
964
965 if (!g_str_has_prefix (tmp, "ss-"))
966 continue;
967 path = g_build_filename (TESTDIRSRC, tmp, NULL);
968
969 for (i = 0; i < AS_TEST_RESIZE_LAST; i++) {
970 g_autofree gchar *new_path = NULL;
971 g_autoptr(GString) basename = NULL;
972
973 basename = g_string_new (tmp);
974 g_string_truncate (basename, basename->len - 4);
975 g_string_append_printf (basename, "-%s.png",
976 as_test_resize_to_string (i));
977 new_path = g_build_filename (output_dir, basename->str, NULL);
978 as_test_image_resize_filename (i, path, new_path);
979 }
980 }
981 }
982
983 static void
as_test_icon_func(void)984 as_test_icon_func (void)
985 {
986 GError *error = NULL;
987 AsNode *n;
988 AsNode *root;
989 GString *xml;
990 const gchar *src = "<icon type=\"cached\">app.png</icon>";
991 gboolean ret;
992 g_autoptr(AsNodeContext) ctx = NULL;
993 g_autofree gchar *prefix = NULL;
994 g_autoptr(AsIcon) icon = NULL;
995 g_autoptr(GdkPixbuf) pixbuf = NULL;
996
997 icon = as_icon_new ();
998
999 /* to object */
1000 root = as_node_from_xml (src, 0, &error);
1001 g_assert_no_error (error);
1002 g_assert (root != NULL);
1003 n = as_node_find (root, "icon");
1004 g_assert (n != NULL);
1005 ctx = as_node_context_new ();
1006 ret = as_icon_node_parse (icon, n, ctx, &error);
1007 g_assert_no_error (error);
1008 g_assert (ret);
1009 as_node_unref (root);
1010
1011 /* verify */
1012 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_CACHED);
1013 g_assert_cmpstr (as_icon_get_name (icon), ==, "app.png");
1014 g_assert_cmpstr (as_icon_get_filename (icon), ==, NULL);
1015 g_assert_cmpstr (as_icon_get_url (icon), ==, NULL);
1016 g_assert_cmpint (as_icon_get_height (icon), ==, 64);
1017 g_assert_cmpint (as_icon_get_width (icon), ==, 64);
1018 g_assert_cmpint (as_icon_get_scale (icon), ==, 1);
1019 g_assert (as_icon_get_pixbuf (icon) == NULL);
1020 g_assert (as_icon_get_data (icon) == NULL);
1021
1022 /* back to node */
1023 root = as_node_new ();
1024 as_node_context_set_version (ctx, 0.4);
1025 n = as_icon_node_insert (icon, root, ctx);
1026 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1027 ret = as_test_compare_lines (xml->str, "<icon type=\"cached\" height=\"64\" width=\"64\">app.png</icon>", &error);
1028 g_assert_no_error (error);
1029 g_assert (ret);
1030 g_string_free (xml, TRUE);
1031 as_node_unref (root);
1032
1033 /* convert to embedded icon */
1034 prefix = as_test_get_filename ("rpmbuild");
1035 g_assert (prefix != NULL);
1036 as_icon_set_prefix (icon, prefix);
1037 ret = as_icon_convert_to_kind (icon, AS_ICON_KIND_EMBEDDED, &error);
1038 g_assert_no_error (error);
1039 g_assert (ret);
1040 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_EMBEDDED);
1041 g_assert_cmpstr (as_icon_get_filename (icon), ==, NULL);
1042 g_assert_cmpstr (as_icon_get_url (icon), ==, NULL);
1043 g_assert (as_icon_get_pixbuf (icon) != NULL);
1044 g_assert (as_icon_get_data (icon) != NULL);
1045 }
1046
1047 static void
as_test_icon_scale_func(void)1048 as_test_icon_scale_func (void)
1049 {
1050 GError *error = NULL;
1051 AsNode *n;
1052 AsNode *root;
1053 GString *xml;
1054 const gchar *src = "<icon type=\"cached\" height=\"128\" scale=\"2\" width=\"128\">app.png</icon>";
1055 gboolean ret;
1056 g_autoptr(AsNodeContext) ctx = NULL;
1057 g_autoptr(AsIcon) icon = NULL;
1058 g_autoptr(GdkPixbuf) pixbuf = NULL;
1059
1060 icon = as_icon_new ();
1061
1062 /* to object */
1063 root = as_node_from_xml (src, 0, &error);
1064 g_assert_no_error (error);
1065 g_assert (root != NULL);
1066 n = as_node_find (root, "icon");
1067 g_assert (n != NULL);
1068 ctx = as_node_context_new ();
1069 ret = as_icon_node_parse (icon, n, ctx, &error);
1070 g_assert_no_error (error);
1071 g_assert (ret);
1072 as_node_unref (root);
1073
1074 /* verify */
1075 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_CACHED);
1076 g_assert_cmpstr (as_icon_get_name (icon), ==, "app.png");
1077 g_assert_cmpstr (as_icon_get_filename (icon), ==, NULL);
1078 g_assert_cmpstr (as_icon_get_url (icon), ==, NULL);
1079 g_assert_cmpint (as_icon_get_height (icon), ==, 128);
1080 g_assert_cmpint (as_icon_get_width (icon), ==, 128);
1081 g_assert_cmpint (as_icon_get_scale (icon), ==, 2);
1082 g_assert (as_icon_get_pixbuf (icon) == NULL);
1083 g_assert (as_icon_get_data (icon) == NULL);
1084
1085 /* back to node */
1086 root = as_node_new ();
1087 as_node_context_set_version (ctx, 0.9);
1088 n = as_icon_node_insert (icon, root, ctx);
1089 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1090 ret = as_test_compare_lines (xml->str, src, &error);
1091 g_assert_no_error (error);
1092 g_assert (ret);
1093 g_string_free (xml, TRUE);
1094 as_node_unref (root);
1095 }
1096
1097 static void
as_test_checksum_func(void)1098 as_test_checksum_func (void)
1099 {
1100 GError *error = NULL;
1101 AsNode *n;
1102 AsNode *root;
1103 GString *xml;
1104 const gchar *src = "<checksum type=\"sha1\" filename=\"f&n.cab\" target=\"container\">12&45</checksum>";
1105 gboolean ret;
1106 g_autoptr(AsNodeContext) ctx = NULL;
1107 g_autoptr(AsChecksum) csum = NULL;
1108
1109 /* helpers */
1110 g_assert_cmpint (as_checksum_target_from_string ("container"), ==, AS_CHECKSUM_TARGET_CONTAINER);
1111 g_assert_cmpint (as_checksum_target_from_string ("content"), ==, AS_CHECKSUM_TARGET_CONTENT);
1112 g_assert_cmpint (as_checksum_target_from_string (NULL), ==, AS_CHECKSUM_TARGET_UNKNOWN);
1113 g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_CONTAINER), ==, "container");
1114 g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_CONTENT), ==, "content");
1115 g_assert_cmpstr (as_checksum_target_to_string (AS_CHECKSUM_TARGET_UNKNOWN), ==, NULL);
1116
1117 csum = as_checksum_new ();
1118
1119 /* to object */
1120 root = as_node_from_xml (src, 0, &error);
1121 g_assert_no_error (error);
1122 g_assert (root != NULL);
1123 n = as_node_find (root, "checksum");
1124 g_assert (n != NULL);
1125 ctx = as_node_context_new ();
1126 ret = as_checksum_node_parse (csum, n, ctx, &error);
1127 g_assert_no_error (error);
1128 g_assert (ret);
1129 as_node_unref (root);
1130
1131 /* verify */
1132 g_assert_cmpint (as_checksum_get_kind (csum), ==, G_CHECKSUM_SHA1);
1133 g_assert_cmpint (as_checksum_get_target (csum), ==, AS_CHECKSUM_TARGET_CONTAINER);
1134 g_assert_cmpstr (as_checksum_get_filename (csum), ==, "f&n.cab");
1135 g_assert_cmpstr (as_checksum_get_value (csum), ==, "12&45");
1136
1137 /* back to node */
1138 root = as_node_new ();
1139 as_node_context_set_version (ctx, 0.4);
1140 n = as_checksum_node_insert (csum, root, ctx);
1141 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1142 ret = as_test_compare_lines (xml->str, src, &error);
1143 g_assert_no_error (error);
1144 g_assert (ret);
1145 g_string_free (xml, TRUE);
1146 as_node_unref (root);
1147 }
1148
1149 static void
as_test_icon_embedded_func(void)1150 as_test_icon_embedded_func (void)
1151 {
1152 GError *error = NULL;
1153 AsNode *n;
1154 AsNode *root;
1155 GString *xml;
1156 const gchar *src =
1157 "<icon type=\"embedded\" height=\"32\" width=\"32\"><name>app.png</name>"
1158 "<filecontent>\n"
1159 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJ\n"
1160 "TUUH1gsaCxQZBldDDAAACLxJREFUWIW9lmtsHNUVx/8zd3Zm9uFd73ptZ/3Gid+OoUlwyAscSJw4\n"
1161 "tIEKCGCQUPuBIlUIhbbEwIfuh0oRUYtKUEEIVQIJSpomPJKACYKQENNg7BiDE8dJnDi7drzrxz5m\n"
1162 "d3a9O3Nnbj8YaOo6qSFSj3Q0V3Nnzv93z9x7znD4kbZzZ4dbM8QWSbBsAoc2XdeLJFH8OJ2m9/j9\n"
1163 "/vRC4wgLfdDv9zsIobcKgqWVF8idAhHKljU20aol1daCggJOFCUcP3709u7uE88CePa6AZ5/frs1\n"
1164 "lbKvAi+0ihbxpzyPqsaGFXp1dY2tsHARJ8syKKWiruvQdQpKDSxf3iz29Pa0/xAA7rvBK688apmY\n"
1165 "KGwmhGwURHErGGtoaGjUa2vqrIsW+Xir1QpKDVCqg1INuk6vCMNgmgxOZy5eevnFbEJJVfr9/vEF\n"
1166 "ZcDv91fabMIrcQVrG5fWmA31jXJxcQlvs9lAqSF+JxaPxwAwMPbvl1NpFUpCQSw+CSWRwrIbb8aN\n"
1167 "TU3m5593tQJ4bUEAVru4b9u2B28qKy3nDGN2hbquIR6PgX2vNiucyWagJOKIK9NQEgnwAoMgJsCL\n"
1168 "Scg5NoTCY7ihcom192TPPQsGoLpWU1ZaziUScRiG8R+Tmp5FXFEQT0SgKHGAmaCaBqaZ4OUoBi8M\n"
1169 "YvCby5gIq8ikDciyFdVV1Uil1Na2trb8zs7Oqf8JIFgs/el0ajXH8aA0i0QyjpgShZKIgeoUpm4A\n"
1170 "1AAhFAwzWFzajO7+Xrz9eidWr1qN9m13o7ysHA6HA6qqIhAM4Msve8Tg6Fjg9g0tuySLdWdnZ2f2\n"
1171 "agCk5bY1zqKikjvcbjfp+uIYdKrA4UzDV8QhEkhh1eoNWPqT5XC5FqFz7xF83H0MqVQKT+/oAC/I\n"
1172 "6Ds1gk9OHkXXmc/x1UAYmmZBbVUl2u+/zzIdibSMBC7dUVpbeiA4HJy3NvCUJx/2f91HRVGCy5UD\n"
1173 "XzGPgkJAsKhIJROwOexIj53AzGfbMTxyBDdUlGPbvfdi7579EJ1leLj9fjze/hhEyxREWwRTioLR\n"
1174 "uIAXXjsY3/qzreamjRtXCTo52NbWJs0L4H/GPzQ6GkwzMHhyvVBiJpRoCn2fKpgcTaJ7910IvfdL\n"
1175 "HB4ahc23FCubm3Hi3V3YuNyHG4sBqps4/OFHICQMrzeNbGoKlaUFiMUVe8dfPn1h2bLlRm1t7cqM\n"
1176 "ln5mXgAAMBn7YGpyAnmeAsTjJoa+pLh1wzY8+rtfw5Xph5Ar4mCPiDs3b0H/P/+OW9dvxqI8J47v\n"
1177 "2op3//oq0lNhWKRJ2B0RuOwmBGRQfUOpoWtJ/uV9PW9sWH8HCBF+09LS4p0XQNP1d86eOzuT68oF\n"
1178 "pYAgisj15IIXZNjK1uPQZyZqapsQHDmHClmD21WAvjd+j4r6tXhsx5PY8vO74c2sh6bH4HAlEY+M\n"
1179 "4aal1VKhzWj6OiR0XQiMRevr6uwgeGheAEnIHhkY6CeECHDluEDsFO/v24vXX3wJB4cbMcSWoqKi\n"
1180 "AuGRYdg8DbjwzVe47NgIx+0dIISDr6QIMnFDFGTkejkEg2dRXVnGWZBesf2B5iWnR+K9xSUl4MC2\n"
1181 "zgvQ0fGcks1qQ6mUijxPPiwOAkflIARbBr/a8QTGYxnIshXBVCGK1z4MX8ujcC6ux7Gut3DondfR\n"
1182 "dfwAbMUJmGoRIpclTE7E4HLYUFNVITYt9qw8P8EGRNECgGuYC/B9MzKovj84GqgvKS4Vhi+JYFYD\n"
1183 "jFogyTISiQQMg0KwyNB1Cosgoq6pCYK9DjwkqIkM5GQ+il0SnPUueHK9IIRH6/p1lsnpqDuWESZ1\n"
1184 "XQeAvKsCUGq8f/rUwFPVVdWCRbBAz4gQigPYv+dVSKIF09PT4J1ZdPd0Y3FZPjwuO0TeDlm2wuuW\n"
1185 "QAgBADDGYDIGMAabLYe/1H/O5+QzBZFIEgAiVwUwTfLV2NioaRizxzEUzYNsNwBJg8frxsTEBDgp\n"
1186 "D26PF+Vl5ZBEAoHnwX3bTxkAZppgAEzTRFY3IYgyhi+OuvPk+NKp6RkA7PS8ewAA/H6/yTgcmZqa\n"
1187 "gMedD6b54OSbUeq9BWtWrcN4KAQzHQMnyNB0A1nNgGEyGObsig2DAeDAgQM4gtSMjoHB8ywYjk/Y\n"
1188 "eWXF9NQ0GLgDV80AAGiZ7L7h4XOtzc23WFfcdDO4b5fnXO/EewcOwJaK4mRfH3JzVsHrsoMaJqyS\n"
1189 "BaJFAGMmpqNRBIJjdGBomI5enuSn4vR8NJY4I1vT9yaTyRQMvHlNANMkHw2eOU1Wr177vTgA5OTk\n"
1190 "YEtbGw59cAhp9SN48grRVL8YIm9CUeJmODSqhcNholMEZij6VM1+9pLquxweu1BeaZt8SlVVAOxP\n"
1191 "R48em54LwM298dxzfzj/yCO/WMLzs1+HEAGEEFBKsePpDoRC47BaraBSsZmb5ws5nTmnrTbHUBau\n"
1192 "s4l0VguEEkYoqhKXNtxSZJ14MDMzwxsmxnjGLZmvK/7XP6Fh0L/1njy5Y+2adZKqJhEKBdiFi8Pq\n"
1193 "xYsXpSJf/sj4+LhDTaWLHRjnI8GQ7RJ1mHGWl8kwryhz0+W5XKRpsaCulKzMrabSAPixhrqyktLx\n"
1194 "VzOb20mXoRt3PfkPRK+agd27H5cymYI9OjU3CYQfN0z2vka1w+mkdnzXrl3JtrY2KavPPA1wv5Uk\n"
1195 "yS5KIgQigOMAxgBqUGhZDdlsNgWwP0oW685Wz5FYfX2NdSZjaoGLZ6IGjNYn38TAvAALtU2bNnk0\n"
1196 "qj2A2fLaiNkiEwFwCuAOiIK45/Dhw1EAeKFdOLvIa6uorLtZVNQ0G/ymV2VU3/LEW+j60QA/xHbf\n"
1197 "h3wmksFKn8NbWN6IGUPA170nUpRqbf8XAAD48wNYyRHyyZIim91b0gCNy0HvF0dAriMmd4XzVziZ\n"
1198 "4wIA8uEphNdV8X1qRr9LZnHRoFlElMTla2VgrgB3Fb/W3Nw42L6ZrClzs7d5ngtrmvHQQgEWInYt\n"
1199 "xxVXYLZ16ADU690D3JzxXLG581caBWBep/71278AZpn8hFce4VcAAAAASUVORK5CYII=\n"
1200 "</filecontent>"
1201 "</icon>";
1202 gboolean ret;
1203 g_autoptr(AsNodeContext) ctx = NULL;
1204 g_autoptr(AsIcon) icon = NULL;
1205 g_autoptr(GdkPixbuf) pixbuf = NULL;
1206
1207 icon = as_icon_new ();
1208
1209 /* to object */
1210 root = as_node_from_xml (src, 0, &error);
1211 g_assert_no_error (error);
1212 g_assert (root != NULL);
1213 n = as_node_find (root, "icon");
1214 g_assert (n != NULL);
1215 ctx = as_node_context_new ();
1216 ret = as_icon_node_parse (icon, n, ctx, &error);
1217 g_assert_no_error (error);
1218 g_assert (ret);
1219 as_node_unref (root);
1220
1221 /* verify */
1222 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_EMBEDDED);
1223 g_assert_cmpstr (as_icon_get_name (icon), ==, "app.png");
1224 g_assert_cmpstr (as_icon_get_filename (icon), ==, NULL);
1225 g_assert_cmpstr (as_icon_get_url (icon), ==, NULL);
1226 g_assert_cmpint (as_icon_get_height (icon), ==, 32);
1227 g_assert_cmpint (as_icon_get_width (icon), ==, 32);
1228 g_assert (as_icon_get_data (icon) != NULL);
1229 g_assert (as_icon_get_pixbuf (icon) != NULL);
1230
1231 /* back to node */
1232 root = as_node_new ();
1233 as_node_context_set_version (ctx, 0.4);
1234 n = as_icon_node_insert (icon, root, ctx);
1235 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1236 ret = as_test_compare_lines (xml->str, src, &error);
1237 g_assert_no_error (error);
1238 g_assert (ret);
1239 g_string_free (xml, TRUE);
1240 as_node_unref (root);
1241
1242 /* convert to cached icon */
1243 as_icon_set_prefix (icon, "/tmp");
1244 ret = as_icon_convert_to_kind (icon, AS_ICON_KIND_CACHED, &error);
1245 g_assert_no_error (error);
1246 g_assert (ret);
1247 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_CACHED);
1248 g_assert_cmpstr (as_icon_get_filename (icon), ==, NULL);
1249 g_assert_cmpstr (as_icon_get_url (icon), ==, NULL);
1250 g_assert (as_icon_get_pixbuf (icon) != NULL);
1251 g_assert (as_icon_get_data (icon) != NULL);
1252 g_assert (g_file_test ("/tmp/32x32/app.png", G_FILE_TEST_EXISTS));
1253 }
1254
1255 static void
as_test_image_func(void)1256 as_test_image_func (void)
1257 {
1258 GError *error = NULL;
1259 AsNode *n;
1260 AsNode *root;
1261 GString *xml;
1262 const gchar *src =
1263 "<image type=\"thumbnail\" height=\"12\" width=\"34\" xml:lang=\"en_GB\">"
1264 "http://www.hughsie.com/a.jpg</image>";
1265 gboolean ret;
1266 g_autoptr(AsNodeContext) ctx = NULL;
1267 g_autofree gchar *filename = NULL;
1268 g_autoptr(AsImage) image = NULL;
1269 g_autoptr(GdkPixbuf) pixbuf = NULL;
1270
1271 image = as_image_new ();
1272
1273 /* to object */
1274 root = as_node_from_xml (src, 0, &error);
1275 g_assert_no_error (error);
1276 g_assert (root != NULL);
1277 n = as_node_find (root, "image");
1278 g_assert (n != NULL);
1279 ctx = as_node_context_new ();
1280 ret = as_image_node_parse (image, n, ctx, &error);
1281 g_assert_no_error (error);
1282 g_assert (ret);
1283 as_node_unref (root);
1284
1285 /* verify */
1286 g_assert_cmpint (as_image_get_kind (image), ==, AS_IMAGE_KIND_THUMBNAIL);
1287 g_assert_cmpint (as_image_get_height (image), ==, 12);
1288 g_assert_cmpint (as_image_get_width (image), ==, 34);
1289 g_assert_cmpstr (as_image_get_locale (image), ==, "en_GB");
1290 g_assert_cmpstr (as_image_get_url (image), ==, "http://www.hughsie.com/a.jpg");
1291
1292 /* back to node */
1293 root = as_node_new ();
1294 as_node_context_set_version (ctx, 0.4);
1295 n = as_image_node_insert (image, root, ctx);
1296 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1297 ret = as_test_compare_lines (xml->str, src, &error);
1298 g_assert_no_error (error);
1299 g_assert (ret);
1300 g_string_free (xml, TRUE);
1301 as_node_unref (root);
1302
1303 /* read from image */
1304 filename = as_test_get_filename ("screenshot.png");
1305 ret = as_image_load_filename (image, filename, &error);
1306 g_assert_no_error (error);
1307 g_assert (ret);
1308 g_assert_cmpint (as_image_get_width (image), ==, 800);
1309 g_assert_cmpint (as_image_get_height (image), ==, 600);
1310 g_assert_cmpstr (as_image_get_basename (image), ==, "screenshot.png");
1311 g_assert_cmpstr (as_image_get_md5 (image), ==, "9de72240c27a6f8f2eaab692795cdafc");
1312
1313 /* resample */
1314 pixbuf = as_image_save_pixbuf (image,
1315 752, 423,
1316 AS_IMAGE_SAVE_FLAG_PAD_16_9);
1317 g_assert_cmpint (gdk_pixbuf_get_width (pixbuf), ==, 752);
1318 g_assert_cmpint (gdk_pixbuf_get_height (pixbuf), ==, 423);
1319
1320 /* save */
1321 ret = as_image_save_filename (image,
1322 "/tmp/foo.png",
1323 0, 0,
1324 AS_IMAGE_SAVE_FLAG_NONE,
1325 &error);
1326 g_assert_no_error (error);
1327 g_assert (ret);
1328 }
1329
1330 static void
as_test_agreement_func(void)1331 as_test_agreement_func (void)
1332 {
1333 GError *error = NULL;
1334 AsAgreementSection *sect;
1335 AsNode *n;
1336 AsNode *root;
1337 GString *xml;
1338 const gchar *src =
1339 "<agreement type=\"eula\" version_id=\"1.2.3a\">\n"
1340 "<agreement_section type=\"intro\">\n"
1341 "<description><p>Mighty Fine</p></description>\n"
1342 "</agreement_section>\n"
1343 "</agreement>\n";
1344 gboolean ret;
1345 g_autoptr(AsAgreement) agreement = NULL;
1346 g_autoptr(AsNodeContext) ctx = NULL;
1347
1348 agreement = as_agreement_new ();
1349
1350 /* to object */
1351 root = as_node_from_xml (src, 0, &error);
1352 g_assert_no_error (error);
1353 g_assert (root != NULL);
1354 n = as_node_find (root, "agreement");
1355 g_assert (n != NULL);
1356 ctx = as_node_context_new ();
1357 ret = as_agreement_node_parse (agreement, n, ctx, &error);
1358 g_assert_no_error (error);
1359 g_assert (ret);
1360 as_node_unref (root);
1361
1362 /* verify */
1363 g_assert_cmpint (as_agreement_get_kind (agreement), ==, AS_AGREEMENT_KIND_EULA);
1364 g_assert_cmpstr (as_agreement_get_version_id (agreement), ==, "1.2.3a");
1365 sect = as_agreement_get_section_default (agreement);
1366 g_assert_nonnull (sect);
1367 g_assert_cmpstr (as_agreement_section_get_kind (sect), ==, "intro");
1368 g_assert_cmpstr (as_agreement_section_get_description (sect, NULL), ==, "<p>Mighty Fine</p>");
1369
1370 /* back to node */
1371 root = as_node_new ();
1372 as_node_context_set_version (ctx, 0.4);
1373 n = as_agreement_node_insert (agreement, root, ctx);
1374 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1375 ret = as_test_compare_lines (xml->str, src, &error);
1376 g_assert_no_error (error);
1377 g_assert (ret);
1378 g_string_free (xml, TRUE);
1379 as_node_unref (root);
1380 }
1381
1382 static void
as_test_review_func(void)1383 as_test_review_func (void)
1384 {
1385 GError *error = NULL;
1386 AsNode *n;
1387 AsNode *root;
1388 GString *xml;
1389 const gchar *src =
1390 "<review date=\"2016-09-15\" id=\"17\" rating=\"80\">\n"
1391 "<priority>5</priority>\n"
1392 "<summary>Hello world</summary>\n"
1393 "<description><p>Mighty Fine</p></description>\n"
1394 "<version>1.2.3</version>\n"
1395 "<reviewer_id>deadbeef</reviewer_id>\n"
1396 "<reviewer_name>Richard Hughes</reviewer_name>\n"
1397 "<lang>en_GB</lang>\n"
1398 "<metadata>\n"
1399 "<value key=\"foo\">bar</value>\n"
1400 "</metadata>\n"
1401 "</review>\n";
1402 gboolean ret;
1403 g_autoptr(AsNodeContext) ctx = NULL;
1404 g_autoptr(AsReview) review = NULL;
1405
1406 review = as_review_new ();
1407
1408 /* to object */
1409 root = as_node_from_xml (src, 0, &error);
1410 g_assert_no_error (error);
1411 g_assert (root != NULL);
1412 n = as_node_find (root, "review");
1413 g_assert (n != NULL);
1414 ctx = as_node_context_new ();
1415 ret = as_review_node_parse (review, n, ctx, &error);
1416 g_assert_no_error (error);
1417 g_assert (ret);
1418 as_node_unref (root);
1419
1420 /* verify */
1421 g_assert_cmpint (as_review_get_priority (review), ==, 5);
1422 g_assert (as_review_get_date (review) != NULL);
1423 g_assert_cmpstr (as_review_get_id (review), ==, "17");
1424 g_assert_cmpstr (as_review_get_version (review), ==, "1.2.3");
1425 g_assert_cmpstr (as_review_get_reviewer_id (review), ==, "deadbeef");
1426 g_assert_cmpstr (as_review_get_reviewer_name (review), ==, "Richard Hughes");
1427 g_assert_cmpstr (as_review_get_summary (review), ==, "Hello world");
1428 g_assert_cmpstr (as_review_get_locale (review), ==, "en_GB");
1429 g_assert_cmpstr (as_review_get_description (review), ==, "<p>Mighty Fine</p>");
1430 g_assert_cmpstr (as_review_get_metadata_item (review, "foo"), ==, "bar");
1431
1432 /* back to node */
1433 root = as_node_new ();
1434 as_node_context_set_version (ctx, 0.4);
1435 n = as_review_node_insert (review, root, ctx);
1436 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1437 ret = as_test_compare_lines (xml->str, src, &error);
1438 g_assert_no_error (error);
1439 g_assert (ret);
1440 g_string_free (xml, TRUE);
1441 as_node_unref (root);
1442 }
1443
1444 static void
as_test_require_func(void)1445 as_test_require_func (void)
1446 {
1447 GError *error = NULL;
1448 AsNode *n;
1449 AsNode *root;
1450 const gchar *src =
1451 "<component type=\"desktop\">\n"
1452 "<requires>\n"
1453 "<id>gimp.desktop</id>\n"
1454 "<firmware compare=\"ge\" version=\"0.1.2\">bootloader</firmware>\n"
1455 "<firmware compare=\"eq\" version=\"1.0.0\">runtime</firmware>\n"
1456 "<hardware>4be0643f-1d98-573b-97cd-ca98a65347dd</hardware>\n"
1457 "</requires>\n"
1458 "</component>\n";
1459 gboolean ret;
1460 GPtrArray *requires;
1461 g_autoptr(AsApp) app = NULL;
1462 g_autoptr(AsNodeContext) ctx = NULL;
1463 g_autoptr(AsRequire) require = NULL;
1464 g_autoptr(GString) xml = NULL;
1465
1466 /* to object */
1467 root = as_node_from_xml (src, 0, &error);
1468 g_assert_no_error (error);
1469 g_assert (root != NULL);
1470 n = as_node_find (root, "component");
1471 g_assert (n != NULL);
1472 ctx = as_node_context_new ();
1473 app = as_app_new ();
1474 ret = as_app_node_parse (app, n, ctx, &error);
1475 g_assert_no_error (error);
1476 g_assert (ret);
1477 as_node_unref (root);
1478
1479 /* verify */
1480 requires = as_app_get_requires (app);
1481 g_assert_cmpint (requires->len, ==, 4);
1482 require = g_ptr_array_index (requires, 0);
1483 g_assert_cmpint (as_require_get_kind (require), ==, AS_REQUIRE_KIND_ID);
1484 g_assert_cmpint (as_require_get_compare (require), ==, AS_REQUIRE_COMPARE_UNKNOWN);
1485 g_assert_cmpstr (as_require_get_version (require), ==, NULL);
1486 g_assert_cmpstr (as_require_get_value (require), ==, "gimp.desktop");
1487 require = as_app_get_require_by_value (app, AS_REQUIRE_KIND_FIRMWARE, "bootloader");
1488 g_assert_cmpint (as_require_get_kind (require), ==, AS_REQUIRE_KIND_FIRMWARE);
1489 g_assert_cmpint (as_require_get_compare (require), ==, AS_REQUIRE_COMPARE_GE);
1490 g_assert_cmpstr (as_require_get_version (require), ==, "0.1.2");
1491 g_assert_cmpstr (as_require_get_value (require), ==, "bootloader");
1492 require = g_ptr_array_index (requires, 3);
1493 g_assert_cmpint (as_require_get_kind (require), ==, AS_REQUIRE_KIND_HARDWARE);
1494 g_assert_cmpint (as_require_get_compare (require), ==, AS_REQUIRE_COMPARE_UNKNOWN);
1495 g_assert_cmpstr (as_require_get_version (require), ==, NULL);
1496 g_assert_cmpstr (as_require_get_value (require), ==, "4be0643f-1d98-573b-97cd-ca98a65347dd");
1497
1498 /* back to node */
1499 root = as_node_new ();
1500 as_node_context_set_version (ctx, 0.4);
1501 n = as_app_node_insert (app, root, ctx);
1502 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1503 ret = as_test_compare_lines (xml->str, src, &error);
1504 g_assert_no_error (error);
1505 g_assert (ret);
1506 as_node_unref (root);
1507
1508 /* test we can go back and forth */
1509 for (guint i = 0; i < AS_REQUIRE_COMPARE_LAST; i++) {
1510 const gchar *tmp = as_require_compare_to_string (i);
1511 g_assert_cmpint (as_require_compare_from_string (tmp), ==, i);
1512 }
1513
1514 /* check predicates */
1515 require = as_require_new ();
1516 as_require_set_version (require, "0.1.2");
1517 as_require_set_compare (require, AS_REQUIRE_COMPARE_EQ);
1518 ret = as_require_version_compare (require, "0.1.2", &error);
1519 g_assert_no_error (error);
1520 g_assert (ret);
1521 as_require_set_compare (require, AS_REQUIRE_COMPARE_LT);
1522 ret = as_require_version_compare (require, "0.1.1", &error);
1523 g_assert_no_error (error);
1524 g_assert (ret);
1525 as_require_set_compare (require, AS_REQUIRE_COMPARE_LE);
1526 ret = as_require_version_compare (require, "0.1.2", &error);
1527 g_assert_no_error (error);
1528 g_assert (ret);
1529
1530 as_require_set_version (require, "0.1.?");
1531 as_require_set_compare (require, AS_REQUIRE_COMPARE_GLOB);
1532 ret = as_require_version_compare (require, "0.1.9", &error);
1533 g_assert_no_error (error);
1534 g_assert (ret);
1535
1536 as_require_set_version (require, "0.1.[0-9]");
1537 as_require_set_compare (require, AS_REQUIRE_COMPARE_REGEX);
1538 ret = as_require_version_compare (require, "0.1.9", &error);
1539 g_assert_no_error (error);
1540 g_assert (ret);
1541 }
1542
1543 static void
as_test_suggest_func(void)1544 as_test_suggest_func (void)
1545 {
1546 GError *error = NULL;
1547 AsNode *n;
1548 AsNode *root;
1549 GString *xml;
1550 const gchar *src =
1551 "<suggests type=\"upstream\">\n"
1552 "<id>gimp.desktop</id>\n"
1553 "<id>mypaint.desktop</id>\n"
1554 "</suggests>\n";
1555 gboolean ret;
1556 g_autoptr(AsNodeContext) ctx = NULL;
1557 g_autoptr(AsSuggest) suggest = NULL;
1558 g_autoptr(GdkPixbuf) pixbuf = NULL;
1559
1560 suggest = as_suggest_new ();
1561
1562 /* to object */
1563 root = as_node_from_xml (src, 0, &error);
1564 g_assert_no_error (error);
1565 g_assert (root != NULL);
1566 n = as_node_find (root, "suggests");
1567 g_assert (n != NULL);
1568 ctx = as_node_context_new ();
1569 ret = as_suggest_node_parse (suggest, n, ctx, &error);
1570 g_assert_no_error (error);
1571 g_assert (ret);
1572 as_node_unref (root);
1573
1574 /* verify */
1575 g_assert_cmpint (as_suggest_get_kind (suggest), ==, AS_SUGGEST_KIND_UPSTREAM);
1576 g_assert_cmpint (as_suggest_get_ids(suggest)->len, ==, 2);
1577
1578 /* back to node */
1579 root = as_node_new ();
1580 as_node_context_set_version (ctx, 0.4);
1581 n = as_suggest_node_insert (suggest, root, ctx);
1582 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1583 ret = as_test_compare_lines (xml->str, src, &error);
1584 g_assert_no_error (error);
1585 g_assert (ret);
1586 g_string_free (xml, TRUE);
1587 as_node_unref (root);
1588 }
1589
1590 static void
as_test_bundle_func(void)1591 as_test_bundle_func (void)
1592 {
1593 GError *error = NULL;
1594 AsNode *n;
1595 AsNode *root;
1596 GString *xml;
1597 const gchar *src =
1598 "<bundle type=\"limba\" runtime=\"1\" sdk=\"2\">gnome-3-16</bundle>";
1599 gboolean ret;
1600 g_autoptr(AsNodeContext) ctx = NULL;
1601 g_autoptr(AsBundle) bundle = NULL;
1602
1603 bundle = as_bundle_new ();
1604
1605 /* to object */
1606 root = as_node_from_xml (src, 0, &error);
1607 g_assert_no_error (error);
1608 g_assert (root != NULL);
1609 n = as_node_find (root, "bundle");
1610 g_assert (n != NULL);
1611 ctx = as_node_context_new ();
1612 ret = as_bundle_node_parse (bundle, n, ctx, &error);
1613 g_assert_no_error (error);
1614 g_assert (ret);
1615 as_node_unref (root);
1616
1617 /* verify */
1618 g_assert_cmpint (as_bundle_get_kind (bundle), ==, AS_BUNDLE_KIND_LIMBA);
1619 g_assert_cmpstr (as_bundle_get_id (bundle), ==, "gnome-3-16");
1620 g_assert_cmpstr (as_bundle_get_runtime (bundle), ==, "1");
1621 g_assert_cmpstr (as_bundle_get_sdk (bundle), ==, "2");
1622
1623 /* back to node */
1624 root = as_node_new ();
1625 as_node_context_set_version (ctx, 0.4);
1626 n = as_bundle_node_insert (bundle, root, ctx);
1627 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1628 ret = as_test_compare_lines (xml->str, src, &error);
1629 g_assert_no_error (error);
1630 g_assert (ret);
1631 g_string_free (xml, TRUE);
1632 as_node_unref (root);
1633 }
1634
1635 static void
as_test_translation_func(void)1636 as_test_translation_func (void)
1637 {
1638 GError *error = NULL;
1639 AsNode *n;
1640 AsNode *root;
1641 GString *xml;
1642 const gchar *src =
1643 "<translation type=\"gettext\">gnome-software</translation>";
1644 gboolean ret;
1645 g_autoptr(AsNodeContext) ctx = NULL;
1646 g_autoptr(AsTranslation) translation = NULL;
1647
1648 translation = as_translation_new ();
1649
1650 /* to object */
1651 root = as_node_from_xml (src, 0, &error);
1652 g_assert_no_error (error);
1653 g_assert (root != NULL);
1654 n = as_node_find (root, "translation");
1655 g_assert (n != NULL);
1656 ctx = as_node_context_new ();
1657 ret = as_translation_node_parse (translation, n, ctx, &error);
1658 g_assert_no_error (error);
1659 g_assert (ret);
1660 as_node_unref (root);
1661
1662 /* verify */
1663 g_assert_cmpint (as_translation_get_kind (translation), ==, AS_TRANSLATION_KIND_GETTEXT);
1664 g_assert_cmpstr (as_translation_get_id (translation), ==, "gnome-software");
1665
1666 /* back to node */
1667 root = as_node_new ();
1668 as_node_context_set_version (ctx, 0.4);
1669 n = as_translation_node_insert (translation, root, ctx);
1670 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
1671 ret = as_test_compare_lines (xml->str, src, &error);
1672 g_assert_no_error (error);
1673 g_assert (ret);
1674 g_string_free (xml, TRUE);
1675 as_node_unref (root);
1676 }
1677
1678 static void
as_test_screenshot_func(void)1679 as_test_screenshot_func (void)
1680 {
1681 GPtrArray *images;
1682 AsImage *im;
1683 GError *error = NULL;
1684 AsNode *n;
1685 AsNode *root;
1686 GString *xml;
1687 const gchar *src =
1688 "<screenshot priority=\"-64\">\n"
1689 "<caption>Hello</caption>\n"
1690 "<image type=\"source\" height=\"800\" width=\"600\">http://1.png</image>\n"
1691 "<image type=\"thumbnail\" height=\"100\" width=\"100\">http://2.png</image>\n"
1692 "</screenshot>\n";
1693 gboolean ret;
1694 g_autoptr(AsNodeContext) ctx = NULL;
1695 g_autoptr(AsScreenshot) screenshot = NULL;
1696
1697 screenshot = as_screenshot_new ();
1698
1699 /* to object */
1700 root = as_node_from_xml (src, 0, &error);
1701 g_assert_no_error (error);
1702 g_assert (root != NULL);
1703 n = as_node_find (root, "screenshot");
1704 g_assert (n != NULL);
1705 ctx = as_node_context_new ();
1706 ret = as_screenshot_node_parse (screenshot, n, ctx, &error);
1707 g_assert_no_error (error);
1708 g_assert (ret);
1709
1710 /* verify */
1711 g_assert_cmpint (as_screenshot_get_kind (screenshot), ==, AS_SCREENSHOT_KIND_NORMAL);
1712 g_assert_cmpint (as_screenshot_get_priority (screenshot), ==, -64);
1713 g_assert_cmpstr (as_screenshot_get_caption (screenshot, "C"), ==, "Hello");
1714 images = as_screenshot_get_images (screenshot);
1715 g_assert_cmpint (images->len, ==, 2);
1716 im = as_screenshot_get_source (screenshot);
1717 g_assert (im != NULL);
1718 g_assert_cmpstr (as_image_get_url (im), ==, "http://1.png");
1719 as_node_unref (root);
1720
1721 /* get closest */
1722 im = as_screenshot_get_image (screenshot, 120, 120);
1723 g_assert (im != NULL);
1724 g_assert_cmpstr (as_image_get_url (im), ==, "http://2.png");
1725 im = as_screenshot_get_image (screenshot, 800, 560);
1726 g_assert (im != NULL);
1727 g_assert_cmpstr (as_image_get_url (im), ==, "http://1.png");
1728
1729 /* back to node */
1730 root = as_node_new ();
1731 as_node_context_set_version (ctx, 0.8);
1732 n = as_screenshot_node_insert (screenshot, root, ctx);
1733 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1734 ret = as_test_compare_lines (xml->str, src, &error);
1735 g_assert_no_error (error);
1736 g_assert (ret);
1737 g_string_free (xml, TRUE);
1738 as_node_unref (root);
1739 }
1740
1741 static void
as_test_content_rating_func(void)1742 as_test_content_rating_func (void)
1743 {
1744 GError *error = NULL;
1745 AsNode *n;
1746 AsNode *root;
1747 GString *xml;
1748 const gchar *src =
1749 "<content_rating type=\"oars-1.0\">\n"
1750 "<content_attribute id=\"drugs-alcohol\">moderate</content_attribute>\n"
1751 "<content_attribute id=\"violence-cartoon\">mild</content_attribute>\n"
1752 "</content_rating>\n";
1753 gboolean ret;
1754 g_autoptr(AsNodeContext) ctx = NULL;
1755 g_autoptr(AsContentRating) content_rating = NULL;
1756 g_autofree const gchar **rating_ids = NULL;
1757 const gchar *expected_rating_ids[] = { "drugs-alcohol", "violence-cartoon", NULL };
1758 gsize i;
1759
1760 content_rating = as_content_rating_new ();
1761
1762 /* to object */
1763 root = as_node_from_xml (src, 0, &error);
1764 g_assert_no_error (error);
1765 g_assert (root != NULL);
1766 n = as_node_find (root, "content_rating");
1767 g_assert (n != NULL);
1768 ctx = as_node_context_new ();
1769 ret = as_content_rating_node_parse (content_rating, n, ctx, &error);
1770 g_assert_no_error (error);
1771 g_assert (ret);
1772
1773 /* verify */
1774 g_assert_cmpstr (as_content_rating_get_kind (content_rating), ==, "oars-1.0");
1775 g_assert_cmpint (as_content_rating_get_value (content_rating, "drugs-alcohol"), ==,
1776 AS_CONTENT_RATING_VALUE_MODERATE);
1777 g_assert_cmpint (as_content_rating_get_value (content_rating, "violence-cartoon"), ==,
1778 AS_CONTENT_RATING_VALUE_MILD);
1779 g_assert_cmpint (as_content_rating_get_value (content_rating, "violence-bloodshed"), ==,
1780 AS_CONTENT_RATING_VALUE_NONE);
1781
1782 rating_ids = as_content_rating_get_rating_ids (content_rating);
1783 g_assert_nonnull (rating_ids);
1784
1785 for (i = 0; rating_ids[i] != NULL && expected_rating_ids[i] != NULL; i++)
1786 g_assert_cmpstr (rating_ids[i], ==, expected_rating_ids[i]);
1787 g_assert_null (rating_ids[i]);
1788 g_assert_null (expected_rating_ids[i]);
1789
1790 as_node_unref (root);
1791
1792 /* check CSM */
1793 g_assert_cmpint (as_content_rating_get_minimum_age (content_rating), ==, 13);
1794
1795 /* back to node */
1796 root = as_node_new ();
1797 as_node_context_set_version (ctx, 0.8);
1798 n = as_content_rating_node_insert (content_rating, root, ctx);
1799 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
1800 ret = as_test_compare_lines (xml->str, src, &error);
1801 g_assert_no_error (error);
1802 g_assert (ret);
1803 g_string_free (xml, TRUE);
1804 as_node_unref (root);
1805 }
1806
1807 /* Test that parsing an empty content rating correctly returns `none` as the
1808 * value for all the ratings defined by that particular kind of content rating,
1809 * and `unknown` for everything else. */
1810 static void
as_test_content_rating_empty(void)1811 as_test_content_rating_empty (void)
1812 {
1813 GError *error = NULL;
1814 AsNode *n;
1815 AsNode *root;
1816 const gchar *src =
1817 "<content_rating type=\"oars-1.0\">\n"
1818 "</content_rating>\n";
1819 gboolean ret;
1820 g_autoptr(AsNodeContext) ctx = NULL;
1821 g_autoptr(AsContentRating) content_rating = NULL;
1822
1823 content_rating = as_content_rating_new ();
1824
1825 /* to object */
1826 root = as_node_from_xml (src, 0, &error);
1827 g_assert_no_error (error);
1828 g_assert_nonnull (root);
1829 n = as_node_find (root, "content_rating");
1830 g_assert_nonnull (n);
1831 ctx = as_node_context_new ();
1832 ret = as_content_rating_node_parse (content_rating, n, ctx, &error);
1833 g_assert_no_error (error);
1834 g_assert_true (ret);
1835
1836 /* verify */
1837 g_assert_cmpstr (as_content_rating_get_kind (content_rating), ==, "oars-1.0");
1838 g_assert_cmpint (as_content_rating_get_value (content_rating, "drugs-alcohol"), ==,
1839 AS_CONTENT_RATING_VALUE_NONE);
1840 g_assert_cmpint (as_content_rating_get_value (content_rating, "violence-cartoon"), ==,
1841 AS_CONTENT_RATING_VALUE_NONE);
1842 g_assert_cmpint (as_content_rating_get_value (content_rating, "violence-bloodshed"), ==,
1843 AS_CONTENT_RATING_VALUE_NONE);
1844
1845 /* This one was only added in OARS-1.1, so it shouldn’t have a value of `none`. */
1846 g_assert_cmpint (as_content_rating_get_value (content_rating, "sex-adultery"), ==,
1847 AS_CONTENT_RATING_VALUE_UNKNOWN);
1848
1849 as_node_unref (root);
1850 }
1851
1852 /* Test that the OARS → CSM mapping table in as_content_rating_attribute_to_csm_age()
1853 * is complete (contains mappings for all known IDs), and that the ages it
1854 * returns are non-decreasing for increasing values of #AsContentRatingValue in
1855 * each ID.
1856 *
1857 * Also test that unknown values of #AsContentRatingValue return an unknown age,
1858 * and unknown IDs do similarly. */
1859 static void
as_test_content_rating_mappings(void)1860 as_test_content_rating_mappings (void)
1861 {
1862 const AsContentRatingValue values[] = {
1863 AS_CONTENT_RATING_VALUE_NONE,
1864 AS_CONTENT_RATING_VALUE_MILD,
1865 AS_CONTENT_RATING_VALUE_MODERATE,
1866 AS_CONTENT_RATING_VALUE_INTENSE,
1867 };
1868 g_autofree const gchar **ids = as_content_rating_get_all_rating_ids ();
1869
1870 for (gsize i = 0; ids[i] != NULL; i++) {
1871 guint max_age = 0;
1872
1873 for (gsize j = 0; j < G_N_ELEMENTS (values); j++) {
1874 guint age = as_content_rating_attribute_to_csm_age (ids[i], values[j]);
1875 g_assert_cmpuint (age, >=, max_age);
1876 max_age = age;
1877 }
1878
1879 g_assert_cmpuint (max_age, >, 0);
1880 g_assert_cmpuint (as_content_rating_attribute_to_csm_age (ids[i], AS_CONTENT_RATING_VALUE_UNKNOWN), ==, 0);
1881 g_assert_cmpuint (as_content_rating_attribute_to_csm_age (ids[i], AS_CONTENT_RATING_VALUE_LAST), ==, 0);
1882 }
1883
1884 g_assert_cmpuint (as_content_rating_attribute_to_csm_age ("not-valid-id", AS_CONTENT_RATING_VALUE_INTENSE), ==, 0);
1885 }
1886
1887 /* Test that gs_utils_content_rating_system_from_locale() returns the correct
1888 * rating system for various standard locales and various forms of locale name.
1889 * See `locale -a` for the list of all available locales which some of these
1890 * test vectors were derived from. */
1891 static void
as_test_content_rating_from_locale(void)1892 as_test_content_rating_from_locale (void)
1893 {
1894 const struct {
1895 const gchar *locale;
1896 AsContentRatingSystem expected_system;
1897 } vectors[] = {
1898 /* Simple tests to get coverage of each rating system: */
1899 { "es_AR", AS_CONTENT_RATING_SYSTEM_INCAA },
1900 { "en_AU", AS_CONTENT_RATING_SYSTEM_ACB },
1901 { "pt_BR", AS_CONTENT_RATING_SYSTEM_DJCTQ },
1902 { "zh_TW", AS_CONTENT_RATING_SYSTEM_GSRR },
1903 { "en_GB", AS_CONTENT_RATING_SYSTEM_PEGI },
1904 { "hy_AM", AS_CONTENT_RATING_SYSTEM_PEGI },
1905 { "bg_BG", AS_CONTENT_RATING_SYSTEM_PEGI },
1906 { "fi_FI", AS_CONTENT_RATING_SYSTEM_KAVI },
1907 { "de_DE", AS_CONTENT_RATING_SYSTEM_USK },
1908 { "az_IR", AS_CONTENT_RATING_SYSTEM_ESRA },
1909 { "jp_JP", AS_CONTENT_RATING_SYSTEM_CERO },
1910 { "en_NZ", AS_CONTENT_RATING_SYSTEM_OFLCNZ },
1911 { "ru_RU", AS_CONTENT_RATING_SYSTEM_RUSSIA },
1912 { "en_SQ", AS_CONTENT_RATING_SYSTEM_MDA },
1913 { "ko_KR", AS_CONTENT_RATING_SYSTEM_GRAC },
1914 { "en_US", AS_CONTENT_RATING_SYSTEM_ESRB },
1915 { "en_US", AS_CONTENT_RATING_SYSTEM_ESRB },
1916 { "en_CA", AS_CONTENT_RATING_SYSTEM_ESRB },
1917 { "es_MX", AS_CONTENT_RATING_SYSTEM_ESRB },
1918 /* Fallback (arbitrarily chosen Venezuela since it seems to use IARC): */
1919 { "es_VE", AS_CONTENT_RATING_SYSTEM_IARC },
1920 /* Locale with a codeset: */
1921 { "nl_NL.iso88591", AS_CONTENT_RATING_SYSTEM_PEGI },
1922 /* Locale with a codeset and modifier: */
1923 { "nl_NL.iso885915@euro", AS_CONTENT_RATING_SYSTEM_PEGI },
1924 /* Locale with a less esoteric codeset: */
1925 { "en_GB.UTF-8", AS_CONTENT_RATING_SYSTEM_PEGI },
1926 /* Locale with a modifier but no codeset: */
1927 { "fi_FI@euro", AS_CONTENT_RATING_SYSTEM_KAVI },
1928 /* Invalid locale: */
1929 { "_invalid", AS_CONTENT_RATING_SYSTEM_IARC },
1930 };
1931
1932 for (gsize i = 0; i < G_N_ELEMENTS (vectors); i++) {
1933 g_test_message ("Test %" G_GSIZE_FORMAT ": %s", i, vectors[i].locale);
1934 g_assert_cmpint (as_content_rating_system_from_locale (vectors[i].locale), ==, vectors[i].expected_system);
1935 }
1936 }
1937
1938 static void
as_test_app_func(void)1939 as_test_app_func (void)
1940 {
1941 AsIcon *ic;
1942 AsBundle *bu;
1943 AsRelease *rel;
1944 AsLaunchable *lau;
1945 GError *error = NULL;
1946 AsNode *n;
1947 AsNode *root;
1948 GPtrArray *icons;
1949 GString *xml;
1950 gboolean ret;
1951 const gchar *src =
1952 "<component type=\"desktop\" merge=\"replace\" priority=\"-4\">\n"
1953 "<id>org.gnome.Software.desktop</id>\n"
1954 "<pkgname>gnome-software</pkgname>\n"
1955 "<source_pkgname>gnome-software-src</source_pkgname>\n"
1956 "<bundle type=\"flatpak\">app/org.gnome.Software/x86_64/master</bundle>\n"
1957 "<translation type=\"gettext\">gnome-software</translation>\n"
1958 "<suggests type=\"upstream\">\n"
1959 "<id>gimp.desktop</id>\n"
1960 "<id>mypaint.desktop</id>\n"
1961 "</suggests>\n"
1962 "<name>Software</name>\n"
1963 "<name xml:lang=\"pl\">Oprogramowanie</name>\n"
1964 "<summary>Application manager</summary>\n"
1965 "<developer_name>GNOME Foundation</developer_name>\n"
1966 "<description><p>Software allows you to find stuff</p></description>\n"
1967 "<description xml:lang=\"pt_BR\"><p>O aplicativo Software.</p></description>\n"
1968 "<icon type=\"cached\" height=\"64\" width=\"64\">org.gnome.Software1.png</icon>\n"
1969 "<icon type=\"cached\" height=\"64\" width=\"64\">org.gnome.Software2.png</icon>\n"
1970 "<categories>\n"
1971 "<category>System</category>\n"
1972 "</categories>\n"
1973 "<architectures>\n"
1974 "<arch>i386</arch>\n"
1975 "</architectures>\n"
1976 "<keywords>\n"
1977 "<keyword>Installing</keyword>\n"
1978 "</keywords>\n"
1979 "<kudos>\n"
1980 "<kudo>SearchProvider</kudo>\n"
1981 "</kudos>\n"
1982 "<permissions>\n"
1983 "<permission>Network</permission>\n"
1984 "</permissions>\n"
1985 "<vetos>\n"
1986 "<veto>Required AppData: ConsoleOnly</veto>\n"
1987 "</vetos>\n"
1988 "<mimetypes>\n"
1989 "<mimetype>application/vnd.oasis.opendocument.spreadsheet</mimetype>\n"
1990 "</mimetypes>\n"
1991 "<project_license>GPLv2+</project_license>\n"
1992 "<url type=\"homepage\">https://wiki.gnome.org/Design/Apps/Software</url>\n"
1993 "<project_group>GNOME</project_group>\n"
1994 "<compulsory_for_desktop>GNOME</compulsory_for_desktop>\n"
1995 "<screenshots>\n"
1996 "<screenshot type=\"default\">\n"
1997 "<image type=\"thumbnail\" height=\"351\" width=\"624\">http://a.png</image>\n"
1998 "</screenshot>\n"
1999 "<screenshot>\n"
2000 "<image type=\"thumbnail\">http://b.png</image>\n"
2001 "</screenshot>\n"
2002 "</screenshots>\n"
2003 "<reviews>\n"
2004 "<review date=\"2016-09-15\">\n"
2005 "<summary>Hello world</summary>\n"
2006 "</review>\n"
2007 "</reviews>\n"
2008 "<content_rating type=\"oars-1.0\">\n"
2009 "<content_attribute id=\"drugs-alcohol\">moderate</content_attribute>\n"
2010 "</content_rating>\n"
2011 "<releases>\n"
2012 "<release timestamp=\"1392724801\" version=\"3.11.91\"/>\n"
2013 "<release timestamp=\"1392724800\" version=\"3.11.90\"/>\n"
2014 "</releases>\n"
2015 "<provides>\n"
2016 "<binary>/usr/bin/gnome-shell</binary>\n"
2017 "<dbus type=\"session\">org.gnome.Software</dbus>\n"
2018 "<dbus type=\"system\">org.gnome.Software2</dbus>\n"
2019 "</provides>\n"
2020 "<launchable type=\"desktop-id\">gnome-software.desktop</launchable>\n"
2021 "<languages>\n"
2022 "<lang percentage=\"90\">en_GB</lang>\n"
2023 "<lang>pl</lang>\n"
2024 "</languages>\n"
2025 "<custom>\n"
2026 "<value key=\"SomethingRandom\"/>\n"
2027 "</custom>\n"
2028 "</component>\n";
2029 g_autoptr(AsNodeContext) ctx = NULL;
2030 g_autoptr(AsApp) app = NULL;
2031
2032 app = as_app_new ();
2033
2034 /* to object */
2035 root = as_node_from_xml (src, 0, &error);
2036 g_assert_no_error (error);
2037 g_assert (root != NULL);
2038 n = as_node_find (root, "component");
2039 g_assert (n != NULL);
2040 ctx = as_node_context_new ();
2041 ret = as_app_node_parse (app, n, ctx, &error);
2042 g_assert_no_error (error);
2043 g_assert (ret);
2044
2045 /* verify */
2046 g_assert_cmpstr (as_app_get_id (app), ==, "org.gnome.Software.desktop");
2047 g_assert_cmpstr (as_app_get_id_filename (app), ==, "org.gnome.Software");
2048 g_assert_cmpstr (as_app_get_unique_id (app), ==, "*/flatpak/*/desktop/org.gnome.Software.desktop/master");
2049 g_assert_cmpstr (as_app_get_name (app, "pl"), ==, "Oprogramowanie");
2050 g_assert_cmpstr (as_app_get_comment (app, NULL), ==, "Application manager");
2051 g_assert_cmpstr (as_app_get_description (app, NULL), ==, "<p>Software allows you to find stuff</p>");
2052 g_assert_cmpstr (as_app_get_description (app, "pt_BR"), ==, "<p>O aplicativo Software.</p>");
2053 g_assert_cmpstr (as_app_get_developer_name (app, NULL), ==, "GNOME Foundation");
2054 g_assert_cmpstr (as_app_get_source_pkgname (app), ==, "gnome-software-src");
2055 g_assert_cmpstr (as_app_get_project_group (app), ==, "GNOME");
2056 g_assert_cmpstr (as_app_get_project_license (app), ==, "GPLv2+");
2057 g_assert_cmpstr (as_app_get_branch (app), ==, "master");
2058 g_assert_cmpint (as_app_get_categories(app)->len, ==, 1);
2059 g_assert_cmpint (as_app_get_priority (app), ==, -4);
2060 g_assert_cmpint (as_app_get_screenshots(app)->len, ==, 2);
2061 g_assert_cmpint (as_app_get_releases(app)->len, ==, 2);
2062 g_assert_cmpint (as_app_get_launchables(app)->len, ==, 1);
2063 g_assert_cmpint (as_app_get_provides(app)->len, ==, 3);
2064 g_assert_cmpint (as_app_get_kudos(app)->len, ==, 1);
2065 g_assert_cmpint (as_app_get_permissions(app)->len, ==, 1);
2066 g_assert_cmpstr (as_app_get_metadata_item (app, "SomethingRandom"), ==, "");
2067 g_assert_cmpint (as_app_get_language (app, "en_GB"), ==, 90);
2068 g_assert_cmpint (as_app_get_language (app, "pl"), ==, 0);
2069 g_assert_cmpint (as_app_get_language (app, "xx_XX"), ==, -1);
2070 g_assert (as_app_has_kudo (app, "SearchProvider"));
2071 g_assert (as_app_has_kudo_kind (app, AS_KUDO_KIND_SEARCH_PROVIDER));
2072 g_assert (as_app_has_permission (app, "Network"));
2073 g_assert (!as_app_has_kudo (app, "MagicValue"));
2074 g_assert (!as_app_has_kudo_kind (app, AS_KUDO_KIND_USER_DOCS));
2075 g_assert (as_app_has_compulsory_for_desktop (app, "GNOME"));
2076 g_assert (!as_app_has_compulsory_for_desktop (app, "KDE"));
2077 as_node_unref (root);
2078
2079 /* check equality */
2080 g_assert (as_app_equal (app, app));
2081
2082 /* check newest release */
2083 rel = as_app_get_release_default (app);
2084 g_assert (rel != NULL);
2085 g_assert_cmpstr (as_release_get_version (rel), ==, "3.11.91");
2086
2087 /* check specific release */
2088 rel = as_app_get_release_by_version (app, "3.11.91");
2089 g_assert (rel != NULL);
2090 g_assert_cmpstr (as_release_get_version (rel), ==, "3.11.91");
2091
2092 /* check icons */
2093 icons = as_app_get_icons (app);
2094 g_assert (icons != NULL);
2095 g_assert_cmpint (icons->len, ==, 2);
2096
2097 /* check bundle */
2098 bu = as_app_get_bundle_default (app);
2099 g_assert (bu != NULL);
2100 g_assert_cmpint (as_bundle_get_kind (bu), ==, AS_BUNDLE_KIND_FLATPAK);
2101 g_assert_cmpstr (as_bundle_get_id (bu), ==, "app/org.gnome.Software/x86_64/master");
2102
2103 /* check launchable */
2104 lau = as_app_get_launchable_by_kind (app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
2105 g_assert (lau != NULL);
2106 g_assert_cmpint (as_launchable_get_kind (lau), ==, AS_LAUNCHABLE_KIND_DESKTOP_ID);
2107 g_assert_cmpstr (as_launchable_get_value (lau), ==, "gnome-software.desktop");
2108
2109 /* check we can get a specific icon */
2110 ic = as_app_get_icon_for_size (app, 999, 999);
2111 g_assert (ic == NULL);
2112 ic = as_app_get_icon_for_size (app, 64, 64);
2113 g_assert (ic != NULL);
2114 g_assert_cmpstr (as_icon_get_name (ic), ==, "org.gnome.Software1.png");
2115 g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_CACHED);
2116
2117 /* we can't extend ourself */
2118 as_app_add_extends (app, "org.gnome.Software.desktop");
2119 g_assert_cmpint (as_app_get_extends(app)->len, ==, 0);
2120
2121 /* back to node */
2122 root = as_node_new ();
2123 as_node_context_set_version (ctx, 1.0);
2124 n = as_app_node_insert (app, root, ctx);
2125 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
2126 ret = as_test_compare_lines (xml->str, src, &error);
2127 g_assert_no_error (error);
2128 g_assert (ret);
2129 g_string_free (xml, TRUE);
2130 as_node_unref (root);
2131
2132 /* test contact demunging */
2133 as_app_set_update_contact (app, "richard_at_hughsie_dot_co_dot_uk");
2134 g_assert_cmpstr (as_app_get_update_contact (app), ==, "richard@hughsie.co.uk");
2135 }
2136
2137 static void
as_test_app_launchable_fallback_func(void)2138 as_test_app_launchable_fallback_func (void)
2139 {
2140 AsLaunchable *lau;
2141 AsNode *n;
2142 gboolean ret;
2143 const gchar *src =
2144 "<component type=\"desktop\">\n"
2145 "<id>org.gnome.Software</id>\n"
2146 "</component>\n";
2147 g_autoptr(AsApp) app = NULL;
2148 g_autoptr(AsNodeContext) ctx = NULL;
2149 g_autoptr(AsNode) root = NULL;
2150 g_autoptr(GError) error = NULL;
2151
2152 app = as_app_new ();
2153
2154 /* to object */
2155 root = as_node_from_xml (src, 0, &error);
2156 g_assert_no_error (error);
2157 g_assert (root != NULL);
2158 n = as_node_find (root, "component");
2159 g_assert (n != NULL);
2160 ctx = as_node_context_new ();
2161 ret = as_app_node_parse (app, n, ctx, &error);
2162 g_assert_no_error (error);
2163 g_assert (ret);
2164
2165 /* verify */
2166 g_assert_cmpstr (as_app_get_id (app), ==, "org.gnome.Software");
2167 g_assert_cmpint (as_app_get_launchables(app)->len, ==, 1);
2168 lau = as_app_get_launchable_by_kind (app, AS_LAUNCHABLE_KIND_DESKTOP_ID);
2169 g_assert (lau != NULL);
2170 g_assert_cmpint (as_launchable_get_kind (lau), ==, AS_LAUNCHABLE_KIND_DESKTOP_ID);
2171 g_assert_cmpstr (as_launchable_get_value (lau), ==, "org.gnome.Software.desktop");
2172 }
2173
2174 static void
as_test_app_validate_check(GPtrArray * array,AsProblemKind kind,const gchar * message)2175 as_test_app_validate_check (GPtrArray *array,
2176 AsProblemKind kind,
2177 const gchar *message)
2178 {
2179 AsProblem *problem;
2180 gchar *tmp;
2181 guint i;
2182
2183 for (i = 0; i < array->len; i++) {
2184 g_autofree gchar *message_no_data = NULL;
2185 problem = g_ptr_array_index (array, i);
2186 if (as_problem_get_kind (problem) != kind)
2187 continue;
2188 message_no_data = g_strdup (as_problem_get_message (problem));
2189 tmp = g_strrstr (message_no_data, " [");
2190 if (tmp != NULL)
2191 *tmp = '\0';
2192 tmp = g_strrstr (message_no_data, ", ");
2193 if (tmp != NULL)
2194 *tmp = '\0';
2195 if (g_strcmp0 (message_no_data, message) == 0)
2196 return;
2197 }
2198 g_print ("\n");
2199 for (i = 0; i < array->len; i++) {
2200 problem = g_ptr_array_index (array, i);
2201 g_print ("%u\t%s\n",
2202 as_problem_get_kind (problem),
2203 as_problem_get_message (problem));
2204 }
2205 g_assert_cmpstr (message, ==, "not-found");
2206 }
2207
2208 static void
as_test_app_validate_appdata_good_func(void)2209 as_test_app_validate_appdata_good_func (void)
2210 {
2211 AsImage *im;
2212 AsProblem *problem;
2213 AsScreenshot *ss;
2214 GError *error = NULL;
2215 GPtrArray *images;
2216 GPtrArray *probs;
2217 GPtrArray *screenshots;
2218 gboolean ret;
2219 guint i;
2220 g_autofree gchar *filename = NULL;
2221 g_autoptr(AsApp) app = NULL;
2222
2223 /* open file */
2224 app = as_app_new ();
2225 filename = as_test_get_filename ("success.appdata.xml");
2226 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2227 g_assert_no_error (error);
2228 g_assert (ret);
2229
2230 /* check success */
2231 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
2232 g_assert_cmpstr (as_app_get_id (app), ==, "gnome-power-statistics.desktop");
2233 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "0 A.D.");
2234 g_assert_cmpstr (as_app_get_comment (app, "C"), ==, "Observe power management");
2235 g_assert_cmpstr (as_app_get_metadata_license (app), ==, "CC0-1.0 AND CC-BY-3.0");
2236 g_assert_cmpstr (as_app_get_update_contact (app), ==, "richard@hughsie.com");
2237 g_assert_cmpstr (as_app_get_project_group (app), ==, "GNOME");
2238 g_assert_cmpstr (as_app_get_url_item (app, AS_URL_KIND_HOMEPAGE), ==,
2239 "http://www.gnome.org/projects/gnome-power-manager/");
2240 g_assert_cmpstr (as_app_get_description (app, "C"), !=, NULL);
2241 g_assert_cmpint (as_app_get_description_size (app), ==, 1);
2242 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NO_NETWORK, &error);
2243 g_assert_no_error (error);
2244 g_assert (probs != NULL);
2245 for (i = 0; i < probs->len; i++) {
2246 problem = g_ptr_array_index (probs, i);
2247 g_print ("%s\n", as_problem_get_message (problem));
2248 }
2249 g_assert_cmpint (probs->len, ==, 0);
2250 g_ptr_array_unref (probs);
2251
2252 /* check screenshots were loaded */
2253 screenshots = as_app_get_screenshots (app);
2254 g_assert_cmpint (screenshots->len, ==, 1);
2255 ss = as_app_get_screenshot_default (app);
2256 g_assert_cmpint (as_screenshot_get_kind (ss), ==, AS_SCREENSHOT_KIND_DEFAULT);
2257 images = as_screenshot_get_images (ss);
2258 g_assert_cmpint (images->len, ==, 1);
2259 im = g_ptr_array_index (images, 0);
2260 g_assert_cmpstr (as_image_get_url (im), ==, "https://projects.gnome.org/gnome-power-manager/images/gpm-low-batt.png");
2261 g_assert_cmpint (as_image_get_width (im), ==, 355);
2262 g_assert_cmpint (as_image_get_height (im), ==, 134);
2263 g_assert_cmpint (as_image_get_kind (im), ==, AS_IMAGE_KIND_SOURCE);
2264 }
2265
2266 static void
as_test_app_validate_metainfo_good_func(void)2267 as_test_app_validate_metainfo_good_func (void)
2268 {
2269 AsProblem *problem;
2270 GError *error = NULL;
2271 GPtrArray *probs;
2272 gboolean ret;
2273 guint i;
2274 g_autofree gchar *filename = NULL;
2275 g_autoptr(AsApp) app = NULL;
2276
2277 /* open file */
2278 app = as_app_new ();
2279 filename = as_test_get_filename ("example.metainfo.xml");
2280 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2281 g_assert_no_error (error);
2282 g_assert (ret);
2283
2284 /* check success */
2285 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_ADDON);
2286 g_assert_cmpstr (as_app_get_id (app), ==, "gedit-code-assistance");
2287 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Code assistance");
2288 g_assert_cmpstr (as_app_get_comment (app, "C"), ==, "Code assistance for C, C++ and Objective-C");
2289 g_assert_cmpstr (as_app_get_metadata_license (app), ==, "CC0-1.0");
2290 g_assert_cmpstr (as_app_get_project_license (app), ==, "GPL-3.0+");
2291 g_assert_cmpstr (as_app_get_update_contact (app), ==, "richard@hughsie.com");
2292 g_assert_cmpstr (as_app_get_url_item (app, AS_URL_KIND_HOMEPAGE), ==,
2293 "http://projects.gnome.org/gedit");
2294 g_assert_cmpstr (as_app_get_description (app, "C"), ==, NULL);
2295
2296 /* validate */
2297 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NO_NETWORK, &error);
2298 g_assert_no_error (error);
2299 g_assert (probs != NULL);
2300 for (i = 0; i < probs->len; i++) {
2301 problem = g_ptr_array_index (probs, i);
2302 g_warning ("%s", as_problem_get_message (problem));
2303 }
2304 g_assert_cmpint (probs->len, ==, 0);
2305 g_ptr_array_unref (probs);
2306 }
2307
2308 static void
as_test_app_validate_intltool_func(void)2309 as_test_app_validate_intltool_func (void)
2310 {
2311 AsProblem *problem;
2312 GError *error = NULL;
2313 GPtrArray *probs;
2314 gboolean ret;
2315 guint i;
2316 g_autofree gchar *filename = NULL;
2317 g_autoptr(AsApp) app = NULL;
2318
2319 /* open file */
2320 app = as_app_new ();
2321 filename = as_test_get_filename ("intltool.appdata.xml.in");
2322 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2323 g_assert_no_error (error);
2324 g_assert (ret);
2325
2326 /* check success */
2327 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
2328 g_assert_cmpstr (as_app_get_id (app), ==, "gnome-power-statistics.desktop");
2329 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "0 A.D.");
2330 g_assert_cmpstr (as_app_get_comment (app, "C"), ==, "Observe power management");
2331 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NO_NETWORK, &error);
2332 g_assert_no_error (error);
2333 g_assert (probs != NULL);
2334 for (i = 0; i < probs->len; i++) {
2335 problem = g_ptr_array_index (probs, i);
2336 g_warning ("%s", as_problem_get_message (problem));
2337 }
2338 g_assert_cmpint (probs->len, ==, 0);
2339 g_ptr_array_unref (probs);
2340 }
2341
2342 static void
as_test_app_translated_func(void)2343 as_test_app_translated_func (void)
2344 {
2345 GError *error = NULL;
2346 gboolean ret;
2347 g_autofree gchar *filename = NULL;
2348 g_autoptr(AsApp) app = NULL;
2349
2350 /* open file */
2351 app = as_app_new ();
2352 filename = as_test_get_filename ("translated.appdata.xml");
2353 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2354 g_assert_no_error (error);
2355 g_assert (ret);
2356
2357 /* check success */
2358 g_assert_cmpstr (as_app_get_description (app, "C"), ==, "<p>Awesome</p>");
2359 g_assert_cmpstr (as_app_get_description (app, "pl"), ==, "<p>Asomeski</p>");
2360 g_assert_cmpint (as_app_get_description_size (app), ==, 2);
2361 }
2362
2363 static void
as_test_app_validate_file_bad_func(void)2364 as_test_app_validate_file_bad_func (void)
2365 {
2366 AsProblem *problem;
2367 GError *error = NULL;
2368 gboolean ret;
2369 guint i;
2370 g_autofree gchar *filename = NULL;
2371 g_autoptr(AsApp) app = NULL;
2372 g_autoptr(GPtrArray) probs = NULL;
2373 g_autoptr(GPtrArray) probs2 = NULL;
2374
2375 /* open file */
2376 app = as_app_new ();
2377 filename = as_test_get_filename ("broken.appdata.xml");
2378 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2379 g_assert_no_error (error);
2380 g_assert (ret);
2381
2382 g_assert_cmpstr (as_app_get_description (app, "C"), !=, NULL);
2383 g_assert_cmpint (as_app_get_description_size (app), ==, 1);
2384
2385 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NONE, &error);
2386 g_assert_no_error (error);
2387 g_assert (probs != NULL);
2388 for (i = 0; i < probs->len; i++) {
2389 problem = g_ptr_array_index (probs, i);
2390 g_debug ("%s", as_problem_get_message (problem));
2391 }
2392
2393 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
2394 "<component> has invalid type attribute");
2395 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2396 "<metadata_license> is not valid");
2397 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2398 "<project_license> is not valid");
2399 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2400 "<url> does not start with 'http://'");
2401 as_test_app_validate_check (probs, AS_PROBLEM_KIND_MARKUP_INVALID,
2402 "<?xml> header not found");
2403 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2404 "<name> cannot end in '.'");
2405 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2406 "Not enough <screenshot> tags");
2407 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2408 "<li> is too short");
2409 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2410 "<ul> cannot start a description");
2411 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2412 "<ul> cannot start a description");
2413 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2414 "<p> should not start with 'This application'");
2415 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2416 "<p> is too short");
2417 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2418 "<p> cannot contain a hyperlink");
2419 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2420 "<release> description should be "
2421 "prose and not contain hyperlinks");
2422 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
2423 "<release> timestamp should be a UNIX time");
2424 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_MISSING,
2425 "<release> has no version");
2426 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_MISSING,
2427 "<release> has no timestamp");
2428 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2429 "<release> versions are not in order");
2430 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2431 "<release> version was duplicated");
2432 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
2433 "<release> timestamp is in the future");
2434 as_test_app_validate_check (probs, AS_PROBLEM_KIND_MARKUP_INVALID,
2435 "<id> has invalid character");
2436 as_test_app_validate_check (probs, AS_PROBLEM_KIND_ATTRIBUTE_INVALID,
2437 "<launchable> has invalid type attribute");
2438 as_test_app_validate_check (probs, AS_PROBLEM_KIND_VALUE_MISSING,
2439 "<launchable> missing value");
2440 g_assert_cmpint (probs->len, ==, 23);
2441
2442 /* again, harder */
2443 probs2 = as_app_validate (app, AS_APP_VALIDATE_FLAG_STRICT, &error);
2444 g_assert_no_error (error);
2445 g_assert (probs2 != NULL);
2446 as_test_app_validate_check (probs2, AS_PROBLEM_KIND_TAG_INVALID,
2447 "XML data contains unknown tag");
2448 g_assert_cmpint (probs2->len, ==, 37);
2449 }
2450
2451 static void
as_test_app_validate_meta_bad_func(void)2452 as_test_app_validate_meta_bad_func (void)
2453 {
2454 AsProblem *problem;
2455 GError *error = NULL;
2456 gboolean ret;
2457 guint i;
2458 g_autofree gchar *filename = NULL;
2459 g_autoptr(AsApp) app = NULL;
2460 g_autoptr(GPtrArray) probs = NULL;
2461
2462 /* open file */
2463 app = as_app_new ();
2464 filename = as_test_get_filename ("broken.metainfo.xml");
2465 ret = as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_NONE, &error);
2466 g_assert_no_error (error);
2467 g_assert (ret);
2468
2469 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NONE, &error);
2470 g_assert_no_error (error);
2471 g_assert (probs != NULL);
2472 for (i = 0; i < probs->len; i++) {
2473 problem = g_ptr_array_index (probs, i);
2474 g_debug ("%s", as_problem_get_message (problem));
2475 }
2476 g_assert_cmpint (probs->len, ==, 6);
2477 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2478 "<name> is not present");
2479 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2480 "<summary> is not present");
2481 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2482 "<url> is not present");
2483 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2484 "<extends> is not present");
2485 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2486 "<metadata_license> is not present");
2487 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2488 "<pkgname> not allowed in metainfo");
2489 }
2490
2491 static void
as_test_store_local_appdata_func(void)2492 as_test_store_local_appdata_func (void)
2493 {
2494 AsApp *app;
2495 AsFormat *format;
2496 GError *error = NULL;
2497 gboolean ret;
2498 g_autofree gchar *filename = NULL;
2499 g_autofree gchar *filename_full = NULL;
2500 g_autofree gchar *canonical_filename;
2501 g_autoptr(AsStore) store = NULL;
2502
2503 /* this are the warnings expected */
2504 #ifdef _WIN32
2505 g_test_expect_message (G_LOG_DOMAIN,
2506 G_LOG_LEVEL_WARNING,
2507 "ignoring description '*' from *\\broken.appdata.xml: Unknown tag '_p'");
2508 #else
2509 g_test_expect_message (G_LOG_DOMAIN,
2510 G_LOG_LEVEL_WARNING,
2511 "ignoring description '*' from */broken.appdata.xml: Unknown tag '_p'");
2512 #endif
2513
2514 /* open test store */
2515 #ifdef _WIN32
2516 g_setenv ("XDG_DATA_DIRS", "/usr/share/", TRUE);
2517 #endif
2518 store = as_store_new ();
2519 filename = as_test_get_filename (".");
2520 as_store_set_destdir (store, filename);
2521 ret = as_store_load (store, AS_STORE_LOAD_FLAG_APPDATA, NULL, &error);
2522 g_assert_no_error (error);
2523 g_assert (ret);
2524 g_assert_cmpint (as_store_get_size (store), ==, 1);
2525
2526 /* make sure app is valid */
2527 app = as_store_get_app_by_id (store, "broken.desktop");
2528 g_assert (app != NULL);
2529 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Broken");
2530
2531 /* check format */
2532 format = as_app_get_format_by_kind (app, AS_FORMAT_KIND_APPDATA);
2533 g_assert (format != NULL);
2534 filename_full = g_build_filename (filename,
2535 "usr/share/appdata/broken.appdata.xml",
2536 NULL);
2537 canonical_filename = g_canonicalize_filename (filename_full, NULL);
2538 g_assert_cmpstr (as_format_get_filename (format), ==, canonical_filename);
2539 }
2540
2541 static void
as_test_store_validate_func(void)2542 as_test_store_validate_func (void)
2543 {
2544 GError *error = NULL;
2545 gboolean ret;
2546 g_autofree gchar *filename = NULL;
2547 g_autoptr(AsStore) store = NULL;
2548 g_autoptr(GFile) file = NULL;
2549 g_autoptr(GPtrArray) probs = NULL;
2550
2551 /* open file */
2552 store = as_store_new ();
2553 filename = as_test_get_filename ("validate.xml.gz");
2554 file = g_file_new_for_path (filename);
2555 ret = as_store_from_file (store, file, NULL, NULL, &error);
2556 g_assert_no_error (error);
2557 g_assert (ret);
2558 g_assert_cmpint (as_store_get_size (store), ==, 1);
2559
2560 probs = as_store_validate (store, AS_APP_VALIDATE_FLAG_NONE, &error);
2561 g_assert_no_error (error);
2562 g_assert (probs != NULL);
2563 g_assert_cmpint (probs->len, ==, 4);
2564 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2565 "metadata version is v0.1 and "
2566 "<screenshots> only introduced in v0.4");
2567 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2568 "metadata version is v0.1 and "
2569 "<compulsory_for_desktop> only introduced in v0.4");
2570 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2571 "metadata version is v0.1 and "
2572 "<project_group> only introduced in v0.4");
2573 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2574 "metadata version is v0.1 and "
2575 "<description> markup was introduced in v0.6");
2576 }
2577
2578 static void
_as_app_add_format_kind(AsApp * app,AsFormatKind kind)2579 _as_app_add_format_kind (AsApp *app, AsFormatKind kind)
2580 {
2581 g_autoptr(AsFormat) format = as_format_new ();
2582 as_format_set_kind (format, kind);
2583 as_app_add_format (app, format);
2584 }
2585
2586 static void
as_test_app_validate_style_func(void)2587 as_test_app_validate_style_func (void)
2588 {
2589 AsProblem *problem;
2590 GError *error = NULL;
2591 guint i;
2592 g_autoptr(AsApp) app = NULL;
2593 g_autoptr(GPtrArray) probs = NULL;
2594
2595 app = as_app_new ();
2596 as_app_add_url (app, AS_URL_KIND_UNKNOWN, "dave.com");
2597 as_app_set_id (app, "dave.exe");
2598 as_app_set_kind (app, AS_APP_KIND_DESKTOP);
2599 _as_app_add_format_kind (app, AS_FORMAT_KIND_APPDATA);
2600 as_app_set_metadata_license (app, "BSD");
2601 as_app_set_project_license (app, "GPL-2.0+");
2602 as_app_set_name (app, "C", "Test app name that is very long indeed although Rob forced me to relax the requirements.");
2603 as_app_set_comment (app, "C", "Awesome");
2604 as_app_set_update_contact (app, "someone_who_cares@upstream_project.org");
2605
2606 probs = as_app_validate (app, AS_APP_VALIDATE_FLAG_NONE, &error);
2607 g_assert_no_error (error);
2608 g_assert (probs != NULL);
2609 for (i = 0; i < probs->len; i++) {
2610 problem = g_ptr_array_index (probs, i);
2611 g_debug ("%s", as_problem_get_message (problem));
2612 }
2613 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2614 "<update_contact> is still set to a dummy value");
2615 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2616 "<url> type invalid");
2617 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2618 "<url> does not start with 'http://'");
2619 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_INVALID,
2620 "<metadata_license> is not valid");
2621 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2622 "<name> is too long");
2623 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2624 "<name> cannot end in '.'");
2625 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2626 "<summary> is too short");
2627 as_test_app_validate_check (probs, AS_PROBLEM_KIND_STYLE_INCORRECT,
2628 "Not enough <screenshot> tags");
2629 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2630 "<url> is not present");
2631 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2632 "<content_rating> required");
2633 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2634 "<release> required");
2635 as_test_app_validate_check (probs, AS_PROBLEM_KIND_TAG_MISSING,
2636 "<description> required");
2637 g_assert_cmpint (probs->len, ==, 12);
2638 }
2639
2640 static void
as_test_app_parse_file_desktop_func(void)2641 as_test_app_parse_file_desktop_func (void)
2642 {
2643 AsFormat *format;
2644 AsIcon *ic;
2645 GError *error = NULL;
2646 gboolean ret;
2647 g_autofree gchar *filename = NULL;
2648 g_autoptr(AsApp) app = NULL;
2649
2650 /* create an AsApp from a desktop file */
2651 app = as_app_new ();
2652 filename = as_test_get_filename ("example.desktop");
2653 ret = as_app_parse_file (app,
2654 filename,
2655 AS_APP_PARSE_FLAG_ALLOW_VETO,
2656 &error);
2657 g_assert_no_error (error);
2658 g_assert (ret);
2659
2660 /* test things we found */
2661 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Color Profile Viewer");
2662 g_assert_cmpstr (as_app_get_name (app, "pl"), ==, "Podgląd profilu kolorów");
2663 g_assert_cmpstr (as_app_get_comment (app, "C"), ==,
2664 "Inspect and compare installed color profiles");
2665 g_assert_cmpstr (as_app_get_comment (app, "pl"), ==,
2666 "Badanie i porównywanie zainstalowanych profilów kolorów");
2667 g_assert_cmpint (as_app_get_vetos(app)->len, ==, 1);
2668 g_assert_cmpstr (as_app_get_project_group (app), ==, NULL);
2669 g_assert_cmpint (as_app_get_categories(app)->len, ==, 1);
2670 g_assert_cmpint (as_app_get_keywords(app, NULL)->len, ==, 2);
2671 g_assert_cmpint (as_app_get_keywords(app, "pl")->len, ==, 1);
2672 g_assert (as_app_has_category (app, "System"));
2673 g_assert (!as_app_has_category (app, "NotGoingToExist"));
2674
2675 /* check format */
2676 g_assert_cmpint (as_app_get_formats(app)->len, ==, 1);
2677 format = as_app_get_format_by_kind (app, AS_FORMAT_KIND_DESKTOP);
2678 g_assert (format != NULL);
2679 g_assert_cmpstr (as_format_get_filename (format), ==, filename);
2680
2681 /* check icons */
2682 g_assert_cmpint (as_app_get_icons(app)->len, ==, 1);
2683 ic = as_app_get_icon_default (app);
2684 g_assert (ic != NULL);
2685 g_assert_cmpstr (as_icon_get_name (ic), ==, "audio-input-microphone");
2686 g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_STOCK);
2687 g_assert_cmpint (as_icon_get_width (ic), ==, 0);
2688 g_assert_cmpint (as_icon_get_height (ic), ==, 0);
2689
2690 /* reparse with heuristics */
2691 ret = as_app_parse_file (app,
2692 filename,
2693 AS_APP_PARSE_FLAG_ALLOW_VETO |
2694 AS_APP_PARSE_FLAG_USE_HEURISTICS,
2695 &error);
2696 g_assert_no_error (error);
2697 g_assert (ret);
2698 g_assert_cmpstr (as_app_get_project_group (app), ==, "GNOME");
2699 g_free (filename);
2700
2701 /* reparse with invalid file */
2702 filename = as_test_get_filename ("settings-panel.desktop");
2703 ret = as_app_parse_file (app, filename, 0, &error);
2704 g_assert_error (error, AS_APP_ERROR, AS_APP_ERROR_INVALID_TYPE);
2705 g_assert (!ret);
2706 g_clear_error (&error);
2707 }
2708
2709 static void
as_test_app_no_markup_func(void)2710 as_test_app_no_markup_func (void)
2711 {
2712 GError *error = NULL;
2713 AsNode *n;
2714 AsNode *root;
2715 GString *xml;
2716 gboolean ret;
2717 const gchar *src =
2718 "<component type=\"desktop\">\n"
2719 "<id>org.gnome.Software.desktop</id>\n"
2720 "<description>Software is awesome:\n\n * Bada\n * Boom!</description>\n"
2721 "<launchable type=\"desktop-id\">org.gnome.Software.desktop</launchable>\n"
2722 "</component>\n";
2723 g_autoptr(AsNodeContext) ctx = NULL;
2724 g_autoptr(AsApp) app = NULL;
2725
2726 app = as_app_new ();
2727
2728 /* to object */
2729 root = as_node_from_xml (src,
2730 AS_NODE_FROM_XML_FLAG_LITERAL_TEXT,
2731 &error);
2732 g_assert_no_error (error);
2733 g_assert (root != NULL);
2734 n = as_node_find (root, "component");
2735 g_assert (n != NULL);
2736 ctx = as_node_context_new ();
2737 ret = as_app_node_parse (app, n, ctx, &error);
2738 g_assert_no_error (error);
2739 g_assert (ret);
2740
2741 /* verify */
2742 g_assert_cmpstr (as_app_get_id (app), ==, "org.gnome.Software.desktop");
2743 g_assert_cmpstr (as_app_get_description (app, "C"), ==,
2744 "Software is awesome:\n\n * Bada\n * Boom!");
2745 as_node_unref (root);
2746
2747 /* back to node */
2748 root = as_node_new ();
2749 as_node_context_set_version (ctx, 0.4);
2750 n = as_app_node_insert (app, root, ctx);
2751 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
2752 ret = as_test_compare_lines (xml->str, src, &error);
2753 g_assert_no_error (error);
2754 g_assert (ret);
2755 g_string_free (xml, TRUE);
2756 as_node_unref (root);
2757 }
2758
2759 static void
as_test_node_reflow_text_func(void)2760 as_test_node_reflow_text_func (void)
2761 {
2762 AsRefString *tmp;
2763
2764 /* plain text */
2765 tmp = as_node_reflow_text ("Dave", -1);
2766 g_assert_cmpstr (tmp, ==, "Dave");
2767 as_ref_string_unref (tmp);
2768
2769 /* stripping */
2770 tmp = as_node_reflow_text (" Dave ", -1);
2771 g_assert_cmpstr (tmp, ==, "Dave");
2772 as_ref_string_unref (tmp);
2773
2774 /* paragraph */
2775 tmp = as_node_reflow_text ("Dave\n\nSoftware", -1);
2776 g_assert_cmpstr (tmp, ==, "Dave\n\nSoftware");
2777 as_ref_string_unref (tmp);
2778
2779 /* pathological */
2780 tmp = as_node_reflow_text (
2781 "\n"
2782 " Dave: \n"
2783 " Software is \n"
2784 " awesome.\n\n\n"
2785 " Okay!\n", -1);
2786 g_assert_cmpstr (tmp, ==, "Dave: Software is awesome.\n\nOkay!");
2787 as_ref_string_unref (tmp);
2788 }
2789
2790 static void
as_test_node_sort_func(void)2791 as_test_node_sort_func (void)
2792 {
2793 g_autoptr(GError) error = NULL;
2794 g_autoptr(AsNode) root = NULL;
2795 g_autoptr(GString) str = NULL;
2796
2797 root = as_node_from_xml ("<d>ddd</d><c>ccc</c><b>bbb</b><a>aaa</a>", 0, &error);
2798 g_assert_no_error (error);
2799 g_assert (root != NULL);
2800
2801 /* verify that the tags are sorted */
2802 str = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_SORT_CHILDREN);
2803 g_assert_cmpstr (str->str, ==, "<a>aaa</a><b>bbb</b><c>ccc</c><d>ddd</d>");
2804 }
2805
2806 static void
as_test_node_func(void)2807 as_test_node_func (void)
2808 {
2809 AsNode *n1;
2810 AsNode *n2;
2811 g_autoptr(AsNode) root = NULL;
2812
2813 /* create a simple tree */
2814 root = as_node_new ();
2815 n1 = as_node_insert (root, "apps", NULL, 0,
2816 "version", "2",
2817 NULL);
2818 g_assert (n1 != NULL);
2819 g_assert_cmpstr (as_node_get_name (n1), ==, "apps");
2820 g_assert_cmpstr (as_node_get_data (n1), ==, NULL);
2821 g_assert_cmpstr (as_node_get_attribute (n1, "version"), ==, "2");
2822 g_assert_cmpint (as_node_get_attribute_as_int (n1, "version"), ==, 2);
2823 g_assert_cmpstr (as_node_get_attribute (n1, "xxx"), ==, NULL);
2824 n2 = as_node_insert (n1, "id", "hal", 0, NULL);
2825 g_assert (n2 != NULL);
2826 g_assert_cmpint (as_node_get_tag (n2), ==, AS_TAG_ID);
2827 g_assert_cmpstr (as_node_get_data (n2), ==, "hal");
2828 g_assert_cmpstr (as_node_get_attribute (n2, "xxx"), ==, NULL);
2829
2830 /* remove an attribute */
2831 as_node_remove_attribute (n1, "version");
2832 g_assert_cmpstr (as_node_get_attribute (n1, "version"), ==, NULL);
2833
2834 /* replace some node data */
2835 as_node_set_data (n2, "udev", 0);
2836 g_assert_cmpstr (as_node_get_data (n2), ==, "udev");
2837 as_node_add_attribute (n2, "enabled", "true");
2838 g_assert_cmpstr (as_node_get_attribute (n2, "enabled"), ==, "true");
2839
2840 /* find the n2 node */
2841 n2 = as_node_find (root, "apps/id");
2842 g_assert (n2 != NULL);
2843 g_assert_cmpint (as_node_get_tag (n2), ==, AS_TAG_ID);
2844
2845 /* don't find invalid nodes */
2846 n2 = as_node_find (root, "apps/id/xxx");
2847 g_assert (n2 == NULL);
2848 n2 = as_node_find (root, "apps/xxx");
2849 g_assert (n2 == NULL);
2850 n2 = as_node_find (root, "apps//id");
2851 g_assert (n2 == NULL);
2852 }
2853
2854 static void
as_test_node_xml_func(void)2855 as_test_node_xml_func (void)
2856 {
2857 const gchar *valid = "<!--\n"
2858 " this documents foo\n"
2859 "-->"
2860 "<foo>"
2861 "<!-- this documents bar -->"
2862 "<bar key=\"value\">baz</bar>"
2863 "</foo>";
2864 GError *error = NULL;
2865 AsNode *n2;
2866 AsNode *root;
2867 GString *xml;
2868 GHashTable *hashtable;
2869
2870 /* invalid XML */
2871 root = as_node_from_xml ("<moo>", 0, &error);
2872 g_assert (root == NULL);
2873 g_assert_error (error, AS_NODE_ERROR, AS_NODE_ERROR_FAILED);
2874 g_clear_error (&error);
2875 root = as_node_from_xml ("<foo></bar>", 0, &error);
2876 g_assert (root == NULL);
2877 g_assert_error (error, AS_NODE_ERROR, AS_NODE_ERROR_FAILED);
2878 g_clear_error (&error);
2879
2880 /* valid XML */
2881 root = as_node_from_xml (valid, 0, &error);
2882 g_assert_no_error (error);
2883 g_assert (root != NULL);
2884
2885 n2 = as_node_find (root, "foo/bar");
2886 g_assert (n2 != NULL);
2887 g_assert_cmpstr (as_node_get_data (n2), ==, "baz");
2888 g_assert_cmpstr (as_node_get_comment (n2), ==, NULL);
2889 g_assert_cmpstr (as_node_get_attribute (n2, "key"), ==, "value");
2890
2891 /* convert back */
2892 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
2893 g_assert (xml != NULL);
2894 g_assert_cmpstr (xml->str, ==, "<foo><bar key=\"value\">baz</bar></foo>");
2895 g_string_free (xml, TRUE);
2896
2897 /* with newlines */
2898 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
2899 g_assert (xml != NULL);
2900 g_assert_cmpstr (xml->str, ==,
2901 "<foo>\n<bar key=\"value\">baz</bar>\n</foo>\n");
2902 g_string_free (xml, TRUE);
2903
2904 /* fully formatted */
2905 xml = as_node_to_xml (root,
2906 AS_NODE_TO_XML_FLAG_ADD_HEADER |
2907 AS_NODE_TO_XML_FLAG_FORMAT_INDENT |
2908 AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
2909 g_assert (xml != NULL);
2910 g_assert_cmpstr (xml->str, ==,
2911 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2912 "<foo>\n <bar key=\"value\">baz</bar>\n</foo>\n");
2913 g_string_free (xml, TRUE);
2914 as_node_unref (root);
2915
2916 /* convert all the children to XML */
2917 root = as_node_from_xml ("<p>One</p><p>Two</p>", 0, &error);
2918 g_assert_no_error (error);
2919 g_assert (root != NULL);
2920 g_assert_cmpint (g_node_n_nodes (root, G_TRAVERSE_ALL), ==, 3);
2921 xml = as_node_to_xml (root->children, AS_NODE_TO_XML_FLAG_INCLUDE_SIBLINGS);
2922 g_assert (xml != NULL);
2923 g_assert_cmpstr (xml->str, ==, "<p>One</p><p>Two</p>");
2924 g_string_free (xml, TRUE);
2925 as_node_unref (root);
2926
2927 /* keep comments */
2928 root = as_node_from_xml (valid,
2929 AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS,
2930 &error);
2931 g_assert_no_error (error);
2932 g_assert (root != NULL);
2933 n2 = as_node_find (root, "foo/bar");
2934 g_assert (n2 != NULL);
2935 g_assert_cmpstr (as_node_get_comment (n2), ==, "this documents bar");
2936 n2 = as_node_find (root, "foo");
2937 g_assert (n2 != NULL);
2938 g_assert_cmpstr (as_node_get_comment (n2), ==, "this documents foo");
2939 as_node_unref (root);
2940
2941 /* keep comment formatting */
2942 root = as_node_from_xml (valid,
2943 AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS |
2944 AS_NODE_FROM_XML_FLAG_LITERAL_TEXT,
2945 &error);
2946 g_assert_no_error (error);
2947 g_assert (root != NULL);
2948 n2 = as_node_find (root, "foo/bar");
2949 g_assert (n2 != NULL);
2950 g_assert_cmpstr (as_node_get_comment (n2), ==, " this documents bar ");
2951 n2 = as_node_find (root, "foo");
2952 g_assert (n2 != NULL);
2953 g_assert_cmpstr (as_node_get_comment (n2), ==, "\n this documents foo\n");
2954
2955 /* check comments were preserved */
2956 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
2957 g_assert (xml != NULL);
2958 g_assert_cmpstr (xml->str, ==, valid);
2959 g_string_free (xml, TRUE);
2960 as_node_unref (root);
2961
2962 /* check comments are appended together */
2963 root = as_node_from_xml ("<!-- 1st -->\n<!-- 2nd -->\n<foo/>\n",
2964 AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS |
2965 AS_NODE_FROM_XML_FLAG_LITERAL_TEXT,
2966 &error);
2967 g_assert_no_error (error);
2968 g_assert (root != NULL);
2969 n2 = as_node_find (root, "foo");
2970 g_assert (n2 != NULL);
2971 g_assert_cmpstr (as_node_get_comment (n2), ==, " 1st <&> 2nd ");
2972
2973 /* check comments were output as two blocks */
2974 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
2975 g_assert (xml != NULL);
2976 g_assert_cmpstr (xml->str, ==, "<!-- 1st -->\n<!-- 2nd -->\n<foo/>\n");
2977 g_string_free (xml, TRUE);
2978 as_node_unref (root);
2979
2980 /* invalid child of ul */
2981 root = as_node_from_xml ("<ul><ul></ul></ul>", 0, &error);
2982 g_assert_no_error (error);
2983 g_assert (root != NULL);
2984 hashtable = as_node_get_localized_unwrap (root, &error);
2985 g_assert_error (error, AS_NODE_ERROR, AS_NODE_ERROR_INVALID_MARKUP);
2986 g_assert_cmpstr (error->message, ==, "Tag ul in ul invalid");
2987 g_clear_error (&error);
2988 g_assert (hashtable == NULL);
2989 }
2990
2991 static void
as_test_node_hash_func(void)2992 as_test_node_hash_func (void)
2993 {
2994 GHashTable *hash;
2995 AsNode *n1;
2996 AsNode *root;
2997 GString *xml;
2998
2999 /* test un-swapped hash */
3000 root = as_node_new ();
3001 n1 = as_node_insert (root, "app", NULL, 0, NULL);
3002 hash = g_hash_table_new (g_str_hash, g_str_equal);
3003 g_hash_table_insert (hash, (gpointer) "a", (gpointer) "1");
3004 g_hash_table_insert (hash, (gpointer) "b", (gpointer) "2");
3005 as_node_insert_hash (n1, "md1", "key", hash, 0);
3006 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
3007 g_assert (xml != NULL);
3008 g_assert_cmpstr (xml->str, ==,
3009 "<app><md1 key=\"a\">1</md1><md1 key=\"b\">2</md1></app>");
3010 g_string_free (xml, TRUE);
3011 g_hash_table_unref (hash);
3012 as_node_unref (root);
3013
3014 /* test swapped hash */
3015 root = as_node_new ();
3016 n1 = as_node_insert (root, "app", NULL, AS_NODE_INSERT_FLAG_NONE, NULL);
3017 hash = g_hash_table_new (g_str_hash, g_str_equal);
3018 g_hash_table_insert (hash, (gpointer) "a", (gpointer) "1");
3019 g_hash_table_insert (hash, (gpointer) "b", (gpointer) "2");
3020 as_node_insert_hash (n1, "md1", "key", hash, AS_NODE_INSERT_FLAG_SWAPPED);
3021 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
3022 g_assert (xml != NULL);
3023 g_assert_cmpstr (xml->str, ==,
3024 "<app><md1 key=\"1\">a</md1><md1 key=\"2\">b</md1></app>");
3025 g_string_free (xml, TRUE);
3026 g_hash_table_unref (hash);
3027 as_node_unref (root);
3028 }
3029
3030 static void
as_test_node_localized_func(void)3031 as_test_node_localized_func (void)
3032 {
3033 GHashTable *hash;
3034 AsNode *n1;
3035 AsNode *root;
3036 GString *xml;
3037
3038 /* writing localized values */
3039 root = as_node_new ();
3040 n1 = as_node_insert (root, "app", NULL, 0, NULL);
3041 hash = g_hash_table_new (g_str_hash, g_str_equal);
3042 g_hash_table_insert (hash, (gpointer) "C", (gpointer) "color");
3043 g_hash_table_insert (hash, (gpointer) "en_XX", (gpointer) "colour");
3044 as_node_insert_localized (n1, "name", hash, AS_NODE_INSERT_FLAG_NONE);
3045 xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
3046 g_assert (xml != NULL);
3047 g_assert_cmpstr (xml->str, ==,
3048 "<app><name>color</name>"
3049 "<name xml:lang=\"en_XX\">colour</name></app>");
3050 g_string_free (xml, TRUE);
3051 g_hash_table_unref (hash);
3052
3053 /* get the best locale */
3054 g_assert_cmpstr (as_node_get_localized_best (n1, "name"), ==, "color");
3055
3056 /* get something that isn't there */
3057 hash = as_node_get_localized (n1, "comment");
3058 g_assert (hash == NULL);
3059
3060 /* read them back */
3061 hash = as_node_get_localized (n1, "name");
3062 g_assert (hash != NULL);
3063 g_assert_cmpint (g_hash_table_size (hash), ==, 2);
3064 g_assert_cmpstr (g_hash_table_lookup (hash, "C"), ==, "color");
3065 g_assert_cmpstr (g_hash_table_lookup (hash, "en_XX"), ==, "colour");
3066 g_hash_table_unref (hash);
3067
3068 as_node_unref (root);
3069 }
3070
3071 static void
as_test_node_localized_wrap_func(void)3072 as_test_node_localized_wrap_func (void)
3073 {
3074 GError *error = NULL;
3075 AsNode *n1;
3076 const gchar *xml =
3077 "<description>"
3078 " <p>Hi</p>"
3079 " <p xml:lang=\"pl\">Czesc</p>"
3080 " <ul>"
3081 " <li>First</li>"
3082 " <li xml:lang=\"pl\">Pierwszy</li>"
3083 " <li xml:lang=\"en_GB\">Hi</li>"
3084 " </ul>"
3085 "</description>";
3086 g_autoptr(GHashTable) hash = NULL;
3087 g_autoptr(AsNode) root = NULL;
3088
3089 root = as_node_from_xml (xml, 0, &error);
3090 g_assert_no_error (error);
3091 g_assert (root != NULL);
3092
3093 /* unwrap the locale data */
3094 n1 = as_node_find (root, "description");
3095 g_assert (n1 != NULL);
3096 hash = as_node_get_localized_unwrap (n1, &error);
3097 g_assert_no_error (error);
3098 g_assert (hash != NULL);
3099 g_assert_cmpint (g_hash_table_size (hash), ==, 3);
3100 g_assert_cmpstr (g_hash_table_lookup (hash, "C"), ==,
3101 "<p>Hi</p><ul><li>First</li></ul>");
3102 g_assert_cmpstr (g_hash_table_lookup (hash, "pl"), ==,
3103 "<p>Czesc</p><ul><li>Pierwszy</li></ul>");
3104 g_assert_cmpstr (g_hash_table_lookup (hash, "en_GB"), ==,
3105 "<ul><li>Hi</li></ul>");
3106 }
3107
3108 static void
as_test_node_intltool_func(void)3109 as_test_node_intltool_func (void)
3110 {
3111 AsNode *n;
3112 g_autoptr(AsNode) root = NULL;
3113 g_autoptr(GString) str = NULL;
3114
3115 root = as_node_new ();
3116 n = as_node_insert (root, "description", NULL, AS_NODE_INSERT_FLAG_NONE, NULL);
3117 as_node_insert (n, "name", "Hello",
3118 AS_NODE_INSERT_FLAG_MARK_TRANSLATABLE, NULL);
3119
3120 /* verify that the tags get prefixed with '_' */
3121 str = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
3122 g_assert_cmpstr (str->str, ==, "<description><_name>Hello</_name></description>");
3123 }
3124
3125 static void
as_test_node_localized_wrap2_func(void)3126 as_test_node_localized_wrap2_func (void)
3127 {
3128 GError *error = NULL;
3129 AsNode *n1;
3130 const gchar *xml =
3131 "<description>"
3132 " <p>Hi</p>"
3133 " <p xml:lang=\"pl\">Czesc</p>"
3134 " <ul>"
3135 " <li>First</li>"
3136 " <li>Second</li>"
3137 " </ul>"
3138 " <ul xml:lang=\"pl\">"
3139 " <li>Pierwszy</li>"
3140 " <li>Secondski</li>"
3141 " </ul>"
3142 "</description>";
3143 g_autoptr(GHashTable) hash = NULL;
3144 g_autoptr(AsNode) root = NULL;
3145
3146 root = as_node_from_xml (xml, 0, &error);
3147 g_assert_no_error (error);
3148 g_assert (root != NULL);
3149
3150 /* unwrap the locale data */
3151 n1 = as_node_find (root, "description");
3152 g_assert (n1 != NULL);
3153 hash = as_node_get_localized_unwrap (n1, &error);
3154 g_assert_no_error (error);
3155 g_assert (hash != NULL);
3156 g_assert_cmpint (g_hash_table_size (hash), ==, 2);
3157 g_assert_cmpstr (g_hash_table_lookup (hash, "C"), ==,
3158 "<p>Hi</p><ul><li>First</li><li>Second</li></ul>");
3159 g_assert_cmpstr (g_hash_table_lookup (hash, "pl"), ==,
3160 "<p>Czesc</p><ul><li>Pierwszy</li><li>Secondski</li></ul>");
3161
3162 /* find the Polish first paragraph */
3163 n1 = as_node_find_with_attribute (root, "description/p", "xml:lang", "pl");
3164 g_assert (n1 != NULL);
3165 g_assert_cmpstr (as_node_get_data (n1), ==, "Czesc");
3166 }
3167
3168 static void
as_test_app_subsume_func(void)3169 as_test_app_subsume_func (void)
3170 {
3171 AsIcon *ic;
3172 GList *list;
3173 g_autoptr(AsApp) app = NULL;
3174 g_autoptr(AsApp) donor = NULL;
3175 g_autoptr(AsIcon) icon = NULL;
3176 g_autoptr(AsIcon) icon2 = NULL;
3177 g_autoptr(AsScreenshot) ss = NULL;
3178
3179 donor = as_app_new ();
3180 icon = as_icon_new ();
3181 as_icon_set_name (icon, "some-custom-icon");
3182 as_icon_set_kind (icon, AS_ICON_KIND_CACHED);
3183 as_app_add_icon (donor, icon);
3184 icon2 = as_icon_new ();
3185 as_icon_set_name (icon2, "gtk-find");
3186 as_icon_set_kind (icon2, AS_ICON_KIND_STOCK);
3187 as_app_add_icon (donor, icon2);
3188 as_app_set_state (donor, AS_APP_STATE_INSTALLED);
3189 as_app_add_pkgname (donor, "hal");
3190 as_app_add_language (donor, -1, "en_GB");
3191 as_app_add_metadata (donor, "donor", "true");
3192 as_app_add_metadata (donor, "overwrite", "1111");
3193 as_app_add_keyword (donor, "C", "klass");
3194 as_app_add_keyword (donor, "pl", "klaski");
3195 ss = as_screenshot_new ();
3196 as_app_add_screenshot (donor, ss);
3197
3198 /* copy all useful properties */
3199 app = as_app_new ();
3200 as_app_add_metadata (app, "overwrite", "2222");
3201 as_app_add_metadata (app, "recipient", "true");
3202 as_app_subsume_full (app, donor,
3203 AS_APP_SUBSUME_FLAG_NO_OVERWRITE |
3204 AS_APP_SUBSUME_FLAG_DEDUPE);
3205 as_app_add_screenshot (app, ss);
3206
3207 g_assert_cmpstr (as_app_get_metadata_item (app, "donor"), ==, "true");
3208 g_assert_cmpstr (as_app_get_metadata_item (app, "overwrite"), ==, "2222");
3209 g_assert_cmpstr (as_app_get_metadata_item (donor, "recipient"), ==, NULL);
3210 g_assert_cmpint (as_app_get_pkgnames(app)->len, ==, 1);
3211 g_assert_cmpint (as_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
3212 g_assert_cmpint (as_app_get_keywords(app, "C")->len, ==, 1);
3213 g_assert_cmpint (as_app_get_keywords(app, "pl")->len, ==, 1);
3214 list = as_app_get_languages (app);
3215 g_assert_cmpint (g_list_length (list), ==, 1);
3216 g_list_free (list);
3217
3218 /* check icon */
3219 g_assert_cmpint (as_app_get_icons(app)->len, ==, 2);
3220 ic = as_app_get_icon_default (app);
3221 g_assert (ic != NULL);
3222 g_assert_cmpstr (as_icon_get_name (ic), ==, "gtk-find");
3223 g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_STOCK);
3224 g_assert_cmpint (as_icon_get_width (ic), ==, 0);
3225 g_assert_cmpint (as_icon_get_height (ic), ==, 0);
3226
3227 /* test both ways */
3228 as_app_subsume_full (app, donor,
3229 AS_APP_SUBSUME_FLAG_BOTH_WAYS |
3230 AS_APP_SUBSUME_FLAG_METADATA);
3231 g_assert_cmpstr (as_app_get_metadata_item (app, "donor"), ==, "true");
3232 g_assert_cmpstr (as_app_get_metadata_item (app, "recipient"), ==, "true");
3233 g_assert_cmpstr (as_app_get_metadata_item (donor, "donor"), ==, "true");
3234 g_assert_cmpstr (as_app_get_metadata_item (donor, "recipient"), ==, "true");
3235 g_assert_cmpint (as_app_get_screenshots(app)->len, ==, 1);
3236 }
3237
3238 static void
as_test_app_screenshot_func(void)3239 as_test_app_screenshot_func (void)
3240 {
3241 AsScreenshot *ss;
3242 GPtrArray *screenshots;
3243 g_autoptr(AsApp) app = as_app_new ();
3244 g_autoptr(AsScreenshot) ss1 = as_screenshot_new ();
3245 g_autoptr(AsScreenshot) ss2 = as_screenshot_new ();
3246
3247 as_screenshot_set_kind (ss1, AS_SCREENSHOT_KIND_DEFAULT);
3248 as_screenshot_set_caption (ss1, NULL, "bbb");
3249 as_app_add_screenshot (app, ss1);
3250
3251 as_screenshot_set_kind (ss2, AS_SCREENSHOT_KIND_NORMAL);
3252 as_screenshot_set_caption (ss2, NULL, "aaa");
3253 as_app_add_screenshot (app, ss2);
3254
3255 screenshots = as_app_get_screenshots (app);
3256 ss = g_ptr_array_index (screenshots, 0);
3257 g_assert (ss == ss1);
3258 g_assert_cmpint (as_screenshot_get_kind (ss), ==, AS_SCREENSHOT_KIND_DEFAULT);
3259 ss = g_ptr_array_index (screenshots, 1);
3260 g_assert (ss == ss2);
3261 g_assert_cmpint (as_screenshot_get_kind (ss), ==, AS_SCREENSHOT_KIND_NORMAL);
3262 }
3263
3264 static void
as_test_app_search_func(void)3265 as_test_app_search_func (void)
3266 {
3267 const gchar *all[] = { "gnome", "install", "software", NULL };
3268 const gchar *none[] = { "gnome", "xxx", "software", NULL };
3269 const gchar *mime[] = { "application/vnd.oasis.opendocument.text", NULL };
3270 g_auto(GStrv) tokens = NULL;
3271 g_autoptr(AsApp) app = NULL;
3272 g_autoptr(GHashTable) search_blacklist = NULL;
3273 g_autoptr(AsStemmer) stemmer = as_stemmer_new ();
3274
3275 app = as_app_new ();
3276 as_app_set_stemmer (app, stemmer);
3277 as_app_set_id (app, "org.gnome.Software.desktop");
3278 as_app_add_pkgname (app, "gnome-software");
3279 as_app_set_name (app, NULL, "GNOME Software X-Plane");
3280 as_app_set_comment (app, NULL, "Install and remove software");
3281 as_app_add_mimetype (app, "application/vnd.oasis.opendocument.text");
3282 as_app_add_keyword (app, NULL, "awesome");
3283 as_app_add_keyword (app, NULL, "c++");
3284 as_app_add_keyword (app, NULL, "d-feet");
3285
3286 search_blacklist = g_hash_table_new (g_str_hash, g_str_equal);
3287 g_hash_table_insert (search_blacklist,
3288 (gpointer) "and",
3289 GUINT_TO_POINTER (1));
3290 as_app_set_search_blacklist (app, search_blacklist);
3291
3292 g_assert_cmpint (as_app_search_matches (app, "software"), ==, 352);
3293 g_assert_cmpint (as_app_search_matches (app, "soft"), ==, 88);
3294 g_assert_cmpint (as_app_search_matches (app, "install"), ==, 32);
3295 g_assert_cmpint (as_app_search_matches (app, "awesome"), ==, 128);
3296 g_assert_cmpint (as_app_search_matches (app, "c++"), ==, 128);
3297 g_assert_cmpint (as_app_search_matches (app, "d-feet"), ==, 128);
3298 g_assert_cmpint (as_app_search_matches_all (app, (gchar**) all), ==, 352);
3299 g_assert_cmpint (as_app_search_matches_all (app, (gchar**) none), ==, 0);
3300 g_assert_cmpint (as_app_search_matches_all (app, (gchar**) mime), ==, 4);
3301
3302 /* test searching for all tokenized tokens */
3303 tokens = as_utils_search_tokenize ("org.gnome.Software");
3304 g_assert_cmpstr (tokens[0], ==, "org.gnome.software");
3305 g_assert_cmpstr (tokens[1], ==, NULL);
3306 g_assert_cmpint (as_app_search_matches_all (app, tokens), ==, 256);
3307
3308 /* test tokenization of hyphenated name */
3309 g_assert_cmpint (as_app_search_matches (app, "x-plane"), ==, 64);
3310 g_assert_cmpint (as_app_search_matches (app, "plane"), ==, 64);
3311
3312 /* do not add short or common keywords */
3313 g_assert_cmpint (as_app_search_matches (app, "and"), ==, 0);
3314 }
3315
3316 /* load and save embedded icons */
3317 static void
as_test_store_embedded_func(void)3318 as_test_store_embedded_func (void)
3319 {
3320 AsApp *app;
3321 AsIcon *icon;
3322 gboolean ret;
3323 g_autoptr(GError) error = NULL;
3324 g_autoptr(AsStore) store = NULL;
3325 g_autoptr(GString) xml = NULL;
3326 const gchar *xml_src =
3327 "<components origin=\"origin\" version=\"0.6\">"
3328 "<component type=\"desktop\">"
3329 "<id>eog.desktop</id>"
3330 "<pkgname>eog</pkgname>"
3331 "<name>Image Viewer</name>"
3332 "<icon type=\"embedded\" height=\"32\" width=\"32\">"
3333 "<name>eog.png</name>"
3334 "<filecontent>\n"
3335 "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJ\n"
3336 "TUUH1gsaCxQZBldDDAAACLxJREFUWIW9lmtsHNUVx/8zd3Zm9uFd73ptZ/3Gid+OoUlwyAscSJw4\n"
3337 "tIEKCGCQUPuBIlUIhbbEwIfuh0oRUYtKUEEIVQIJSpomPJKACYKQENNg7BiDE8dJnDi7drzrxz5m\n"
3338 "d3a9O3Nnbj8YaOo6qSFSj3Q0V3Nnzv93z9x7znD4kbZzZ4dbM8QWSbBsAoc2XdeLJFH8OJ2m9/j9\n"
3339 "/vRC4wgLfdDv9zsIobcKgqWVF8idAhHKljU20aol1daCggJOFCUcP3709u7uE88CePa6AZ5/frs1\n"
3340 "lbKvAi+0ihbxpzyPqsaGFXp1dY2tsHARJ8syKKWiruvQdQpKDSxf3iz29Pa0/xAA7rvBK688apmY\n"
3341 "KGwmhGwURHErGGtoaGjUa2vqrIsW+Xir1QpKDVCqg1INuk6vCMNgmgxOZy5eevnFbEJJVfr9/vEF\n"
3342 "ZcDv91fabMIrcQVrG5fWmA31jXJxcQlvs9lAqSF+JxaPxwAwMPbvl1NpFUpCQSw+CSWRwrIbb8aN\n"
3343 "TU3m5593tQJ4bUEAVru4b9u2B28qKy3nDGN2hbquIR6PgX2vNiucyWagJOKIK9NQEgnwAoMgJsCL\n"
3344 "Scg5NoTCY7ihcom192TPPQsGoLpWU1ZaziUScRiG8R+Tmp5FXFEQT0SgKHGAmaCaBqaZ4OUoBi8M\n"
3345 "YvCby5gIq8ikDciyFdVV1Uil1Na2trb8zs7Oqf8JIFgs/el0ajXH8aA0i0QyjpgShZKIgeoUpm4A\n"
3346 "1AAhFAwzWFzajO7+Xrz9eidWr1qN9m13o7ysHA6HA6qqIhAM4Msve8Tg6Fjg9g0tuySLdWdnZ2f2\n"
3347 "agCk5bY1zqKikjvcbjfp+uIYdKrA4UzDV8QhEkhh1eoNWPqT5XC5FqFz7xF83H0MqVQKT+/oAC/I\n"
3348 "6Ds1gk9OHkXXmc/x1UAYmmZBbVUl2u+/zzIdibSMBC7dUVpbeiA4HJy3NvCUJx/2f91HRVGCy5UD\n"
3349 "XzGPgkJAsKhIJROwOexIj53AzGfbMTxyBDdUlGPbvfdi7579EJ1leLj9fjze/hhEyxREWwRTioLR\n"
3350 "uIAXXjsY3/qzreamjRtXCTo52NbWJs0L4H/GPzQ6GkwzMHhyvVBiJpRoCn2fKpgcTaJ7910IvfdL\n"
3351 "HB4ahc23FCubm3Hi3V3YuNyHG4sBqps4/OFHICQMrzeNbGoKlaUFiMUVe8dfPn1h2bLlRm1t7cqM\n"
3352 "ln5mXgAAMBn7YGpyAnmeAsTjJoa+pLh1wzY8+rtfw5Xph5Ar4mCPiDs3b0H/P/+OW9dvxqI8J47v\n"
3353 "2op3//oq0lNhWKRJ2B0RuOwmBGRQfUOpoWtJ/uV9PW9sWH8HCBF+09LS4p0XQNP1d86eOzuT68oF\n"
3354 "pYAgisj15IIXZNjK1uPQZyZqapsQHDmHClmD21WAvjd+j4r6tXhsx5PY8vO74c2sh6bH4HAlEY+M\n"
3355 "4aal1VKhzWj6OiR0XQiMRevr6uwgeGheAEnIHhkY6CeECHDluEDsFO/v24vXX3wJB4cbMcSWoqKi\n"
3356 "AuGRYdg8DbjwzVe47NgIx+0dIISDr6QIMnFDFGTkejkEg2dRXVnGWZBesf2B5iWnR+K9xSUl4MC2\n"
3357 "zgvQ0fGcks1qQ6mUijxPPiwOAkflIARbBr/a8QTGYxnIshXBVCGK1z4MX8ujcC6ux7Gut3DondfR\n"
3358 "dfwAbMUJmGoRIpclTE7E4HLYUFNVITYt9qw8P8EGRNECgGuYC/B9MzKovj84GqgvKS4Vhi+JYFYD\n"
3359 "jFogyTISiQQMg0KwyNB1Cosgoq6pCYK9DjwkqIkM5GQ+il0SnPUueHK9IIRH6/p1lsnpqDuWESZ1\n"
3360 "XQeAvKsCUGq8f/rUwFPVVdWCRbBAz4gQigPYv+dVSKIF09PT4J1ZdPd0Y3FZPjwuO0TeDlm2wuuW\n"
3361 "QAgBADDGYDIGMAabLYe/1H/O5+QzBZFIEgAiVwUwTfLV2NioaRizxzEUzYNsNwBJg8frxsTEBDgp\n"
3362 "D26PF+Vl5ZBEAoHnwX3bTxkAZppgAEzTRFY3IYgyhi+OuvPk+NKp6RkA7PS8ewAA/H6/yTgcmZqa\n"
3363 "gMedD6b54OSbUeq9BWtWrcN4KAQzHQMnyNB0A1nNgGEyGObsig2DAeDAgQM4gtSMjoHB8ywYjk/Y\n"
3364 "eWXF9NQ0GLgDV80AAGiZ7L7h4XOtzc23WFfcdDO4b5fnXO/EewcOwJaK4mRfH3JzVsHrsoMaJqyS\n"
3365 "BaJFAGMmpqNRBIJjdGBomI5enuSn4vR8NJY4I1vT9yaTyRQMvHlNANMkHw2eOU1Wr177vTgA5OTk\n"
3366 "YEtbGw59cAhp9SN48grRVL8YIm9CUeJmODSqhcNholMEZij6VM1+9pLquxweu1BeaZt8SlVVAOxP\n"
3367 "R48em54LwM298dxzfzj/yCO/WMLzs1+HEAGEEFBKsePpDoRC47BaraBSsZmb5ws5nTmnrTbHUBau\n"
3368 "s4l0VguEEkYoqhKXNtxSZJ14MDMzwxsmxnjGLZmvK/7XP6Fh0L/1njy5Y+2adZKqJhEKBdiFi8Pq\n"
3369 "xYsXpSJf/sj4+LhDTaWLHRjnI8GQ7RJ1mHGWl8kwryhz0+W5XKRpsaCulKzMrabSAPixhrqyktLx\n"
3370 "VzOb20mXoRt3PfkPRK+agd27H5cymYI9OjU3CYQfN0z2vka1w+mkdnzXrl3JtrY2KavPPA1wv5Uk\n"
3371 "yS5KIgQigOMAxgBqUGhZDdlsNgWwP0oW685Wz5FYfX2NdSZjaoGLZ6IGjNYn38TAvAALtU2bNnk0\n"
3372 "qj2A2fLaiNkiEwFwCuAOiIK45/Dhw1EAeKFdOLvIa6uorLtZVNQ0G/ymV2VU3/LEW+j60QA/xHbf\n"
3373 "h3wmksFKn8NbWN6IGUPA170nUpRqbf8XAAD48wNYyRHyyZIim91b0gCNy0HvF0dAriMmd4XzVziZ\n"
3374 "4wIA8uEphNdV8X1qRr9LZnHRoFlElMTla2VgrgB3Fb/W3Nw42L6ZrClzs7d5ngtrmvHQQgEWInYt\n"
3375 "xxVXYLZ16ADU690D3JzxXLG581caBWBep/71278AZpn8hFce4VcAAAAASUVORK5CYII=\n"
3376 "</filecontent>"
3377 "</icon>"
3378 "<launchable type=\"desktop-id\">eog.desktop</launchable>"
3379 "</component>"
3380 "</components>";
3381
3382 /* load AppStream file with embedded icon */
3383 store = as_store_new ();
3384 as_store_set_origin (store, "origin");
3385 ret = as_store_from_xml (store, xml_src, "/tmp/origin", &error);
3386 g_assert_no_error (error);
3387 g_assert (ret);
3388
3389 /* check the icon was parsed */
3390 g_assert_cmpint (as_store_get_size (store), ==, 1);
3391 app = as_store_get_app_by_id (store, "eog.desktop");
3392 g_assert (app != NULL);
3393 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
3394 icon = as_app_get_icon_default (app);
3395 g_assert (icon != NULL);
3396 g_assert_cmpint (as_icon_get_kind (icon), ==, AS_ICON_KIND_EMBEDDED);
3397 g_assert_cmpstr (as_icon_get_name (icon), ==, "eog.png");
3398 g_assert_cmpstr (as_icon_get_prefix (icon), ==, "/tmp/origin/icons");
3399
3400 /* convert back to a file */
3401 xml = as_store_to_xml (store, AS_NODE_TO_XML_FLAG_NONE);
3402 ret = as_test_compare_lines (xml->str, xml_src, &error);
3403 g_assert_no_error (error);
3404 g_assert (ret);
3405
3406 /* strip out the embedded icons */
3407 ret = as_store_convert_icons (store, AS_ICON_KIND_CACHED, &error);
3408 g_assert_no_error (error);
3409 g_assert (ret);
3410
3411 /* check exists */
3412 g_assert (g_file_test ("/tmp/origin/icons/32x32/eog.png", G_FILE_TEST_EXISTS));
3413 }
3414
3415 static void
store_changed_cb(AsStore * store,guint * cnt)3416 store_changed_cb (AsStore *store, guint *cnt)
3417 {
3418 as_test_loop_quit ();
3419 (*cnt)++;
3420 g_debug ("changed callback, now #%u", *cnt);
3421 }
3422
3423 static void
store_app_changed_cb(AsStore * store,AsApp * app,guint * cnt)3424 store_app_changed_cb (AsStore *store, AsApp *app, guint *cnt)
3425 {
3426 (*cnt)++;
3427 }
3428
3429 /* automatically reload changed directories */
3430 static void
as_test_store_auto_reload_dir_func(void)3431 as_test_store_auto_reload_dir_func (void)
3432 {
3433 AsApp *app;
3434 gboolean ret;
3435 guint cnt = 0;
3436 guint cnt_added = 0;
3437 guint cnt_removed = 0;
3438 g_autoptr(GError) error = NULL;
3439 g_autoptr(AsStore) store = NULL;
3440
3441 /* add this file to a store */
3442 store = as_store_new ();
3443 g_signal_connect (store, "changed",
3444 G_CALLBACK (store_changed_cb), &cnt);
3445 g_signal_connect (store, "app-added",
3446 G_CALLBACK (store_app_changed_cb), &cnt_added);
3447 g_signal_connect (store, "app-removed",
3448 G_CALLBACK (store_app_changed_cb), &cnt_removed);
3449 as_store_set_watch_flags (store, AS_STORE_WATCH_FLAG_ADDED |
3450 AS_STORE_WATCH_FLAG_REMOVED);
3451
3452 as_store_set_destdir (store, "/tmp/repo-tmp");
3453 g_mkdir_with_parents ("/tmp/repo-tmp/usr/share/app-info/xmls", 0700);
3454 g_unlink ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml");
3455
3456 /* load store */
3457 ret = as_store_load (store, AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM, NULL, &error);
3458 g_assert_no_error (error);
3459 g_assert (ret);
3460 g_assert_cmpint (cnt, ==, 1);
3461 g_assert_cmpint (cnt_added, ==, 0);
3462 g_assert_cmpint (cnt_removed, ==, 0);
3463
3464 /* create file */
3465 ret = g_file_set_contents ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml",
3466 "<components version=\"0.6\">"
3467 "<component type=\"desktop\">"
3468 "<id>test.desktop</id>"
3469 "</component>"
3470 "</components>",
3471 -1, &error);
3472 g_assert_no_error (error);
3473 g_assert (ret);
3474
3475 as_test_loop_run_with_timeout (2000);
3476 g_assert_cmpint (cnt, ==, 2);
3477 g_assert_cmpint (cnt_added, ==, 1);
3478 g_assert_cmpint (cnt_removed, ==, 0);
3479
3480 /* verify */
3481 app = as_store_get_app_by_id (store, "test.desktop");
3482 g_assert (app != NULL);
3483
3484 /* remove file */
3485 g_unlink ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml");
3486 as_test_loop_run_with_timeout (2000);
3487 g_assert_cmpint (cnt, ==, 3);
3488 g_assert_cmpint (cnt_added, ==, 1);
3489 g_assert_cmpint (cnt_removed, ==, 1);
3490 app = as_store_get_app_by_id (store, "test.desktop");
3491 g_assert (app == NULL);
3492 }
3493
3494 /* automatically reload changed files */
3495 static void
as_test_store_auto_reload_file_func(void)3496 as_test_store_auto_reload_file_func (void)
3497 {
3498 AsApp *app;
3499 AsFormat *format;
3500 AsRelease *rel;
3501 gboolean ret;
3502 guint cnt = 0;
3503 guint cnt_added = 0;
3504 g_autoptr(GError) error = NULL;
3505 g_autoptr(AsStore) store = NULL;
3506 g_autoptr(GFile) file = NULL;
3507
3508 /* set initial file */
3509 ret = g_file_set_contents ("/tmp/foo.xml",
3510 "<components version=\"0.6\">"
3511 "<component type=\"desktop\">"
3512 "<id>test.desktop</id>"
3513 "<releases>"
3514 "<release version=\"0.1.2\" timestamp=\"123\">"
3515 "</release>"
3516 "</releases>"
3517 "</component>"
3518 "</components>",
3519 -1, &error);
3520 g_assert_no_error (error);
3521 g_assert (ret);
3522
3523 /* add this file to a store */
3524 store = as_store_new ();
3525 g_signal_connect (store, "changed",
3526 G_CALLBACK (store_changed_cb), &cnt);
3527 g_signal_connect (store, "app-added",
3528 G_CALLBACK (store_app_changed_cb), &cnt_added);
3529 g_signal_connect (store, "app-removed",
3530 G_CALLBACK (store_app_changed_cb), &cnt_added);
3531 as_store_set_watch_flags (store, AS_STORE_WATCH_FLAG_ADDED |
3532 AS_STORE_WATCH_FLAG_REMOVED);
3533 file = g_file_new_for_path ("/tmp/foo.xml");
3534 ret = as_store_from_file (store, file, NULL, NULL, &error);
3535 g_assert_no_error (error);
3536 g_assert (ret);
3537 g_assert_cmpint (cnt, ==, 1);
3538
3539 /* verify */
3540 app = as_store_get_app_by_id (store, "test.desktop");
3541 g_assert (app != NULL);
3542 rel = as_app_get_release_default (app);
3543 g_assert_cmpstr (as_release_get_version (rel), ==, "0.1.2");
3544
3545 /* check format */
3546 format = as_app_get_format_by_kind (app, AS_FORMAT_KIND_APPSTREAM);
3547 g_assert (format != NULL);
3548 g_assert_cmpstr (as_format_get_filename (format), ==, "/tmp/foo.xml");
3549
3550 /* change the file, and ensure we get the callback */
3551 g_debug ("changing file");
3552 ret = g_file_set_contents ("/tmp/foo.xml",
3553 "<components version=\"0.6\">"
3554 "<component type=\"desktop\">"
3555 "<id>test.desktop</id>"
3556 "<releases>"
3557 "<release version=\"0.1.0\" timestamp=\"100\">"
3558 "</release>"
3559 "</releases>"
3560 "</component>"
3561 "<component type=\"desktop\">"
3562 "<id>baz.desktop</id>"
3563 "</component>"
3564 "</components>",
3565 -1, &error);
3566 g_assert_no_error (error);
3567 g_assert (ret);
3568 as_test_loop_run_with_timeout (2000);
3569 g_assert_cmpint (cnt, ==, 2);
3570
3571 /* verify */
3572 app = as_store_get_app_by_id (store, "baz.desktop");
3573 g_assert (app != NULL);
3574 app = as_store_get_app_by_id (store, "test.desktop");
3575 g_assert (app != NULL);
3576 rel = as_app_get_release_default (app);
3577 g_assert_cmpstr (as_release_get_version (rel), ==, "0.1.0");
3578
3579 /* remove file */
3580 g_unlink ("/tmp/foo.xml");
3581 as_test_loop_run_with_timeout (2000);
3582 g_assert_cmpint (cnt, ==, 3);
3583 app = as_store_get_app_by_id (store, "baz.desktop");
3584 g_assert (app == NULL);
3585 app = as_store_get_app_by_id (store, "test.desktop");
3586 g_assert (app == NULL);
3587 }
3588
3589 /* get an application from the store ignoring the prefix */
3590 static void
as_test_store_prefix_func(void)3591 as_test_store_prefix_func (void)
3592 {
3593 g_autoptr (AsStore) store = as_store_new ();
3594 g_autoptr (AsApp) app = as_app_new ();
3595 g_autoptr (GPtrArray) apps = NULL;
3596 AsApp *app_tmp;
3597
3598 /* add app */
3599 as_app_set_id (app, "flatpak-user:org.gnome.Software.desktop");
3600 as_store_add_app (store, app);
3601
3602 app_tmp = as_store_get_app_by_id (store, "org.gnome.Software.desktop");
3603 g_assert (app_tmp == NULL);
3604 app_tmp = as_store_get_app_by_id_ignore_prefix (store, "org.gnome.Software.desktop");
3605 g_assert (app_tmp != NULL);
3606 g_assert_cmpstr (as_app_get_id (app_tmp), ==,
3607 "flatpak-user:org.gnome.Software.desktop");
3608
3609 /* there might be multiple apps we want to get */
3610 apps = as_store_get_apps_by_id (store, "flatpak-user:org.gnome.Software.desktop");
3611 g_assert (apps != NULL);
3612 g_assert_cmpint (apps->len, ==, 1);
3613 app_tmp = g_ptr_array_index (apps, 0);
3614 g_assert_cmpstr (as_app_get_id (app_tmp), ==,
3615 "flatpak-user:org.gnome.Software.desktop");
3616
3617 /* exact unique match */
3618 app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/test/*",
3619 AS_STORE_SEARCH_FLAG_NONE);
3620 g_assert (app_tmp == NULL);
3621 app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/test/*",
3622 AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
3623 g_assert (app_tmp == NULL);
3624 app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/org.gnome.Software.desktop/*",
3625 AS_STORE_SEARCH_FLAG_NONE);
3626 g_assert (app_tmp != NULL);
3627 app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/org.gnome.Software.desktop/*",
3628 AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
3629 g_assert (app_tmp != NULL);
3630 app_tmp = as_store_get_app_by_unique_id (store, "*/*/*/*/*/*",
3631 AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
3632 g_assert (app_tmp != NULL);
3633 }
3634
3635 static void
as_test_store_wildcard_func(void)3636 as_test_store_wildcard_func (void)
3637 {
3638 AsApp *app_tmp;
3639 g_autoptr (AsApp) app1 = as_app_new ();
3640 g_autoptr (AsApp) app2 = as_app_new ();
3641 g_autoptr (AsStore) store = as_store_new ();
3642
3643 /* package from fedora */
3644 as_app_set_id (app1, "gimp.desktop");
3645 as_app_set_origin (app1, "fedora");
3646 as_app_add_pkgname (app1, "polari");
3647 _as_app_add_format_kind (app1, AS_FORMAT_KIND_DESKTOP);
3648 as_store_add_app (store, app1);
3649
3650 /* package from updates */
3651 as_app_set_id (app2, "gimp.desktop");
3652 as_app_set_origin (app2, "updates");
3653 as_app_add_pkgname (app2, "polari");
3654 _as_app_add_format_kind (app2, AS_FORMAT_KIND_DESKTOP);
3655 as_store_add_app (store, app2);
3656
3657 /* check negative match */
3658 app_tmp = as_store_get_app_by_unique_id (store, "*/*/xxx/*/gimp.desktop/*",
3659 AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
3660 g_assert (app_tmp == NULL);
3661 app_tmp = as_store_get_app_by_unique_id (store, "*/snap/*/*/gimp.desktop/*",
3662 AS_STORE_SEARCH_FLAG_USE_WILDCARDS);
3663 g_assert (app_tmp == NULL);
3664 }
3665
3666 /* load a store with a origin and scope encoded in the symlink name */
3667 static void
as_test_store_flatpak_func(void)3668 as_test_store_flatpak_func (void)
3669 {
3670 AsApp *app;
3671 AsFormat *format;
3672 GError *error = NULL;
3673 gboolean ret;
3674 g_autofree gchar *filename = NULL;
3675 g_autofree gchar *filename_root = NULL;
3676 g_autoptr(AsStore) store = NULL;
3677 g_autoptr(GFile) file = NULL;
3678 g_autoptr(GPtrArray) apps = NULL;
3679
3680 /* make throws us under a bus, yet again */
3681 g_setenv ("AS_SELF_TEST_PREFIX_DELIM", "_", TRUE);
3682
3683 /* load a symlinked file to the store */
3684 store = as_store_new ();
3685 filename_root = as_test_get_filename (".");
3686 filename = g_build_filename (filename_root, "flatpak_remote-name.xml", NULL);
3687 if (!g_file_test (filename, G_FILE_TEST_IS_SYMLINK)) {
3688 g_debug ("not doing symlink test in distcheck as regular file");
3689 return;
3690 }
3691 file = g_file_new_for_path (filename);
3692 ret = as_store_from_file (store, file, NULL, NULL, &error);
3693 g_assert_no_error (error);
3694 g_assert (ret);
3695
3696 /* test extraction of symlink data */
3697 g_assert_cmpstr (as_store_get_origin (store), ==, "flatpak");
3698 g_assert_cmpint (as_store_get_size (store), ==, 1);
3699 apps = as_store_dup_apps (store);
3700 g_assert_cmpint (apps->len, ==, 1);
3701 app = g_ptr_array_index (apps, 0);
3702 g_assert_cmpstr (as_app_get_id (app), ==, "flatpak:test.desktop");
3703 g_assert_cmpstr (as_app_get_unique_id (app), ==, "system/flatpak/remote-name/desktop/test.desktop/master");
3704 g_assert_cmpstr (as_app_get_id_filename (app), ==, "test");
3705 g_assert_cmpstr (as_app_get_origin (app), ==, "remote-name");
3706
3707 /* check format */
3708 format = as_app_get_format_by_kind (app, AS_FORMAT_KIND_APPSTREAM);
3709 g_assert (format != NULL);
3710 g_assert_cmpstr (as_format_get_filename (format), ==, filename);
3711
3712 /* back to normality */
3713 g_unsetenv ("AS_SELF_TEST_PREFIX_DELIM");
3714 }
3715
3716 /* demote the .desktop "application" to an addon */
3717 static void
as_test_store_demote_func(void)3718 as_test_store_demote_func (void)
3719 {
3720 AsApp *app;
3721 GError *error = NULL;
3722 gboolean ret;
3723 g_autofree gchar *filename1 = NULL;
3724 g_autofree gchar *filename2 = NULL;
3725 g_autoptr(AsApp) app_appdata = NULL;
3726 g_autoptr(AsApp) app_desktop = NULL;
3727 g_autoptr(AsStore) store = NULL;
3728 g_autoptr(GString) xml = NULL;
3729
3730 /* load example desktop file */
3731 app_desktop = as_app_new ();
3732 filename1 = as_test_get_filename ("example.desktop");
3733 ret = as_app_parse_file (app_desktop, filename1,
3734 AS_APP_PARSE_FLAG_ALLOW_VETO, &error);
3735 g_assert_no_error (error);
3736 g_assert (ret);
3737 g_assert_cmpint (as_app_get_kind (app_desktop), ==, AS_APP_KIND_DESKTOP);
3738
3739 /* load example appdata file */
3740 app_appdata = as_app_new ();
3741 filename2 = as_test_get_filename ("example.appdata.xml");
3742 ret = as_app_parse_file (app_appdata, filename2,
3743 AS_APP_PARSE_FLAG_ALLOW_VETO, &error);
3744 g_assert_no_error (error);
3745 g_assert (ret);
3746 g_assert_cmpint (as_app_get_kind (app_appdata), ==, AS_APP_KIND_ADDON);
3747
3748 /* add apps */
3749 store = as_store_new ();
3750 as_store_set_api_version (store, 0.8);
3751 as_store_add_app (store, app_desktop);
3752 as_store_add_app (store, app_appdata);
3753
3754 /* check we demoted */
3755 g_assert_cmpint (as_store_get_size (store), ==, 1);
3756 app = as_store_get_app_by_id (store, "example.desktop");
3757 g_assert (app != NULL);
3758 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_ADDON);
3759 g_assert_cmpint (as_app_get_extends(app)->len, >, 0);
3760
3761 /* dump */
3762 xml = as_store_to_xml (store,
3763 AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE |
3764 AS_NODE_TO_XML_FLAG_FORMAT_INDENT);
3765 g_debug ("%s", xml->str);
3766 }
3767
3768 static void
as_test_store_merges_func(void)3769 as_test_store_merges_func (void)
3770 {
3771 AsApp *app_tmp;
3772 g_autoptr(AsApp) app_appdata = NULL;
3773 g_autoptr(AsApp) app_appinfo = NULL;
3774 g_autoptr(AsApp) app_desktop = NULL;
3775 g_autoptr(AsStore) store_all = NULL;
3776 g_autoptr(AsStore) store_desktop_appdata = NULL;
3777
3778 /* test desktop + appdata */
3779 store_desktop_appdata = as_store_new ();
3780
3781 app_desktop = as_app_new ();
3782 as_app_set_id (app_desktop, "gimp.desktop");
3783 _as_app_add_format_kind (app_desktop, AS_FORMAT_KIND_DESKTOP);
3784 as_app_set_name (app_desktop, NULL, "GIMP");
3785 as_app_set_comment (app_desktop, NULL, "GNU Bla Bla");
3786 as_app_set_priority (app_desktop, -1);
3787 as_app_set_state (app_desktop, AS_APP_STATE_INSTALLED);
3788 as_app_set_scope (app_desktop, AS_APP_SCOPE_SYSTEM);
3789
3790 app_appdata = as_app_new ();
3791 as_app_set_id (app_appdata, "gimp.desktop");
3792 _as_app_add_format_kind (app_appdata, AS_FORMAT_KIND_APPDATA);
3793 as_app_set_description (app_appdata, NULL, "<p>Gimp is awesome</p>");
3794 as_app_add_pkgname (app_appdata, "gimp");
3795 as_app_set_priority (app_appdata, -1);
3796 as_app_set_state (app_appdata, AS_APP_STATE_INSTALLED);
3797 as_app_set_scope (app_desktop, AS_APP_SCOPE_SYSTEM);
3798
3799 as_store_add_app (store_desktop_appdata, app_desktop);
3800 as_store_add_app (store_desktop_appdata, app_appdata);
3801
3802 app_tmp = as_store_get_app_by_id (store_desktop_appdata, "gimp.desktop");
3803 g_assert (app_tmp != NULL);
3804 g_assert_cmpstr (as_app_get_name (app_tmp, NULL), ==, "GIMP");
3805 g_assert_cmpstr (as_app_get_comment (app_tmp, NULL), ==, "GNU Bla Bla");
3806 g_assert_cmpstr (as_app_get_description (app_tmp, NULL), ==, "<p>Gimp is awesome</p>");
3807 g_assert_cmpstr (as_app_get_pkgname_default (app_tmp), ==, "gimp");
3808 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_DESKTOP) != NULL);
3809 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_APPDATA) != NULL);
3810 g_assert_cmpint (as_app_get_state (app_tmp), ==, AS_APP_STATE_INSTALLED);
3811
3812 /* test desktop + appdata + appstream */
3813 store_all = as_store_new ();
3814
3815 app_appinfo = as_app_new ();
3816 as_app_set_id (app_appinfo, "gimp.desktop");
3817 _as_app_add_format_kind (app_appinfo, AS_FORMAT_KIND_APPSTREAM);
3818 as_app_set_name (app_appinfo, NULL, "GIMP");
3819 as_app_set_comment (app_appinfo, NULL, "GNU Bla Bla");
3820 as_app_set_description (app_appinfo, NULL, "<p>Gimp is Distro</p>");
3821 as_app_add_pkgname (app_appinfo, "gimp");
3822 as_app_set_priority (app_appinfo, 0);
3823
3824 as_store_add_app (store_all, app_appinfo);
3825 as_store_add_app (store_all, app_desktop);
3826 as_store_add_app (store_all, app_appdata);
3827
3828 /* ensure the AppStream entry 'wins' */
3829 app_tmp = as_store_get_app_by_id (store_all, "gimp.desktop");
3830 g_assert (app_tmp != NULL);
3831 g_assert_cmpstr (as_app_get_name (app_tmp, NULL), ==, "GIMP");
3832 g_assert_cmpstr (as_app_get_comment (app_tmp, NULL), ==, "GNU Bla Bla");
3833 g_assert_cmpstr (as_app_get_description (app_tmp, NULL), ==, "<p>Gimp is Distro</p>");
3834 g_assert_cmpstr (as_app_get_pkgname_default (app_tmp), ==, "gimp");
3835 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_DESKTOP) != NULL);
3836 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_APPDATA) != NULL);
3837 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_APPSTREAM) != NULL);
3838 g_assert_cmpint (as_app_get_formats(app_tmp)->len, ==, 3);
3839 g_assert_cmpint (as_app_get_state (app_tmp), ==, AS_APP_STATE_INSTALLED);
3840 }
3841
3842 static void
as_test_store_merges_local_func(void)3843 as_test_store_merges_local_func (void)
3844 {
3845 AsApp *app_tmp;
3846 g_autoptr(AsApp) app_appdata = NULL;
3847 g_autoptr(AsApp) app_appinfo = NULL;
3848 g_autoptr(AsApp) app_desktop = NULL;
3849 g_autoptr(AsStore) store = NULL;
3850
3851 /* test desktop + appdata + appstream */
3852 store = as_store_new ();
3853 as_store_set_add_flags (store, AS_STORE_ADD_FLAG_PREFER_LOCAL);
3854
3855 app_desktop = as_app_new ();
3856 as_app_set_id (app_desktop, "gimp.desktop");
3857 _as_app_add_format_kind (app_desktop, AS_FORMAT_KIND_DESKTOP);
3858 as_app_set_name (app_desktop, NULL, "GIMP");
3859 as_app_set_comment (app_desktop, NULL, "GNU Bla Bla");
3860 as_app_set_priority (app_desktop, -1);
3861 as_app_set_state (app_desktop, AS_APP_STATE_INSTALLED);
3862
3863 app_appdata = as_app_new ();
3864 as_app_set_id (app_appdata, "gimp.desktop");
3865 _as_app_add_format_kind (app_appdata, AS_FORMAT_KIND_APPDATA);
3866 as_app_set_description (app_appdata, NULL, "<p>Gimp is awesome</p>");
3867 as_app_add_pkgname (app_appdata, "gimp");
3868 as_app_set_priority (app_appdata, -1);
3869 as_app_set_state (app_appdata, AS_APP_STATE_INSTALLED);
3870
3871 app_appinfo = as_app_new ();
3872 as_app_set_id (app_appinfo, "gimp.desktop");
3873 _as_app_add_format_kind (app_appinfo, AS_FORMAT_KIND_APPSTREAM);
3874 as_app_set_name (app_appinfo, NULL, "GIMP");
3875 as_app_set_comment (app_appinfo, NULL, "Fedora GNU Bla Bla");
3876 as_app_set_description (app_appinfo, NULL, "<p>Gimp is Distro</p>");
3877 as_app_add_pkgname (app_appinfo, "gimp");
3878 as_app_set_priority (app_appinfo, 0);
3879
3880 /* this is actually the install order we get at startup */
3881 as_store_add_app (store, app_appinfo);
3882 as_store_add_app (store, app_desktop);
3883 as_store_add_app (store, app_appdata);
3884
3885 /* ensure the local entry 'wins' */
3886 app_tmp = as_store_get_app_by_id (store, "gimp.desktop");
3887 g_assert (app_tmp != NULL);
3888 g_assert_cmpstr (as_app_get_name (app_tmp, NULL), ==, "GIMP");
3889 g_assert_cmpstr (as_app_get_comment (app_tmp, NULL), ==, "GNU Bla Bla");
3890 g_assert_cmpstr (as_app_get_description (app_tmp, NULL), ==, "<p>Gimp is awesome</p>");
3891 g_assert_cmpstr (as_app_get_pkgname_default (app_tmp), ==, "gimp");
3892 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_DESKTOP) != NULL);
3893 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_APPDATA) != NULL);
3894 g_assert (as_app_get_format_by_kind (app_tmp, AS_FORMAT_KIND_APPSTREAM) != NULL);
3895 g_assert_cmpint (as_app_get_formats(app_tmp)->len, ==, 3);
3896 g_assert_cmpint (as_app_get_state (app_tmp), ==, AS_APP_STATE_INSTALLED);
3897 }
3898
3899 static void
as_test_store_empty_func(void)3900 as_test_store_empty_func (void)
3901 {
3902 gboolean ret;
3903 g_autoptr(GError) error = NULL;
3904 g_autoptr(AsStore) store = NULL;
3905
3906 store = as_store_new ();
3907 ret = as_store_from_xml (store, "", NULL, &error);
3908 g_assert_no_error (error);
3909 g_assert (ret);
3910 }
3911
3912 static void
as_test_store_func(void)3913 as_test_store_func (void)
3914 {
3915 AsApp *app;
3916 GString *xml;
3917 gboolean ret;
3918 g_autoptr(AsStore) store = NULL;
3919 g_autoptr(GError) error = NULL;
3920
3921 /* create a store and add a single app */
3922 store = as_store_new ();
3923 g_assert_cmpfloat (as_store_get_api_version (store), <, 1.f);
3924 g_assert_cmpfloat (as_store_get_api_version (store), >, 0.f);
3925 app = as_app_new ();
3926 as_app_set_id (app, "gnome-software.desktop");
3927 as_app_set_kind (app, AS_APP_KIND_DESKTOP);
3928 as_store_add_app (store, app);
3929 g_object_unref (app);
3930 g_assert_cmpstr (as_store_get_origin (store), ==, NULL);
3931
3932 /* check string output */
3933 as_store_set_api_version (store, 0.6);
3934 xml = as_store_to_xml (store, 0);
3935 ret = as_test_compare_lines (xml->str,
3936 "<components version=\"0.6\">"
3937 "<component type=\"desktop\">"
3938 "<id>gnome-software.desktop</id>"
3939 "</component>"
3940 "</components>",
3941 &error);
3942 g_assert_no_error (error);
3943 g_assert (ret);
3944 g_string_free (xml, TRUE);
3945
3946 /* add and then remove another app */
3947 app = as_app_new ();
3948 as_app_set_id (app, "junk.desktop");
3949 as_app_set_kind (app, AS_APP_KIND_FONT);
3950 as_store_add_app (store, app);
3951 g_object_unref (app);
3952 as_store_remove_app (store, app);
3953
3954 /* check string output */
3955 as_store_set_api_version (store, 0.6);
3956 xml = as_store_to_xml (store, 0);
3957 ret = as_test_compare_lines (xml->str,
3958 "<components version=\"0.6\">"
3959 "<component type=\"desktop\">"
3960 "<id>gnome-software.desktop</id>"
3961 "</component>"
3962 "</components>",
3963 &error);
3964 g_assert_no_error (error);
3965 g_assert (ret);
3966 g_string_free (xml, TRUE);
3967
3968 /* add another app and ensure it's sorted */
3969 app = as_app_new ();
3970 as_app_set_id (app, "aaa.desktop");
3971 as_app_set_kind (app, AS_APP_KIND_FONT);
3972 as_store_add_app (store, app);
3973 g_object_unref (app);
3974 xml = as_store_to_xml (store, 0);
3975 g_assert_cmpstr (xml->str, ==,
3976 "<components version=\"0.6\">"
3977 "<component type=\"font\">"
3978 "<id>aaa.desktop</id>"
3979 "</component>"
3980 "<component type=\"desktop\">"
3981 "<id>gnome-software.desktop</id>"
3982 "</component>"
3983 "</components>");
3984 g_string_free (xml, TRUE);
3985
3986 /* empty the store */
3987 as_store_remove_all (store);
3988 g_assert_cmpint (as_store_get_size (store), ==, 0);
3989 g_assert (as_store_get_app_by_id (store, "aaa.desktop") == NULL);
3990 g_assert (as_store_get_app_by_id (store, "gnome-software.desktop") == NULL);
3991 xml = as_store_to_xml (store, 0);
3992 g_assert_cmpstr (xml->str, ==,
3993 "<components version=\"0.6\"/>");
3994 g_string_free (xml, TRUE);
3995 }
3996
3997 static void
as_test_store_unique_func(void)3998 as_test_store_unique_func (void)
3999 {
4000 AsApp *app;
4001 g_autoptr(AsApp) app1 = NULL;
4002 g_autoptr(AsApp) app2 = NULL;
4003 g_autoptr(AsApp) app3 = NULL;
4004 g_autoptr(AsBundle) bundle2 = NULL;
4005 g_autoptr(AsBundle) bundle3 = NULL;
4006 g_autoptr(AsStore) store = NULL;
4007 g_autoptr(GPtrArray) apps = NULL;
4008
4009 /* create a store and add a single app */
4010 store = as_store_new ();
4011 as_store_set_add_flags (store, AS_STORE_ADD_FLAG_USE_UNIQUE_ID);
4012 app1 = as_app_new ();
4013 as_app_set_id (app1, "org.gnome.Software.desktop");
4014 as_app_set_kind (app1, AS_APP_KIND_DESKTOP);
4015 as_app_add_pkgname (app1, "gnome-software");
4016 as_store_add_app (store, app1);
4017
4018 /* add a stable bundle */
4019 app2 = as_app_new ();
4020 bundle2 = as_bundle_new ();
4021 as_bundle_set_kind (bundle2, AS_BUNDLE_KIND_FLATPAK);
4022 as_bundle_set_id (bundle2, "app/org.gnome.Software/i386/3-18");
4023 as_app_set_id (app2, "org.gnome.Software.desktop");
4024 as_app_set_kind (app2, AS_APP_KIND_DESKTOP);
4025 as_app_add_bundle (app2, bundle2);
4026 as_store_add_app (store, app2);
4027
4028 /* add a master bundle */
4029 app3 = as_app_new ();
4030 bundle3 = as_bundle_new ();
4031 as_bundle_set_kind (bundle3, AS_BUNDLE_KIND_FLATPAK);
4032 as_bundle_set_id (bundle3, "app/org.gnome.Software/i386/master");
4033 as_app_set_id (app3, "org.gnome.Software.desktop");
4034 as_app_set_kind (app3, AS_APP_KIND_DESKTOP);
4035 as_app_add_bundle (app3, bundle3);
4036 as_store_add_app (store, app3);
4037
4038 g_assert_cmpint (as_store_get_size (store), ==, 3);
4039 apps = as_store_get_apps_by_id (store, "org.gnome.Software.desktop");
4040 g_assert_cmpint (apps->len, ==, 3);
4041 app = g_ptr_array_index (apps, 0);
4042 g_assert_cmpstr (as_app_get_unique_id (app), ==,
4043 "*/package/*/desktop/org.gnome.Software.desktop/*");
4044 app = g_ptr_array_index (apps, 1);
4045 g_assert_cmpstr (as_app_get_unique_id (app), ==,
4046 "*/flatpak/*/desktop/org.gnome.Software.desktop/3-18");
4047 app = g_ptr_array_index (apps, 2);
4048 g_assert_cmpstr (as_app_get_unique_id (app), ==,
4049 "*/flatpak/*/desktop/org.gnome.Software.desktop/master");
4050 app = as_store_get_app_by_unique_id (store,
4051 "*/flatpak/*/desktop/"
4052 "org.gnome.Software.desktop/master",
4053 AS_STORE_SEARCH_FLAG_NONE);
4054 g_assert (app != NULL);
4055 }
4056
4057 static void
as_test_store_provides_func(void)4058 as_test_store_provides_func (void)
4059 {
4060 AsApp *app;
4061 gboolean ret;
4062 g_autoptr(GError) error = NULL;
4063 g_autoptr(AsStore) store = NULL;
4064 g_autoptr(GPtrArray) apps1 = NULL;
4065 g_autoptr(GPtrArray) apps2 = NULL;
4066
4067 /* create a store and add a single app */
4068 store = as_store_new ();
4069 ret = as_store_from_xml (store,
4070 "<components version=\"0.6\">"
4071 "<component type=\"desktop\">"
4072 "<id>test.desktop</id>"
4073 "<provides>"
4074 "<firmware type=\"flashed\">deadbeef</firmware>"
4075 "</provides>"
4076 "</component>"
4077 "</components>", NULL, &error);
4078 g_assert_no_error (error);
4079 g_assert (ret);
4080
4081 /* get an appication by the provide value */
4082 app = as_store_get_app_by_provide (store,
4083 AS_PROVIDE_KIND_FIRMWARE_FLASHED,
4084 "deadbeef");
4085 g_assert_cmpstr (as_app_get_id (app), ==, "test.desktop");
4086 app = as_store_get_app_by_provide (store,
4087 AS_PROVIDE_KIND_FIRMWARE_RUNTIME,
4088 "deadbeef");
4089 g_assert (app == NULL);
4090 app = as_store_get_app_by_provide (store,
4091 AS_PROVIDE_KIND_FIRMWARE_FLASHED,
4092 "beefdead");
4093 g_assert (app == NULL);
4094
4095 /* arrays of apps */
4096 apps1 = as_store_get_apps_by_provide (store,
4097 AS_PROVIDE_KIND_FIRMWARE_FLASHED,
4098 "deadbeef");
4099 g_assert_cmpint (apps1->len, ==, 1);
4100 app = g_ptr_array_index (apps1, 0);
4101 g_assert_cmpstr (as_app_get_id (app), ==, "test.desktop");
4102 apps2 = as_store_get_apps_by_provide (store,
4103 AS_PROVIDE_KIND_FIRMWARE_FLASHED,
4104 "beefdead");
4105 g_assert_cmpint (apps2->len, ==, 0);
4106 }
4107
4108 static void
as_test_store_versions_func(void)4109 as_test_store_versions_func (void)
4110 {
4111 AsApp *app;
4112 AsStore *store;
4113 GError *error = NULL;
4114 gboolean ret;
4115 GString *xml;
4116
4117 /* load a file to the store */
4118 store = as_store_new ();
4119 ret = as_store_from_xml (store,
4120 "<components version=\"0.6\">"
4121 "<component type=\"desktop\">"
4122 "<id>test.desktop</id>"
4123 "<description><p>Hello world</p></description>"
4124 "<architectures><arch>i386</arch></architectures>"
4125 "<releases>"
4126 "<release version=\"0.1.2\" timestamp=\"123\">"
4127 "<description><p>Hello</p></description>"
4128 "</release>"
4129 "</releases>"
4130 "</component>"
4131 "</components>", NULL, &error);
4132 g_assert_no_error (error);
4133 g_assert (ret);
4134 g_assert_cmpfloat (as_store_get_api_version (store), <, 0.6 + 0.01);
4135 g_assert_cmpfloat (as_store_get_api_version (store), >, 0.6 - 0.01);
4136
4137 /* verify source kind */
4138 app = as_store_get_app_by_id (store, "test.desktop");
4139 g_assert (as_app_get_format_by_kind (app, AS_FORMAT_KIND_APPSTREAM) != NULL);
4140
4141 /* test with latest features */
4142 as_store_set_api_version (store, 0.6);
4143 g_assert_cmpfloat (as_store_get_api_version (store), <, 0.6 + 0.01);
4144 g_assert_cmpfloat (as_store_get_api_version (store), >, 0.6 - 0.01);
4145 xml = as_store_to_xml (store, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
4146 ret = as_test_compare_lines (xml->str,
4147 "<components version=\"0.6\">\n"
4148 "<component type=\"desktop\">\n"
4149 "<id>test.desktop</id>\n"
4150 "<description><p>Hello world</p></description>\n"
4151 "<architectures>\n"
4152 "<arch>i386</arch>\n"
4153 "</architectures>\n"
4154 "<releases>\n"
4155 "<release timestamp=\"123\" version=\"0.1.2\">\n"
4156 "<description><p>Hello</p></description>\n"
4157 "</release>\n"
4158 "</releases>\n"
4159 "<launchable type=\"desktop-id\">test.desktop</launchable>\n"
4160 "</component>\n"
4161 "</components>\n", &error);
4162 g_assert_no_error (error);
4163 g_assert (ret);
4164 g_string_free (xml, TRUE);
4165 g_object_unref (store);
4166
4167 /* load a version 0.6 file to the store */
4168 store = as_store_new ();
4169 ret = as_store_from_xml (store,
4170 "<components version=\"0.6\">"
4171 "<component type=\"desktop\">"
4172 "<id>test.desktop</id>"
4173 "</component>"
4174 "</components>", NULL, &error);
4175 g_assert_no_error (error);
4176 g_assert (ret);
4177
4178 /* test latest spec version */
4179 xml = as_store_to_xml (store, 0);
4180 g_assert_cmpstr (xml->str, ==,
4181 "<components version=\"0.6\">"
4182 "<component type=\"desktop\">"
4183 "<id>test.desktop</id>"
4184 "<launchable type=\"desktop-id\">test.desktop</launchable>"
4185 "</component>"
4186 "</components>");
4187 g_string_free (xml, TRUE);
4188
4189 g_object_unref (store);
4190 }
4191
4192 static void
as_test_store_addons_func(void)4193 as_test_store_addons_func (void)
4194 {
4195 AsApp *app;
4196 GError *error = NULL;
4197 GPtrArray *data;
4198 gboolean ret;
4199 const gchar *xml =
4200 "<components version=\"0.7\">"
4201 "<component type=\"addon\">"
4202 "<id>eclipse-php.jar</id>"
4203 "<mimetypes>"
4204 "<mimetype>xtest</mimetype>"
4205 "</mimetypes>"
4206 "<extends>eclipse.desktop</extends>"
4207 "</component>"
4208 "<component type=\"desktop\">"
4209 "<id>eclipse.desktop</id>"
4210 "<launchable type=\"desktop-id\">eclipse.desktop</launchable>"
4211 "</component>"
4212 "</components>";
4213 g_autoptr(AsStore) store = NULL;
4214 g_autoptr(GString) str = NULL;
4215
4216 /* load a file to the store */
4217 store = as_store_new ();
4218 ret = as_store_from_xml (store, xml, NULL, &error);
4219 g_assert_no_error (error);
4220 g_assert (ret);
4221
4222 /* check the addon references the main application */
4223 app = as_store_get_app_by_id (store, "eclipse-php.jar");
4224 g_assert (app != NULL);
4225 data = as_app_get_extends (app);
4226 g_assert_cmpint (data->len, ==, 1);
4227 g_assert_cmpstr (g_ptr_array_index (data, 0), ==, "eclipse.desktop");
4228
4229 /* check the main application has a ref to the addon */
4230 app = as_store_get_app_by_id (store, "eclipse.desktop");
4231 data = as_app_get_addons (app);
4232 g_assert_cmpint (data->len, ==, 1);
4233 app = g_ptr_array_index (data, 0);
4234 g_assert_cmpstr (as_app_get_id (app), ==, "eclipse-php.jar");
4235
4236 /* check we can search for token from the addon */
4237 g_assert_cmpint (as_app_search_matches (app, "xtest"), >, 0);
4238 g_assert_cmpint (as_app_search_matches (app, "eclipse-php"), >, 0);
4239
4240 /* check it marshals back to the same XML */
4241 str = as_store_to_xml (store, 0);
4242 ret = as_test_compare_lines (str->str, xml, &error);
4243 g_assert_no_error (error);
4244 g_assert (ret);
4245 }
4246
4247 /*
4248 * test that we don't save the same translated data as C back to the file
4249 */
4250 static void
as_test_node_no_dup_c_func(void)4251 as_test_node_no_dup_c_func (void)
4252 {
4253 GError *error = NULL;
4254 AsNode *n;
4255 AsNode *root;
4256 GString *xml;
4257 gboolean ret;
4258 const gchar *src =
4259 "<component type=\"desktop\">"
4260 "<id>test.desktop</id>"
4261 "<name>Krita</name>"
4262 "<name xml:lang=\"pl\">Krita</name>"
4263 "</component>";
4264 g_autoptr(AsApp) app = NULL;
4265 g_autoptr(AsNodeContext) ctx = NULL;
4266
4267 /* to object */
4268 app = as_app_new ();
4269 root = as_node_from_xml (src, 0, &error);
4270 g_assert_no_error (error);
4271 g_assert (root != NULL);
4272 n = as_node_find (root, "component");
4273 g_assert (n != NULL);
4274 ctx = as_node_context_new ();
4275 ret = as_app_node_parse (app, n, ctx, &error);
4276 g_assert_no_error (error);
4277 g_assert (ret);
4278
4279 /* verify */
4280 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Krita");
4281 g_assert_cmpstr (as_app_get_name (app, "pl"), ==, "Krita");
4282 as_node_unref (root);
4283
4284 /* back to node */
4285 root = as_node_new ();
4286 as_node_context_set_version (ctx, 0.4);
4287 n = as_app_node_insert (app, root, ctx);
4288 xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_NONE);
4289 g_assert_cmpstr (xml->str, ==,
4290 "<component type=\"desktop\">"
4291 "<id>test.desktop</id>"
4292 "<name>Krita</name>"
4293 "<launchable type=\"desktop-id\">test.desktop</launchable>"
4294 "</component>");
4295 g_string_free (xml, TRUE);
4296 as_node_unref (root);
4297 }
4298
4299 static void
as_test_store_origin_func(void)4300 as_test_store_origin_func (void)
4301 {
4302 AsApp *app;
4303 AsFormat *format;
4304 GError *error = NULL;
4305 gboolean ret;
4306 g_autofree gchar *filename = NULL;
4307 g_autoptr(AsStore) store = NULL;
4308 g_autoptr(GFile) file = NULL;
4309
4310 /* load a file to the store */
4311 store = as_store_new ();
4312 filename = as_test_get_filename ("origin.xml");
4313 file = g_file_new_for_path (filename);
4314 ret = as_store_from_file (store, file, NULL, NULL, &error);
4315 g_assert_no_error (error);
4316 g_assert (ret);
4317
4318 /* test icon path */
4319 g_assert_cmpstr (as_store_get_origin (store), ==, "fedora-21");
4320 g_assert_cmpint (as_store_get_size (store), ==, 1);
4321 app = as_store_get_app_by_id (store, "test.desktop");
4322 g_assert (app != NULL);
4323 g_assert_cmpstr (as_app_get_icon_path (app), !=, NULL);
4324 g_assert (g_str_has_suffix (as_app_get_icon_path (app), "icons"));
4325 g_assert_cmpstr (as_app_get_origin (app), ==, "fedora-21");
4326
4327 /* check format */
4328 format = as_app_get_format_by_kind (app, AS_FORMAT_KIND_APPSTREAM);
4329 g_assert (format != NULL);
4330 g_assert_cmpstr (as_format_get_filename (format), ==, filename);
4331 }
4332
4333 static void
as_test_store_speed_appstream_func(void)4334 as_test_store_speed_appstream_func (void)
4335 {
4336 GError *error = NULL;
4337 gboolean ret;
4338 guint i;
4339 guint loops = 10;
4340 g_autofree gchar *filename = NULL;
4341 g_autoptr(GFile) file = NULL;
4342 g_autoptr(GTimer) timer = NULL;
4343
4344 filename = as_test_get_filename ("example-v04.xml.gz");
4345 file = g_file_new_for_path (filename);
4346 timer = g_timer_new ();
4347 for (i = 0; i < loops; i++) {
4348 g_autoptr(AsStore) store = NULL;
4349 store = as_store_new ();
4350 as_store_set_add_flags (store, AS_STORE_ADD_FLAG_ONLY_NATIVE_LANGS);
4351 ret = as_store_from_file (store, file, NULL, NULL, &error);
4352 g_assert_no_error (error);
4353 g_assert (ret);
4354 g_assert_cmpint (as_store_get_apps (store)->len, >=, 1415);
4355 g_assert (as_store_get_app_by_id (store, "org.gnome.Software.desktop") != NULL);
4356 g_assert (as_store_get_app_by_pkgname (store, "gnome-software") != NULL);
4357 }
4358 g_print ("%.0f ms: ", g_timer_elapsed (timer, NULL) * 1000 / loops);
4359 }
4360
4361 static void
as_test_store_speed_search_func(void)4362 as_test_store_speed_search_func (void)
4363 {
4364 AsApp *app;
4365 GPtrArray *apps;
4366 GError *error = NULL;
4367 gboolean ret;
4368 guint i;
4369 guint j;
4370 guint loops = 1000;
4371 g_autofree gchar *filename = NULL;
4372 g_autoptr(GFile) file = NULL;
4373 g_autoptr(GTimer) timer = NULL;
4374 g_autoptr(AsStore) store = NULL;
4375
4376 /* run creating a store and tokenizing */
4377 filename = as_test_get_filename ("example-v04.xml.gz");
4378 file = g_file_new_for_path (filename);
4379 store = as_store_new ();
4380 ret = as_store_from_file (store, file, NULL, NULL, &error);
4381 g_assert_no_error (error);
4382 g_assert (ret);
4383
4384 /* tokenize and search */
4385 timer = g_timer_new ();
4386 apps = as_store_get_apps (store);
4387 for (j = 0; j < apps->len; j++) {
4388 app = g_ptr_array_index (apps, j);
4389 as_app_search_matches (app, "xxx");
4390 }
4391 g_print ("cold=%.0fms: ", g_timer_elapsed (timer, NULL) * 1000);
4392
4393 /* search again */
4394 g_timer_reset (timer);
4395 for (i = 0; i < loops; i++) {
4396 for (j = 0; j < apps->len; j++) {
4397 app = g_ptr_array_index (apps, j);
4398 as_app_search_matches (app, "xxx");
4399 }
4400 }
4401 g_print ("hot=%.2f ms: ", (g_timer_elapsed (timer, NULL) * 1000) / (gdouble) loops);
4402 }
4403
4404 static void
as_test_store_speed_appdata_func(void)4405 as_test_store_speed_appdata_func (void)
4406 {
4407 GError *error = NULL;
4408 gboolean ret;
4409 guint i;
4410 guint loops = 10;
4411 g_autofree gchar *filename = NULL;
4412 g_autoptr(GTimer) timer = NULL;
4413
4414 filename = as_test_get_filename (".");
4415 timer = g_timer_new ();
4416 for (i = 0; i < loops; i++) {
4417 g_autoptr(AsStore) store = NULL;
4418 store = as_store_new ();
4419 as_store_set_destdir (store, filename);
4420 g_test_expect_message (G_LOG_DOMAIN,
4421 G_LOG_LEVEL_WARNING,
4422 "ignoring description '*' from */broken.appdata.xml: Unknown tag '_p'");
4423 ret = as_store_load (store, AS_STORE_LOAD_FLAG_APPDATA, NULL, &error);
4424 g_assert_no_error (error);
4425 g_assert (ret);
4426 g_assert_cmpint (as_store_get_apps (store)->len, >, 0);
4427 }
4428 g_print ("%.0f ms: ", g_timer_elapsed (timer, NULL) * 1000 / loops);
4429 }
4430
4431 static void
as_test_store_speed_desktop_func(void)4432 as_test_store_speed_desktop_func (void)
4433 {
4434 GError *error = NULL;
4435 gboolean ret;
4436 guint i;
4437 guint loops = 10;
4438 g_autofree gchar *filename = NULL;
4439 g_autoptr(GTimer) timer = NULL;
4440
4441 filename = as_test_get_filename (".");
4442 timer = g_timer_new ();
4443 for (i = 0; i < loops; i++) {
4444 g_autoptr(AsStore) store = NULL;
4445 store = as_store_new ();
4446 as_store_set_destdir (store, filename);
4447 ret = as_store_load (store, AS_STORE_LOAD_FLAG_DESKTOP, NULL, &error);
4448 g_assert_no_error (error);
4449 g_assert (ret);
4450 g_assert_cmpint (as_store_get_apps (store)->len, >, 0);
4451 }
4452 g_print ("%.0f ms: ", g_timer_elapsed (timer, NULL) * 1000 / loops);
4453 }
4454
4455 static void
as_test_utils_appstream_id_func(void)4456 as_test_utils_appstream_id_func (void)
4457 {
4458 g_autofree gchar *id = NULL;
4459 g_assert (as_utils_appstream_id_valid ("org.gnome.Software"));
4460 g_assert (!as_utils_appstream_id_valid ("xml:gravatar@jr.rlabs.io"));
4461 id = as_utils_appstream_id_build ("gravatar@jr.rlabs.io");
4462 g_assert_cmpstr (id, ==, "gravatar_jr.rlabs.io");
4463 }
4464
4465 static void
as_test_utils_guid_func(void)4466 as_test_utils_guid_func (void)
4467 {
4468 #ifndef _WIN32
4469 g_autofree gchar *guid1 = NULL;
4470 g_autofree gchar *guid2 = NULL;
4471
4472 /* invalid */
4473 g_assert (!as_utils_guid_is_valid (NULL));
4474 g_assert (!as_utils_guid_is_valid (""));
4475 g_assert (!as_utils_guid_is_valid ("1ff60ab2-3905-06a1-b476"));
4476 g_assert (!as_utils_guid_is_valid ("1ff60ab2-XXXX-XXXX-XXXX-0371f00c9e9b"));
4477 g_assert (!as_utils_guid_is_valid (" 1ff60ab2-3905-06a1-b476-0371f00c9e9b"));
4478
4479 /* valid */
4480 g_assert (as_utils_guid_is_valid ("1ff60ab2-3905-06a1-b476-0371f00c9e9b"));
4481
4482 /* make valid */
4483 guid1 = as_utils_guid_from_string ("python.org");
4484 g_assert_cmpstr (guid1, ==, "886313e1-3b8a-5372-9b90-0c9aee199e5d");
4485 guid2 = as_utils_guid_from_string ("8086:0406");
4486 g_assert_cmpstr (guid2, ==, "1fbd1f2c-80f4-5d7c-a6ad-35c7b9bd5486");
4487 #endif
4488 }
4489
4490 static void
as_test_utils_icons_func(void)4491 as_test_utils_icons_func (void)
4492 {
4493 gchar *tmp;
4494 GError *error = NULL;
4495 g_autofree gchar *destdir = NULL;
4496
4497 destdir = as_test_get_filename (".");
4498
4499 /* full path */
4500 tmp = as_utils_find_icon_filename (destdir, "/usr/share/pixmaps/test.png", &error);
4501 g_assert_cmpstr (tmp, !=, NULL);
4502 g_assert_no_error (error);
4503 g_free (tmp);
4504
4505 /* full pixmaps name */
4506 tmp = as_utils_find_icon_filename (destdir, "test.png", &error);
4507 g_assert_cmpstr (tmp, !=, NULL);
4508 g_assert_no_error (error);
4509 g_free (tmp);
4510
4511 /* pixmaps name */
4512 tmp = as_utils_find_icon_filename (destdir, "test", &error);
4513 g_assert_cmpstr (tmp, !=, NULL);
4514 g_assert_no_error (error);
4515 g_free (tmp);
4516
4517 /* full theme name */
4518 tmp = as_utils_find_icon_filename (destdir, "test2.png", &error);
4519 g_assert_cmpstr (tmp, !=, NULL);
4520 g_assert_no_error (error);
4521 g_free (tmp);
4522
4523 /* theme name */
4524 tmp = as_utils_find_icon_filename (destdir, "test2", &error);
4525 g_assert_cmpstr (tmp, !=, NULL);
4526 g_assert_no_error (error);
4527 g_free (tmp);
4528
4529 /* theme name, HiDPI */
4530 tmp = as_utils_find_icon_filename_full (destdir, "test3",
4531 AS_UTILS_FIND_ICON_HI_DPI,
4532 &error);
4533 g_assert_cmpstr (tmp, !=, NULL);
4534 g_assert_no_error (error);
4535 g_free (tmp);
4536
4537 /* full pixmaps invalid */
4538 tmp = as_utils_find_icon_filename (destdir, "/usr/share/pixmaps/not-going-to-exist.png", &error);
4539 g_assert_cmpstr (tmp, ==, NULL);
4540 g_assert_error (error, AS_UTILS_ERROR, AS_UTILS_ERROR_FAILED);
4541 g_free (tmp);
4542 g_clear_error (&error);
4543
4544 /* all invalid */
4545 tmp = as_utils_find_icon_filename (destdir, "not-going-to-exist.png", &error);
4546 g_assert_cmpstr (tmp, ==, NULL);
4547 g_assert_error (error, AS_UTILS_ERROR, AS_UTILS_ERROR_FAILED);
4548 g_free (tmp);
4549 g_clear_error (&error);
4550 }
4551
4552 static void
as_test_utils_spdx_token_func(void)4553 as_test_utils_spdx_token_func (void)
4554 {
4555 gchar **tok;
4556 gchar *tmp;
4557
4558 /* simple */
4559 tok = as_utils_spdx_license_tokenize ("LGPL-2.0+");
4560 tmp = g_strjoinv (" ", tok);
4561 g_assert_cmpstr (tmp, ==, "@LGPL-2.0+");
4562 g_strfreev (tok);
4563 g_free (tmp);
4564
4565 /* empty */
4566 tok = as_utils_spdx_license_tokenize ("");
4567 tmp = g_strjoinv (" ", tok);
4568 g_assert_cmpstr (tmp, ==, "");
4569 g_strfreev (tok);
4570 g_free (tmp);
4571
4572 /* invalid */
4573 tok = as_utils_spdx_license_tokenize (NULL);
4574 g_assert (tok == NULL);
4575
4576 /* random */
4577 tok = as_utils_spdx_license_tokenize ("Public Domain");
4578 tmp = g_strjoinv (" ", tok);
4579 g_assert_cmpstr (tmp, ==, "Public Domain");
4580 g_strfreev (tok);
4581 g_free (tmp);
4582
4583 /* multiple licences */
4584 tok = as_utils_spdx_license_tokenize ("LGPL-2.0+ AND GPL-2.0 AND LGPL-3.0");
4585 tmp = g_strjoinv (" ", tok);
4586 g_assert_cmpstr (tmp, ==, "@LGPL-2.0+ & @GPL-2.0 & @LGPL-3.0");
4587 g_strfreev (tok);
4588 g_free (tmp);
4589
4590 /* multiple licences, using the new style */
4591 tok = as_utils_spdx_license_tokenize ("LGPL-2.0-or-later AND GPL-2.0-only");
4592 tmp = g_strjoinv (" ", tok);
4593 g_assert_cmpstr (tmp, ==, "@LGPL-2.0+ & @GPL-2.0");
4594 g_strfreev (tok);
4595 g_free (tmp);
4596
4597 /* multiple licences, deprecated 'and' & 'or' */
4598 tok = as_utils_spdx_license_tokenize ("LGPL-2.0+ and GPL-2.0 or LGPL-3.0");
4599 tmp = g_strjoinv (" ", tok);
4600 g_assert_cmpstr (tmp, ==, "@LGPL-2.0+ & @GPL-2.0 | @LGPL-3.0");
4601 g_strfreev (tok);
4602 g_free (tmp);
4603
4604 /* brackets */
4605 tok = as_utils_spdx_license_tokenize ("LGPL-2.0+ and (GPL-2.0 or GPL-2.0+) and MIT");
4606 tmp = g_strjoinv (" ", tok);
4607 g_assert_cmpstr (tmp, ==, "@LGPL-2.0+ & ( @GPL-2.0 | @GPL-2.0+ ) & @MIT");
4608 g_strfreev (tok);
4609 g_free (tmp);
4610
4611 /* detokenisation */
4612 tok = as_utils_spdx_license_tokenize ("LGPLv2+ and (QPL or GPLv2) and MIT");
4613 tmp = as_utils_spdx_license_detokenize (tok);
4614 g_assert_cmpstr (tmp, ==, "LGPLv2+ AND (QPL OR GPLv2) AND MIT");
4615 g_strfreev (tok);
4616 g_free (tmp);
4617
4618 /* "+" operator */
4619 tok = as_utils_spdx_license_tokenize ("CC-BY-SA-3.0+ AND Zlib");
4620 tmp = g_strjoinv (" ", tok);
4621 g_assert_cmpstr (tmp, ==, "@CC-BY-SA-3.0 + & @Zlib");
4622 g_free (tmp);
4623 tmp = as_utils_spdx_license_detokenize (tok);
4624 g_assert_cmpstr (tmp, ==, "CC-BY-SA-3.0+ AND Zlib");
4625 g_strfreev (tok);
4626 g_free (tmp);
4627
4628 /* detokenisation literals */
4629 tok = as_utils_spdx_license_tokenize ("Public Domain");
4630 tmp = as_utils_spdx_license_detokenize (tok);
4631 g_assert_cmpstr (tmp, ==, "Public Domain");
4632 g_strfreev (tok);
4633 g_free (tmp);
4634
4635 /* invalid tokens */
4636 tmp = as_utils_spdx_license_detokenize (NULL);
4637 g_assert (tmp == NULL);
4638
4639 /* leading brackets */
4640 tok = as_utils_spdx_license_tokenize ("(MPLv1.1 or LGPLv3+) and LGPLv3");
4641 tmp = g_strjoinv (" ", tok);
4642 g_assert_cmpstr (tmp, ==, "( MPLv1.1 | LGPLv3+ ) & LGPLv3");
4643 g_strfreev (tok);
4644 g_free (tmp);
4645
4646 /* trailing brackets */
4647 tok = as_utils_spdx_license_tokenize ("MPLv1.1 and (LGPLv3 or GPLv3)");
4648 tmp = g_strjoinv (" ", tok);
4649 g_assert_cmpstr (tmp, ==, "MPLv1.1 & ( LGPLv3 | GPLv3 )");
4650 g_strfreev (tok);
4651 g_free (tmp);
4652
4653 /* deprecated names */
4654 tok = as_utils_spdx_license_tokenize ("CC0 and (CC0 or CC0)");
4655 tmp = g_strjoinv (" ", tok);
4656 g_assert_cmpstr (tmp, ==, "@CC0-1.0 & ( @CC0-1.0 | @CC0-1.0 )");
4657 g_strfreev (tok);
4658 g_free (tmp);
4659
4660 /* SPDX strings */
4661 g_assert (as_utils_is_spdx_license ("CC0"));
4662 g_assert (as_utils_is_spdx_license ("LicenseRef-proprietary"));
4663 g_assert (as_utils_is_spdx_license ("CC0 and GFDL-1.3"));
4664 g_assert (as_utils_is_spdx_license ("CC0 AND GFDL-1.3"));
4665 g_assert (as_utils_is_spdx_license ("CC-BY-SA-3.0+"));
4666 g_assert (as_utils_is_spdx_license ("CC-BY-SA-3.0+ AND Zlib"));
4667 g_assert (as_utils_is_spdx_license ("NOASSERTION"));
4668 g_assert (!as_utils_is_spdx_license ("CC0 dave"));
4669 g_assert (!as_utils_is_spdx_license (""));
4670 g_assert (!as_utils_is_spdx_license (NULL));
4671
4672 /* importing non-SPDX formats */
4673 tmp = as_utils_license_to_spdx ("CC0 and (Public Domain and GPLv3+ with exceptions)");
4674 g_assert_cmpstr (tmp, ==, "CC0-1.0 AND (LicenseRef-public-domain AND GPL-3.0+)");
4675 g_free (tmp);
4676 }
4677
4678 static void
as_test_utils_markup_import_func(void)4679 as_test_utils_markup_import_func (void)
4680 {
4681 guint i;
4682 struct {
4683 const gchar *old;
4684 const gchar *new;
4685 } table[] = {
4686 { "", NULL },
4687 { "dave", "<p>dave</p>" },
4688 { "dave!\ndave?", "<p>dave! dave?</p>" },
4689 { "dave!\n\ndave?", "<p>dave!</p><p>dave?</p>" },
4690 { NULL, NULL }
4691 };
4692 for (i = 0; table[i].old != NULL; i++) {
4693 g_autofree gchar *new = NULL;
4694 g_autoptr(GError) error = NULL;
4695 new = as_markup_import (table[i].old,
4696 AS_MARKUP_CONVERT_FORMAT_SIMPLE,
4697 &error);
4698 g_assert_no_error (error);
4699 g_assert_cmpstr (new, ==, table[i].new);
4700 }
4701 }
4702
4703 static void
as_test_utils_func(void)4704 as_test_utils_func (void)
4705 {
4706 gboolean ret;
4707 gchar *tmp;
4708 gchar **tokens;
4709 GError *error = NULL;
4710
4711 /* as_utils_is_stock_icon_name */
4712 g_assert (!as_utils_is_stock_icon_name (NULL));
4713 g_assert (!as_utils_is_stock_icon_name (""));
4714 g_assert (!as_utils_is_stock_icon_name ("indigo-blue"));
4715 g_assert (as_utils_is_stock_icon_name ("accessories-calculator"));
4716 g_assert (as_utils_is_stock_icon_name ("insert-image"));
4717 g_assert (as_utils_is_stock_icon_name ("zoom-out"));
4718
4719 /* environments */
4720 g_assert (as_utils_is_environment_id ("GNOME"));
4721 g_assert (!as_utils_is_environment_id ("RandomDE"));
4722
4723 /* categories */
4724 g_assert (as_utils_is_category_id ("AudioVideoEditing"));
4725 g_assert (!as_utils_is_category_id ("SpellEditing"));
4726
4727 /* valid description markup */
4728 tmp = as_markup_convert_simple ("<p>Hello world!</p>", &error);
4729 g_assert_no_error (error);
4730 g_assert_cmpstr (tmp, ==, "Hello world!");
4731 g_free (tmp);
4732 tmp = as_markup_convert_simple ("<p>Hello world</p><p></p>"
4733 "<ul><li>Item</li></ul>",
4734 &error);
4735 g_assert_no_error (error);
4736 g_assert_cmpstr (tmp, ==, "Hello world\n • Item");
4737 g_free (tmp);
4738
4739 /* valid description markup */
4740 tmp = as_markup_convert ("<p>Hello world with a very long line that"
4741 " probably needs splitting at least once in"
4742 " the right place.</p>"
4743 "<ul><li>"
4744 "This is an overly long item that needs to be"
4745 " broken into multiple lines that only has one"
4746 " initial bullet point."
4747 "</li></ul>",
4748 AS_MARKUP_CONVERT_FORMAT_MARKDOWN, &error);
4749 g_assert_no_error (error);
4750 g_assert_cmpstr (tmp, ==,
4751 "Hello world with a very long line that probably"
4752 " needs splitting at least once\n"
4753 "in the right place.\n"
4754 " * This is an overly long item that needs to be"
4755 " broken into multiple lines that\n"
4756 " only has one initial bullet point.");
4757 g_free (tmp);
4758
4759 /* valid description markup */
4760 tmp = as_markup_convert_simple ("bare text", &error);
4761 g_assert_no_error (error);
4762 g_assert_cmpstr (tmp, ==, "bare text");
4763 g_free (tmp);
4764
4765 /* invalid XML */
4766 tmp = as_markup_convert_simple ("<p>Hello world</dave>", &error);
4767 g_assert_error (error, AS_NODE_ERROR, AS_NODE_ERROR_FAILED);
4768 g_assert_cmpstr (tmp, ==, NULL);
4769 g_clear_error (&error);
4770
4771 /* validate */
4772 ret = as_markup_validate ("<p>hello</p>", &error);
4773 g_assert_no_error (error);
4774 g_assert (ret);
4775 ret = as_markup_validate ("<ol><li>hello</ol>", &error);
4776 g_assert_error (error, AS_NODE_ERROR, AS_NODE_ERROR_FAILED);
4777 g_assert (!ret);
4778 g_clear_error (&error);
4779
4780 /* passthrough */
4781 tmp = as_markup_convert ("<p>pa&ra</p><ul><li>one</li><li>two</li></ul>",
4782 AS_MARKUP_CONVERT_FORMAT_APPSTREAM,
4783 &error);
4784 g_assert_no_error (error);
4785 g_assert_cmpstr (tmp, ==, "<p>pa&ra</p><ul><li>one</li><li>two</li></ul>");
4786 g_free (tmp);
4787
4788 /* ignore errors */
4789 tmp = as_markup_convert_full ("<p>para</p><ol><li>one</li></ol><li>two</li>",
4790 AS_MARKUP_CONVERT_FORMAT_APPSTREAM,
4791 AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS,
4792 &error);
4793 g_assert_no_error (error);
4794 g_assert_cmpstr (tmp, ==, "<p>para</p><ul><li>one</li></ul>");
4795 g_free (tmp);
4796 tmp = as_markup_convert_full ("<p>para</p><ul><li>one</li><li>two</ul>",
4797 AS_MARKUP_CONVERT_FORMAT_APPSTREAM,
4798 AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS,
4799 &error);
4800 g_assert_no_error (error);
4801 g_assert_cmpstr (tmp, ==, "<p>para</p>");
4802 g_free (tmp);
4803
4804 /* valid tokens */
4805 g_assert (as_utils_search_token_valid ("battery"));
4806 g_assert (!as_utils_search_token_valid ("<b>"));
4807
4808 /* check tokenisation */
4809 tokens = as_utils_search_tokenize ("a c b");
4810 g_assert (tokens == NULL);
4811 tokens = as_utils_search_tokenize ("batteries are (really) stupid");
4812 g_assert_cmpstr (tokens[0], ==, "batteries");
4813 g_assert_cmpstr (tokens[1], ==, "are");
4814 g_assert_cmpstr (tokens[2], ==, "stupid");
4815 g_assert_cmpstr (tokens[3], ==, NULL);
4816 g_strfreev (tokens);
4817 }
4818
4819 static void
as_test_utils_version_func(void)4820 as_test_utils_version_func (void)
4821 {
4822 guint i;
4823 struct {
4824 guint32 val;
4825 const gchar *ver;
4826 AsVersionParseFlag flags;
4827 } version_from_uint32[] = {
4828 { 0x0, "0.0.0.0", AS_VERSION_PARSE_FLAG_NONE },
4829 { 0xff, "0.0.0.255", AS_VERSION_PARSE_FLAG_NONE },
4830 { 0xff01, "0.0.255.1", AS_VERSION_PARSE_FLAG_NONE },
4831 { 0xff0001, "0.255.0.1", AS_VERSION_PARSE_FLAG_NONE },
4832 { 0xff000100, "255.0.1.0", AS_VERSION_PARSE_FLAG_NONE },
4833 { 0x0, "0.0.0", AS_VERSION_PARSE_FLAG_USE_TRIPLET },
4834 { 0xff, "0.0.255", AS_VERSION_PARSE_FLAG_USE_TRIPLET },
4835 { 0xff01, "0.0.65281", AS_VERSION_PARSE_FLAG_USE_TRIPLET },
4836 { 0xff0001, "0.255.1", AS_VERSION_PARSE_FLAG_USE_TRIPLET },
4837 { 0xff000100, "255.0.256", AS_VERSION_PARSE_FLAG_USE_TRIPLET },
4838 { 0, NULL }
4839 };
4840 struct {
4841 guint16 val;
4842 const gchar *ver;
4843 AsVersionParseFlag flags;
4844 } version_from_uint16[] = {
4845 { 0x0, "0.0", AS_VERSION_PARSE_FLAG_NONE },
4846 { 0xff, "0.255", AS_VERSION_PARSE_FLAG_NONE },
4847 { 0xff01, "255.1", AS_VERSION_PARSE_FLAG_NONE },
4848 { 0x0, "0.0", AS_VERSION_PARSE_FLAG_USE_BCD },
4849 { 0x0110, "1.10", AS_VERSION_PARSE_FLAG_USE_BCD },
4850 { 0x9999, "99.99", AS_VERSION_PARSE_FLAG_USE_BCD },
4851 { 0, NULL }
4852 };
4853 struct {
4854 const gchar *old;
4855 const gchar *new;
4856 } version_parse[] = {
4857 { "0", "0" },
4858 { "0x1a", "0.0.26" },
4859 { "257", "0.0.257" },
4860 { "1.2.3", "1.2.3" },
4861 { "0xff0001", "0.255.1" },
4862 { "16711681", "0.255.1" },
4863 { "20150915", "20150915" },
4864 { "dave", "dave" },
4865 { "0x1x", "0x1x" },
4866 { NULL, NULL }
4867 };
4868
4869 /* check version conversion */
4870 for (i = 0; version_from_uint32[i].ver != NULL; i++) {
4871 g_autofree gchar *ver = NULL;
4872 ver = as_utils_version_from_uint32 (version_from_uint32[i].val,
4873 version_from_uint32[i].flags);
4874 g_assert_cmpstr (ver, ==, version_from_uint32[i].ver);
4875 }
4876 for (i = 0; version_from_uint16[i].ver != NULL; i++) {
4877 g_autofree gchar *ver = NULL;
4878 ver = as_utils_version_from_uint16 (version_from_uint16[i].val,
4879 version_from_uint16[i].flags);
4880 g_assert_cmpstr (ver, ==, version_from_uint16[i].ver);
4881 }
4882
4883 /* check version parsing */
4884 for (i = 0; version_parse[i].old != NULL; i++) {
4885 g_autofree gchar *ver = NULL;
4886 ver = as_utils_version_parse (version_parse[i].old);
4887 g_assert_cmpstr (ver, ==, version_parse[i].new);
4888 }
4889 }
4890
4891 static void
as_test_store_metadata_func(void)4892 as_test_store_metadata_func (void)
4893 {
4894 GError *error = NULL;
4895 GPtrArray *apps;
4896 gboolean ret;
4897 const gchar *xml =
4898 "<components version=\"0.6\">"
4899 "<component type=\"desktop\">"
4900 "<id>test.desktop</id>"
4901 "<metadata>"
4902 "<value key=\"foo\">bar</value>"
4903 "</metadata>"
4904 "</component>"
4905 "<component type=\"desktop\">"
4906 "<id>tested.desktop</id>"
4907 "<metadata>"
4908 "<value key=\"foo\">bar</value>"
4909 "</metadata>"
4910 "</component>"
4911 "</components>";
4912 g_autoptr(AsStore) store = NULL;
4913
4914 store = as_store_new ();
4915 ret = as_store_from_xml (store, xml, NULL, &error);
4916 g_assert_no_error (error);
4917 g_assert (ret);
4918
4919 apps = as_store_get_apps_by_metadata (store, "foo", "bar");
4920 g_assert_cmpint (apps->len, ==, 2);
4921 g_ptr_array_unref (apps);
4922 }
4923
4924 static void
as_test_store_metadata_index_func(void)4925 as_test_store_metadata_index_func (void)
4926 {
4927 GPtrArray *apps;
4928 const guint repeats = 500;
4929 guint i;
4930 g_autoptr(AsStore) store = NULL;
4931 g_autoptr(GTimer) timer = NULL;
4932
4933 /* create lots of applications in the store */
4934 store = as_store_new ();
4935 as_store_add_metadata_index (store, "X-CacheID");
4936 for (i = 0; i < repeats; i++) {
4937 g_autofree gchar *id = g_strdup_printf ("app-%05u", i);
4938 g_autoptr(AsApp) app = as_app_new ();
4939 as_app_set_id (app, id);
4940 as_app_add_metadata (app, "X-CacheID", "dave.i386");
4941 as_app_add_metadata (app, "baz", "dave");
4942 as_store_add_app (store, app);
4943 }
4944
4945 /* find out how long this takes with an index */
4946 timer = g_timer_new ();
4947 for (i = 0; i < repeats; i++) {
4948 apps = as_store_get_apps_by_metadata (store, "X-CacheID", "dave.i386");
4949 g_assert_cmpint (apps->len, ==, repeats);
4950 g_ptr_array_unref (apps);
4951 apps = as_store_get_apps_by_metadata (store, "X-CacheID", "notgoingtoexist");
4952 g_assert_cmpint (apps->len, ==, 0);
4953 g_ptr_array_unref (apps);
4954 }
4955 g_assert_cmpfloat (g_timer_elapsed (timer, NULL), <, 0.5);
4956 g_print ("%.0fms: ", g_timer_elapsed (timer, NULL) * 1000);
4957 }
4958
4959 static void
as_test_yaml_broken_func(void)4960 as_test_yaml_broken_func (void)
4961 {
4962 #ifdef AS_BUILD_DEP11
4963 g_autoptr(AsYaml) node = NULL;
4964 g_autoptr(GError) error1 = NULL;
4965 g_autoptr(GError) error2 = NULL;
4966 node = as_yaml_from_data ("s---\n"
4967 "File: DEP-11\n",
4968 -1,
4969 AS_YAML_FROM_FLAG_NONE,
4970 &error1);
4971 g_assert_error (error1, AS_NODE_ERROR, AS_NODE_ERROR_INVALID_MARKUP);
4972 g_assert (node == NULL);
4973 node = as_yaml_from_data ("---\n"
4974 "%File: DEP-11\n",
4975 -1,
4976 AS_YAML_FROM_FLAG_NONE,
4977 &error2);
4978 g_assert_error (error2, AS_NODE_ERROR, AS_NODE_ERROR_INVALID_MARKUP);
4979 g_assert_cmpstr (error2->message, ==,
4980 "scanner error: while scanning a directive at ln:2 col:1, "
4981 "found unexpected non-alphabetical character at ln:2 col:6");
4982 g_assert (node == NULL);
4983 #else
4984 g_test_skip ("Compiled without YAML (DEP-11) support");
4985 #endif
4986 }
4987
4988 static void
as_test_yaml_func(void)4989 as_test_yaml_func (void)
4990 {
4991 #ifdef AS_BUILD_DEP11
4992 AsYaml *node;
4993 GError *error = NULL;
4994 GString *str;
4995 const gchar *expected;
4996 g_autofree gchar *filename = NULL;
4997 g_autoptr(GFile) file = NULL;
4998 gboolean ret;
4999
5000 /* simple header */
5001 node = as_yaml_from_data (
5002 "File: DEP-11\n"
5003 "Origin: aequorea\n"
5004 "Version: '0.6'\n",
5005 -1,
5006 AS_YAML_FROM_FLAG_NONE,
5007 &error);
5008 g_assert_no_error (error);
5009 g_assert (node != NULL);
5010 str = as_yaml_to_string (node);
5011 expected =
5012 "[MAP]{\n"
5013 " [KVL]File=DEP-11\n"
5014 " [KVL]Origin=aequorea\n"
5015 " [KVL]Version=0.6\n";
5016 if (g_strcmp0 (str->str, expected) != 0)
5017 g_warning ("Expected:\n%s\nGot:\n%s", expected, str->str);
5018 g_assert_cmpstr (str->str, ==, expected);
5019 g_string_free (str, TRUE);
5020 as_yaml_unref (node);
5021
5022 /* simple list */
5023 node = as_yaml_from_data (
5024 "---\n"
5025 "Mimetypes:\n"
5026 " - text/html\n"
5027 " - text/xml\n"
5028 " - application/xhtml+xml\n"
5029 "Kudos:\n"
5030 " - AppMenu\n"
5031 " - SearchProvider\n"
5032 " - Notifications\n",
5033 -1,
5034 AS_YAML_FROM_FLAG_NONE,
5035 &error);
5036 g_assert_no_error (error);
5037 g_assert (node != NULL);
5038 str = as_yaml_to_string (node);
5039 expected =
5040 "[MAP]{\n"
5041 " [SEQ]Mimetypes\n"
5042 " [KEY]text/html\n"
5043 " [KEY]text/xml\n"
5044 " [KEY]application/xhtml+xml\n"
5045 " [SEQ]Kudos\n"
5046 " [KEY]AppMenu\n"
5047 " [KEY]SearchProvider\n"
5048 " [KEY]Notifications\n";
5049 if (g_strcmp0 (str->str, expected) != 0)
5050 g_warning ("Expected:\n%s\nGot:\n%s", expected, str->str);
5051 g_assert_cmpstr (str->str, ==, expected);
5052 g_string_free (str, TRUE);
5053 as_yaml_unref (node);
5054
5055 /* dummy application */
5056 filename = as_test_get_filename ("usr/share/app-info/yaml/aequorea.yml");
5057 g_assert (filename != NULL);
5058 file = g_file_new_for_path (filename);
5059 node = as_yaml_from_file (file, AS_YAML_FROM_FLAG_NONE, NULL, &error);
5060 g_assert_no_error (error);
5061 g_assert (node != NULL);
5062 str = as_yaml_to_string (node);
5063 expected =
5064 "[MAP]{\n"
5065 " [KVL]File=DEP-11\n"
5066 " [KVL]Origin=aequorea\n"
5067 " [KVL]Version=0.6\n"
5068 "[MAP]{\n"
5069 " [KVL]Type=desktop-app\n"
5070 " [KVL]ID=iceweasel.desktop\n"
5071 " [MAP]Name\n"
5072 " [KVL]C=Iceweasel\n"
5073 " [KVL]Package=iceweasel\n"
5074 " [MAP]Icon\n"
5075 " [SEQ]cached\n"
5076 " [MAP]{\n"
5077 " [KVL]name=iceweasel.png\n"
5078 " [KVL]width=64\n"
5079 " [KVL]height=64\n"
5080 " [MAP]Keywords\n"
5081 " [SEQ]C\n"
5082 " [KEY]browser\n"
5083 " [SEQ]Screenshots\n"
5084 " [MAP]{\n"
5085 " [KVL]default=true\n"
5086 " [MAP]source-image\n"
5087 " [KVL]height=770\n"
5088 " [KVL]url=http://localhost/source/screenshot.png\n"
5089 " [KVL]width=1026\n"
5090 " [SEQ]thumbnails\n"
5091 " [MAP]{\n"
5092 " [KVL]height=423\n"
5093 " [KVL]url=http://localhost/752x423/screenshot.png\n"
5094 " [KVL]width=752\n"
5095 "[MAP]{\n"
5096 " [KVL]Type=desktop-app\n"
5097 " [KVL]ID=dave.desktop\n"
5098 " [MAP]Name\n"
5099 " [KVL]C=dave\n";
5100 ret = as_test_compare_lines (str->str, expected, &error);
5101 g_assert_no_error (error);
5102 g_assert (ret);
5103 g_string_free (str, TRUE);
5104 as_yaml_unref (node);
5105 #else
5106 g_test_skip ("Compiled without YAML (DEP-11) support");
5107 #endif
5108 }
5109
5110 static void
as_test_store_yaml_func(void)5111 as_test_store_yaml_func (void)
5112 {
5113 #ifdef AS_BUILD_DEP11
5114 AsApp *app;
5115 GError *error = NULL;
5116 gboolean ret;
5117 g_autofree gchar *filename = NULL;
5118 g_autoptr(AsStore) store = NULL;
5119 g_autoptr(GFile) file = NULL;
5120 g_autoptr(GString) str = NULL;
5121 const gchar *xml =
5122 "<components origin=\"aequorea\" version=\"0.6\">\n"
5123 "<component type=\"desktop\">\n"
5124 "<id>dave.desktop</id>\n"
5125 "<name>dave</name>\n"
5126 "</component>\n"
5127 "<component type=\"desktop\">\n"
5128 "<id>iceweasel.desktop</id>\n"
5129 "<pkgname>iceweasel</pkgname>\n"
5130 "<name>Iceweasel</name>\n"
5131 "<icon type=\"cached\" height=\"64\" width=\"64\">iceweasel.png</icon>\n"
5132 "<keywords>\n"
5133 "<keyword>browser</keyword>\n"
5134 "</keywords>\n"
5135 "<screenshots>\n"
5136 "<screenshot type=\"default\">\n"
5137 "<image type=\"source\" height=\"770\" width=\"1026\">http://localhost/source/screenshot.png</image>\n"
5138 "<image type=\"thumbnail\" height=\"423\" width=\"752\">http://localhost/752x423/screenshot.png</image>\n"
5139 "</screenshot>\n"
5140 "</screenshots>\n"
5141 "</component>\n"
5142 "</components>\n";
5143
5144 /* load store */
5145 store = as_store_new ();
5146 filename = as_test_get_filename ("usr/share/app-info/yaml/aequorea.yml");
5147 g_assert (filename != NULL);
5148 file = g_file_new_for_path (filename);
5149 ret = as_store_from_file (store, file, NULL, NULL, &error);
5150 g_assert_no_error (error);
5151 g_assert (ret);
5152
5153 /* test it matches expected XML */
5154 str = as_store_to_xml (store, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE);
5155 ret = as_test_compare_lines (str->str, xml, &error);
5156 g_assert_no_error (error);
5157 g_assert (ret);
5158
5159 /* test store properties */
5160 g_assert_cmpstr (as_store_get_origin (store), ==, "aequorea");
5161 g_assert_cmpfloat (as_store_get_api_version (store), <, 0.6 + 0.01);
5162 g_assert_cmpfloat (as_store_get_api_version (store), >, 0.6 - 0.01);
5163 g_assert_cmpint (as_store_get_size (store), ==, 2);
5164 g_assert (as_store_get_app_by_id (store, "iceweasel.desktop") != NULL);
5165 g_assert (as_store_get_app_by_id (store, "dave.desktop") != NULL);
5166
5167 /* test application properties */
5168 app = as_store_get_app_by_id (store, "iceweasel.desktop");
5169 g_assert_cmpint (as_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
5170 g_assert_cmpstr (as_app_get_pkgname_default (app), ==, "iceweasel");
5171 g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Iceweasel");
5172 g_assert_cmpstr (as_app_get_origin (app), ==, "aequorea");
5173 #else
5174 g_test_skip ("Compiled without YAML (DEP-11) support");
5175 #endif
5176 }
5177
5178 static void
as_test_store_speed_yaml_func(void)5179 as_test_store_speed_yaml_func (void)
5180 {
5181 #ifdef AS_BUILD_DEP11
5182 GError *error = NULL;
5183 gboolean ret;
5184 guint i;
5185 guint loops = 10;
5186 g_autofree gchar *filename = NULL;
5187 g_autoptr(GFile) file = NULL;
5188 g_autoptr(GTimer) timer = NULL;
5189
5190 filename = as_test_get_filename ("example-v06.yml.gz");
5191 g_assert (filename != NULL);
5192 file = g_file_new_for_path (filename);
5193 timer = g_timer_new ();
5194 for (i = 0; i < loops; i++) {
5195 g_autoptr(AsStore) store = NULL;
5196 store = as_store_new ();
5197 ret = as_store_from_file (store, file, NULL, NULL, &error);
5198 g_assert_no_error (error);
5199 g_assert (ret);
5200
5201 /* test store properties */
5202 g_assert_cmpstr (as_store_get_origin (store), ==, "bartholomea");
5203 g_assert_cmpfloat (as_store_get_api_version (store), <, 0.6 + 0.01);
5204 g_assert_cmpfloat (as_store_get_api_version (store), >, 0.6 - 0.01);
5205 g_assert_cmpint (as_store_get_size (store), ==, 85);
5206 g_assert (as_store_get_app_by_id (store, "blobwars.desktop") != NULL);
5207 }
5208 g_print ("%.0f ms: ", g_timer_elapsed (timer, NULL) * 1000 / loops);
5209 #else
5210 g_test_skip ("Compiled without YAML (DEP-11) support");
5211 #endif
5212 }
5213
5214 static void
as_test_utils_vercmp_func(void)5215 as_test_utils_vercmp_func (void)
5216 {
5217 /* same */
5218 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.3"), ==, 0);
5219 g_assert_cmpint (as_utils_vercmp ("001.002.003", "001.002.003"), ==, 0);
5220
5221 /* same, not dotted decimal */
5222 g_assert_cmpint (as_utils_vercmp ("1.2.3", "0x1020003"), ==, 0);
5223 g_assert_cmpint (as_utils_vercmp ("0x10203", "0x10203"), ==, 0);
5224
5225 /* upgrade and downgrade */
5226 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.4"), <, 0);
5227 g_assert_cmpint (as_utils_vercmp ("001.002.000", "001.002.009"), <, 0);
5228 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.2"), >, 0);
5229 g_assert_cmpint (as_utils_vercmp ("001.002.009", "001.002.000"), >, 0);
5230
5231 /* unequal depth */
5232 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.3.1"), <, 0);
5233 g_assert_cmpint (as_utils_vercmp ("1.2.3.1", "1.2.4"), <, 0);
5234
5235 /* mixed-alpha-numeric */
5236 g_assert_cmpint (as_utils_vercmp ("1.2.3a", "1.2.3a"), ==, 0);
5237 g_assert_cmpint (as_utils_vercmp ("1.2.3a", "1.2.3b"), <, 0);
5238 g_assert_cmpint (as_utils_vercmp ("1.2.3b", "1.2.3a"), >, 0);
5239
5240 /* alpha version append */
5241 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.3a"), <, 0);
5242 g_assert_cmpint (as_utils_vercmp ("1.2.3a", "1.2.3"), >, 0);
5243
5244 /* alpha only */
5245 g_assert_cmpint (as_utils_vercmp ("alpha", "alpha"), ==, 0);
5246 g_assert_cmpint (as_utils_vercmp ("alpha", "beta"), <, 0);
5247 g_assert_cmpint (as_utils_vercmp ("beta", "alpha"), >, 0);
5248
5249 /* alpha-compare */
5250 g_assert_cmpint (as_utils_vercmp ("1.2a.3", "1.2a.3"), ==, 0);
5251 g_assert_cmpint (as_utils_vercmp ("1.2a.3", "1.2b.3"), <, 0);
5252 g_assert_cmpint (as_utils_vercmp ("1.2b.3", "1.2a.3"), >, 0);
5253
5254 /* tilde is all-powerful */
5255 g_assert_cmpint (as_utils_vercmp ("1.2.3~rc1", "1.2.3~rc1"), ==, 0);
5256 g_assert_cmpint (as_utils_vercmp ("1.2.3~rc1", "1.2.3"), <, 0);
5257 g_assert_cmpint (as_utils_vercmp ("1.2.3", "1.2.3~rc1"), >, 0);
5258 g_assert_cmpint (as_utils_vercmp ("1.2.3~rc2", "1.2.3~rc1"), >, 0);
5259
5260 /* invalid */
5261 g_assert_cmpint (as_utils_vercmp ("1", NULL), ==, G_MAXINT);
5262 g_assert_cmpint (as_utils_vercmp (NULL, "1"), ==, G_MAXINT);
5263 g_assert_cmpint (as_utils_vercmp (NULL, NULL), ==, G_MAXINT);
5264
5265 /* full version gets some more checks right */
5266 g_assert_cmpint (as_utils_vercmp_full ("0.9", "1", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5267 g_assert_cmpint (as_utils_vercmp_full ("9", "9a", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5268 g_assert_cmpint (as_utils_vercmp_full ("9a", "10", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5269 g_assert_cmpint (as_utils_vercmp_full ("9+", "10", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5270 g_assert_cmpint (as_utils_vercmp_full ("9half", "10", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5271 g_assert_cmpint (as_utils_vercmp_full ("9.5", "10", AS_VERSION_COMPARE_FLAG_NONE), <, 0);
5272 }
5273
5274 static void
as_test_utils_install_filename_func(void)5275 as_test_utils_install_filename_func (void)
5276 {
5277 gboolean ret;
5278 GError *error = NULL;
5279 g_autofree gchar *filename1 = NULL;
5280 g_autofree gchar *filename2 = NULL;
5281 g_autofree gchar *filename3 = NULL;
5282 g_autofree gchar *filename4 = NULL;
5283
5284 /* appdata to shared */
5285 filename1 = as_test_get_filename ("broken.appdata.xml");
5286 ret = as_utils_install_filename (AS_UTILS_LOCATION_SHARED,
5287 filename1, NULL,
5288 "/tmp/destdir/",
5289 &error);
5290 g_assert_no_error (error);
5291 g_assert (ret);
5292 g_assert (g_file_test ("/tmp/destdir/usr/share/appdata/broken.appdata.xml", G_FILE_TEST_EXISTS));
5293
5294 /* metainfo to cache */
5295 filename2 = as_test_get_filename ("example.metainfo.xml");
5296 ret = as_utils_install_filename (AS_UTILS_LOCATION_CACHE,
5297 filename2, NULL,
5298 "/tmp/destdir/",
5299 &error);
5300 g_assert_error (error, AS_UTILS_ERROR, AS_UTILS_ERROR_INVALID_TYPE);
5301 g_assert (!ret);
5302 g_assert (!g_file_test ("/tmp/destdir/var/cache/appdata/example.metainfo.xml", G_FILE_TEST_EXISTS));
5303 g_clear_error (&error);
5304
5305 /* appstream to cache */
5306 filename3 = as_test_get_filename ("origin.xml");
5307 ret = as_utils_install_filename (AS_UTILS_LOCATION_CACHE,
5308 filename3, NULL,
5309 "/tmp/destdir/",
5310 &error);
5311 g_assert_no_error (error);
5312 g_assert (ret);
5313 g_assert (g_file_test ("/tmp/destdir/var/cache/app-info/xmls/origin.xml", G_FILE_TEST_EXISTS));
5314
5315 /* icons to cache, override origin */
5316 filename4 = as_test_get_filename ("origin-icons.tar.gz");
5317 ret = as_utils_install_filename (AS_UTILS_LOCATION_CACHE,
5318 filename4, "neworigin",
5319 "/tmp/destdir/",
5320 &error);
5321 g_assert_no_error (error);
5322 g_assert (ret);
5323 g_assert (g_file_test ("/tmp/destdir/var/cache/app-info/icons/neworigin/64x64/org.gnome.Software.png", G_FILE_TEST_EXISTS));
5324
5325 /* icons to shared */
5326 ret = as_utils_install_filename (AS_UTILS_LOCATION_SHARED,
5327 filename4, NULL,
5328 "/tmp/destdir/",
5329 &error);
5330 g_assert_no_error (error);
5331 g_assert (ret);
5332 g_assert (g_file_test ("/tmp/destdir/usr/share/app-info/icons/origin/64x64/org.gnome.Software.png", G_FILE_TEST_EXISTS));
5333 }
5334
5335 static void
as_test_utils_string_replace_func(void)5336 as_test_utils_string_replace_func (void)
5337 {
5338 guint i;
5339 struct {
5340 const gchar *str;
5341 const gchar *search;
5342 const gchar *replace;
5343 const gchar *result;
5344 } table[] = {
5345 { "", "", "", "" },
5346 { "one", "one", "two", "two" },
5347 { "one", "one", "1", "1" },
5348 { "one", "one", "onlyme", "onlyme" },
5349 { "we few ppl", " few ", "", "weppl" },
5350 { "bee&", "&", "&", "bee&" },
5351 { NULL, NULL, NULL, NULL }
5352 };
5353 for (i = 0; table[i].str != NULL; i++) {
5354 g_autoptr(GString) str = g_string_new (table[i].str);
5355 as_utils_string_replace (str,
5356 table[i].search,
5357 table[i].replace);
5358 g_assert_cmpstr (str->str, ==, table[i].result);
5359 }
5360 }
5361
5362 static void
as_test_utils_locale_compat_func(void)5363 as_test_utils_locale_compat_func (void)
5364 {
5365 /* empty */
5366 g_assert (as_utils_locale_is_compatible (NULL, NULL));
5367
5368 /* same */
5369 g_assert (as_utils_locale_is_compatible ("en_GB", "en_GB"));
5370
5371 /* forward and reverse compatible */
5372 g_assert (as_utils_locale_is_compatible ("en_GB", "en"));
5373 g_assert (as_utils_locale_is_compatible ("en", "en_GB"));
5374
5375 /* different language and locale */
5376 g_assert (!as_utils_locale_is_compatible ("en_GB", "fr_FR"));
5377
5378 /* politics */
5379 g_assert (!as_utils_locale_is_compatible ("zh_CN", "zh_TW"));
5380
5381 /* never going to match system locale or language */
5382 g_assert (!as_utils_locale_is_compatible ("xx_XX", NULL));
5383 g_assert (!as_utils_locale_is_compatible (NULL, "xx_XX"));
5384 }
5385
5386 static void
as_test_markup_import_html(void)5387 as_test_markup_import_html (void)
5388 {
5389 const gchar *input;
5390 g_autofree gchar *out_complex = NULL;
5391 g_autofree gchar *out_list = NULL;
5392 g_autofree gchar *out_simple = NULL;
5393 g_autoptr(GError) error = NULL;
5394 guint i;
5395 struct {
5396 const gchar *html;
5397 const gchar *markup;
5398 } table[] = {
5399 { "", "" },
5400 { "dave", "<p>dave</p>" },
5401 { "™", "<p>™</p>" },
5402 { "<p>paul</p>", "<p>paul</p>" },
5403 { "<p>tim</p><p>baz</p>", "<p>tim</p>\n<p>baz</p>" },
5404 { "<ul><li>1</li></ul>", "<ul><li>1</li></ul>" },
5405 { "<ul><li>1</li><li>2</li></ul>", "<ul><li>1</li><li>2</li></ul>" },
5406 { "<p>foo<i>awesome</i></p>", "<p>fooawesome</p>" },
5407 { "a<img src=\"moo.png\">b", "<p>ab</p>" },
5408 { "<h2>title</h2>content", "<p>content</p>" },
5409 { "para1<br><br>para2", "<p>para1</p>\n<p>para2</p>" },
5410 { "para1<h1>ignore</h1>para2", "<p>para1</p>\n<p>para2</p>" },
5411 { NULL, NULL}
5412 };
5413 for (i = 0; table[i].html != NULL; i++) {
5414 g_autofree gchar *tmp = NULL;
5415 g_autoptr(GError) error_local = NULL;
5416 tmp = as_markup_import (table[i].html,
5417 AS_MARKUP_CONVERT_FORMAT_HTML,
5418 &error_local);
5419 g_assert_no_error (error_local);
5420 g_assert_cmpstr (tmp, ==, table[i].markup);
5421 }
5422
5423 /* simple, from meta */
5424 input = "This game is simply awesome™ in every way!";
5425 out_simple = as_markup_import (input, AS_MARKUP_CONVERT_FORMAT_HTML, &error);
5426 g_assert_no_error (error);
5427 g_assert_cmpstr (out_simple, ==, "<p>This game is simply awesome™ in every way!</p>");
5428
5429 /* complex non-compliant HTML, from div */
5430 input = " <h1>header</h1>"
5431 " <p>First line of the <i>description</i> is okay...</p>"
5432 " <img src=\"moo.png\">"
5433 " <img src=\"png\">"
5434 " <p>Second <strong>line</strong> is <a href=\"#moo\">even</a> better!</p>";
5435 out_complex = as_markup_import (input, AS_MARKUP_CONVERT_FORMAT_HTML, &error);
5436 g_assert_no_error (error);
5437 g_assert_cmpstr (out_complex, ==, "<p>First line of the description is okay...</p>\n"
5438 "<p>Second line is even better!</p>");
5439
5440 /* complex list */
5441 input = " <ul>"
5442 " <li>First line of the list</li>"
5443 " <li>Second line of the list</li>"
5444 " </ul>";
5445 out_list = as_markup_import (input, AS_MARKUP_CONVERT_FORMAT_HTML, &error);
5446 g_assert_no_error (error);
5447 g_assert_cmpstr (out_list, ==, "<ul><li>First line of the list</li><li>Second line of the list</li></ul>");
5448 }
5449
5450 static void
as_test_utils_unique_id_func(void)5451 as_test_utils_unique_id_func (void)
5452 {
5453 const guint loops = 100000;
5454 guint i;
5455 gdouble duration_ns;
5456 g_autoptr(GTimer) timer = g_timer_new ();
5457
5458 /* pathological cases */
5459 g_assert (!as_utils_unique_id_equal ("foo", "bar"));
5460 g_assert (!as_utils_unique_id_equal ("foo/bar/baz", "foo/bar"));
5461
5462 for (i = 0; i < loops; i++) {
5463 g_assert (as_utils_unique_id_equal ("aa/bb/cc/dd/ee/ff",
5464 "aa/bb/cc/dd/ee/ff"));
5465 g_assert (as_utils_unique_id_equal ("aa/bb/cc/dd/ee/ff",
5466 "aa/*/cc/dd/ee/ff"));
5467 g_assert (as_utils_unique_id_equal ("user/flatpak/utopia/desktop/gimp.desktop/master",
5468 "*/*/*/*/*/*"));
5469 g_assert (!as_utils_unique_id_equal ("zz/zz/zz/zz/zz/zz",
5470 "aa/bb/cc/dd/ee/ff"));
5471 g_assert (!as_utils_unique_id_equal ("user/*/*/shell-extension/gmail_notify@jablona123.pl.shell-extension/*",
5472 "*/*/*/desktop/org.gnome.accerciser.desktop/*"));
5473 }
5474 duration_ns = g_timer_elapsed (timer, NULL) * 1000000000.f;
5475 g_print ("%.0f ns: ", duration_ns / (loops * 4));
5476
5477 /* allow ignoring using bitfields */
5478 g_assert (as_utils_unique_id_match ("aa/bb/cc/dd/ee/ff",
5479 "aa/bb/cc/dd/ee/XXXXXXXXXXXXX",
5480 AS_UNIQUE_ID_MATCH_FLAG_SCOPE |
5481 AS_UNIQUE_ID_MATCH_FLAG_BUNDLE_KIND |
5482 AS_UNIQUE_ID_MATCH_FLAG_ORIGIN |
5483 AS_UNIQUE_ID_MATCH_FLAG_KIND |
5484 AS_UNIQUE_ID_MATCH_FLAG_ID));
5485 g_assert (as_utils_unique_id_match ("XXXXXXXXXXXXX/bb/cc/dd/ee/ff",
5486 "aa/bb/cc/dd/ee/ff",
5487 AS_UNIQUE_ID_MATCH_FLAG_BUNDLE_KIND |
5488 AS_UNIQUE_ID_MATCH_FLAG_ORIGIN |
5489 AS_UNIQUE_ID_MATCH_FLAG_KIND |
5490 AS_UNIQUE_ID_MATCH_FLAG_ID |
5491 AS_UNIQUE_ID_MATCH_FLAG_BRANCH));
5492 }
5493
5494 static void
as_test_store_merge_func(void)5495 as_test_store_merge_func (void)
5496 {
5497 g_autoptr (AsApp) app1 = NULL;
5498 g_autoptr (AsApp) app2 = NULL;
5499 g_autoptr (AsApp) app_merge = NULL;
5500 g_autoptr (AsStore) store = NULL;
5501 g_autoptr (AsFormat) format = NULL;
5502
5503 store = as_store_new ();
5504 as_store_set_add_flags (store,
5505 AS_STORE_ADD_FLAG_USE_UNIQUE_ID |
5506 AS_STORE_ADD_FLAG_USE_MERGE_HEURISTIC);
5507
5508 /* add app */
5509 app1 = as_app_new ();
5510 as_app_set_id (app1, "org.gnome.Software.desktop");
5511 as_app_set_branch (app1, "master");
5512 _as_app_add_format_kind (app1, AS_FORMAT_KIND_APPDATA);
5513 as_app_add_pkgname (app1, "gnome-software");
5514 g_assert_cmpstr (as_app_get_unique_id (app1), ==,
5515 "*/package/*/*/org.gnome.Software.desktop/master");
5516 as_store_add_app (store, app1);
5517
5518 /* add merge component */
5519 app_merge = as_app_new ();
5520 as_app_set_kind (app_merge, AS_APP_KIND_DESKTOP);
5521 as_app_set_id (app_merge, "org.gnome.Software.desktop");
5522 _as_app_add_format_kind (app_merge, AS_FORMAT_KIND_APPSTREAM);
5523 as_app_set_origin (app_merge, "utopia");
5524 as_app_set_scope (app_merge, AS_APP_SCOPE_USER);
5525 as_app_add_category (app_merge, "special");
5526 format = as_format_new ();
5527 as_format_set_filename (format, "DO-NOT-SUBSUME.xml");
5528 as_app_add_format (app_merge, format);
5529 as_store_add_app (store, app_merge);
5530 g_assert_cmpstr (as_app_get_unique_id (app_merge), ==,
5531 "*/*/*/desktop/org.gnome.Software.desktop/*");
5532
5533 /* add app */
5534 app2 = as_app_new ();
5535 as_app_set_id (app2, "org.gnome.Software.desktop");
5536 as_app_set_branch (app2, "stable");
5537 _as_app_add_format_kind (app2, AS_FORMAT_KIND_APPSTREAM);
5538 as_app_add_pkgname (app2, "gnome-software");
5539 g_assert_cmpstr (as_app_get_unique_id (app2), ==,
5540 "*/package/*/*/org.gnome.Software.desktop/stable");
5541 as_store_add_app (store, app2);
5542
5543 /* verify that both apps have the category */
5544 g_assert (as_app_has_category (app1, "special"));
5545 g_assert (as_app_has_category (app2, "special"));
5546
5547 /* verify we didn't inherit the private bits */
5548 g_assert (as_app_get_format_by_kind (app1, AS_FORMAT_KIND_UNKNOWN) == NULL);
5549 g_assert (as_app_get_format_by_kind (app2, AS_FORMAT_KIND_UNKNOWN) == NULL);
5550 }
5551
5552 static void
as_test_store_merge_replace_func(void)5553 as_test_store_merge_replace_func (void)
5554 {
5555 g_autoptr (AsApp) app1 = NULL;
5556 g_autoptr (AsApp) app2 = NULL;
5557 g_autoptr (AsApp) app_merge = NULL;
5558 g_autoptr (AsStore) store = NULL;
5559
5560 store = as_store_new ();
5561 as_store_set_add_flags (store, AS_STORE_ADD_FLAG_USE_UNIQUE_ID);
5562
5563 /* add app */
5564 app1 = as_app_new ();
5565 as_app_set_id (app1, "org.gnome.Software.desktop");
5566 as_app_set_branch (app1, "master");
5567 _as_app_add_format_kind (app1, AS_FORMAT_KIND_APPDATA);
5568 as_app_add_pkgname (app1, "gnome-software");
5569 as_app_add_category (app1, "Family");
5570 as_store_add_app (store, app1);
5571
5572 /* add merge component */
5573 app_merge = as_app_new ();
5574 as_app_set_kind (app_merge, AS_APP_KIND_DESKTOP);
5575 as_app_set_id (app_merge, "org.gnome.Software.desktop");
5576 _as_app_add_format_kind (app_merge, AS_FORMAT_KIND_APPSTREAM);
5577 as_app_set_origin (app_merge, "utopia");
5578 as_app_set_scope (app_merge, AS_APP_SCOPE_USER);
5579 as_app_set_merge_kind (app_merge, AS_APP_MERGE_KIND_REPLACE);
5580 as_app_add_category (app_merge, "Horror");
5581 as_store_add_app (store, app_merge);
5582 g_assert_cmpstr (as_app_get_unique_id (app_merge), ==,
5583 "*/*/*/desktop/org.gnome.Software.desktop/*");
5584
5585 /* add app */
5586 app2 = as_app_new ();
5587 as_app_set_id (app2, "org.gnome.Software.desktop");
5588 as_app_set_branch (app2, "stable");
5589 _as_app_add_format_kind (app2, AS_FORMAT_KIND_APPSTREAM);
5590 as_app_add_pkgname (app2, "gnome-software");
5591 as_app_add_category (app2, "Family");
5592 as_store_add_app (store, app2);
5593
5594 /* verify that both apps have the category */
5595 g_assert (as_app_has_category (app1, "Horror"));
5596 g_assert (as_app_has_category (app2, "Horror"));
5597
5598 /* verify we replaced rather than appended */
5599 g_assert (!as_app_has_category (app1, "Family"));
5600 g_assert (!as_app_has_category (app2, "Family"));
5601 }
5602
5603 static void
as_test_store_merge_then_replace_func(void)5604 as_test_store_merge_then_replace_func (void)
5605 {
5606 g_autoptr (AsApp) app1 = NULL;
5607 g_autoptr (AsApp) app2 = NULL;
5608 g_autoptr (AsApp) app3 = NULL;
5609 g_autoptr (AsStore) store = NULL;
5610
5611 store = as_store_new ();
5612
5613 /* this test case checks that a memory error using app names as keys is fixed */
5614
5615 /* add app */
5616 app1 = as_app_new ();
5617 as_app_set_id (app1, "org.gnome.Software.desktop");
5618 _as_app_add_format_kind (app1, AS_FORMAT_KIND_DESKTOP);
5619 as_app_set_priority (app1, 0);
5620 as_store_add_app (store, app1);
5621 g_clear_object (&app1);
5622
5623 /* add app that merges with the first */
5624 app2 = as_app_new ();
5625 as_app_set_id (app2, "org.gnome.Software.desktop");
5626 _as_app_add_format_kind (app2, AS_FORMAT_KIND_DESKTOP);
5627 as_app_set_priority (app2, 0);
5628 as_store_add_app (store, app2);
5629 g_clear_object (&app2);
5630
5631 /* add app that replaces the second */
5632 app3 = as_app_new ();
5633 as_app_set_id (app3, "org.gnome.Software.desktop");
5634 _as_app_add_format_kind (app3, AS_FORMAT_KIND_DESKTOP);
5635 as_app_set_priority (app3, 1);
5636 as_store_add_app (store, app3);
5637 g_clear_object (&app3);
5638 }
5639
5640 /* shows the unique-id globbing functions at work */
5641 static void
as_test_utils_unique_id_hash_func(void)5642 as_test_utils_unique_id_hash_func (void)
5643 {
5644 AsApp *found;
5645 g_autoptr(AsApp) app1 = NULL;
5646 g_autoptr(AsApp) app2 = NULL;
5647 g_autoptr(GHashTable) hash = NULL;
5648
5649 /* create new couple of apps */
5650 app1 = as_app_new ();
5651 as_app_set_id (app1, "org.gnome.Software.desktop");
5652 as_app_set_branch (app1, "master");
5653 g_assert_cmpstr (as_app_get_unique_id (app1), ==,
5654 "*/*/*/*/org.gnome.Software.desktop/master");
5655 app2 = as_app_new ();
5656 as_app_set_id (app2, "org.gnome.Software.desktop");
5657 as_app_set_branch (app2, "stable");
5658 g_assert_cmpstr (as_app_get_unique_id (app2), ==,
5659 "*/*/*/*/org.gnome.Software.desktop/stable");
5660
5661 /* add to hash table using the unique ID as a key */
5662 hash = g_hash_table_new ((GHashFunc) as_utils_unique_id_hash,
5663 (GEqualFunc) as_utils_unique_id_equal);
5664 g_hash_table_insert (hash, (gpointer) as_app_get_unique_id (app1), app1);
5665 g_hash_table_insert (hash, (gpointer) as_app_get_unique_id (app2), app2);
5666
5667 /* get with exact key */
5668 found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/master");
5669 g_assert (found != NULL);
5670 found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/stable");
5671 g_assert (found != NULL);
5672
5673 /* get with more details specified */
5674 found = g_hash_table_lookup (hash, "system/*/*/*/org.gnome.Software.desktop/master");
5675 g_assert (found != NULL);
5676 found = g_hash_table_lookup (hash, "system/*/*/*/org.gnome.Software.desktop/stable");
5677 g_assert (found != NULL);
5678
5679 /* get with less details specified */
5680 found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/*");
5681 g_assert (found != NULL);
5682
5683 /* different key */
5684 found = g_hash_table_lookup (hash, "*/*/*/*/gimp.desktop/*");
5685 g_assert (found == NULL);
5686
5687 /* different branch */
5688 found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/obsolete");
5689 g_assert (found == NULL);
5690
5691 /* check hash function */
5692 g_assert_cmpint (as_utils_unique_id_hash ("*/*/*/*/gimp.desktop/master"), ==,
5693 as_utils_unique_id_hash ("system/*/*/*/gimp.desktop/stable"));
5694 }
5695
5696 /* shows the as_utils_unique_id_*_safe functions are safe with bare text */
5697 static void
as_test_utils_unique_id_hash_safe_func(void)5698 as_test_utils_unique_id_hash_safe_func (void)
5699 {
5700 AsApp *found;
5701 g_autoptr(AsApp) app = NULL;
5702 g_autoptr(GHashTable) hash = NULL;
5703
5704 /* create new app */
5705 app = as_app_new ();
5706 as_app_set_id (app, "org.gnome.Software.desktop");
5707
5708 /* add to hash table using the unique ID as a key */
5709 hash = g_hash_table_new ((GHashFunc) as_utils_unique_id_hash,
5710 (GEqualFunc) as_utils_unique_id_equal);
5711 g_hash_table_insert (hash, (gpointer) "dave", app);
5712
5713 /* get with exact key */
5714 found = g_hash_table_lookup (hash, "dave");
5715 g_assert (found != NULL);
5716
5717 /* different key */
5718 found = g_hash_table_lookup (hash, "frank");
5719 g_assert (found == NULL);
5720 }
5721
5722 static void
as_test_app_parse_data_func(void)5723 as_test_app_parse_data_func (void)
5724 {
5725 const gchar *data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
5726 "<component>\n</component>\n ";
5727 gboolean ret;
5728 g_autoptr(GBytes) blob = NULL;
5729 g_autoptr(AsApp) app = as_app_new ();
5730 g_autoptr(GError) error = NULL;
5731
5732 blob = g_bytes_new (data, strlen (data));
5733 ret = as_app_parse_data (app, blob, AS_APP_PARSE_FLAG_NONE, &error);
5734 g_assert_no_error (error);
5735 g_assert (ret);
5736 }
5737
5738 static void
as_test_ref_string_func(void)5739 as_test_ref_string_func (void)
5740 {
5741 AsRefString *rstr;
5742
5743 /* basic refcounting */
5744 rstr = as_ref_string_new ("test");
5745 g_assert (rstr != NULL);
5746 g_assert_cmpstr (rstr, ==, "test");
5747 g_assert (as_ref_string_ref (rstr) != NULL);
5748 g_assert (as_ref_string_unref (rstr) != NULL);
5749 g_assert (as_ref_string_unref (rstr) == NULL);
5750 }
5751
5752 int
main(int argc,char ** argv)5753 main (int argc, char **argv)
5754 {
5755 g_test_init (&argc, &argv, NULL);
5756
5757 /* only critical and error are fatal */
5758 g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
5759
5760 /* tests go here */
5761 g_test_add_func ("/AppStream/ref-string", as_test_ref_string_func);
5762 g_test_add_func ("/AppStream/utils{unique_id-hash}", as_test_utils_unique_id_hash_func);
5763 g_test_add_func ("/AppStream/utils{unique_id-hash2}", as_test_utils_unique_id_hash_safe_func);
5764 g_test_add_func ("/AppStream/utils{unique_id}", as_test_utils_unique_id_func);
5765 g_test_add_func ("/AppStream/utils{locale-compat}", as_test_utils_locale_compat_func);
5766 g_test_add_func ("/AppStream/utils{string-replace}", as_test_utils_string_replace_func);
5767 g_test_add_func ("/AppStream/tag", as_test_tag_func);
5768 g_test_add_func ("/AppStream/launchable", as_test_launchable_func);
5769 g_test_add_func ("/AppStream/provide", as_test_provide_func);
5770 g_test_add_func ("/AppStream/require", as_test_require_func);
5771 g_test_add_func ("/AppStream/checksum", as_test_checksum_func);
5772 g_test_add_func ("/AppStream/content_rating", as_test_content_rating_func);
5773 g_test_add_func ("/AppStream/content_rating/empty", as_test_content_rating_empty);
5774 g_test_add_func ("/AppStream/content_rating/mappings", as_test_content_rating_mappings);
5775 g_test_add_func ("/AppStream/content_rating/from-locale", as_test_content_rating_from_locale);
5776 g_test_add_func ("/AppStream/release", as_test_release_func);
5777 g_test_add_func ("/AppStream/release{date}", as_test_release_date_func);
5778 g_test_add_func ("/AppStream/release{appdata}", as_test_release_appdata_func);
5779 g_test_add_func ("/AppStream/release{appstream}", as_test_release_appstream_func);
5780 g_test_add_func ("/AppStream/icon", as_test_icon_func);
5781 g_test_add_func ("/AppStream/icon{scale}", as_test_icon_scale_func);
5782 g_test_add_func ("/AppStream/icon{embedded}", as_test_icon_embedded_func);
5783 g_test_add_func ("/AppStream/bundle", as_test_bundle_func);
5784 g_test_add_func ("/AppStream/review", as_test_review_func);
5785 g_test_add_func ("/AppStream/agreement", as_test_agreement_func);
5786 g_test_add_func ("/AppStream/translation", as_test_translation_func);
5787 g_test_add_func ("/AppStream/suggest", as_test_suggest_func);
5788 g_test_add_func ("/AppStream/image", as_test_image_func);
5789 g_test_add_func ("/AppStream/image{resize}", as_test_image_resize_func);
5790 g_test_add_func ("/AppStream/image{alpha}", as_test_image_alpha_func);
5791 g_test_add_func ("/AppStream/screenshot", as_test_screenshot_func);
5792 g_test_add_func ("/AppStream/app", as_test_app_func);
5793 g_test_add_func ("/AppStream/app{launchable:fallback}", as_test_app_launchable_fallback_func);
5794 g_test_add_func ("/AppStream/app{builder:gettext}", as_test_app_builder_gettext_func);
5795 g_test_add_func ("/AppStream/app{builder:gettext-nodomain}", as_test_app_builder_gettext_nodomain_func);
5796 g_test_add_func ("/AppStream/app{builder:qt}", as_test_app_builder_qt_func);
5797 g_test_add_func ("/AppStream/app{builder:qt-subdir}", as_test_app_builder_qt_subdir_func);
5798 g_test_add_func ("/AppStream/app{translated}", as_test_app_translated_func);
5799 g_test_add_func ("/AppStream/app{validate-style}", as_test_app_validate_style_func);
5800 g_test_add_func ("/AppStream/app{validate-appdata-good}", as_test_app_validate_appdata_good_func);
5801 g_test_add_func ("/AppStream/app{validate-metainfo-good}", as_test_app_validate_metainfo_good_func);
5802 g_test_add_func ("/AppStream/app{validate-file-bad}", as_test_app_validate_file_bad_func);
5803 g_test_add_func ("/AppStream/app{validate-meta-bad}", as_test_app_validate_meta_bad_func);
5804 g_test_add_func ("/AppStream/app{validate-intltool}", as_test_app_validate_intltool_func);
5805 g_test_add_func ("/AppStream/app{parse-data}", as_test_app_parse_data_func);
5806 g_test_add_func ("/AppStream/app{parse-file:desktop}", as_test_app_parse_file_desktop_func);
5807 g_test_add_func ("/AppStream/app{no-markup}", as_test_app_no_markup_func);
5808 g_test_add_func ("/AppStream/app{subsume}", as_test_app_subsume_func);
5809 g_test_add_func ("/AppStream/app{search}", as_test_app_search_func);
5810 g_test_add_func ("/AppStream/app{screenshot}", as_test_app_screenshot_func);
5811 g_test_add_func ("/AppStream/markup{import-html}", as_test_markup_import_html);
5812 g_test_add_func ("/AppStream/node", as_test_node_func);
5813 g_test_add_func ("/AppStream/node{reflow}", as_test_node_reflow_text_func);
5814 g_test_add_func ("/AppStream/node{xml}", as_test_node_xml_func);
5815 g_test_add_func ("/AppStream/node{hash}", as_test_node_hash_func);
5816 g_test_add_func ("/AppStream/node{no-dup-c}", as_test_node_no_dup_c_func);
5817 g_test_add_func ("/AppStream/node{localized}", as_test_node_localized_func);
5818 g_test_add_func ("/AppStream/node{localized-wrap}", as_test_node_localized_wrap_func);
5819 g_test_add_func ("/AppStream/node{localized-wrap2}", as_test_node_localized_wrap2_func);
5820 g_test_add_func ("/AppStream/node{intltool}", as_test_node_intltool_func);
5821 g_test_add_func ("/AppStream/node{sort}", as_test_node_sort_func);
5822 g_test_add_func ("/AppStream/utils", as_test_utils_func);
5823 g_test_add_func ("/AppStream/utils{markup-import}", as_test_utils_markup_import_func);
5824 g_test_add_func ("/AppStream/utils{version}", as_test_utils_version_func);
5825 g_test_add_func ("/AppStream/utils{guid}", as_test_utils_guid_func);
5826 g_test_add_func ("/AppStream/utils{appstream-id}", as_test_utils_appstream_id_func);
5827 g_test_add_func ("/AppStream/utils{icons}", as_test_utils_icons_func);
5828 g_test_add_func ("/AppStream/utils{spdx-token}", as_test_utils_spdx_token_func);
5829 g_test_add_func ("/AppStream/utils{install-filename}", as_test_utils_install_filename_func);
5830 g_test_add_func ("/AppStream/utils{vercmp}", as_test_utils_vercmp_func);
5831 if (g_test_slow ()) {
5832 g_test_add_func ("/AppStream/monitor{dir}", as_test_monitor_dir_func);
5833 g_test_add_func ("/AppStream/monitor{file}", as_test_monitor_file_func);
5834 }
5835 g_test_add_func ("/AppStream/yaml", as_test_yaml_func);
5836 g_test_add_func ("/AppStream/yaml{broken}", as_test_yaml_broken_func);
5837 g_test_add_func ("/AppStream/store", as_test_store_func);
5838 g_test_add_func ("/AppStream/store{unique}", as_test_store_unique_func);
5839 g_test_add_func ("/AppStream/store{merge}", as_test_store_merge_func);
5840 g_test_add_func ("/AppStream/store{merge-replace}", as_test_store_merge_replace_func);
5841 g_test_add_func ("/AppStream/store{merge-then-replace}", as_test_store_merge_then_replace_func);
5842 g_test_add_func ("/AppStream/store{empty}", as_test_store_empty_func);
5843 if (g_test_slow ()) {
5844 g_test_add_func ("/AppStream/store{auto-reload-dir}", as_test_store_auto_reload_dir_func);
5845 g_test_add_func ("/AppStream/store{auto-reload-file}", as_test_store_auto_reload_file_func);
5846 }
5847 g_test_add_func ("/AppStream/store{flatpak}", as_test_store_flatpak_func);
5848 g_test_add_func ("/AppStream/store{prefix}", as_test_store_prefix_func);
5849 g_test_add_func ("/AppStream/store{wildcard}", as_test_store_wildcard_func);
5850 g_test_add_func ("/AppStream/store{demote}", as_test_store_demote_func);
5851 g_test_add_func ("/AppStream/store{merges}", as_test_store_merges_func);
5852 g_test_add_func ("/AppStream/store{merges-local}", as_test_store_merges_local_func);
5853 g_test_add_func ("/AppStream/store{addons}", as_test_store_addons_func);
5854 g_test_add_func ("/AppStream/store{versions}", as_test_store_versions_func);
5855 g_test_add_func ("/AppStream/store{origin}", as_test_store_origin_func);
5856 g_test_add_func ("/AppStream/store{yaml}", as_test_store_yaml_func);
5857 g_test_add_func ("/AppStream/store{metadata}", as_test_store_metadata_func);
5858 g_test_add_func ("/AppStream/store{metadata-index}", as_test_store_metadata_index_func);
5859 g_test_add_func ("/AppStream/store{validate}", as_test_store_validate_func);
5860 g_test_add_func ("/AppStream/store{embedded}", as_test_store_embedded_func);
5861 g_test_add_func ("/AppStream/store{provides}", as_test_store_provides_func);
5862 g_test_add_func ("/AppStream/store{local-appdata}", as_test_store_local_appdata_func);
5863 if (g_test_slow ()) {
5864 g_test_add_func ("/AppStream/store{speed-appstream}", as_test_store_speed_appstream_func);
5865 g_test_add_func ("/AppStream/store{speed-search}", as_test_store_speed_search_func);
5866 g_test_add_func ("/AppStream/store{speed-appdata}", as_test_store_speed_appdata_func);
5867 g_test_add_func ("/AppStream/store{speed-desktop}", as_test_store_speed_desktop_func);
5868 g_test_add_func ("/AppStream/store{speed-yaml}", as_test_store_speed_yaml_func);
5869 }
5870
5871 return g_test_run ();
5872 }
5873