tests: turn toc check macros into proper functions
[platform/upstream/gstreamer.git] / tests / check / gst / gsttocsetter.c
1 /* GStreamer GstTocSetter interface unit tests
2  * Copyright (C) 2010, 2012 Alexander Saprykin <xelfium@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gst/check/gstcheck.h>
21 #include <gst/gst.h>
22 #include <string.h>
23
24 #define ENTRY_ED1       "/edition1"
25 #define ENTRY_ED2       "/edition2"
26 #define ENTRY_ED3       "test-edition"
27
28 #define ENTRY_CH1       "/edition1/chapter1"
29 #define ENTRY_CH2       "/edition1/chapter2"
30 #define ENTRY_CH3       "/edition2/chapter3"
31 #define ENTRY_CH4       "/test-chapter"
32
33 #define ENTRY_SUB1      "/edition2/chapter3/subchapter1"
34
35 #define ENTRY_TAG       "EntryTag"
36 #define TOC_TAG         "TocTag"
37
38 static void
39 CHECK_TOC_ENTRY (GstTocEntry * entry_c, GstTocEntryType type_c,
40     const gchar * uid_c)
41 {
42   GstTagList *tags;
43   gchar *tag_c;
44
45   fail_unless_equals_string (gst_toc_entry_get_uid (entry_c), uid_c);
46   fail_unless (gst_toc_entry_get_entry_type (entry_c) == type_c);
47
48   tags = gst_toc_entry_get_tags (entry_c);
49   fail_unless (tags != NULL);
50   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_c));
51   fail_unless_equals_string (tag_c, ENTRY_TAG);
52   g_free (tag_c);
53 }
54
55 static void
56 CHECK_TOC (GstToc * toc_t)
57 {
58   GstTocEntry *entry_t, *subentry_t;
59   GstTagList *tags;
60   GList *entries, *subentries, *subsubentries;
61   gchar *tag_t;
62
63   /* dump TOC */
64   gst_toc_dump (toc_t);
65
66   /* check TOC */
67   tags = gst_toc_get_tags (toc_t);
68   fail_unless (tags != NULL);
69   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_t));
70   fail_unless_equals_string (tag_t, TOC_TAG);
71   g_free (tag_t);
72
73   entries = gst_toc_get_entries (toc_t);
74   fail_unless_equals_int (g_list_length (entries), 2);
75   /* check edition1 */
76   entry_t = g_list_nth_data (entries, 0);
77   fail_if (entry_t == NULL);
78   subentries = gst_toc_entry_get_sub_entries (entry_t);
79   fail_unless_equals_int (g_list_length (subentries), 2);
80   CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1);
81   /* check chapter1 */
82   subentry_t = g_list_nth_data (subentries, 0);
83   fail_if (subentry_t == NULL);
84   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
85   fail_unless_equals_int (g_list_length (subsubentries), 0);
86   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1);
87   /* check chapter2 */
88   subentry_t = g_list_nth_data (subentries, 1);
89   fail_if (subentry_t == NULL);
90   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
91   fail_unless_equals_int (g_list_length (subsubentries), 0);
92   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2);
93   /* check edition2 */
94   entry_t = g_list_nth_data (entries, 1);
95   fail_if (entry_t == NULL);
96   subentries = gst_toc_entry_get_sub_entries (entry_t);
97   fail_unless_equals_int (g_list_length (subentries), 1);
98   CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2);
99   /* check chapter3 */
100   subentry_t = g_list_nth_data (subentries, 0);
101   fail_if (subentry_t == NULL);
102   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
103   fail_unless_equals_int (g_list_length (subsubentries), 1);
104   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3);
105   /* check subchapter1 */
106   subentry_t = g_list_nth_data (subentries, 0);
107   fail_if (subentry_t == NULL);
108   GST_ERROR ("%s", gst_toc_entry_get_uid (subentry_t));
109   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
110   GST_ERROR ("%p", subsubentries);
111   fail_unless_equals_int (g_list_length (subsubentries), 0);
112   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1);
113 }
114
115 /* some minimal GstTocSetter object */
116 #define GST_TYPE_DUMMY_ENC gst_dummy_enc_get_type()
117
118 typedef GstElement GstDummyEnc;
119 typedef GstElementClass GstDummyEncClass;
120
121 GType gst_dummy_enc_get_type (void);
122 G_DEFINE_TYPE_WITH_CODE (GstDummyEnc, gst_dummy_enc,
123     GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_TOC_SETTER, NULL));
124
125 static void
126 gst_dummy_enc_class_init (GstDummyEncClass * klass)
127 {
128 }
129
130 static void
131 gst_dummy_enc_init (GstDummyEnc * enc)
132 {
133 }
134
135 static GstToc *
136 create_toc (void)
137 {
138   GstToc *toc;
139   GstTocEntry *ed, *ch, *subch;
140   GstTagList *tags;
141
142   toc = gst_toc_new ();
143   tags = gst_tag_list_new_empty ();
144   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, TOC_TAG, NULL);
145   gst_toc_set_tags (toc, tags);
146
147   /* create edition1 */
148   ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1);
149   tags = gst_tag_list_new_empty ();
150   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
151   gst_toc_entry_set_tags (ed, tags);
152
153   /* append chapter1 to edition1 */
154   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1);
155   tags = gst_tag_list_new_empty ();
156   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
157   gst_toc_entry_set_tags (ch, tags);
158
159   gst_toc_entry_append_sub_entry (ed, ch);
160
161   /* append chapter2 to edition1 */
162   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2);
163   tags = gst_tag_list_new_empty ();
164   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
165   gst_toc_entry_set_tags (ch, tags);
166
167   gst_toc_entry_append_sub_entry (ed, ch);
168
169   /* append edition1 to the TOC */
170   gst_toc_append_entry (toc, ed);
171
172   /* create edition2 */
173   ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2);
174   tags = gst_tag_list_new_empty ();
175   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
176   gst_toc_entry_set_tags (ed, tags);
177
178   /* create chapter3 */
179   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3);
180   tags = gst_tag_list_new_empty ();
181   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
182   gst_toc_entry_set_tags (ch, tags);
183
184   /* create subchapter1 */
185   subch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1);
186   tags = gst_tag_list_new_empty ();
187   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
188   gst_toc_entry_set_tags (subch, tags);
189
190   /* append subchapter1 to chapter3 */
191   gst_toc_entry_append_sub_entry (ch, subch);
192
193   /* append chapter3 to edition2 */
194   gst_toc_entry_append_sub_entry (ed, ch);
195
196   /* finally append edition2 to the TOC */
197   gst_toc_append_entry (toc, ed);
198
199   return toc;
200 }
201
202 GST_START_TEST (test_set)
203 {
204   GstToc *toc;
205 #if 0
206   GstTocEntry *entry, *ed;
207 #endif
208   GstTocSetter *setter;
209   GstElement *enc;
210
211   enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL);
212   fail_unless (enc != NULL);
213
214   setter = GST_TOC_SETTER (enc);
215
216   toc = create_toc ();
217   fail_unless (toc != NULL);
218
219   gst_toc_setter_set_toc (setter, toc);
220
221   gst_toc_unref (toc);
222   toc = gst_toc_setter_get_toc (setter);
223
224   CHECK_TOC (toc);
225
226 #if 0
227   /* test entry adding into the root TOC */
228   entry = g_list_last (toc->entries)->data;
229   toc->entries = g_list_remove (toc->entries, entry);
230
231   gst_toc_setter_set_toc (setter, toc);
232   gst_toc_setter_add_toc_entry (setter, "0", entry);
233
234   gst_toc_unref (toc);
235   gst_toc_entry_unref (entry);
236   toc = gst_toc_setter_get_toc (setter);
237
238   CHECK_TOC (toc);
239 #endif
240
241 #if 0
242   /* test entry adding into the arbitrary entry */
243   entry = gst_toc_find_entry (toc, ENTRY_CH2);
244   fail_if (entry == NULL);
245
246   ed = toc->entries->data;
247   ed->subentries = g_list_remove (ed->subentries, entry);
248
249   gst_toc_setter_add_toc_entry (setter, ed->uid, entry);
250
251   CHECK_TOC (toc);
252 #endif
253
254   gst_toc_unref (toc);
255   gst_toc_setter_reset (setter);
256   toc = gst_toc_setter_get_toc (setter);
257
258   fail_unless (toc == NULL);
259
260   g_object_unref (enc);
261 }
262
263 GST_END_TEST static int spin_and_wait = 1;
264 static int threads_running = 0;
265
266 #define THREADS_TEST_SECONDS 1.5
267
268 static gpointer
269 test_threads_thread_func1 (gpointer data)
270 {
271   GstToc *toc;
272   GstTocSetter *setter = GST_TOC_SETTER (data);
273   GTimer *timer;
274
275   toc = create_toc ();
276   timer = g_timer_new ();
277
278   g_atomic_int_inc (&threads_running);
279   while (g_atomic_int_get (&spin_and_wait))
280     g_usleep (0);
281
282   GST_INFO ("Go!");
283   g_timer_start (timer);
284
285   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS)
286     gst_toc_setter_set_toc (setter, toc);
287
288   gst_toc_unref (toc);
289   g_timer_destroy (timer);
290   GST_INFO ("Done");
291
292   return NULL;
293 }
294
295 static gpointer
296 test_threads_thread_func2 (gpointer data)
297 {
298   GstToc *toc;
299   GstTocSetter *setter = GST_TOC_SETTER (data);
300   GTimer *timer;
301
302   toc = create_toc ();
303   timer = g_timer_new ();
304
305   g_atomic_int_inc (&threads_running);
306   while (g_atomic_int_get (&spin_and_wait))
307     g_usleep (0);
308
309   GST_INFO ("Go!");
310   g_timer_start (timer);
311
312   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS)
313     gst_toc_setter_set_toc (setter, toc);
314
315   gst_toc_unref (toc);
316   g_timer_destroy (timer);
317   GST_INFO ("Done");
318
319   return NULL;
320 }
321
322 static gpointer
323 test_threads_thread_func3 (gpointer data)
324 {
325   GstTocSetter *setter = GST_TOC_SETTER (data);
326   GTimer *timer;
327
328   timer = g_timer_new ();
329
330   g_atomic_int_inc (&threads_running);
331   while (g_atomic_int_get (&spin_and_wait))
332     g_usleep (0);
333
334   GST_INFO ("Go!");
335   g_timer_start (timer);
336
337   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) {
338     gst_toc_setter_reset (setter);
339   }
340
341   g_timer_destroy (timer);
342   GST_INFO ("Done");
343
344   return NULL;
345 }
346
347 GST_START_TEST (test_threads)
348 {
349   GstTocSetter *setter;
350   GThread *threads[3];
351
352   setter = GST_TOC_SETTER (g_object_new (GST_TYPE_DUMMY_ENC, NULL));
353
354   spin_and_wait = TRUE;
355   threads[0] = g_thread_create (test_threads_thread_func1, setter, TRUE, NULL);
356   threads[1] = g_thread_create (test_threads_thread_func2, setter, TRUE, NULL);
357   threads[2] = g_thread_create (test_threads_thread_func3, setter, TRUE, NULL);
358
359   while (g_atomic_int_get (&threads_running) < 3)
360     g_usleep (10);
361
362   g_atomic_int_set (&spin_and_wait, FALSE);
363
364   g_thread_join (threads[0]);
365   g_thread_join (threads[1]);
366   g_thread_join (threads[2]);
367
368   g_object_unref (G_OBJECT (setter));
369 }
370
371 GST_END_TEST static Suite *
372 gst_toc_setter_suite (void)
373 {
374   Suite *s = suite_create ("GstTocSetter");
375   TCase *tc_chain = tcase_create ("general");
376
377   suite_add_tcase (s, tc_chain);
378   tcase_add_test (tc_chain, test_set);
379   tcase_add_test (tc_chain, test_threads);
380
381   return s;
382 }
383
384 GST_CHECK_MAIN (gst_toc_setter);