2 * Copyright (C) 2012 Intel Corporation.
3 * Copyright (C) 2013 Jens Georg <mail@jensge.org>
5 * Author: Jens Georg <jensg@openismus.com>
6 * Jens Georg <mail@jensge.org>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include <libgupnp-av/gupnp-media-collection.h>
28 /* Flat DIDL_S playlist */
29 #define TEST_PARSE_COLLECTION_1 \
30 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
32 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" \
33 " xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\"" \
34 " xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"" \
35 " xmlns:pv=\"http://www.pv.com/pvns/\"" \
36 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" \
37 " xsi:schemaLocation=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" \
38 " http://www.upnp.org/schemas/av/didl-lite-v2-20060531.xsd" \
39 " urn:schemas-upnp-org:metadata-1-0/upnp/" \
40 " http://www.upnp.org/schemas/av/upnp-v2-20060531.xsd\">" \
41 " <item id=\"\" parentID=\"0\" restricted=\"0\">" \
42 " <dc:title>Song1</dc:title>" \
43 " <upnp:class>object.item.audioItem</upnp:class>" \
44 " <res protocolInfo=\"*:*:*:*\" />" \
45 " <upnp:artist></upnp:artist>" \
47 " <item id=\"\" parentID=\"0\" restricted=\"0\">" \
48 " <dc:title>Song2</dc:title>" \
49 " <upnp:class>object.item.audioItem</upnp:class>" \
50 " <res protocolInfo=\"*:*:*:*\" />" \
52 " <item id=\"\" parentID=\"0\" restricted=\"0\">" \
53 " <dc:title>Song3</dc:title>" \
54 " <upnp:class>object.item.audioItem</upnp:class>" \
55 " <res protocolInfo=\"*:*:*:*\" />" \
59 /* Nested DIDL_S playlist */
60 #define TEST_PARSE_COLLECTION_2 \
61 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
63 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" \
64 " xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\"" \
65 " xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"" \
66 " xmlns:pv=\"http://www.pv.com/pvns/\"" \
67 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" \
68 " xsi:schemaLocation=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" \
69 " http://www.upnp.org/schemas/av/didl-lite-v2-20060531.xsd" \
70 " urn:schemas-upnp-org:metadata-1-0/upnp/" \
71 " http://www.upnp.org/schemas/av/upnp-v2-20060531.xsd\">" \
72 " <container id=\"1\" parentID=\"0\" restricted=\"0\">" \
73 " <dc:title>NonFlatCollection</dc:title>" \
74 " <dc:creator>NonFlatCollection Author</dc:creator>" \
75 " <item id=\"\" parentID=\"1\" restricted=\"0\">" \
76 " <dc:title>Song1</dc:title>" \
77 " <upnp:class>object.item.audioItem</upnp:class>" \
78 " <res protocolInfo=\"*:*:*:*\" />" \
79 " <upnp:artist></upnp:artist>" \
81 " <item id=\"\" parentID=\"1\" restricted=\"0\">" \
82 " <dc:title>Song2</dc:title>" \
83 " <upnp:class>object.item.audioItem</upnp:class>" \
84 " <res protocolInfo=\"*:*:*:*\" />" \
86 " <item id=\"\" parentID=\"1\" restricted=\"0\">" \
87 " <dc:title>Song3</dc:title>" \
88 " <upnp:class>object.item.audioItem</upnp:class>" \
89 " <res protocolInfo=\"*:*:*:*\" />" \
94 #define TEST_CREATE_FLAT \
96 "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" " \
97 "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" " \
98 "xmlns:pv=\"http://www.pv.com/pvns/\" " \
99 "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">" \
100 "<item restricted=\"1\">" \
101 "<dc:title>Song1</dc:title>" \
102 "<upnp:class>object.item.audioItem</upnp:class>" \
103 "<res>http://example.com/song1.mp3</res>" \
105 "<item restricted=\"1\">" \
106 "<dc:title>Song2</dc:title>" \
107 "<upnp:class>object.item.audioItem</upnp:class>" \
108 "<res>http://example.com/song2.mp3</res>" \
110 "<item restricted=\"1\">" \
111 "<dc:title>Song3</dc:title>" \
112 "<upnp:class>object.item.audioItem</upnp:class>" \
113 "<res>http://example.com/song3.mp3</res>" \
117 #define TEST_CREATE_FULL \
119 "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" " \
120 "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" " \
121 "xmlns:pv=\"http://www.pv.com/pvns/\" " \
122 "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">" \
124 "<dc:title>TestCollection1</dc:title>" \
125 "<dc:creator>TestCollection1Author</dc:creator>" \
126 "<item restricted=\"1\">" \
127 "<dc:title>Song1</dc:title>" \
128 "<upnp:class>object.item.audioItem</upnp:class>" \
129 "<res>http://example.com/song1.mp3</res>" \
131 "<item restricted=\"1\">" \
132 "<dc:title>Song2</dc:title>" \
133 "<upnp:class>object.item.audioItem</upnp:class>" \
134 "<res>http://example.com/song2.mp3</res>" \
136 "<item restricted=\"1\">" \
137 "<dc:title>Song3</dc:title>" \
138 "<upnp:class>object.item.audioItem</upnp:class>" \
139 "<res>http://example.com/song3.mp3</res>" \
144 #define TEST_CREATE_FULL_REPARENT \
146 "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" " \
147 "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" " \
148 "xmlns:pv=\"http://www.pv.com/pvns/\" " \
149 "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">" \
151 "<item restricted=\"1\">" \
152 "<dc:title>Song1</dc:title>" \
153 "<upnp:class>object.item.audioItem</upnp:class>" \
154 "<res>http://example.com/song1.mp3</res>" \
156 "<item restricted=\"1\">" \
157 "<dc:title>Song2</dc:title>" \
158 "<upnp:class>object.item.audioItem</upnp:class>" \
159 "<res>http://example.com/song2.mp3</res>" \
161 "<item restricted=\"1\">" \
162 "<dc:title>Song3</dc:title>" \
163 "<upnp:class>object.item.audioItem</upnp:class>" \
164 "<res>http://example.com/song3.mp3</res>" \
166 "<dc:title>TestCollection1</dc:title>" \
167 "<dc:creator>TestCollection1Author</dc:creator>" \
171 #define TEST_PARSE_NO_XML "This is just some random text"
174 test_didl_collection_construction ()
176 GUPnPMediaCollection *collection;
178 /* Check that a collection created via auxillary function is mutable */
179 collection = gupnp_media_collection_new ();
180 g_assert (gupnp_media_collection_get_mutable (collection));
181 g_object_unref (collection);
183 /* Check that a collection created via auxillary parse function is
185 collection = gupnp_media_collection_new_from_string
186 (TEST_PARSE_COLLECTION_1);
187 g_assert (!gupnp_media_collection_get_mutable (collection));
188 g_object_unref (collection);
190 /* Check that creating a collection via g_object_new and title/author
191 * properties set is mutable */
192 collection = g_object_new (GUPNP_TYPE_MEDIA_COLLECTION,
193 "title", "test01collection",
194 "author", "test01author",
196 g_assert (gupnp_media_collection_get_mutable (collection));
197 g_object_unref (collection);
199 /* Check that creating a collection via g_object_new and data is not
201 collection = g_object_new (GUPNP_TYPE_MEDIA_COLLECTION,
202 "data", TEST_PARSE_COLLECTION_1,
204 g_assert (!gupnp_media_collection_get_mutable (collection));
205 g_object_unref (collection);
207 /* Check that creating a collection with all properties set will result
208 * in a collection that ignored "title" and "author" properties.
210 collection = g_object_new (GUPNP_TYPE_MEDIA_COLLECTION,
211 "title", "test01collection",
212 "author", "test01author",
213 "data", TEST_PARSE_COLLECTION_1,
215 g_assert (!gupnp_media_collection_get_mutable (collection));
216 g_assert_cmpstr (gupnp_media_collection_get_author (collection), ==,
218 g_assert_cmpstr (gupnp_media_collection_get_title (collection), ==,
220 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
221 TEST_PARSE_COLLECTION_1);
222 g_object_unref (collection);
226 test_didl_collection_parse_flat ()
228 GUPnPMediaCollection *collection;
231 collection = gupnp_media_collection_new_from_string
232 (TEST_PARSE_COLLECTION_1);
233 g_assert_cmpstr (gupnp_media_collection_get_author (collection), ==,
235 g_assert_cmpstr (gupnp_media_collection_get_title (collection), ==,
237 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
238 TEST_PARSE_COLLECTION_1);
240 it = items = gupnp_media_collection_get_items (collection);
241 g_assert_cmpint (g_list_length (items), ==, 3);
242 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
245 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
248 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
250 g_list_free_full (items, (GDestroyNotify) g_object_unref);
254 test_didl_collection_parse_full ()
256 GUPnPMediaCollection *collection;
259 collection = gupnp_media_collection_new_from_string
260 (TEST_PARSE_COLLECTION_2);
261 g_assert_cmpstr (gupnp_media_collection_get_author (collection), ==,
262 "NonFlatCollection Author");
263 g_assert_cmpstr (gupnp_media_collection_get_title (collection), ==,
264 "NonFlatCollection");
265 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
266 TEST_PARSE_COLLECTION_2);
268 it = items = gupnp_media_collection_get_items (collection);
269 g_assert_cmpint (g_list_length (items), ==, 3);
270 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
273 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
276 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
278 g_list_free_full (items, (GDestroyNotify) g_object_unref);
281 #define ERROR_MESSAGE "Failed to parse DIDL-Lite: No 'DIDL-Lite' node in the DIDL-Lite XML:"
284 ignore_xml_parse_error (G_GNUC_UNUSED const gchar *log_domain,
285 G_GNUC_UNUSED GLogLevelFlags log_level,
286 const gchar *message,
287 G_GNUC_UNUSED gpointer user_data)
289 if (strncmp (message,
291 g_utf8_strlen (ERROR_MESSAGE, -1) - 1) == 0) {
299 test_didl_collection_parse_invalid ()
301 GUPnPMediaCollection *collection;
304 g_test_log_set_fatal_handler (ignore_xml_parse_error, NULL);
305 collection = gupnp_media_collection_new_from_string (TEST_PARSE_NO_XML);
306 items = gupnp_media_collection_get_items (collection);
308 g_assert (items == NULL);
309 g_object_unref (collection);
313 test_didl_collection_create_flat ()
315 GUPnPMediaCollection *collection;
316 GUPnPDIDLLiteItem *item;
318 GUPnPDIDLLiteResource *res;
320 collection = gupnp_media_collection_new ();
321 item = gupnp_media_collection_add_item (collection);
322 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
324 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
325 "object.item.audioItem");
326 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
327 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song1.mp3");
328 g_object_unref (res);
329 g_object_unref (item);
330 item = gupnp_media_collection_add_item (collection);
331 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
333 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
334 "object.item.audioItem");
335 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
336 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song2.mp3");
337 g_object_unref (res);
338 g_object_unref (item);
339 item = gupnp_media_collection_add_item (collection);
340 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
342 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
343 "object.item.audioItem");
344 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
345 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song3.mp3");
346 g_object_unref (res);
347 g_object_unref (item);
348 it = items = gupnp_media_collection_get_items (collection);
349 g_assert_cmpint (g_list_length (items), ==, 3);
350 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
353 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
356 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
358 g_list_free_full (items, (GDestroyNotify) g_object_unref);
359 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
364 test_didl_collection_create_full ()
366 GUPnPMediaCollection *collection;
367 GUPnPDIDLLiteItem *item;
369 GUPnPDIDLLiteResource *res;
371 collection = gupnp_media_collection_new ();
372 gupnp_media_collection_set_title (collection, "TestCollection1");
373 gupnp_media_collection_set_author (collection, "TestCollection1Author");
375 item = gupnp_media_collection_add_item (collection);
376 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
378 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
379 "object.item.audioItem");
380 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
381 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song1.mp3");
382 g_object_unref (res);
383 g_object_unref (item);
384 item = gupnp_media_collection_add_item (collection);
385 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
387 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
388 "object.item.audioItem");
389 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
390 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song2.mp3");
391 g_object_unref (res);
392 g_object_unref (item);
393 item = gupnp_media_collection_add_item (collection);
394 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
396 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
397 "object.item.audioItem");
398 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
399 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song3.mp3");
400 g_object_unref (res);
401 g_object_unref (item);
402 it = items = gupnp_media_collection_get_items (collection);
403 g_assert_cmpint (g_list_length (items), ==, 3);
404 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
407 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
410 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
412 g_list_free_full (items, (GDestroyNotify) g_object_unref);
413 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
418 test_didl_collection_create_reparent ()
420 GUPnPMediaCollection *collection;
421 GUPnPDIDLLiteItem *item;
423 GUPnPDIDLLiteResource *res;
425 collection = gupnp_media_collection_new ();
427 item = gupnp_media_collection_add_item (collection);
428 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
430 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
431 "object.item.audioItem");
432 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
433 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song1.mp3");
434 g_object_unref (res);
435 g_object_unref (item);
436 item = gupnp_media_collection_add_item (collection);
437 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
439 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
440 "object.item.audioItem");
441 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
442 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song2.mp3");
443 g_object_unref (res);
444 g_object_unref (item);
445 item = gupnp_media_collection_add_item (collection);
446 gupnp_didl_lite_object_set_title (GUPNP_DIDL_LITE_OBJECT (item),
448 gupnp_didl_lite_object_set_upnp_class (GUPNP_DIDL_LITE_OBJECT (item),
449 "object.item.audioItem");
450 res = gupnp_didl_lite_object_add_resource (GUPNP_DIDL_LITE_OBJECT (item));
451 gupnp_didl_lite_resource_set_uri (res, "http://example.com/song3.mp3");
452 g_object_unref (res);
453 g_object_unref (item);
454 it = items = gupnp_media_collection_get_items (collection);
456 /* Force reparenting of the items in the XML */
457 gupnp_media_collection_set_title (collection, "TestCollection1");
458 gupnp_media_collection_set_author (collection, "TestCollection1Author");
460 g_assert_cmpint (g_list_length (items), ==, 3);
461 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
464 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
467 g_assert_cmpstr (gupnp_didl_lite_object_get_title (GUPNP_DIDL_LITE_OBJECT (it->data)), ==,
469 g_list_free_full (items, (GDestroyNotify) g_object_unref);
471 g_assert_cmpstr (gupnp_media_collection_get_string (collection), ==,
472 TEST_CREATE_FULL_REPARENT);
475 int main (int argc, char *argv[])
477 #if !GLIB_CHECK_VERSION (2, 35, 0)
480 g_test_init (&argc, &argv, NULL);
482 g_test_add_func ("/didl/collection/construction",
483 test_didl_collection_construction);
484 g_test_add_func ("/didl/collection/parse_flat",
485 test_didl_collection_parse_flat);
486 g_test_add_func ("/didl/collection/parse_full",
487 test_didl_collection_parse_full);
488 g_test_add_func ("/didl/collection/parse_invalid",
489 test_didl_collection_parse_invalid);
491 g_test_add_func ("/didl/collection/create_flat",
492 test_didl_collection_create_flat);
493 g_test_add_func ("/didl/collection/create_full",
494 test_didl_collection_create_full);
495 g_test_add_func ("/didl/collection/create_reparent",
496 test_didl_collection_create_reparent);
498 return g_test_run ();