• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include <gst/check/gstcheck.h>
24 #include <gst/gst.h>
25 #include <string.h>
26 
27 #define ENTRY_ED1       "/edition1"
28 #define ENTRY_ED2       "/edition2"
29 #define ENTRY_ED3       "test-edition"
30 
31 #define ENTRY_CH1       "/edition1/chapter1"
32 #define ENTRY_CH2       "/edition1/chapter2"
33 #define ENTRY_CH3       "/edition2/chapter3"
34 #define ENTRY_CH4       "/test-chapter"
35 
36 #define ENTRY_SUB1      "/edition2/chapter3/subchapter1"
37 
38 #define ENTRY_TAG       "EntryTag"
39 #define TOC_TAG         "TocTag"
40 
41 static void
CHECK_TOC_ENTRY(GstTocEntry * entry_c,GstTocEntryType type_c,const gchar * uid_c)42 CHECK_TOC_ENTRY (GstTocEntry * entry_c, GstTocEntryType type_c,
43     const gchar * uid_c)
44 {
45   GstTagList *tags;
46   gchar *tag_c;
47 
48   fail_unless_equals_string (gst_toc_entry_get_uid (entry_c), uid_c);
49   fail_unless (gst_toc_entry_get_entry_type (entry_c) == type_c);
50 
51   tags = gst_toc_entry_get_tags (entry_c);
52   fail_unless (tags != NULL);
53   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_c));
54   fail_unless_equals_string (tag_c, ENTRY_TAG);
55   g_free (tag_c);
56 }
57 
58 static void
CHECK_TOC(GstToc * toc_t)59 CHECK_TOC (GstToc * toc_t)
60 {
61   GstTocEntry *entry_t, *subentry_t;
62   GstTagList *tags;
63   GList *entries, *subentries, *subsubentries;
64   gchar *tag_t;
65 
66   /* dump TOC */
67   gst_toc_dump (toc_t);
68 
69   /* check TOC */
70   tags = gst_toc_get_tags (toc_t);
71   fail_unless (tags != NULL);
72   fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &tag_t));
73   fail_unless_equals_string (tag_t, TOC_TAG);
74   g_free (tag_t);
75 
76   entries = gst_toc_get_entries (toc_t);
77   fail_unless_equals_int (g_list_length (entries), 2);
78   /* check edition1 */
79   entry_t = g_list_nth_data (entries, 0);
80   fail_if (entry_t == NULL);
81   subentries = gst_toc_entry_get_sub_entries (entry_t);
82   fail_unless_equals_int (g_list_length (subentries), 2);
83   CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1);
84   /* check chapter1 */
85   subentry_t = g_list_nth_data (subentries, 0);
86   fail_if (subentry_t == NULL);
87   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
88   fail_unless_equals_int (g_list_length (subsubentries), 0);
89   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1);
90   /* check chapter2 */
91   subentry_t = g_list_nth_data (subentries, 1);
92   fail_if (subentry_t == NULL);
93   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
94   fail_unless_equals_int (g_list_length (subsubentries), 0);
95   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2);
96   /* check edition2 */
97   entry_t = g_list_nth_data (entries, 1);
98   fail_if (entry_t == NULL);
99   subentries = gst_toc_entry_get_sub_entries (entry_t);
100   fail_unless_equals_int (g_list_length (subentries), 1);
101   CHECK_TOC_ENTRY (entry_t, GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2);
102   /* check chapter3 */
103   subentry_t = g_list_nth_data (subentries, 0);
104   fail_if (subentry_t == NULL);
105   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
106   fail_unless_equals_int (g_list_length (subsubentries), 1);
107   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3);
108   /* check subchapter1 */
109   subentry_t = g_list_nth_data (subsubentries, 0);
110   fail_if (subentry_t == NULL);
111   subsubentries = gst_toc_entry_get_sub_entries (subentry_t);
112   fail_unless_equals_int (g_list_length (subsubentries), 0);
113   CHECK_TOC_ENTRY (subentry_t, GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1);
114 }
115 
116 /* some minimal GstTocSetter object */
117 #define GST_TYPE_DUMMY_ENC gst_dummy_enc_get_type()
118 
119 typedef GstElement GstDummyEnc;
120 typedef GstElementClass GstDummyEncClass;
121 
122 GType gst_dummy_enc_get_type (void);
123 G_DEFINE_TYPE_WITH_CODE (GstDummyEnc, gst_dummy_enc,
124     GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_TOC_SETTER, NULL));
125 
126 static void
gst_dummy_enc_class_init(GstDummyEncClass * klass)127 gst_dummy_enc_class_init (GstDummyEncClass * klass)
128 {
129 }
130 
131 static void
gst_dummy_enc_init(GstDummyEnc * enc)132 gst_dummy_enc_init (GstDummyEnc * enc)
133 {
134 }
135 
136 static GstToc *
create_toc(void)137 create_toc (void)
138 {
139   GstToc *toc;
140   GstTocEntry *ed, *ch, *subch;
141   GstTagList *tags;
142 
143   toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
144   tags = gst_tag_list_new_empty ();
145   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, TOC_TAG, NULL);
146   gst_toc_set_tags (toc, tags);
147 
148   /* create edition1 */
149   ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED1);
150   tags = gst_tag_list_new_empty ();
151   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
152   gst_toc_entry_set_tags (ed, tags);
153 
154   /* append chapter1 to edition1 */
155   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH1);
156   tags = gst_tag_list_new_empty ();
157   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
158   gst_toc_entry_set_tags (ch, tags);
159 
160   gst_toc_entry_append_sub_entry (ed, ch);
161 
162   /* append chapter2 to edition1 */
163   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH2);
164   tags = gst_tag_list_new_empty ();
165   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
166   gst_toc_entry_set_tags (ch, tags);
167 
168   gst_toc_entry_append_sub_entry (ed, ch);
169 
170   /* append edition1 to the TOC */
171   gst_toc_append_entry (toc, ed);
172 
173   /* create edition2 */
174   ed = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, ENTRY_ED2);
175   tags = gst_tag_list_new_empty ();
176   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
177   gst_toc_entry_set_tags (ed, tags);
178 
179   /* create chapter3 */
180   ch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_CH3);
181   tags = gst_tag_list_new_empty ();
182   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
183   gst_toc_entry_set_tags (ch, tags);
184 
185   /* create subchapter1 */
186   subch = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, ENTRY_SUB1);
187   tags = gst_tag_list_new_empty ();
188   gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, ENTRY_TAG, NULL);
189   gst_toc_entry_set_tags (subch, tags);
190 
191   /* append subchapter1 to chapter3 */
192   gst_toc_entry_append_sub_entry (ch, subch);
193 
194   /* append chapter3 to edition2 */
195   gst_toc_entry_append_sub_entry (ed, ch);
196 
197   /* finally append edition2 to the TOC */
198   gst_toc_append_entry (toc, ed);
199 
200   return toc;
201 }
202 
GST_START_TEST(test_set)203 GST_START_TEST (test_set)
204 {
205   GstToc *toc;
206 #if 0
207   GstTocEntry *entry, *ed;
208 #endif
209   GstTocSetter *setter;
210   GstElement *enc;
211 
212   enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL);
213   fail_unless (enc != NULL);
214 
215   setter = GST_TOC_SETTER (enc);
216 
217   toc = create_toc ();
218   fail_unless (toc != NULL);
219 
220   gst_toc_setter_set_toc (setter, toc);
221 
222   gst_toc_unref (toc);
223   toc = gst_toc_setter_get_toc (setter);
224 
225   CHECK_TOC (toc);
226 
227 #if 0
228   /* test entry adding into the root TOC */
229   entry = g_list_last (toc->entries)->data;
230   toc->entries = g_list_remove (toc->entries, entry);
231 
232   gst_toc_setter_set_toc (setter, toc);
233   gst_toc_setter_add_toc_entry (setter, "0", entry);
234 
235   gst_toc_unref (toc);
236   gst_toc_entry_unref (entry);
237   toc = gst_toc_setter_get_toc (setter);
238 
239   CHECK_TOC (toc);
240 #endif
241 
242 #if 0
243   /* test entry adding into the arbitrary entry */
244   entry = gst_toc_find_entry (toc, ENTRY_CH2);
245   fail_if (entry == NULL);
246 
247   ed = toc->entries->data;
248   ed->subentries = g_list_remove (ed->subentries, entry);
249 
250   gst_toc_setter_add_toc_entry (setter, ed->uid, entry);
251 
252   CHECK_TOC (toc);
253 #endif
254 
255   gst_toc_unref (toc);
256   gst_toc_setter_reset (setter);
257   toc = gst_toc_setter_get_toc (setter);
258 
259   fail_unless (toc == NULL);
260 
261   gst_object_unref (enc);
262 }
263 
264 GST_END_TEST static int spin_and_wait = 1;
265 static int threads_running = 0;
266 
267 #define THREADS_TEST_SECONDS 1.5
268 
269 static gpointer
test_threads_thread_func1(gpointer data)270 test_threads_thread_func1 (gpointer data)
271 {
272   GstToc *toc;
273   GstTocSetter *setter = GST_TOC_SETTER (data);
274   GTimer *timer;
275 
276   toc = create_toc ();
277   timer = g_timer_new ();
278 
279   g_atomic_int_inc (&threads_running);
280   while (g_atomic_int_get (&spin_and_wait))
281     g_usleep (0);
282 
283   GST_INFO ("Go!");
284   g_timer_start (timer);
285 
286   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS)
287     gst_toc_setter_set_toc (setter, toc);
288 
289   gst_toc_unref (toc);
290   g_timer_destroy (timer);
291   GST_INFO ("Done");
292 
293   return NULL;
294 }
295 
296 static gpointer
test_threads_thread_func2(gpointer data)297 test_threads_thread_func2 (gpointer data)
298 {
299   GstToc *toc;
300   GstTocSetter *setter = GST_TOC_SETTER (data);
301   GTimer *timer;
302 
303   toc = create_toc ();
304   timer = g_timer_new ();
305 
306   g_atomic_int_inc (&threads_running);
307   while (g_atomic_int_get (&spin_and_wait))
308     g_usleep (0);
309 
310   GST_INFO ("Go!");
311   g_timer_start (timer);
312 
313   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS)
314     gst_toc_setter_set_toc (setter, toc);
315 
316   gst_toc_unref (toc);
317   g_timer_destroy (timer);
318   GST_INFO ("Done");
319 
320   return NULL;
321 }
322 
323 static gpointer
test_threads_thread_func3(gpointer data)324 test_threads_thread_func3 (gpointer data)
325 {
326   GstTocSetter *setter = GST_TOC_SETTER (data);
327   GTimer *timer;
328 
329   timer = g_timer_new ();
330 
331   g_atomic_int_inc (&threads_running);
332   while (g_atomic_int_get (&spin_and_wait))
333     g_usleep (0);
334 
335   GST_INFO ("Go!");
336   g_timer_start (timer);
337 
338   while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) {
339     gst_toc_setter_reset (setter);
340   }
341 
342   g_timer_destroy (timer);
343   GST_INFO ("Done");
344 
345   return NULL;
346 }
347 
GST_START_TEST(test_threads)348 GST_START_TEST (test_threads)
349 {
350   GstTocSetter *setter;
351   GThread *threads[3];
352 
353   setter = GST_TOC_SETTER (g_object_new (GST_TYPE_DUMMY_ENC, NULL));
354 
355   spin_and_wait = TRUE;
356   threads[0] = g_thread_try_new ("gst-check", test_threads_thread_func1,
357       setter, NULL);
358   threads[1] = g_thread_try_new ("gst-check", test_threads_thread_func2,
359       setter, NULL);
360   threads[2] = g_thread_try_new ("gst-check", test_threads_thread_func3,
361       setter, NULL);
362 
363   while (g_atomic_int_get (&threads_running) < 3)
364     g_usleep (10);
365 
366   g_atomic_int_set (&spin_and_wait, FALSE);
367 
368   g_thread_join (threads[0]);
369   g_thread_join (threads[1]);
370   g_thread_join (threads[2]);
371 
372   gst_object_unref (setter);
373 }
374 
375 GST_END_TEST static Suite *
gst_toc_setter_suite(void)376 gst_toc_setter_suite (void)
377 {
378   Suite *s = suite_create ("GstTocSetter");
379   TCase *tc_chain = tcase_create ("general");
380 
381   suite_add_tcase (s, tc_chain);
382   tcase_add_test (tc_chain, test_set);
383   tcase_add_test (tc_chain, test_threads);
384 
385   return s;
386 }
387 
388 GST_CHECK_MAIN (gst_toc_setter);
389