|
1 /* GStreamer unit test for the gnomevfssink element |
|
2 * |
|
3 * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org> |
|
4 * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net> |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Library General Public |
|
8 * License as published by the Free Software Foundation; either |
|
9 * version 2 of the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Library General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Library General Public |
|
17 * License along with this library; if not, write to the |
|
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
19 * Boston, MA 02111-1307, USA. |
|
20 */ |
|
21 |
|
22 #ifdef HAVE_CONFIG_H |
|
23 #include "config.h" |
|
24 #endif |
|
25 |
|
26 #include <stdio.h> |
|
27 |
|
28 #include <glib.h> |
|
29 #include <glib/gstdio.h> |
|
30 |
|
31 #ifdef HAVE_UNISTD_H |
|
32 #include <unistd.h> /* for close() */ |
|
33 #endif |
|
34 |
|
35 #include <gst/check/gstcheck.h> |
|
36 |
|
37 static GstPad *mysrcpad; |
|
38 |
|
39 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", |
|
40 GST_PAD_SRC, |
|
41 GST_PAD_ALWAYS, |
|
42 GST_STATIC_CAPS_ANY); |
|
43 |
|
44 static GstElement * |
|
45 setup_gnomevfssink (void) |
|
46 { |
|
47 GstElement *gnomevfssink; |
|
48 |
|
49 GST_DEBUG ("setup_gnomevfssink"); |
|
50 gnomevfssink = gst_check_setup_element ("gnomevfssink"); |
|
51 mysrcpad = gst_check_setup_src_pad (gnomevfssink, &srctemplate, NULL); |
|
52 gst_pad_set_active (mysrcpad, TRUE); |
|
53 return gnomevfssink; |
|
54 } |
|
55 |
|
56 static void |
|
57 cleanup_gnomevfssink (GstElement * gnomevfssink) |
|
58 { |
|
59 gst_pad_set_active (mysrcpad, FALSE); |
|
60 gst_check_teardown_src_pad (gnomevfssink); |
|
61 gst_check_teardown_element (gnomevfssink); |
|
62 } |
|
63 |
|
64 #if 0 |
|
65 /* this queries via the element vfunc, which is currently not implemented */ |
|
66 #define CHECK_QUERY_POSITION(gnomevfssink,format,position) \ |
|
67 G_STMT_START { \ |
|
68 GstFormat fmt = format; \ |
|
69 gint64 pos; \ |
|
70 fail_unless (gst_element_query_position (gnomevfssink, &fmt, &pos)); \ |
|
71 fail_unless_equals_int (pos, position); \ |
|
72 } G_STMT_END |
|
73 #else |
|
74 #define CHECK_QUERY_POSITION(gnomevfssink,format,position) \ |
|
75 G_STMT_START { \ |
|
76 GstFormat fmt = format; \ |
|
77 GstPad *pad; \ |
|
78 gint64 pos; \ |
|
79 pad = gst_element_get_pad (gnomevfssink, "sink"); \ |
|
80 fail_unless (gst_pad_query_position (pad, &fmt, &pos)); \ |
|
81 fail_unless_equals_int (pos, position); \ |
|
82 gst_object_unref (pad); \ |
|
83 } G_STMT_END |
|
84 #endif |
|
85 |
|
86 #define PUSH_BYTES(num_bytes) \ |
|
87 G_STMT_START { \ |
|
88 GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes); \ |
|
89 GRand *rand = g_rand_new_with_seed (num_bytes); \ |
|
90 guint i; \ |
|
91 for (i = 0; i < num_bytes; ++i) \ |
|
92 GST_BUFFER_DATA(buf)[i] = (g_rand_int (rand) >> 24) & 0xff; \ |
|
93 fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \ |
|
94 g_rand_free (rand); \ |
|
95 } G_STMT_END |
|
96 |
|
97 /* TODO: we don't check that the data is actually written to the right |
|
98 * position after a seek */ |
|
99 GST_START_TEST (test_seeking) |
|
100 { |
|
101 const gchar *tmpdir; |
|
102 GstElement *gnomevfssink; |
|
103 gchar *tmp_fn; |
|
104 gint fd; |
|
105 |
|
106 tmpdir = g_get_tmp_dir (); |
|
107 if (tmpdir == NULL) |
|
108 return; |
|
109 |
|
110 /* this is just silly, but gcc warns if we try to use tpmnam() */ |
|
111 tmp_fn = |
|
112 g_build_filename (tmpdir, "gstreamer-gnomevfssink-test-XXXXXX", NULL); |
|
113 fd = g_mkstemp (tmp_fn); |
|
114 if (fd < 0) { |
|
115 GST_ERROR ("can't create temp file %s: %s", tmp_fn, g_strerror (errno)); |
|
116 g_free (tmp_fn); |
|
117 return; |
|
118 } |
|
119 /* don't want the file, just a filename (hence silly, see above) */ |
|
120 close (fd); |
|
121 g_remove (tmp_fn); |
|
122 |
|
123 gnomevfssink = setup_gnomevfssink (); |
|
124 |
|
125 GST_LOG ("using temp file '%s'", tmp_fn); |
|
126 g_object_set (gnomevfssink, "location", tmp_fn, NULL); |
|
127 |
|
128 fail_unless_equals_int (gst_element_set_state (gnomevfssink, |
|
129 GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC); |
|
130 |
|
131 #if 0 |
|
132 /* Test that gnomevfssink is seekable with a file fd */ |
|
133 /* gnomevfssink doesn't implement seekable query at the moment */ |
|
134 GstQuery *seeking_query; |
|
135 gboolean seekable; |
|
136 |
|
137 fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) |
|
138 != NULL); |
|
139 fail_unless (gst_element_query (gnomevfssink, seeking_query) == TRUE); |
|
140 gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL); |
|
141 fail_unless (seekable == TRUE); |
|
142 gst_query_unref (seeking_query); |
|
143 #endif |
|
144 |
|
145 fail_unless (gst_pad_push_event (mysrcpad, |
|
146 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0))); |
|
147 |
|
148 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 0); |
|
149 |
|
150 /* push buffer with size 0 and NULL data */ |
|
151 PUSH_BYTES (0); |
|
152 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 0); |
|
153 |
|
154 PUSH_BYTES (1); |
|
155 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 1); |
|
156 |
|
157 PUSH_BYTES (99); |
|
158 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 100); |
|
159 |
|
160 PUSH_BYTES (8800); |
|
161 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8900); |
|
162 |
|
163 if (gst_pad_push_event (mysrcpad, |
|
164 gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 8800, -1, |
|
165 0))) { |
|
166 GST_LOG ("seek ok"); |
|
167 /* make sure that that new position is reported immediately */ |
|
168 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8800); |
|
169 PUSH_BYTES (1); |
|
170 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8801); |
|
171 PUSH_BYTES (9256); |
|
172 CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 18057); |
|
173 } else { |
|
174 GST_INFO ("seeking not supported for tempfile?!"); |
|
175 } |
|
176 |
|
177 fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); |
|
178 |
|
179 fail_unless_equals_int (gst_element_set_state (gnomevfssink, GST_STATE_NULL), |
|
180 GST_STATE_CHANGE_SUCCESS); |
|
181 |
|
182 /* cleanup */ |
|
183 cleanup_gnomevfssink (gnomevfssink); |
|
184 |
|
185 /* check that we wrote data to the right position after the seek */ |
|
186 { |
|
187 gchar *data = NULL; |
|
188 gsize len; |
|
189 |
|
190 fail_unless (g_file_get_contents (tmp_fn, &data, &len, NULL), |
|
191 "Failed to read in newly-created file '%s'", tmp_fn); |
|
192 fail_unless_equals_int (len, 18057); |
|
193 { |
|
194 /* we wrote 9256 bytes at position 8801 */ |
|
195 GRand *rand = g_rand_new_with_seed (9256); |
|
196 guint i; |
|
197 |
|
198 for (i = 0; i < 9256; ++i) { |
|
199 guint8 byte_written = *(((guint8 *) data) + 8801 + i); |
|
200 |
|
201 fail_unless_equals_int (byte_written, g_rand_int (rand) >> 24); |
|
202 } |
|
203 g_rand_free (rand); |
|
204 } |
|
205 g_free (data); |
|
206 } |
|
207 |
|
208 /* remove file */ |
|
209 g_remove (tmp_fn); |
|
210 g_free (tmp_fn); |
|
211 } |
|
212 |
|
213 GST_END_TEST; |
|
214 |
|
215 GST_START_TEST (test_coverage) |
|
216 { |
|
217 GstElement *gnomevfssink; |
|
218 gchar *location; |
|
219 GstBus *bus; |
|
220 GstMessage *message; |
|
221 |
|
222 gnomevfssink = setup_gnomevfssink (); |
|
223 bus = gst_bus_new (); |
|
224 |
|
225 gst_element_set_bus (gnomevfssink, bus); |
|
226 |
|
227 g_object_set (gnomevfssink, "location", "/i/do/not/exist", NULL); |
|
228 g_object_get (gnomevfssink, "location", &location, NULL); |
|
229 fail_unless_equals_string (location, "/i/do/not/exist"); |
|
230 g_free (location); |
|
231 |
|
232 fail_unless_equals_int (gst_element_set_state (gnomevfssink, |
|
233 GST_STATE_PLAYING), GST_STATE_CHANGE_FAILURE); |
|
234 |
|
235 /* a state change and an error */ |
|
236 fail_if ((message = gst_bus_pop (bus)) == NULL); |
|
237 fail_unless_message_error (message, RESOURCE, OPEN_WRITE); |
|
238 gst_message_unref (message); |
|
239 |
|
240 g_object_set (gnomevfssink, "location", NULL, NULL); |
|
241 g_object_get (gnomevfssink, "location", &location, NULL); |
|
242 fail_if (location); |
|
243 |
|
244 /* cleanup */ |
|
245 gst_element_set_bus (gnomevfssink, NULL); |
|
246 gst_object_unref (GST_OBJECT (bus)); |
|
247 cleanup_gnomevfssink (gnomevfssink); |
|
248 } |
|
249 |
|
250 GST_END_TEST; |
|
251 |
|
252 GST_START_TEST (test_uri_interface) |
|
253 { |
|
254 GstElement *gnomevfssink; |
|
255 gchar *location; |
|
256 GstBus *bus; |
|
257 |
|
258 gnomevfssink = setup_gnomevfssink (); |
|
259 bus = gst_bus_new (); |
|
260 |
|
261 gst_element_set_bus (gnomevfssink, bus); |
|
262 |
|
263 g_object_set (G_OBJECT (gnomevfssink), "location", "/i/do/not/exist", NULL); |
|
264 g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); |
|
265 fail_unless_equals_string (location, "/i/do/not/exist"); |
|
266 g_free (location); |
|
267 |
|
268 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); |
|
269 fail_unless_equals_string (location, "file://%2Fi%2Fdo%2Fnot%2Fexist"); |
|
270 |
|
271 /* should accept file:///foo/bar URIs */ |
|
272 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), |
|
273 "file:///foo/bar")); |
|
274 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); |
|
275 fail_unless_equals_string (location, "file://%2Ffoo%2Fbar"); |
|
276 g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); |
|
277 fail_unless_equals_string (location, "/foo/bar"); |
|
278 g_free (location); |
|
279 |
|
280 /* should accept file://localhost/foo/bar URIs */ |
|
281 fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), |
|
282 "file://localhost/foo/baz")); |
|
283 location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); |
|
284 fail_unless_equals_string (location, "file://%2Ffoo%2Fbaz"); |
|
285 g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); |
|
286 fail_unless_equals_string (location, "/foo/baz"); |
|
287 g_free (location); |
|
288 |
|
289 /* should fail with other hostnames */ |
|
290 fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), |
|
291 "file://hostname/foo/foo")); |
|
292 |
|
293 /* cleanup */ |
|
294 gst_element_set_bus (gnomevfssink, NULL); |
|
295 gst_object_unref (GST_OBJECT (bus)); |
|
296 cleanup_gnomevfssink (gnomevfssink); |
|
297 } |
|
298 |
|
299 GST_END_TEST; |
|
300 |
|
301 static Suite * |
|
302 gnomevfssink_suite (void) |
|
303 { |
|
304 Suite *s = suite_create ("gnomevfssink"); |
|
305 TCase *tc_chain = tcase_create ("general"); |
|
306 |
|
307 suite_add_tcase (s, tc_chain); |
|
308 |
|
309 /* FIXME: these two tests fail right now because of uri/location stuff */ |
|
310 if (0) { |
|
311 tcase_add_test (tc_chain, test_coverage); |
|
312 tcase_add_test (tc_chain, test_uri_interface); |
|
313 } |
|
314 tcase_add_test (tc_chain, test_seeking); |
|
315 |
|
316 return s; |
|
317 } |
|
318 |
|
319 GST_CHECK_MAIN (gnomevfssink); |