1 /*
2 * Unittest for curlfilesink
3 */
4
5 #include <gst/check/gstcheck.h>
6 #include <glib/gstdio.h>
7 #include <curl/curl.h>
8 #include <unistd.h>
9
10 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
11 GST_PAD_SRC,
12 GST_PAD_ALWAYS,
13 GST_STATIC_CAPS_ANY);
14
15 static GstPad *srcpad;
16
17 static GstElement *sink;
18
19 static GstElement *
setup_curlfilesink(void)20 setup_curlfilesink (void)
21 {
22 GST_DEBUG ("setup_curlfilesink");
23 sink = gst_check_setup_element ("curlfilesink");
24 srcpad = gst_check_setup_src_pad (sink, &srctemplate);
25 fail_unless (gst_pad_set_active (srcpad, TRUE));
26
27 return sink;
28 }
29
30 static void
cleanup_curlfilesink(GstElement * sink)31 cleanup_curlfilesink (GstElement * sink)
32 {
33 GST_DEBUG ("cleanup_curlfilesink");
34
35 gst_check_teardown_src_pad (sink);
36 gst_check_teardown_element (sink);
37 }
38
39 static void
test_verify_file_data(const gchar * dir,gchar * file_name,const gchar * expected_file_content)40 test_verify_file_data (const gchar * dir, gchar * file_name,
41 const gchar * expected_file_content)
42 {
43 GError *err = NULL;
44 gchar *res_file_content = NULL;
45 gchar *path = NULL;
46
47 path = g_strdup_printf ("%s/%s", dir, file_name);
48 g_free (file_name);
49
50 if (!g_file_get_contents (path, &res_file_content, NULL, &err)) {
51 GST_WARNING ("Error loading file: %s (%s)", file_name, err->message);
52 g_error_free (err);
53 }
54
55 fail_unless (res_file_content != NULL);
56
57 fail_unless (strncmp (res_file_content, expected_file_content,
58 strlen (expected_file_content)) == 0);
59 g_free (res_file_content);
60 g_unlink (path);
61 g_free (path);
62 }
63
64 static void
test_set_and_play_buffer(const gchar * _data)65 test_set_and_play_buffer (const gchar * _data)
66 {
67 gpointer data = (gpointer) _data;
68 GstBuffer *buffer;
69 gint num_bytes;
70
71 num_bytes = strlen (data);
72 buffer = gst_buffer_new ();
73 gst_buffer_insert_memory (buffer, 0,
74 gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
75 data, num_bytes, 0, num_bytes, data, NULL));
76
77 fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
78 }
79
80 static void
test_set_and_fail_to_play_buffer(const gchar * _data)81 test_set_and_fail_to_play_buffer (const gchar * _data)
82 {
83 gpointer data = (gpointer) _data;
84 GstBuffer *buffer;
85 gint num_bytes;
86
87 num_bytes = strlen (data);
88 buffer = gst_buffer_new ();
89 gst_buffer_insert_memory (buffer, 0,
90 gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
91 data, num_bytes, 0, num_bytes, data, NULL));
92
93 fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_ERROR);
94 }
95
GST_START_TEST(test_properties)96 GST_START_TEST (test_properties)
97 {
98 GstElement *sink;
99 GstCaps *caps;
100 const gchar *location = "file:///tmp/";
101 const gchar *file_contents = "line 1\r\n";
102 gchar *file_name = g_strdup_printf ("curlfilesink_%d", g_random_int ());
103 gchar *res_location = NULL;
104 gchar *res_file_name = NULL;
105 gboolean res_create_dirs = FALSE;
106 gchar *path = NULL;
107
108 sink = setup_curlfilesink ();
109
110 g_object_set (G_OBJECT (sink), "location", "mylocation", NULL);
111 g_object_set (G_OBJECT (sink), "file-name", "myfile", NULL);
112 g_object_set (G_OBJECT (sink), "create-dirs", TRUE, NULL);
113
114 g_object_get (sink,
115 "location", &res_location,
116 "file-name", &res_file_name, "create-dirs", &res_create_dirs, NULL);
117
118 fail_unless (strncmp (res_location, "mylocation", strlen ("mylocation"))
119 == 0);
120 fail_unless (strncmp (res_file_name, "myfile", strlen ("myfile"))
121 == 0);
122 fail_unless (res_create_dirs == TRUE);
123 g_free (res_location);
124 g_free (res_file_name);
125
126 /* change properties */
127 g_object_set (G_OBJECT (sink), "location", location, NULL);
128 g_object_set (G_OBJECT (sink), "file-name", file_name, NULL);
129 g_object_set (G_OBJECT (sink), "create-dirs", FALSE, NULL);
130
131 g_object_get (sink,
132 "location", &res_location,
133 "file-name", &res_file_name, "create-dirs", &res_create_dirs, NULL);
134
135 fail_unless (strncmp (res_location, location, strlen (location))
136 == 0);
137 fail_unless (strncmp (res_file_name, file_name, strlen (file_name))
138 == 0);
139 fail_unless (res_create_dirs == FALSE);
140 g_free (res_location);
141 g_free (res_file_name);
142
143 /* start playing */
144 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
145 caps = gst_caps_from_string ("application/x-gst-check");
146 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
147
148 /* setup buffer */
149 test_set_and_play_buffer (file_contents);
150
151 /* try to change location property while in PLAYING state */
152 g_object_set (G_OBJECT (sink), "location", "newlocation", NULL);
153 g_object_get (sink, "location", &res_location, NULL);
154
155 /* verify that location has not been altered */
156 fail_unless (strncmp (res_location, location, strlen (location))
157 == 0);
158 g_free (res_location);
159
160 /* eos */
161 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
162 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
163
164 gst_caps_unref (caps);
165 cleanup_curlfilesink (sink);
166
167 path = g_strdup_printf ("/tmp/%s", file_name);
168 g_unlink (path);
169 g_free (file_name);
170 g_free (path);
171 }
172
173 GST_END_TEST;
174
GST_START_TEST(test_one_file)175 GST_START_TEST (test_one_file)
176 {
177 GstElement *sink;
178 GstCaps *caps;
179 const gchar *location = "file:///tmp/";
180 gchar *file_name = g_strdup_printf ("curlfilesink_%d", g_random_int ());
181 const gchar *file_content = "line 1\r\n";
182 gchar *res_location = NULL;
183 gchar *res_file_name = NULL;
184
185 sink = setup_curlfilesink ();
186
187 g_object_set (G_OBJECT (sink), "location", location, NULL);
188 g_object_set (G_OBJECT (sink), "file-name", file_name, NULL);
189
190 g_object_get (sink,
191 "location", &res_location, "file-name", &res_file_name, NULL);
192
193 fail_unless (strncmp (res_location, location, strlen (location))
194 == 0);
195 fail_unless (strncmp (res_file_name, file_name, strlen (file_name))
196 == 0);
197
198 g_free (res_location);
199 g_free (res_file_name);
200
201 /* start playing */
202 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
203 caps = gst_caps_from_string ("application/x-gst-check");
204 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
205
206 /* setup buffer */
207 test_set_and_play_buffer (file_content);
208
209 /* eos */
210 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
211 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
212
213 gst_caps_unref (caps);
214 cleanup_curlfilesink (sink);
215
216 /* verify file content */
217 test_verify_file_data ("/tmp", file_name, file_content);
218 }
219
220 GST_END_TEST;
221
GST_START_TEST(test_one_big_file)222 GST_START_TEST (test_one_big_file)
223 {
224 GstElement *sink;
225 GstCaps *caps;
226 const gchar *location = "file:///tmp/";
227 gchar *file_name = g_strdup_printf ("curlfilesink_%d", g_random_int ());
228 const gchar *file_line1 = "line 1\r\n";
229 const gchar *file_line2 = "line 2\r\n";
230 const gchar *file_line3 = "line 3\r\n";
231 const gchar *expected_file_content = "line 1\r\n" "line 2\r\n" "line 3\r\n";
232 gchar *res_location = NULL;
233 gchar *res_file_name = NULL;
234
235 sink = setup_curlfilesink ();
236
237 g_object_set (G_OBJECT (sink), "location", location, NULL);
238 g_object_set (G_OBJECT (sink), "file-name", file_name, NULL);
239
240 g_object_get (sink,
241 "location", &res_location, "file-name", &res_file_name, NULL);
242
243 fail_unless (strncmp (res_location, location, strlen (location))
244 == 0);
245 fail_unless (strncmp (res_file_name, file_name, strlen (file_name))
246 == 0);
247
248 g_free (res_location);
249 g_free (res_file_name);
250
251 /* start playing */
252 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
253 caps = gst_caps_from_string ("application/x-gst-check");
254 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
255
256 /* setup first buffer */
257 test_set_and_play_buffer (file_line1);
258
259 /* setup second buffer */
260 test_set_and_play_buffer (file_line2);
261
262 /* setup third buffer */
263 test_set_and_play_buffer (file_line3);
264
265 /* eos */
266 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
267 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
268
269 gst_caps_unref (caps);
270 cleanup_curlfilesink (sink);
271
272 /* verify file content */
273 test_verify_file_data ("/tmp", file_name, expected_file_content);
274 }
275
276 GST_END_TEST;
277
GST_START_TEST(test_two_files)278 GST_START_TEST (test_two_files)
279 {
280 GstElement *sink;
281 GstCaps *caps;
282 const gchar *location = "file:///tmp/";
283 gchar *file_name1 = g_strdup_printf ("curlfilesink_%d", g_random_int ());
284 gchar *file_name2 = g_strdup_printf ("curlfilesink_%d", g_random_int ());
285 const gchar *file_content1 = "file content 1\r\n";
286 const gchar *file_content2 = "file content 2\r\n";
287 gchar *res_location = NULL;
288 gchar *res_file_name = NULL;
289
290 sink = setup_curlfilesink ();
291
292 g_object_set (G_OBJECT (sink), "location", location, NULL);
293 g_object_set (G_OBJECT (sink), "file-name", file_name1, NULL);
294
295 g_object_get (sink,
296 "location", &res_location, "file-name", &res_file_name, NULL);
297
298 fail_unless (strncmp (res_location, location, strlen (location))
299 == 0);
300 fail_unless (strncmp (res_file_name, file_name1, strlen (file_name1))
301 == 0);
302
303 g_free (res_location);
304 g_free (res_file_name);
305
306 /* start playing */
307 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
308 caps = gst_caps_from_string ("application/x-gst-check");
309 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
310
311 /* setup first buffer - content of the first file */
312 test_set_and_play_buffer (file_content1);
313
314 g_object_set (G_OBJECT (sink), "file-name", file_name2, NULL);
315 g_object_get (sink, "file-name", &res_file_name, NULL);
316 fail_unless (strncmp (res_file_name, file_name2, strlen (file_name2))
317 == 0);
318 g_free (res_file_name);
319
320 /* setup second buffer - content of the second file */
321 test_set_and_play_buffer (file_content2);
322
323 /* eos */
324 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
325 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
326
327 gst_caps_unref (caps);
328 cleanup_curlfilesink (sink);
329
330 /* verify file contents of the first file */
331 test_verify_file_data ("/tmp", file_name1, file_content1);
332 test_verify_file_data ("/tmp", file_name2, file_content2);
333 }
334
335 GST_END_TEST;
336
GST_START_TEST(test_create_dirs)337 GST_START_TEST (test_create_dirs)
338 {
339 GstElement *sink;
340 GstCaps *caps;
341 gchar *tmp_dir = g_strdup ("/tmp/curlfilesink_XXXXXX");
342 gchar *sub_dir;
343 gchar *sub_sub_dir;
344 gchar *location;
345 gchar *file_name = g_strdup_printf ("curlfilesink_%d", g_random_int ());
346 const gchar *file_content = "line 1\r\n";
347
348 /* create temp dir as base dir (mkdtemp saves dir name in tmp_dir) */
349 fail_unless (mkdtemp (tmp_dir) != NULL);
350
351 /* use sub-sub directory as location */
352 sub_dir = g_strdup_printf ("%s/a", tmp_dir);
353 sub_sub_dir = g_strdup_printf ("%s/b", sub_dir);
354 location = g_strdup_printf ("file://%s/", sub_sub_dir);
355
356 sink = setup_curlfilesink ();
357
358 g_object_set (G_OBJECT (sink), "location", location, NULL);
359 g_object_set (G_OBJECT (sink), "file-name", file_name, NULL);
360 g_object_set (G_OBJECT (sink), "create-dirs", TRUE, NULL);
361
362 /* start playing */
363 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
364 caps = gst_caps_from_string ("application/x-gst-check");
365 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
366
367 /* setup buffer */
368 test_set_and_play_buffer (file_content);
369
370 /* eos */
371 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
372 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
373
374 gst_caps_unref (caps);
375 cleanup_curlfilesink (sink);
376
377 /* verify file content in sub-sub dir created by sink */
378 test_verify_file_data (sub_sub_dir, file_name, file_content);
379
380 /* remove directories */
381 fail_unless (g_rmdir (sub_sub_dir) == 0);
382 fail_unless (g_rmdir (sub_dir) == 0);
383 fail_unless (g_rmdir (tmp_dir) == 0);
384 g_free (sub_sub_dir);
385 g_free (sub_dir);
386 g_free (tmp_dir);
387 g_free (location);
388 }
389
390 GST_END_TEST;
391
GST_START_TEST(test_missing_path)392 GST_START_TEST (test_missing_path)
393 {
394 GstElement *sink;
395 GstCaps *caps;
396 const gchar *location = "file:///missing/path/";
397 gchar *file_name = g_strdup_printf ("curlfilesink_%d", g_random_int ());
398 const gchar *file_content = "line 1\r\n";
399 gchar *res_location = NULL;
400 gchar *res_file_name = NULL;
401
402 sink = setup_curlfilesink ();
403
404 g_object_set (G_OBJECT (sink), "location", location, NULL);
405 g_object_set (G_OBJECT (sink), "file-name", file_name, NULL);
406
407 g_object_get (sink,
408 "location", &res_location, "file-name", &res_file_name, NULL);
409
410 fail_unless (strncmp (res_location, location, strlen (location))
411 == 0);
412 fail_unless (strncmp (res_file_name, file_name, strlen (file_name))
413 == 0);
414
415 g_free (res_location);
416 g_free (res_file_name);
417 g_free (file_name);
418
419 /* start playing */
420 ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
421 caps = gst_caps_from_string ("application/x-gst-check");
422 gst_check_setup_events (srcpad, sink, caps, GST_FORMAT_BYTES);
423
424 /* setup & play buffer which should fail due to the missing path */
425 test_set_and_fail_to_play_buffer (file_content);
426
427 /* eos */
428 fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
429 ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
430
431 gst_caps_unref (caps);
432 cleanup_curlfilesink (sink);
433 }
434
435 GST_END_TEST;
436
437 static Suite *
curlsink_suite(void)438 curlsink_suite (void)
439 {
440 Suite *s = suite_create ("curlfilesink");
441 TCase *tc_chain = tcase_create ("general");
442
443 suite_add_tcase (s, tc_chain);
444 tcase_set_timeout (tc_chain, 20);
445 tcase_add_test (tc_chain, test_properties);
446 tcase_add_test (tc_chain, test_one_file);
447 tcase_add_test (tc_chain, test_one_big_file);
448 tcase_add_test (tc_chain, test_two_files);
449 tcase_add_test (tc_chain, test_missing_path);
450 tcase_add_test (tc_chain, test_create_dirs);
451
452 return s;
453 }
454
455 GST_CHECK_MAIN (curlsink);
456