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