fix request pad
[platform/upstream/gstreamer.git] / tests / check / pipelines / parse-launch.c
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24
25 #ifdef HAVE_VALGRIND_H
26 # include <valgrind/valgrind.h>
27 # include <valgrind/memcheck.h>
28 #endif
29
30 #include <gst/check/gstcheck.h>
31
32 #define GST_TYPE_PARSE_TEST_ELEMENT (gst_parse_test_element_get_type())
33 static GType gst_parse_test_element_get_type (void);
34
35 static GstElement *
36 setup_pipeline (const gchar * pipe_descr)
37 {
38   GstElement *pipeline;
39   GError *error = NULL;
40
41   pipeline = gst_parse_launch (pipe_descr, &error);
42
43   GST_DEBUG ("created %s", pipe_descr);
44
45   if (error != NULL) {
46     fail_if (error != NULL, "Error parsing pipeline %s: %s", pipe_descr,
47         error->message);
48     g_error_free (error);
49   }
50   fail_unless (pipeline != NULL, "Failed to create pipeline %s", pipe_descr);
51   return pipeline;
52 }
53
54 static void
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
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-yuv ! fakesink silent=true",
99   "fakesrc !   video/raw,  format=(string)YUY2; video/raw, format=(string)YV12 ! fakesink silent=true",
100   "fakesrc ! audio/x-raw-int, 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.",
103   "fakesrc ! 1dentity ! fakesink silent=true",
104   NULL
105 };
106
107 GST_START_TEST (test_launch_lines)
108 {
109   GstElement *pipeline;
110   const gchar **s;
111   GType type;
112   GstElementFactory *efac;
113
114   efac = gst_element_factory_find ("identity");
115   fail_unless (efac != NULL);
116   efac =
117       GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (efac)));
118   fail_unless (efac != NULL);
119   type = gst_element_factory_get_element_type (efac);
120   fail_unless (type != 0);
121   g_object_unref (efac);
122   fail_unless (gst_element_register (NULL, "1dentity", GST_RANK_NONE, type));
123
124   for (s = test_lines; *s != NULL; s++) {
125     pipeline = setup_pipeline (*s);
126     gst_object_unref (pipeline);
127   }
128 }
129
130 GST_END_TEST;
131
132 #define PIPELINE1  "fakesrc"
133 #define PIPELINE2  "fakesrc name=donald num-buffers= 27 silent =TruE sizetype = 3 data=   Subbuffer\\ data"
134 #define PIPELINE3  "fakesrc identity silent=true fakesink silent=true"
135 #define PIPELINE4  "fakesrc num-buffers=4 .src ! identity silent=true !.sink identity silent=true .src ! .sink fakesink silent=true"
136 #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"
137 #define PIPELINE6  "pipeline.(name=\"john\" fakesrc num-buffers=4 ( bin. ( ! queue ! identity silent=true !( queue ! fakesink silent=true )) ))"
138 #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."
139 /* aggregator is borked
140  * #define PIPELINE8  "fakesrc num-buffers=4 ! tee name=tee1 .src0,src1 ! .sink0, sink1 aggregator ! fakesink silent=true"
141  * */
142 #define PIPELINE8  "fakesrc num-buffers=4 ! fakesink silent=true"
143 #define PIPELINE9  "fakesrc num-buffers=4 ! test. fakesink silent=true name=test"
144 #define PIPELINE10 "( fakesrc num-buffers=\"4\" ! ) identity silent=true ! fakesink silent=true"
145 #define PIPELINE11 "fakesink silent=true name = sink identity silent=true name=id ( fakesrc num-buffers=\"4\" ! id. ) id. ! sink."
146 #define PIPELINE12 "file:///tmp/test.file ! fakesink silent=true"
147 #define PIPELINE13 "fakesrc ! file:///tmp/test.file"
148 #define PIPELINE14 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\,x\""
149 #define PIPELINE15 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\\"x\\,x\""
150
151 GST_START_TEST (test_launch_lines2)
152 {
153   GstElement *cur;
154   gint i;
155   gboolean b;
156   gchar *s = NULL;
157
158   /**
159    * checks:
160    * - specifying an element works :)
161    * - if only 1 element is requested, no bin is returned, but the element
162    */
163   cur = setup_pipeline (PIPELINE1);
164   fail_unless (G_OBJECT_TYPE (cur) == g_type_from_name ("GstFakeSrc"),
165       "parse_launch did not produce a fakesrc");
166   gst_object_unref (cur);
167
168   /**
169    * checks:
170    * - properties works
171    * - string, int, boolean and enums can be properly set
172    * - first test of escaping strings
173    */
174   cur = setup_pipeline (PIPELINE2);
175   g_object_get (G_OBJECT (cur), "name", &s, "num-buffers", &i,
176       "silent", &b, NULL);
177   fail_if (s == NULL, "name was NULL");
178   fail_unless (strcmp (s, "donald") == 0, "fakesrc name was not 'donald'");
179   fail_unless (i == 27, "num-buffers was not 27");
180   fail_unless (b == TRUE, "silent was not TRUE");
181   g_free (s);
182
183   g_object_get (G_OBJECT (cur), "sizetype", &i, NULL);
184   fail_unless (i == 3, "sizetype != 3");
185
186   g_object_get (G_OBJECT (cur), "data", &i, NULL);
187   fail_unless (i == 2, "data != 2");
188   gst_object_unref (cur);
189
190   /**
191    * checks:
192    * - specifying multiple elements without links works
193    * - if multiple toplevel elements exist, a pipeline is returned
194    */
195   cur = setup_pipeline (PIPELINE3);
196   fail_unless (GST_BIN_NUMCHILDREN (cur) == 3,
197       "Pipeline does not contain 3 children");
198   gst_object_unref (cur);
199
200   /**
201    * checks:
202    * - test default link "!"
203    * - test if specifying pads on links works
204    */
205   cur = setup_pipeline (PIPELINE4);
206   check_pipeline_runs (cur);
207   gst_object_unref (cur);
208
209   /**
210    * checks:
211    * - test if appending the links works, too
212    * - check if the pipeline constructed works the same as the one before (how?)
213    */
214   cur = setup_pipeline (PIPELINE5);
215   check_pipeline_runs (cur);
216   gst_object_unref (cur);
217
218   /**
219    * checks:
220    * - test various types of bins
221    * - test if linking across bins works
222    * - test if escaping strings works
223    */
224   cur = setup_pipeline (PIPELINE6);
225   fail_unless (GST_IS_PIPELINE (cur), "Parse did not produce a pipeline");
226   g_object_get (G_OBJECT (cur), "name", &s, NULL);
227   fail_if (s == NULL, "name was NULL");
228   fail_unless (strcmp (s, "john") == 0, "Name was not 'john'");
229   g_free (s);
230   check_pipeline_runs (cur);
231   gst_object_unref (cur);
232
233   /**
234    * checks:
235    * - test request pads
236    */
237   cur = setup_pipeline (PIPELINE7);
238   check_pipeline_runs (cur);
239   gst_object_unref (cur);
240
241   /**
242    * checks:
243    * - multiple pads on 1 link
244    */
245   cur = setup_pipeline (PIPELINE8);
246   check_pipeline_runs (cur);
247   gst_object_unref (cur);
248
249   /**
250    * checks:
251    * - failed in grammar.y cvs version 1.17
252    */
253   cur = setup_pipeline (PIPELINE9);
254   check_pipeline_runs (cur);
255   gst_object_unref (cur);
256
257   /**
258    * checks:
259    * - failed in grammar.y cvs version 1.17
260    */
261   cur = setup_pipeline (PIPELINE10);
262   check_pipeline_runs (cur);
263   gst_object_unref (cur);
264
265   /**
266    * checks:
267    * - failed in grammar.y cvs version 1.18
268    */
269   cur = setup_pipeline (PIPELINE11);
270   check_pipeline_runs (cur);
271   gst_object_unref (cur);
272
273   /**
274    * checks:
275    * - URI detection works
276    */
277   cur = setup_pipeline (PIPELINE12);
278   gst_object_unref (cur);
279
280   /** * checks:
281    * - URI sink detection works
282    */
283   cur = setup_pipeline (PIPELINE13);
284   gst_object_unref (cur);
285
286   /* Checks handling of a assignment followed by error inside a bin. 
287    * This should warn, but ignore the error and carry on */
288   cur = setup_pipeline ("( filesrc blocksize=4 location=/dev/null @ )");
289   gst_object_unref (cur);
290
291   /**
292    * Checks if characters inside quotes are not escaped.
293   */
294   cur = setup_pipeline (PIPELINE14);
295   gst_object_unref (cur);
296
297   /**
298    * Checks if escaped quotes inside quotes are not treated as end string quotes.
299    * This would make the rest of characters to be escaped incorrectly.
300    */
301   cur = setup_pipeline (PIPELINE15);
302   gst_object_unref (cur);
303 }
304
305 GST_END_TEST;
306
307 static const gchar *expected_failures[] = {
308   /* checks: fails because a=b. is not a valid element reference in parse.l */
309   "fakesrc num-buffers=4 name=\"a=b\"  a=b. ! fakesink silent=true",
310   /* checks: Error branch for a non-deserialisable property value */
311   "filesrc blocksize=absdff",
312   /* checks: That broken caps which don't parse can't create a pipeline */
313   "fakesrc ! video/raw,format=(antwerp)monkeys ! fakesink silent=true",
314   /* checks: Empty pipeline is invalid */
315   "",
316   /* checks: Link without sink element failes */
317   "fakesrc ! ",
318   /* checks: Link without src element failes */
319   " ! fakesink silent=true",
320   /* checks: Source URI for which no element exists is a failure */
321   "borky://fdaffd ! fakesink silent=true",
322   /* checks: Sink URI for which no element exists is a failure */
323   "fakesrc ! borky://fdaffd",
324   /* checks: Referencing non-existent source element by name can't link */
325   "fakesrc name=src fakesink silent=true name=sink noexiste. ! sink.",
326   /* checks: Referencing non-existent sink element by name can't link */
327   "fakesrc name=src fakesink silent=true name=sink src. ! noexiste.",
328   /* checks: Can't link 2 elements that only have sink pads */
329   "fakesink silent=true ! fakesink silent=true",
330   /* checks multi-chain link without src element fails. */
331   "! identity silent=true ! identity silent=true ! fakesink silent=true",
332   /* Empty bin not allowed */
333   "bin.( )",
334   /* bin with non-existent element counts as empty, and not allowed */
335   "bin.( non_existent_element )",
336   /* END: */
337   NULL
338 };
339
340 GST_START_TEST (expected_to_fail_pipes)
341 {
342   const gchar **s;
343
344   for (s = expected_failures; *s != NULL; s++) {
345     expected_fail_pipe (*s);
346   }
347 }
348
349 GST_END_TEST;
350
351 static const gchar *leaking_failures[] = {
352   /* checks: Invalid pipeline syntax fails */
353   "fakesrc ! identity silent=true ! sgsdfagfd @ gfdgfdsgfsgSF",
354   /* checks: Attempting to link to a non-existent pad on an element 
355    * created via URI handler should fail */
356   "fakesrc ! .foo file:///dev/null",
357   /* checks: That requesting an element which doesn't exist doesn't work */
358   "error-does-not-exist-src",
359   NULL
360 };
361
362 GST_START_TEST (leaking_fail_pipes)
363 {
364   const gchar **s;
365
366   for (s = leaking_failures; *s != NULL; s++) {
367     /* Uncomment if you want to try fixing the leaks */
368 #if 0
369     g_print ("Trying pipe: %s\n", *s);
370     expected_fail_pipe (*s);
371 #endif
372 #ifdef HAVE_VALGRIND_H
373     VALGRIND_DO_LEAK_CHECK;
374 #endif
375   }
376 }
377
378 GST_END_TEST;
379
380 /* Helper function to test delayed linking support in parse_launch by creating
381  * a test element based on bin, which contains a fakesrc and a sometimes 
382  * pad-template, and trying to link to a fakesink. When the bin transitions
383  * to paused it adds a pad, which should get linked to the fakesink */
384 static void
385 run_delayed_test (const gchar * pipe_str, const gchar * peer,
386     gboolean expect_link)
387 {
388   GstElement *pipe, *src, *sink;
389   GstPad *srcpad, *sinkpad, *peerpad = NULL;
390
391   pipe = setup_pipeline (pipe_str);
392
393   src = gst_bin_get_by_name (GST_BIN (pipe), "src");
394   fail_if (src == NULL, "Test source element was not created");
395
396   sink = gst_bin_get_by_name (GST_BIN (pipe), "sink");
397   fail_if (sink == NULL, "Test sink element was not created");
398
399   /* The src should not yet have a src pad */
400   srcpad = gst_element_get_static_pad (src, "src");
401   fail_unless (srcpad == NULL, "Source element already has a source pad");
402
403   /* Set the state to PAUSED and wait until the src at least reaches that
404    * state */
405   fail_if (gst_element_set_state (pipe, GST_STATE_PAUSED) ==
406       GST_STATE_CHANGE_FAILURE);
407
408   fail_if (gst_element_get_state (src, NULL, NULL, GST_CLOCK_TIME_NONE) ==
409       GST_STATE_CHANGE_FAILURE);
410
411   /* Now, the source element should have a src pad, and if "peer" was passed, 
412    * then the src pad should have gotten linked to the 'sink' pad of that 
413    * peer */
414   srcpad = gst_element_get_static_pad (src, "src");
415   fail_if (srcpad == NULL, "Source element did not create source pad");
416
417   peerpad = gst_pad_get_peer (srcpad);
418
419   if (expect_link == TRUE) {
420     fail_if (peerpad == NULL, "Source element pad did not get linked");
421   } else {
422     fail_if (peerpad != NULL,
423         "Source element pad got linked but should not have");
424   }
425   if (peerpad != NULL)
426     gst_object_unref (peerpad);
427
428   if (peer != NULL) {
429     GstElement *peer_elem = gst_bin_get_by_name (GST_BIN (pipe), peer);
430
431     fail_if (peer_elem == NULL, "Could not retrieve peer %s", peer);
432
433     sinkpad = gst_element_get_static_pad (peer_elem, "sink");
434     fail_if (sinkpad == NULL, "Peer element did not have a 'sink' pad");
435
436     fail_unless (peerpad == sinkpad,
437         "Source src pad got connected to the wrong peer");
438     gst_object_unref (sinkpad);
439   }
440
441   gst_object_unref (srcpad);
442
443   gst_object_unref (src);
444   gst_object_unref (sink);
445
446   gst_element_set_state (pipe, GST_STATE_NULL);
447   gst_object_unref (pipe);
448 }
449
450 GST_START_TEST (delayed_link)
451 {
452   fail_unless (gst_element_register (NULL, "parsetestelement",
453           GST_RANK_NONE, GST_TYPE_PARSE_TEST_ELEMENT));
454
455   /* This tests the delayed linking support in parse_launch by creating
456    * a test element based on bin, which contains a fakesrc and a sometimes 
457    * pad-template, and trying to link to a fakesink. When the bin transitions
458    * to paused it adds a pad, which should get linked to the fakesink */
459   run_delayed_test
460       ("parsetestelement name=src ! fakesink silent=true name=sink", "sink",
461       TRUE);
462
463   /* Test, but this time specifying both pad names */
464   run_delayed_test ("parsetestelement name=src .src ! "
465       ".sink fakesink silent=true name=sink", "sink", TRUE);
466
467   /* Now try with a caps filter, but not testing that
468    * the peerpad == sinkpad, because the peer will actually
469    * be a capsfilter */
470   run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
471       "fakesink silent=true name=sink", NULL, TRUE);
472
473   /* Now try with mutually exclusive caps filters that 
474    * will prevent linking, but only once gets around to happening -
475    * ie, the pipeline should create ok but fail to change state */
476   run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
477       "identity silent=true ! application/x-other-caps ! "
478       "fakesink silent=true name=sink silent=true", NULL, FALSE);
479 }
480
481 GST_END_TEST;
482
483 typedef struct _GstParseTestElement
484 {
485   GstBin parent;
486
487   GstElement *fakesrc;
488 } GstParseTestElement;
489
490 typedef struct _GstParseTestElementClass
491 {
492   GstBinClass parent;
493 } GstParseTestElementClass;
494
495 static GstStaticPadTemplate test_element_pad_template =
496 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
497     GST_PAD_SOMETIMES, GST_STATIC_CAPS ("application/x-test-caps"));
498 #define gst_parse_test_element_parent_class parent_class
499 G_DEFINE_TYPE (GstParseTestElement, gst_parse_test_element, GST_TYPE_BIN);
500
501 static GstStateChangeReturn
502 gst_parse_test_element_change_state (GstElement * element,
503     GstStateChange transition);
504
505 static void
506 gst_parse_test_element_class_init (GstParseTestElementClass * klass)
507 {
508   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
509
510   gst_element_class_add_pad_template (gstelement_class,
511       gst_static_pad_template_get (&test_element_pad_template));
512
513   gst_element_class_set_details_simple (gstelement_class,
514       "Test element for parse launch tests", "Source",
515       "Test element for parse launch tests in core",
516       "GStreamer Devel <gstreamer-devel@lists.sf.net>");
517
518   gstelement_class->change_state = gst_parse_test_element_change_state;
519 }
520
521 static void
522 gst_parse_test_element_init (GstParseTestElement * src)
523 {
524   /* Create a fakesrc and add it to ourselves */
525   src->fakesrc = gst_element_factory_make ("fakesrc", NULL);
526   if (src->fakesrc)
527     gst_bin_add (GST_BIN (src), src->fakesrc);
528 }
529
530 static GstStateChangeReturn
531 gst_parse_test_element_change_state (GstElement * element,
532     GstStateChange transition)
533 {
534   GstParseTestElement *src = (GstParseTestElement *) element;
535
536   if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
537     /* Add our pad */
538     GstPad *pad;
539     GstPad *ghost;
540
541     if (src->fakesrc == NULL)
542       return GST_STATE_CHANGE_FAILURE;
543
544     pad = gst_element_get_static_pad (src->fakesrc, "src");
545     if (pad == NULL)
546       return GST_STATE_CHANGE_FAILURE;
547
548     ghost = gst_ghost_pad_new ("src", pad);
549     fail_if (ghost == NULL, "Failed to create ghost pad");
550     /* activate and add */
551     gst_pad_set_active (ghost, TRUE);
552     gst_element_add_pad (GST_ELEMENT (src), ghost);
553     gst_object_unref (pad);
554   }
555
556   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
557 }
558
559 GST_START_TEST (test_missing_elements)
560 {
561   GstParseContext *ctx;
562   GstElement *element;
563   GError *err = NULL;
564   gchar **arr;
565
566   /* avoid misleading 'no such element' error debug messages when using cvs */
567   if (!g_getenv ("GST_DEBUG"))
568     gst_debug_set_default_threshold (GST_LEVEL_NONE);
569
570   /* one missing element */
571   ctx = gst_parse_context_new ();
572   element = gst_parse_launch_full ("fakesrc ! coffeesink", ctx,
573       GST_PARSE_FLAG_FATAL_ERRORS, &err);
574   fail_unless (err != NULL, "expected error");
575   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
576   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
577   arr = gst_parse_context_get_missing_elements (ctx);
578   fail_unless (arr != NULL, "expected missing elements");
579   fail_unless_equals_string (arr[0], "coffeesink");
580   fail_unless (arr[1] == NULL);
581   g_strfreev (arr);
582   gst_parse_context_free (ctx);
583   g_error_free (err);
584   err = NULL;
585
586   /* multiple missing elements */
587   ctx = gst_parse_context_new ();
588   element = gst_parse_launch_full ("fakesrc ! bogusenc ! identity ! goomux ! "
589       "fakesink", ctx, GST_PARSE_FLAG_FATAL_ERRORS, &err);
590   fail_unless (err != NULL, "expected error");
591   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
592   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
593   arr = gst_parse_context_get_missing_elements (ctx);
594   fail_unless (arr != NULL, "expected missing elements");
595   fail_unless_equals_string (arr[0], "bogusenc");
596   fail_unless_equals_string (arr[1], "goomux");
597   fail_unless (arr[2] == NULL);
598   g_strfreev (arr);
599   gst_parse_context_free (ctx);
600   g_error_free (err);
601   err = NULL;
602
603   /* multiple missing elements, different link pattern */
604   ctx = gst_parse_context_new ();
605   element = gst_parse_launch_full ("fakesrc ! bogusenc ! mux.sink "
606       "blahsrc ! goomux name=mux ! fakesink   fakesrc ! goosink", ctx,
607       GST_PARSE_FLAG_FATAL_ERRORS, &err);
608   fail_unless (err != NULL, "expected error");
609   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
610   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
611   arr = gst_parse_context_get_missing_elements (ctx);
612   fail_unless (arr != NULL, "expected missing elements");
613   fail_unless_equals_string (arr[0], "bogusenc");
614   fail_unless_equals_string (arr[1], "blahsrc");
615   fail_unless_equals_string (arr[2], "goomux");
616   fail_unless_equals_string (arr[3], "goosink");
617   fail_unless (arr[4] == NULL);
618   g_strfreev (arr);
619   gst_parse_context_free (ctx);
620   g_error_free (err);
621   err = NULL;
622 }
623
624 GST_END_TEST;
625
626 GST_START_TEST (test_flags)
627 {
628   GstElement *element;
629   GError *err = NULL;
630
631   /* avoid misleading 'no such element' error debug messages when using cvs */
632   if (!g_getenv ("GST_DEBUG"))
633     gst_debug_set_default_threshold (GST_LEVEL_NONE);
634
635   /* default behaviour is to return any already constructed bins/elements */
636   element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, 0, &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 partial pipeline/element");
640   g_error_free (err);
641   err = NULL;
642   gst_object_unref (element);
643
644   /* test GST_PARSE_FLAG_FATAL_ERRORS */
645   element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
646       GST_PARSE_FLAG_FATAL_ERRORS, &err);
647   fail_unless (err != NULL, "expected error");
648   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
649   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
650   g_error_free (err);
651   err = NULL;
652 }
653
654 GST_END_TEST;
655
656 GST_START_TEST (test_parsing)
657 {
658   GstElement *pipeline;
659
660   /* make sure we don't read beyond the end of the string */
661   pipeline = gst_parse_launch_full ("filesrc location=x\\", NULL, 0, NULL);
662   gst_object_unref (pipeline);
663 }
664
665 GST_END_TEST;
666
667 static Suite *
668 parse_suite (void)
669 {
670   Suite *s = suite_create ("Parse Launch syntax");
671   TCase *tc_chain = tcase_create ("parselaunch");
672
673   /* time out after 20s, not the default 3 */
674   tcase_set_timeout (tc_chain, 20);
675
676   suite_add_tcase (s, tc_chain);
677   tcase_add_test (tc_chain, test_launch_lines);
678   tcase_add_test (tc_chain, test_launch_lines2);
679   tcase_add_test (tc_chain, expected_to_fail_pipes);
680   tcase_add_test (tc_chain, leaking_fail_pipes);
681   tcase_add_test (tc_chain, delayed_link);
682   tcase_add_test (tc_chain, test_flags);
683   tcase_add_test (tc_chain, test_missing_elements);
684   tcase_add_test (tc_chain, test_parsing);
685   return s;
686 }
687
688 GST_CHECK_MAIN (parse);