1 /* GStreamer gst_parse_launch unit tests
2 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
3 * Copyright (C) <2008> Tim-Philipp Müller <tim centricular 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
27 #define GST_TYPE_PARSE_TEST_ELEMENT (gst_parse_test_element_get_type())
28 static GType gst_parse_test_element_get_type (void);
29
30 static GstElement *
setup_pipeline(const gchar * pipe_descr)31 setup_pipeline (const gchar * pipe_descr)
32 {
33 GstElement *pipeline;
34 GError *error = NULL;
35
36 GST_DEBUG ("creating [%s] setup_pipeline", pipe_descr);
37
38 pipeline = gst_parse_launch (pipe_descr, &error);
39
40 GST_DEBUG ("created [%s] setup_pipeline", pipe_descr);
41
42 if (error != NULL) {
43 fail_if (error != NULL, "Error parsing pipeline %s: %s", pipe_descr,
44 error->message);
45 g_error_free (error);
46 }
47 fail_unless (pipeline != NULL, "Failed to create pipeline %s", pipe_descr);
48 /* Newly returned object should be floating reffed */
49 fail_unless (g_object_is_floating (pipeline));
50 g_assert_cmpuint (G_OBJECT (pipeline)->ref_count, ==, 1);
51 return pipeline;
52 }
53
54 static void
expected_fail_pipe(const gchar * pipe_descr)55 expected_fail_pipe (const gchar * pipe_descr)
56 {
57 GstElement *pipeline;
58 GError *error = NULL;
59
60 #ifndef GST_DISABLE_GST_DEBUG
61 gst_debug_set_default_threshold (GST_LEVEL_NONE);
62 #endif
63
64 pipeline = gst_parse_launch (pipe_descr, &error);
65 fail_unless (pipeline == NULL || error != NULL,
66 "Expected failure pipeline %s: succeeded!", pipe_descr);
67 g_error_free (error);
68
69 /* We get a pipeline back even when parsing has failed, sometimes! */
70 if (pipeline)
71 gst_object_unref (pipeline);
72 }
73
74 static void
check_pipeline_runs(GstElement * p)75 check_pipeline_runs (GstElement * p)
76 {
77 GstStateChangeReturn ret;
78
79 /* Check that the pipeline changes state to PAUSED and back to NULL */
80 ret = gst_element_set_state (p, GST_STATE_PAUSED);
81 if (ret == GST_STATE_CHANGE_ASYNC)
82 ret = gst_element_get_state (p, NULL, NULL, GST_CLOCK_TIME_NONE);
83 fail_unless (ret != GST_STATE_CHANGE_FAILURE,
84 "Could not set pipeline to paused");
85
86 ret = gst_element_set_state (p, GST_STATE_NULL);
87 if (ret == GST_STATE_CHANGE_ASYNC)
88 ret = gst_element_get_state (p, NULL, NULL, GST_CLOCK_TIME_NONE);
89 fail_unless (ret != GST_STATE_CHANGE_FAILURE,
90 "Could not set pipeline to null");
91 }
92
93 static const gchar *test_lines[] = {
94 "filesrc location=music.mp3 ! identity silent=true ! fakesink silent=true",
95 "filesrc location=music.ogg ! tee ! identity silent=true ! identity silent=true ! fakesink silent=true",
96 "filesrc location=http://domain.com/music.mp3 ! identity silent=true ! fakesink silent=true",
97 "filesrc location=movie.avi ! tee name=demuxer ! ( queue ! identity silent=true ! fakesink silent=true ) ( demuxer. ! queue ! identity silent=true ! fakesink silent=true )",
98 "fakesrc ! video/x-raw ! fakesink silent=true",
99 "fakesrc ! video/raw, format=(string)YUY2; video/raw, format=(string)YV12 ! fakesink silent=true",
100 "fakesrc ! audio/x-raw, width=[16, 32], depth={16, 24, 32}, signed=TRUE ! fakesink silent=true",
101 "fakesrc ! identity silent=true ! identity silent=true ! identity silent=true ! fakesink silent=true",
102 "fakesrc name=100 fakesink name=101 silent=true 100. ! 101.", /* linking with named reference on both sides */
103 "fakesrc ! 1__dentity ! fakesink silent=true", /* using a freshly registered element type */
104 "fakesrc ! tee name=t t.src_12 ! queue ! fakesink t.src_3 ! queue ! fakesink",
105 "fakesrc name=foo name=fin fin. ! fakesink", /* testing assignments are executed in correct order (left-to-right) */
106 "( fakesrc ) ! fakesink", /* ghostPad creation on-the-fly, infix notation link */
107 "( fakesrc name=dasrc ) dasrc. ! fakesink", /* ghostPad creation on-the-fly, named link */
108 /* "(name=mabin fakesrc) mabin. ! fakesink", FIXME: linking to named bin does not work yet */
109 /* "(name=mabin name=yoyo fakesrc) yoyo. ! fakesink", FIXME: linking to named bin does not work yet */
110 "deepsrc. ! fakesink fakesrc ! ( identity ! ( identity ! ( identity name=deepsrc ) ) )", /* deep name resolution, multilevel ghostpad creation */
111 "fakesrc : fakesink", /* linking all matching pads */
112 "fakesrc : video/x-all : fakesink", /* linking all matching pads with filter */
113 "fakesrc ! video/x-all : fakesink", /* linking all matching pads with filter */
114 "fakesrc : video/x-all ! fakesink", /* linking all matching pads with filter */
115 NULL
116 };
117
GST_START_TEST(test_launch_lines)118 GST_START_TEST (test_launch_lines)
119 {
120 GstElement *pipeline;
121 const gchar **s;
122 GType type;
123 GstElementFactory *efac;
124
125 efac = gst_element_factory_find ("identity");
126 fail_unless (efac != NULL);
127 efac =
128 GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (efac)));
129 fail_unless (efac != NULL);
130 type = gst_element_factory_get_element_type (efac);
131 fail_unless (type != 0);
132 gst_object_unref (efac);
133 gst_object_unref (efac);
134 fail_unless (gst_element_register (NULL, "1__dentity", GST_RANK_NONE, type));
135
136 for (s = test_lines; *s != NULL; s++) {
137 pipeline = setup_pipeline (*s);
138 gst_object_unref (pipeline);
139 }
140 }
141
142 GST_END_TEST;
143
144 #define PIPELINE1 "fakesrc"
145 #define PIPELINE2 "fakesrc name=donald num-buffers= 27 silent =TruE sizetype = 3 data= Subbuffer\\ data"
146 #define PIPELINE3 "fakesrc identity silent=true fakesink silent=true"
147 #define PIPELINE4 "fakesrc num-buffers=4 .src ! identity silent=true !.sink identity silent=true .src ! .sink fakesink silent=true"
148 #define PIPELINE5 "fakesrc num-buffers=4 name=src identity silent=true name=id1 identity silent=true name = id2 fakesink silent=true name =sink src. ! id1. id1.! id2.sink id2.src!sink.sink"
149 #define PIPELINE6 "pipeline.(name=\"john\" fakesrc num-buffers=4 ! ( bin. ( queue ! identity silent=true !( queue ! fakesink silent=true )) ))"
150 #define PIPELINE7 "fakesrc num-buffers=4 ! tee name=tee .src_%u ! queue ! fakesink silent=true tee.src_%u ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src_%u ! foo."
151 /* aggregator is borked
152 * #define PIPELINE8 "fakesrc num-buffers=4 ! tee name=tee1 .src0,src1 ! .sink0, sink1 aggregator ! fakesink silent=true"
153 * */
154 #define PIPELINE8 "fakesrc num-buffers=4 ! fakesink silent=true"
155 #define PIPELINE9 "fakesrc num-buffers=4 ! test. fakesink silent=true name=test"
156 #define PIPELINE10 "( fakesrc num-buffers=\"4\" ) ! identity silent=true ! fakesink silent=true"
157 #define PIPELINE11 "fakesink silent=true name = sink identity silent=true name=id ( fakesrc num-buffers=\"4\" ! id. ) id. ! sink."
158 #define PIPELINE12 "file:///tmp/test.file ! fakesink silent=true"
159 #define PIPELINE13 "fakesrc ! file:///tmp/test.file"
160 #define PIPELINE14 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\,x\""
161 #define PIPELINE15 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\\"x\\,x\""
162
GST_START_TEST(test_launch_lines2)163 GST_START_TEST (test_launch_lines2)
164 {
165 GstElement *cur;
166 gint i;
167 gboolean b;
168 gchar *s = NULL;
169
170 /**
171 * checks:
172 * - specifying an element works :)
173 * - if only 1 element is requested, no bin is returned, but the element
174 */
175 cur = setup_pipeline (PIPELINE1);
176 fail_unless (G_OBJECT_TYPE (cur) == g_type_from_name ("GstFakeSrc"),
177 "parse_launch did not produce a fakesrc");
178 gst_object_unref (cur);
179
180 /**
181 * checks:
182 * - properties works
183 * - string, int, boolean and enums can be properly set
184 * - first test of escaping strings
185 */
186 cur = setup_pipeline (PIPELINE2);
187 g_object_get (G_OBJECT (cur), "name", &s, "num-buffers", &i,
188 "silent", &b, NULL);
189 fail_if (s == NULL, "name was NULL");
190 fail_unless (strcmp (s, "donald") == 0, "fakesrc name was not 'donald'");
191 fail_unless (i == 27, "num-buffers was not 27");
192 fail_unless (b == TRUE, "silent was not TRUE");
193 g_free (s);
194
195 g_object_get (G_OBJECT (cur), "sizetype", &i, NULL);
196 fail_unless (i == 3, "sizetype != 3");
197
198 g_object_get (G_OBJECT (cur), "data", &i, NULL);
199 fail_unless (i == 2, "data != 2");
200 gst_object_unref (cur);
201
202 /**
203 * checks:
204 * - specifying multiple elements without links works
205 * - if multiple toplevel elements exist, a pipeline is returned
206 */
207 cur = setup_pipeline (PIPELINE3);
208 fail_unless (GST_BIN_NUMCHILDREN (cur) == 3,
209 "Pipeline does not contain 3 children");
210 gst_object_unref (cur);
211
212 /**
213 * checks:
214 * - test default link "!"
215 * - test if specifying pads on links works
216 */
217 cur = setup_pipeline (PIPELINE4);
218 check_pipeline_runs (cur);
219 gst_object_unref (cur);
220
221 /**
222 * checks:
223 * - test if appending the links works, too
224 * - check if the pipeline constructed works the same as the one before (how?)
225 */
226 cur = setup_pipeline (PIPELINE5);
227 check_pipeline_runs (cur);
228 gst_object_unref (cur);
229
230 /**
231 * checks:
232 * - test various types of bins
233 * - test if linking across bins works
234 * - test if escaping strings works
235 */
236 cur = setup_pipeline (PIPELINE6);
237 /* FIXME: valgrind finds element later */
238 fail_unless (GST_IS_PIPELINE (cur), "Parse did not produce a pipeline");
239 g_object_get (G_OBJECT (cur), "name", &s, NULL);
240 fail_if (s == NULL, "name was NULL");
241 fail_unless (strcmp (s, "john") == 0, "Name was not 'john'");
242 g_free (s);
243 check_pipeline_runs (cur);
244 gst_object_unref (cur);
245
246 /**
247 * checks:
248 * - test request pads
249 */
250 cur = setup_pipeline (PIPELINE7);
251 check_pipeline_runs (cur);
252 gst_object_unref (cur);
253
254 /**
255 * checks:
256 * - multiple pads on 1 link
257 */
258 cur = setup_pipeline (PIPELINE8);
259 check_pipeline_runs (cur);
260 gst_object_unref (cur);
261
262 /**
263 * checks:
264 * - failed in grammar.y cvs version 1.17
265 */
266 cur = setup_pipeline (PIPELINE9);
267 check_pipeline_runs (cur);
268 gst_object_unref (cur);
269
270 /**
271 * checks:
272 * - failed in grammar.y cvs version 1.17
273 */
274 cur = setup_pipeline (PIPELINE10);
275 check_pipeline_runs (cur);
276 gst_object_unref (cur);
277
278 /**
279 * checks:
280 * - failed in grammar.y cvs version 1.18
281 */
282 cur = setup_pipeline (PIPELINE11);
283 check_pipeline_runs (cur);
284 gst_object_unref (cur);
285
286 /**
287 * checks:
288 * - URI detection works
289 */
290 cur = setup_pipeline (PIPELINE12);
291 gst_object_unref (cur);
292
293 /** * checks:
294 * - URI sink detection works
295 */
296 cur = setup_pipeline (PIPELINE13);
297 gst_object_unref (cur);
298
299 /**
300 * Checks if characters inside quotes are not escaped.
301 */
302 cur = setup_pipeline (PIPELINE14);
303 gst_object_unref (cur);
304
305 /**
306 * Checks if escaped quotes inside quotes are not treated as end string quotes.
307 * This would make the rest of characters to be escaped incorrectly.
308 */
309 cur = setup_pipeline (PIPELINE15);
310 gst_object_unref (cur);
311 }
312
313 GST_END_TEST;
314
315 static const gchar *expected_failures[] = {
316 /* checks: fails because a=b. is not a valid element reference in parse.l */
317 "fakesrc num-buffers=4 name=\"a=b\" a=b. ! fakesink silent=true",
318 /* checks: Error branch for a non-deserialisable property value */
319 "filesrc blocksize=absdff",
320 /* checks: That broken caps which don't parse can't create a pipeline */
321 "fakesrc ! video/raw,format=(antwerp)monkeys ! fakesink silent=true",
322 /* checks: Empty pipeline is invalid */
323 "",
324 /* checks: Link without sink element fails */
325 "fakesrc ! ",
326 /* checks: Link without src element fails */
327 " ! fakesink silent=true",
328 /* checks: Source URI for which no element exists is a failure */
329 "borky://fdaffd ! fakesink silent=true",
330 /* checks: Sink URI for which no element exists is a failure */
331 "fakesrc ! borky://fdaffd",
332 /* checks: Referencing non-existent source element by name can't link */
333 "fakesrc name=src fakesink silent=true name=sink noexiste. ! sink.",
334 /* checks: Referencing non-existent sink element by name can't link */
335 "fakesrc name=src fakesink silent=true name=sink src. ! noexiste.",
336 /* checks: Can't link 2 elements that only have sink pads */
337 "fakesink silent=true ! fakesink silent=true",
338 /* checks multi-chain link without src element fails. */
339 "! identity silent=true ! identity silent=true ! fakesink silent=true",
340 /* Empty bin not allowed */
341 "bin.( )",
342 /* bin with non-existent element counts as empty, and not allowed */
343 "bin.( non_existent_element )",
344 /* bin with an element, assignments and then a syntax error */
345 "( filesrc blocksize=4 location=/dev/null @ )",
346 /* bin linking with the ! inside the bin and no ! outside */
347 "( fakesrc num-buffers=\"4\" ! ) identity silent=true ! fakesink silent=true",
348 /* bins with linking without ! */
349 /* FIXME: one element leaks as reported by valgrind */
350 "pipeline.(name=\"john\" fakesrc num-buffers=4 ( bin. ( ! queue ! identity silent=true !( queue ! fakesink silent=true )) ))",
351 /* non-existent bin-type containing already created elements */
352 "coffeebin.( fakesrc ! identity ! fakesink )",
353 /* non-existent bin-type in pipeline */
354 "fakesrc ! coffeebin.( identity ) ! fakesink",
355 /* unexpected pad references Part I */
356 "fakesrc ! .ch0 .ch1 fakesink",
357 /* unexpected pad references Part II */
358 "fakesrc .ch0 .ch1 ! fakesink",
359 /* unexpected pad references Part III */
360 "(fakesrc .ch1) ! fakesink",
361 /* unexpected full reference, I */
362 "(fakesrc name=s s.ch1) ! fakesink",
363 /* unexpected full reference, II */
364 "s.ch1 fakesrc ! fakesink",
365 /* unexpected full reference, III */
366 "fakesrc ! fakesink s.ch1",
367 /* unlinked src/sink URI */
368 "http://eff.org fakesrc ! fakesink",
369 /* catch assignments evaluated in wrong order */
370 "fakesrc name=ss name=st ss. ! fakesink",
371 /* unbalanced brackets */
372 "(", ")", ") (",
373 /* END: */
374 NULL
375 };
376
GST_START_TEST(expected_to_fail_pipes)377 GST_START_TEST (expected_to_fail_pipes)
378 {
379 const gchar **s;
380
381 for (s = expected_failures; *s != NULL; s++) {
382 expected_fail_pipe (*s);
383 }
384 }
385
386 GST_END_TEST;
387
388 static const gchar *leaking_failures[] = {
389 /* checks: Invalid pipeline syntax fails */
390 "fakesrc ! identity silent=true ! sgsdfagfd @ gfdgfdsgfsgSF",
391 /* checks: Attempting to link to a non-existent pad on an element
392 * created via URI handler should fail */
393 "fakesrc ! .foo file:///dev/null",
394 /* checks: That requesting an element which doesn't exist doesn't work */
395 "error-does-not-exist-src",
396 NULL
397 };
398
399 /* These don't seem to leak any longer? */
GST_START_TEST(leaking_fail_pipes)400 GST_START_TEST (leaking_fail_pipes)
401 {
402 const gchar **s;
403
404 for (s = leaking_failures; *s != NULL; s++) {
405 GST_INFO ("Trying pipe: %s", *s);
406 expected_fail_pipe (*s);
407 }
408 }
409
410 GST_END_TEST;
411
412 /* Helper function to test delayed linking support in parse_launch by creating
413 * a test element based on bin, which contains a fakesrc and a sometimes
414 * pad-template, and trying to link to a fakesink. When the bin transitions
415 * to paused it adds a pad, which should get linked to the fakesink */
416 static void
run_delayed_test(const gchar * pipe_str,const gchar * peer,gboolean expect_link)417 run_delayed_test (const gchar * pipe_str, const gchar * peer,
418 gboolean expect_link)
419 {
420 GstElement *pipe, *src, *sink;
421 GstPad *srcpad, *sinkpad, *peerpad = NULL;
422 GstStateChangeReturn ret;
423
424 pipe = setup_pipeline (pipe_str);
425
426 src = gst_bin_get_by_name (GST_BIN (pipe), "src");
427 fail_if (src == NULL, "Test source element was not created");
428
429 sink = gst_bin_get_by_name (GST_BIN (pipe), "sink");
430 fail_if (sink == NULL, "Test sink element was not created");
431
432 /* The src should not yet have a src pad */
433 srcpad = gst_element_get_static_pad (src, "src");
434 fail_unless (srcpad == NULL, "Source element already has a source pad");
435
436 /* Set the state to PAUSED and wait until the src at least reaches that
437 * state */
438 ret = gst_element_set_state (pipe, GST_STATE_PAUSED);
439
440 if (expect_link) {
441 fail_if (ret == GST_STATE_CHANGE_FAILURE);
442 } else {
443 fail_unless (ret == GST_STATE_CHANGE_FAILURE
444 || ret == GST_STATE_CHANGE_ASYNC);
445 }
446
447 ret = gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
448
449 if (expect_link) {
450 fail_if (ret == GST_STATE_CHANGE_FAILURE);
451 } else {
452 fail_unless (ret == GST_STATE_CHANGE_FAILURE);
453 }
454
455 /* Now, the source element should have a src pad, and if "peer" was passed,
456 * then the src pad should have gotten linked to the 'sink' pad of that
457 * peer */
458 srcpad = gst_element_get_static_pad (src, "src");
459 fail_if (srcpad == NULL, "Source element did not create source pad");
460
461 peerpad = gst_pad_get_peer (srcpad);
462
463 if (expect_link == TRUE) {
464 fail_if (peerpad == NULL, "Source element pad did not get linked");
465 } else {
466 fail_if (peerpad != NULL,
467 "Source element pad got linked but should not have");
468 }
469 if (peerpad != NULL)
470 gst_object_unref (peerpad);
471
472 if (peer != NULL) {
473 GstElement *peer_elem = gst_bin_get_by_name (GST_BIN (pipe), peer);
474
475 fail_if (peer_elem == NULL, "Could not retrieve peer %s", peer);
476
477 sinkpad = gst_element_get_static_pad (peer_elem, "sink");
478 gst_object_unref (peer_elem);
479 fail_if (sinkpad == NULL, "Peer element did not have a 'sink' pad");
480
481 fail_unless (peerpad == sinkpad,
482 "Source src pad got connected to the wrong peer");
483 gst_object_unref (sinkpad);
484 }
485
486 gst_object_unref (srcpad);
487
488 gst_object_unref (src);
489 gst_object_unref (sink);
490
491 gst_element_set_state (pipe, GST_STATE_NULL);
492 gst_object_unref (pipe);
493 }
494
GST_START_TEST(delayed_link)495 GST_START_TEST (delayed_link)
496 {
497 fail_unless (gst_element_register (NULL, "parsetestelement",
498 GST_RANK_NONE, GST_TYPE_PARSE_TEST_ELEMENT));
499
500 /* This tests the delayed linking support in parse_launch by creating
501 * a test element based on bin, which contains a fakesrc and a sometimes
502 * pad-template, and trying to link to a fakesink. When the bin transitions
503 * to paused it adds a pad, which should get linked to the fakesink */
504 run_delayed_test
505 ("parsetestelement name=src ! fakesink silent=true name=sink", "sink",
506 TRUE);
507 /* FIXME: valgrind finds one element */
508
509 /* Test, but this time specifying both pad names */
510 run_delayed_test ("parsetestelement name=src .src ! "
511 ".sink fakesink silent=true name=sink", "sink", TRUE);
512 /* FIXME: valgrind finds one element */
513
514 /* Now try with a caps filter, but not testing that
515 * the peerpad == sinkpad, because the peer will actually
516 * be a capsfilter */
517 run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
518 "fakesink silent=true name=sink", NULL, TRUE);
519
520 /* Now try with mutually exclusive caps filters that
521 * will prevent linking, but only once gets around to happening -
522 * ie, the pipeline should create ok but fail to change state */
523 run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
524 "identity silent=true ! application/x-other-caps ! "
525 "fakesink silent=true name=sink silent=true", NULL, FALSE);
526 }
527
528 GST_END_TEST;
529
530 typedef struct _GstParseTestElement
531 {
532 GstBin parent;
533
534 GstElement *fakesrc;
535 } GstParseTestElement;
536
537 typedef struct _GstParseTestElementClass
538 {
539 GstBinClass parent;
540 } GstParseTestElementClass;
541
542 static GstStaticPadTemplate test_element_pad_template =
543 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
544 GST_PAD_SOMETIMES, GST_STATIC_CAPS ("application/x-test-caps"));
545 #define gst_parse_test_element_parent_class parent_class
546 G_DEFINE_TYPE (GstParseTestElement, gst_parse_test_element, GST_TYPE_BIN);
547
548 static GstStateChangeReturn
549 gst_parse_test_element_change_state (GstElement * element,
550 GstStateChange transition);
551
552 static void
gst_parse_test_element_class_init(GstParseTestElementClass * klass)553 gst_parse_test_element_class_init (GstParseTestElementClass * klass)
554 {
555 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
556
557 gst_element_class_add_static_pad_template (gstelement_class,
558 &test_element_pad_template);
559
560 gst_element_class_set_metadata (gstelement_class,
561 "Test element for parse launch tests", "Source",
562 "Test element for parse launch tests in core",
563 "GStreamer Devel <gstreamer-devel@lists.sf.net>");
564
565 gstelement_class->change_state = gst_parse_test_element_change_state;
566 }
567
568 static void
gst_parse_test_element_init(GstParseTestElement * src)569 gst_parse_test_element_init (GstParseTestElement * src)
570 {
571 /* Create a fakesrc and add it to ourselves */
572 src->fakesrc = gst_element_factory_make ("fakesrc", NULL);
573 if (src->fakesrc)
574 gst_bin_add (GST_BIN (src), src->fakesrc);
575 }
576
577 static GstStateChangeReturn
gst_parse_test_element_change_state(GstElement * element,GstStateChange transition)578 gst_parse_test_element_change_state (GstElement * element,
579 GstStateChange transition)
580 {
581 GstParseTestElement *src = (GstParseTestElement *) element;
582
583 if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
584 /* Add our pad */
585 GstPad *pad;
586 GstPad *ghost;
587
588 if (src->fakesrc == NULL)
589 return GST_STATE_CHANGE_FAILURE;
590
591 pad = gst_element_get_static_pad (src->fakesrc, "src");
592 if (pad == NULL)
593 return GST_STATE_CHANGE_FAILURE;
594
595 ghost = gst_ghost_pad_new ("src", pad);
596 fail_if (ghost == NULL, "Failed to create ghost pad");
597 /* activate and add */
598 gst_pad_set_active (ghost, TRUE);
599 gst_element_add_pad (GST_ELEMENT (src), ghost);
600 gst_object_unref (pad);
601 }
602
603 return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
604 }
605
GST_START_TEST(test_missing_elements)606 GST_START_TEST (test_missing_elements)
607 {
608 GstParseContext *ctx;
609 GstElement *element;
610 GError *err = NULL;
611 gchar **arr;
612
613 /* avoid misleading 'no such element' error debug messages when using cvs */
614 if (!g_getenv ("GST_DEBUG"))
615 gst_debug_set_default_threshold (GST_LEVEL_NONE);
616
617 /* one missing element */
618 ctx = gst_parse_context_new ();
619 element = gst_parse_launch_full ("fakesrc ! coffeesink", ctx,
620 GST_PARSE_FLAG_FATAL_ERRORS, &err);
621 fail_unless (err != NULL, "expected error");
622 fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
623 fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
624 arr = gst_parse_context_get_missing_elements (ctx);
625 fail_unless (arr != NULL, "expected missing elements");
626 fail_unless_equals_string (arr[0], "coffeesink");
627 fail_unless (arr[1] == NULL);
628 g_strfreev (arr);
629 gst_parse_context_free (ctx);
630 g_error_free (err);
631 err = NULL;
632
633 /* multiple missing elements */
634 ctx = gst_parse_context_new ();
635 element = gst_parse_launch_full ("fakesrc ! bogusenc ! identity ! goomux ! "
636 "fakesink", ctx, GST_PARSE_FLAG_FATAL_ERRORS, &err);
637 fail_unless (err != NULL, "expected error");
638 fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
639 fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
640 arr = gst_parse_context_get_missing_elements (ctx);
641 fail_unless (arr != NULL, "expected missing elements");
642 fail_unless_equals_string (arr[0], "bogusenc");
643 fail_unless_equals_string (arr[1], "goomux");
644 fail_unless (arr[2] == NULL);
645 g_strfreev (arr);
646 gst_parse_context_free (ctx);
647 g_error_free (err);
648 err = NULL;
649
650 /* multiple missing elements, different link pattern */
651 ctx = gst_parse_context_new ();
652 element = gst_parse_launch_full ("fakesrc ! bogusenc ! mux.sink "
653 "blahsrc ! goomux name=mux ! fakesink fakesrc ! goosink", ctx,
654 GST_PARSE_FLAG_FATAL_ERRORS, &err);
655 fail_unless (err != NULL, "expected error");
656 fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
657 fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
658 arr = gst_parse_context_get_missing_elements (ctx);
659 fail_unless (arr != NULL, "expected missing elements");
660 fail_unless_equals_string (arr[0], "bogusenc");
661 fail_unless_equals_string (arr[1], "blahsrc");
662 fail_unless_equals_string (arr[2], "goomux");
663 fail_unless_equals_string (arr[3], "goosink");
664 fail_unless (arr[4] == NULL);
665 g_strfreev (arr);
666 gst_parse_context_free (ctx);
667 g_error_free (err);
668 err = NULL;
669 }
670
671 GST_END_TEST;
672
GST_START_TEST(test_preset)673 GST_START_TEST (test_preset)
674 {
675 GstElement *element;
676 GError *err = NULL;
677
678 /* missing preset */
679 element =
680 gst_parse_launch
681 ("fakesrc ! identity @preset=\"Wrong preset\" ! fakesink", &err);
682 fail_unless (err != NULL, "expected error");
683 fail_unless_equals_int (err->code, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY);
684 fail_unless (element != NULL, "Doesn't NULL return without FATAL_ERRORS");
685 gst_clear_object (&element);
686 g_clear_error (&err);
687 }
688
689 GST_END_TEST;
690
GST_START_TEST(test_flags)691 GST_START_TEST (test_flags)
692 {
693 GstElement *element;
694 GError *err = NULL;
695
696 /* avoid misleading 'no such element' error debug messages when using cvs */
697 if (!g_getenv ("GST_DEBUG"))
698 gst_debug_set_default_threshold (GST_LEVEL_NONE);
699
700 /* default behaviour is to return any already constructed bins/elements */
701 element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, 0, &err);
702 fail_unless (err != NULL, "expected error");
703 fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
704 fail_unless (element != NULL, "expected partial pipeline/element");
705 g_error_free (err);
706 err = NULL;
707 gst_object_unref (element);
708
709 /* test GST_PARSE_FLAG_FATAL_ERRORS */
710 element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
711 GST_PARSE_FLAG_FATAL_ERRORS, &err);
712 fail_unless (err != NULL, "expected error");
713 fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
714 fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
715 g_error_free (err);
716 err = NULL;
717
718 /* test GST_PARSE_FLAG_FATAL_ERRORS without GError */
719 element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
720 GST_PARSE_FLAG_FATAL_ERRORS, NULL);
721 fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
722 }
723
724 GST_END_TEST;
725
GST_START_TEST(test_parsing)726 GST_START_TEST (test_parsing)
727 {
728 GstElement *pipeline;
729
730 /* make sure we don't read beyond the end of the string */
731 pipeline = gst_parse_launch_full ("filesrc location=x\\", NULL, 0, NULL);
732 gst_object_unref (pipeline);
733 }
734
735 GST_END_TEST;
736
737 static Suite *
parse_suite(void)738 parse_suite (void)
739 {
740 Suite *s = suite_create ("Parse Launch syntax");
741 TCase *tc_chain = tcase_create ("parselaunch");
742
743 /* time out after 20s, not the default 3 */
744 tcase_set_timeout (tc_chain, 20);
745
746 suite_add_tcase (s, tc_chain);
747 tcase_add_test (tc_chain, test_launch_lines);
748 tcase_add_test (tc_chain, test_launch_lines2);
749 tcase_add_test (tc_chain, expected_to_fail_pipes);
750 tcase_add_test (tc_chain, leaking_fail_pipes);
751 tcase_add_test (tc_chain, delayed_link);
752 tcase_add_test (tc_chain, test_flags);
753 tcase_add_test (tc_chain, test_missing_elements);
754 tcase_add_test (tc_chain, test_parsing);
755 tcase_add_test (tc_chain, test_preset);
756 return s;
757 }
758
759 GST_CHECK_MAIN (parse);
760