1 /* GStreamer unit tests for discoverer
2  *
3  * Copyright (C) 2011 Stefan Kost <ensonic@users.sf.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24 
25 #include <gst/check/gstcheck.h>
26 #include <gst/pbutils/pbutils.h>
27 
28 #include <stdio.h>
29 #include <glib/gstdio.h>
30 #include <glib/gprintf.h>
31 
32 static gboolean have_theora, have_ogg;
33 
GST_START_TEST(test_disco_init)34 GST_START_TEST (test_disco_init)
35 {
36   GError *err = NULL;
37   GstDiscoverer *dc;
38 
39   dc = gst_discoverer_new (GST_SECOND, &err);
40   fail_unless (dc != NULL);
41   fail_unless (err == NULL);
42 
43   g_object_unref (dc);
44 }
45 
46 GST_END_TEST;
47 
GST_START_TEST(test_disco_serializing)48 GST_START_TEST (test_disco_serializing)
49 {
50   GError *err = NULL;
51   GstDiscoverer *dc;
52   GstDiscovererInfo *info, *dinfo;
53   gchar *uri;
54   GVariant *serialized, *reserialized;
55   GList *audio_streams;
56   gchar *path =
57       g_build_filename (GST_TEST_FILES_PATH, "theora-vorbis.ogg", NULL);
58 
59   /* high timeout, in case we're running under valgrind */
60   dc = gst_discoverer_new (30 * GST_SECOND, &err);
61   fail_unless (dc != NULL);
62   fail_unless (err == NULL);
63 
64   uri = gst_filename_to_uri (path, &err);
65   g_free (path);
66   fail_unless (err == NULL);
67 
68   info = gst_discoverer_discover_uri (dc, uri, &err);
69   fail_unless (info);
70   if (have_theora && have_ogg) {
71     fail_unless_equals_int (gst_discoverer_info_get_result (info),
72         GST_DISCOVERER_OK);
73   } else {
74     fail_unless_equals_int (gst_discoverer_info_get_result (info),
75         GST_DISCOVERER_MISSING_PLUGINS);
76     g_clear_error (&err);
77     goto missing_plugins;
78   }
79   serialized =
80       gst_discoverer_info_to_variant (info, GST_DISCOVERER_SERIALIZE_ALL);
81 
82 
83   fail_unless (serialized);
84   dinfo = gst_discoverer_info_from_variant (serialized);
85 
86   fail_unless (dinfo);
87   audio_streams = gst_discoverer_info_get_audio_streams (dinfo);
88   fail_unless_equals_int (g_list_length (audio_streams), 1);
89   gst_discoverer_stream_info_list_free (audio_streams);
90 
91   reserialized =
92       gst_discoverer_info_to_variant (dinfo, GST_DISCOVERER_SERIALIZE_ALL);
93 
94   fail_unless (g_variant_equal (serialized, reserialized));
95 
96   gst_discoverer_info_unref (dinfo);
97   g_variant_unref (serialized);
98   g_variant_unref (reserialized);
99 
100 missing_plugins:
101 
102   gst_discoverer_info_unref (info);
103   g_object_unref (dc);
104   g_free (uri);
105 }
106 
107 GST_END_TEST;
108 
GST_START_TEST(test_disco_sync)109 GST_START_TEST (test_disco_sync)
110 {
111   GError *err = NULL;
112   GstDiscoverer *dc;
113   GstDiscovererInfo *info;
114   GstDiscovererResult result;
115   gchar *uri;
116 
117   /* high timeout, in case we're running under valgrind */
118   dc = gst_discoverer_new (30 * GST_SECOND, &err);
119   fail_unless (dc != NULL);
120   fail_unless (err == NULL);
121 
122   /* GST_TEST_FILE comes from makefile CFLAGS */
123   GST_INFO ("discovering file '%s'", GST_TEST_FILE);
124   uri = g_filename_to_uri (GST_TEST_FILE, NULL, &err);
125   fail_unless (err == NULL);
126   GST_INFO ("discovering uri '%s'", uri);
127 
128   info = gst_discoverer_discover_uri (dc, uri, &err);
129   result = gst_discoverer_info_get_result (info);
130   GST_INFO ("result: %d", result);
131   gst_discoverer_info_unref (info);
132   g_free (uri);
133 
134   if (err) {
135     /* we won't have the codec for the jpeg */
136     g_error_free (err);
137   }
138 
139   g_object_unref (dc);
140 }
141 
142 GST_END_TEST;
143 static void
test_disco_sync_reuse(const gchar * test_fn,guint num,GstClockTime timeout)144 test_disco_sync_reuse (const gchar * test_fn, guint num, GstClockTime timeout)
145 {
146   GError *err = NULL;
147   GstDiscoverer *dc;
148   GstDiscovererInfo *info;
149   GstDiscovererResult result;
150   gchar *uri, *path;
151   int i;
152 
153   dc = gst_discoverer_new (timeout, &err);
154   fail_unless (dc != NULL);
155   fail_unless (err == NULL);
156 
157   /* GST_TEST_FILE comes from makefile CFLAGS */
158   path = g_build_filename (GST_TEST_FILES_PATH, test_fn, NULL);
159   uri = gst_filename_to_uri (path, &err);
160   g_free (path);
161   fail_unless (err == NULL);
162 
163   for (i = 0; i < num; ++i) {
164     GST_INFO ("[%02d] discovering uri '%s'", i, uri);
165     info = gst_discoverer_discover_uri (dc, uri, &err);
166     if (info) {
167       result = gst_discoverer_info_get_result (info);
168       GST_INFO ("result: %d", result);
169       gst_discoverer_info_unref (info);
170     }
171     /* in case we don't have some of the elements needed */
172     if (err) {
173       g_error_free (err);
174       err = NULL;
175     }
176   }
177   g_free (uri);
178 
179   g_object_unref (dc);
180 }
181 
GST_START_TEST(test_disco_sync_reuse_ogg)182 GST_START_TEST (test_disco_sync_reuse_ogg)
183 {
184   test_disco_sync_reuse ("theora-vorbis.ogg", 2, 10 * GST_SECOND);
185 }
186 
187 GST_END_TEST;
188 
GST_START_TEST(test_disco_sync_reuse_mp3)189 GST_START_TEST (test_disco_sync_reuse_mp3)
190 {
191   /* this will cause errors because -base doesn't do mp3 parsing or decoding */
192   test_disco_sync_reuse ("test.mp3", 3, 10 * GST_SECOND);
193 }
194 
195 GST_END_TEST;
196 
GST_START_TEST(test_disco_sync_reuse_timeout)197 GST_START_TEST (test_disco_sync_reuse_timeout)
198 {
199   /* set minimum timeout to test that, esp. leakage under valgrind */
200   /* FIXME: should really be even shorter */
201   test_disco_sync_reuse ("theora-vorbis.ogg", 2, GST_SECOND);
202 }
203 
204 GST_END_TEST;
205 
GST_START_TEST(test_disco_missing_plugins)206 GST_START_TEST (test_disco_missing_plugins)
207 {
208   const gchar *files[] = { "test.mkv", "test.mp3", "partialframe.mjpeg" };
209   GError *err = NULL;
210   GstDiscoverer *dc;
211   GstDiscovererInfo *info;
212   GstDiscovererResult result;
213   gchar *uri, *path;
214   int i;
215 
216   for (i = 0; i < G_N_ELEMENTS (files); ++i) {
217     dc = gst_discoverer_new (5 * GST_SECOND, &err);
218     fail_unless (dc != NULL);
219     fail_unless (err == NULL);
220 
221     /* GST_TEST_FILE comes from makefile CFLAGS */
222     path = g_build_filename (GST_TEST_FILES_PATH, files[i], NULL);
223     uri = gst_filename_to_uri (path, &err);
224     g_free (path);
225     fail_unless (err == NULL);
226 
227     GST_INFO ("discovering uri '%s'", uri);
228     info = gst_discoverer_discover_uri (dc, uri, &err);
229     fail_unless (info != NULL);
230     fail_unless (err != NULL);
231     result = gst_discoverer_info_get_result (info);
232     GST_INFO ("result: %d, error message: %s", result, err->message);
233     fail_unless_equals_int (result, GST_DISCOVERER_MISSING_PLUGINS);
234 #ifndef GST_DISABLE_DEPRECATED
235     GST_INFO ("misc: %" GST_PTR_FORMAT, gst_discoverer_info_get_misc (info));
236 #endif
237 
238     gst_discoverer_info_unref (info);
239     g_error_free (err);
240     err = NULL;
241     g_free (uri);
242     g_object_unref (dc);
243   }
244 }
245 
246 GST_END_TEST;
247 
248 typedef struct _AsyncTestData
249 {
250   gchar *uri;
251   GMainLoop *loop;
252   GstDiscovererResult result;
253 } AsyncTestData;
254 
255 static void
discovered_cb(GstDiscoverer * discoverer,GstDiscovererInfo * info,GError * err,AsyncTestData * data)256 discovered_cb (GstDiscoverer * discoverer,
257     GstDiscovererInfo * info, GError * err, AsyncTestData * data)
258 {
259   const gchar *uri = gst_discoverer_info_get_uri (info);
260 
261   fail_unless_equals_string (data->uri, uri);
262 
263   /* cannot ensure GST_DISCOVERER_OK since there might be missing plugins */
264   data->result = gst_discoverer_info_get_result (info);
265 
266   g_main_loop_quit (data->loop);
267 }
268 
269 static void
test_disco_async_with_context(GMainContext * context)270 test_disco_async_with_context (GMainContext * context)
271 {
272   GstDiscoverer *dc;
273   GError *err = NULL;
274   AsyncTestData data = { 0, };
275   gchar *path =
276       g_build_filename (GST_TEST_FILES_PATH, "theora-vorbis.ogg", NULL);
277 
278   if (context)
279     g_main_context_push_thread_default (context);
280 
281   data.uri = gst_filename_to_uri (path, &err);
282   /* something wrong if we have error here */
283   fail_unless (err == NULL);
284   g_free (path);
285 
286   data.loop = g_main_loop_new (context, FALSE);
287 
288   /* high timeout, in case we're running under valgrind */
289   dc = gst_discoverer_new (30 * GST_SECOND, &err);
290   fail_unless (dc != NULL);
291   fail_unless (err == NULL);
292 
293   g_signal_connect (dc, "discovered", G_CALLBACK (discovered_cb), &data);
294 
295   gst_discoverer_start (dc);
296   fail_unless (gst_discoverer_discover_uri_async (dc, data.uri) == TRUE);
297 
298   g_main_loop_run (data.loop);
299 
300   if (have_theora && have_ogg) {
301     fail_unless_equals_int (data.result, GST_DISCOVERER_OK);
302   } else {
303     fail_unless_equals_int (data.result, GST_DISCOVERER_MISSING_PLUGINS);
304   }
305 
306   gst_discoverer_stop (dc);
307   g_object_unref (dc);
308   g_free (data.uri);
309 
310   g_main_loop_unref (data.loop);
311 
312   if (context)
313     g_main_context_pop_thread_default (context);
314 }
315 
GST_START_TEST(test_disco_async)316 GST_START_TEST (test_disco_async)
317 {
318   /* use default GMainContext */
319   test_disco_async_with_context (NULL);
320 }
321 
322 GST_END_TEST;
323 
324 typedef struct _CustomContextData
325 {
326   GMutex lock;
327   GCond cond;
328   gboolean finish;
329 } CustomContextData;
330 
331 
332 static gpointer
custom_context_thread_func(CustomContextData * data)333 custom_context_thread_func (CustomContextData * data)
334 {
335   GMainContext *context;
336 
337   /* test async APIs with custom GMainContext */
338   context = g_main_context_new ();
339   test_disco_async_with_context (context);
340   g_main_context_unref (context);
341 
342   data->finish = TRUE;
343   g_cond_signal (&data->cond);
344 
345   return NULL;
346 }
347 
GST_START_TEST(test_disco_async_custom_context)348 GST_START_TEST (test_disco_async_custom_context)
349 {
350   GThread *thread;
351   CustomContextData data;
352 
353   g_mutex_init (&data.lock);
354   g_cond_init (&data.cond);
355   data.finish = FALSE;
356 
357   /* ensure default context here, but we will use other thread default context
358    * instead of this */
359   g_main_context_default ();
360 
361   thread = g_thread_new ("test-custom-context-thread",
362       (GThreadFunc) custom_context_thread_func, &data);
363 
364   g_mutex_lock (&data.lock);
365   while (!data.finish)
366     g_cond_wait (&data.cond, &data.lock);
367   g_mutex_unlock (&data.lock);
368 
369   g_thread_join (thread);
370   g_mutex_clear (&data.lock);
371   g_cond_clear (&data.cond);
372 }
373 
374 GST_END_TEST;
375 
376 static Suite *
discoverer_suite(void)377 discoverer_suite (void)
378 {
379   Suite *s = suite_create ("discoverer");
380   TCase *tc_chain = tcase_create ("general");
381 
382   have_theora = gst_registry_check_feature_version (gst_registry_get (),
383       "theoradec", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
384   have_ogg = gst_registry_check_feature_version (gst_registry_get (),
385       "oggdemux", GST_VERSION_MAJOR, GST_VERSION_MINOR, 0);
386 
387   suite_add_tcase (s, tc_chain);
388   tcase_add_test (tc_chain, test_disco_init);
389   tcase_add_test (tc_chain, test_disco_sync);
390   tcase_add_test (tc_chain, test_disco_sync_reuse_ogg);
391   tcase_add_test (tc_chain, test_disco_sync_reuse_mp3);
392   tcase_add_test (tc_chain, test_disco_sync_reuse_timeout);
393   tcase_add_test (tc_chain, test_disco_missing_plugins);
394   tcase_add_test (tc_chain, test_disco_serializing);
395   tcase_add_test (tc_chain, test_disco_async);
396   tcase_add_test (tc_chain, test_disco_async_custom_context);
397   return s;
398 }
399 
400 GST_CHECK_MAIN (discoverer);
401