3 * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
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.
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.
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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 #include <sys/types.h>
26 #include <gst/check/gstcheck.h>
28 static gboolean have_eos = FALSE;
29 static GCond *eos_cond;
30 static GMutex *event_mutex;
32 static GstPad *mysinkpad;
34 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
40 event_func (GstPad * pad, GstEvent * event)
44 g_mutex_lock (event_mutex);
45 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
47 GST_DEBUG ("signal EOS");
48 g_cond_broadcast (eos_cond);
50 g_mutex_unlock (event_mutex);
52 gst_event_unref (event);
60 g_mutex_lock (event_mutex);
61 GST_DEBUG ("waiting for EOS");
63 g_cond_wait (eos_cond, event_mutex);
65 GST_DEBUG ("received EOS");
66 g_mutex_unlock (event_mutex);
74 GST_DEBUG ("setup_filesrc");
75 filesrc = gst_check_setup_element ("filesrc");
76 mysinkpad = gst_check_setup_sink_pad (filesrc, &sinktemplate, NULL);
77 gst_pad_set_event_function (mysinkpad, event_func);
78 gst_pad_set_active (mysinkpad, TRUE);
80 eos_cond = g_cond_new ();
81 event_mutex = g_mutex_new ();
87 cleanup_filesrc (GstElement * filesrc)
89 gst_pad_set_active (mysinkpad, FALSE);
90 gst_check_teardown_sink_pad (filesrc);
91 gst_check_teardown_element (filesrc);
93 g_cond_free (eos_cond);
94 g_mutex_free (event_mutex);
97 GST_START_TEST (test_seeking)
100 GstQuery *seeking_query;
104 #error TESTFILE not defined
106 src = setup_filesrc ();
108 g_object_set (G_OBJECT (src), "location", TESTFILE, NULL);
109 fail_unless (gst_element_set_state (src,
110 GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
111 "could not set to paused");
113 /* Test that filesrc is seekable with a file fd */
114 fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES))
116 fail_unless (gst_element_query (src, seeking_query) == TRUE);
117 gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL);
118 fail_unless (seekable == TRUE);
119 gst_query_unref (seeking_query);
121 fail_unless (gst_element_set_state (src,
122 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
125 cleanup_filesrc (src);
130 GST_START_TEST (test_reverse)
135 #error TESTFILE not defined
137 src = setup_filesrc ();
139 g_object_set (G_OBJECT (src), "location", TESTFILE, NULL);
140 /* we're going to perform the seek in ready */
141 fail_unless (gst_element_set_state (src,
142 GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
143 "could not set to ready");
145 /* reverse seek from end to start */
146 gst_element_seek (src, -1.0, GST_FORMAT_BYTES, 0, GST_SEEK_TYPE_SET, 100,
147 GST_SEEK_TYPE_SET, -1);
149 fail_unless (gst_element_set_state (src,
150 GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
151 "could not set to paused");
156 fail_unless (gst_element_set_state (src,
157 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
160 cleanup_filesrc (src);
165 GST_START_TEST (test_pull)
168 GstQuery *seeking_query;
169 gboolean res, seekable;
173 GstBuffer *buffer1, *buffer2;
175 src = setup_filesrc ();
177 g_object_set (G_OBJECT (src), "location", TESTFILE, NULL);
178 fail_unless (gst_element_set_state (src,
179 GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
180 "could not set to ready");
182 /* get the source pad */
183 pad = gst_element_get_static_pad (src, "src");
184 fail_unless (pad != NULL);
186 /* activate the pad in pull mode */
187 res = gst_pad_activate_pull (pad, TRUE);
188 fail_unless (res == TRUE);
190 /* not start playing */
191 fail_unless (gst_element_set_state (src,
192 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
193 "could not set to paused");
195 /* Test that filesrc is seekable with a file fd */
196 fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES))
198 fail_unless (gst_element_query (src, seeking_query) == TRUE);
200 /* get the seeking capabilities */
201 gst_query_parse_seeking (seeking_query, NULL, &seekable, &start, &stop);
202 fail_unless (seekable == TRUE);
203 fail_unless (start == 0);
204 fail_unless (start != -1);
205 gst_query_unref (seeking_query);
208 ret = gst_pad_get_range (pad, 0, 100, &buffer1);
209 fail_unless (ret == GST_FLOW_OK);
210 fail_unless (buffer1 != NULL);
211 fail_unless (GST_BUFFER_SIZE (buffer1) == 100);
213 ret = gst_pad_get_range (pad, 0, 50, &buffer2);
214 fail_unless (ret == GST_FLOW_OK);
215 fail_unless (buffer2 != NULL);
216 fail_unless (GST_BUFFER_SIZE (buffer2) == 50);
218 /* this should be the same */
219 fail_unless (memcmp (GST_BUFFER_DATA (buffer1), GST_BUFFER_DATA (buffer2),
222 gst_buffer_unref (buffer2);
224 /* read next 50 bytes */
225 ret = gst_pad_get_range (pad, 50, 50, &buffer2);
226 fail_unless (ret == GST_FLOW_OK);
227 fail_unless (buffer2 != NULL);
228 fail_unless (GST_BUFFER_SIZE (buffer2) == 50);
230 /* compare with previously read data */
231 fail_unless (memcmp (GST_BUFFER_DATA (buffer1) + 50,
232 GST_BUFFER_DATA (buffer2), 50) == 0);
234 gst_buffer_unref (buffer1);
235 gst_buffer_unref (buffer2);
237 /* read 10 bytes at end-10 should give exactly 10 bytes */
238 ret = gst_pad_get_range (pad, stop - 10, 10, &buffer1);
239 fail_unless (ret == GST_FLOW_OK);
240 fail_unless (buffer1 != NULL);
241 fail_unless (GST_BUFFER_SIZE (buffer1) == 10);
242 gst_buffer_unref (buffer1);
244 /* read 20 bytes at end-10 should give exactly 10 bytes */
245 ret = gst_pad_get_range (pad, stop - 10, 20, &buffer1);
246 fail_unless (ret == GST_FLOW_OK);
247 fail_unless (buffer1 != NULL);
248 fail_unless (GST_BUFFER_SIZE (buffer1) == 10);
249 gst_buffer_unref (buffer1);
251 /* read 0 bytes at end-1 should return 0 bytes */
252 ret = gst_pad_get_range (pad, stop - 1, 0, &buffer1);
253 fail_unless (ret == GST_FLOW_OK);
254 fail_unless (buffer1 != NULL);
255 fail_unless (GST_BUFFER_SIZE (buffer1) == 0);
256 gst_buffer_unref (buffer1);
258 /* read 10 bytes at end-1 should return 1 byte */
259 ret = gst_pad_get_range (pad, stop - 1, 10, &buffer1);
260 fail_unless (ret == GST_FLOW_OK);
261 fail_unless (buffer1 != NULL);
262 fail_unless (GST_BUFFER_SIZE (buffer1) == 1);
263 gst_buffer_unref (buffer1);
265 /* read 0 bytes at end should EOS */
266 ret = gst_pad_get_range (pad, stop, 0, &buffer1);
267 fail_unless (ret == GST_FLOW_UNEXPECTED);
269 /* read 10 bytes before end should EOS */
270 ret = gst_pad_get_range (pad, stop, 10, &buffer1);
271 fail_unless (ret == GST_FLOW_UNEXPECTED);
273 /* read 0 bytes after end should EOS */
274 ret = gst_pad_get_range (pad, stop + 10, 0, &buffer1);
275 fail_unless (ret == GST_FLOW_UNEXPECTED);
277 /* read 10 bytes after end should EOS too */
278 ret = gst_pad_get_range (pad, stop + 10, 10, &buffer1);
279 fail_unless (ret == GST_FLOW_UNEXPECTED);
281 fail_unless (gst_element_set_state (src,
282 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
285 gst_object_unref (pad);
286 cleanup_filesrc (src);
291 GST_START_TEST (test_coverage)
298 src = setup_filesrc ();
299 bus = gst_bus_new ();
301 gst_element_set_bus (src, bus);
303 g_object_set (G_OBJECT (src), "location", "/i/do/not/exist", NULL);
304 g_object_get (G_OBJECT (src), "location", &location, NULL);
305 fail_unless_equals_string (location, "/i/do/not/exist");
307 fail_unless (gst_element_set_state (src,
308 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE,
309 "could set to playing with wrong location");
311 /* a state change and an error */
312 fail_if ((message = gst_bus_pop (bus)) == NULL);
313 gst_message_unref (message);
314 fail_if ((message = gst_bus_pop (bus)) == NULL);
315 fail_unless_message_error (message, RESOURCE, NOT_FOUND);
316 gst_message_unref (message);
318 g_object_set (G_OBJECT (src), "location", NULL, NULL);
319 g_object_get (G_OBJECT (src), "location", &location, NULL);
323 gst_element_set_bus (src, NULL);
324 gst_object_unref (GST_OBJECT (bus));
325 cleanup_filesrc (src);
330 GST_START_TEST (test_uri_interface)
336 src = setup_filesrc ();
337 bus = gst_bus_new ();
339 gst_element_set_bus (src, bus);
341 g_object_set (G_OBJECT (src), "location", "/i/do/not/exist", NULL);
342 g_object_get (G_OBJECT (src), "location", &location, NULL);
343 fail_unless_equals_string (location, "/i/do/not/exist");
346 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
347 fail_unless_equals_string (location, "file:///i/do/not/exist");
349 /* should accept file:///foo/bar URIs */
350 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
352 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
353 fail_unless_equals_string (location, "file:///foo/bar");
354 g_object_get (G_OBJECT (src), "location", &location, NULL);
355 fail_unless_equals_string (location, "/foo/bar");
358 /* should accept file://localhost/foo/bar URIs */
359 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
360 "file://localhost/foo/baz"));
361 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
362 fail_unless_equals_string (location, "file:///foo/baz");
363 g_object_get (G_OBJECT (src), "location", &location, NULL);
364 fail_unless_equals_string (location, "/foo/baz");
367 /* should escape non-uri characters for the URI but not for the location */
368 g_object_set (G_OBJECT (src), "location", "/foo/b?r", NULL);
369 g_object_get (G_OBJECT (src), "location", &location, NULL);
370 fail_unless_equals_string (location, "/foo/b?r");
372 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (src));
373 fail_unless_equals_string (location, "file:///foo/b%3Fr");
375 /* should fail with other hostnames */
376 fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (src),
377 "file://hostname/foo/foo"));
380 gst_element_set_bus (src, NULL);
381 gst_object_unref (GST_OBJECT (bus));
382 cleanup_filesrc (src);
388 check_uri_for_uri (GstElement * e, const gchar * in_uri, const gchar * uri)
391 gchar *query_uri = NULL;
393 gst_uri_handler_set_uri (GST_URI_HANDLER (e), in_uri);
395 query = gst_query_new_uri ();
396 fail_unless (gst_element_query (e, query));
397 gst_query_parse_uri (query, &query_uri);
398 gst_query_unref (query);
401 fail_unless_equals_string (query_uri, uri);
405 fail_unless (gst_uri_is_valid (query_uri));
406 fn = g_filename_from_uri (query_uri, NULL, NULL);
407 fail_unless (g_path_is_absolute (fn));
408 fail_unless (fn != NULL);
416 check_uri_for_location (GstElement * e, const gchar * location,
420 gchar *query_uri = NULL;
422 g_object_set (e, "location", location, NULL);
423 query = gst_query_new_uri ();
424 fail_unless (gst_element_query (e, query));
425 gst_query_parse_uri (query, &query_uri);
426 gst_query_unref (query);
429 fail_unless_equals_string (query_uri, uri);
433 fail_unless (gst_uri_is_valid (query_uri));
434 fn = g_filename_from_uri (query_uri, NULL, NULL);
435 fail_unless (g_path_is_absolute (fn));
436 fail_unless (fn != NULL);
443 GST_START_TEST (test_uri_query)
447 src = setup_filesrc ();
452 check_uri_for_location (src, "/i/do/not/exist", "file:///i/do/not/exist");
453 check_uri_for_location (src, "/i/do/not/../exist", "file:///i/do/exist");
454 check_uri_for_location (src, "/i/do/not/.././exist", "file:///i/do/exist");
455 check_uri_for_location (src, "/i/./do/not/../exist", "file:///i/do/exist");
456 check_uri_for_location (src, "/i/do/./not/../exist", "file:///i/do/exist");
457 check_uri_for_location (src, "/i/do/not/./../exist", "file:///i/do/exist");
458 check_uri_for_location (src, "/i/./do/./././././exist",
459 "file:///i/do/exist");
460 check_uri_for_location (src, "/i/do/not/../../exist", "file:///i/exist");
461 check_uri_for_location (src, "/i/../not/../exist", "file:///exist");
462 /* hard to test relative URIs, just make sure it returns an URI of sorts */
463 check_uri_for_location (src, "foo", NULL);
464 check_uri_for_location (src, "foo/../bar", NULL);
465 check_uri_for_location (src, "./foo", NULL);
466 check_uri_for_location (src, "../foo", NULL);
467 check_uri_for_location (src, "foo/./bar", NULL);
468 /* make sure non-ASCII characters are escaped properly (U+00F6 here) */
469 check_uri_for_location (src, "/i/./d\303\266/not/../exist",
470 "file:///i/d%C3%B6/exist");
471 /* let's see what happens if we set a malformed URI with ISO-8859-1 chars,
472 * i.e. one that the input characters haven't been escaped properly. We
473 * should get back a properly escaped URI */
474 check_uri_for_uri (src, "file:///M\366t\366r", "file:///M%F6t%F6r");
478 cleanup_filesrc (src);
486 Suite *s = suite_create ("filesrc");
487 TCase *tc_chain = tcase_create ("general");
489 suite_add_tcase (s, tc_chain);
490 tcase_add_test (tc_chain, test_seeking);
491 tcase_add_test (tc_chain, test_reverse);
492 tcase_add_test (tc_chain, test_pull);
493 tcase_add_test (tc_chain, test_coverage);
494 tcase_add_test (tc_chain, test_uri_interface);
495 tcase_add_test (tc_chain, test_uri_query);
500 GST_CHECK_MAIN (filesrc);