"Fossies" - the Fresh Open Source Software Archive

Member "gstreamer-1.16.1/tests/check/pipelines/parse-launch.c" (19 Apr 2019, 25970 Bytes) of package /linux/misc/gstreamer-1.16.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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 *
   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
   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 ! 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 
  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   g_object_unref (efac);
  133   g_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 
  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 failes */
  325   "fakesrc ! ",
  326   /* checks: Link without src element failes */
  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 
  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? */
  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
  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 
  423   pipe = setup_pipeline (pipe_str);
  424 
  425   src = gst_bin_get_by_name (GST_BIN (pipe), "src");
  426   fail_if (src == NULL, "Test source element was not created");
  427 
  428   sink = gst_bin_get_by_name (GST_BIN (pipe), "sink");
  429   fail_if (sink == NULL, "Test sink element was not created");
  430 
  431   /* The src should not yet have a src pad */
  432   srcpad = gst_element_get_static_pad (src, "src");
  433   fail_unless (srcpad == NULL, "Source element already has a source pad");
  434 
  435   /* Set the state to PAUSED and wait until the src at least reaches that
  436    * state */
  437   fail_if (gst_element_set_state (pipe, GST_STATE_PAUSED) ==
  438       GST_STATE_CHANGE_FAILURE);
  439 
  440   fail_if (gst_element_get_state (src, NULL, NULL, GST_CLOCK_TIME_NONE) ==
  441       GST_STATE_CHANGE_FAILURE);
  442 
  443   /* Now, the source element should have a src pad, and if "peer" was passed, 
  444    * then the src pad should have gotten linked to the 'sink' pad of that 
  445    * peer */
  446   srcpad = gst_element_get_static_pad (src, "src");
  447   fail_if (srcpad == NULL, "Source element did not create source pad");
  448 
  449   peerpad = gst_pad_get_peer (srcpad);
  450 
  451   if (expect_link == TRUE) {
  452     fail_if (peerpad == NULL, "Source element pad did not get linked");
  453   } else {
  454     fail_if (peerpad != NULL,
  455         "Source element pad got linked but should not have");
  456   }
  457   if (peerpad != NULL)
  458     gst_object_unref (peerpad);
  459 
  460   if (peer != NULL) {
  461     GstElement *peer_elem = gst_bin_get_by_name (GST_BIN (pipe), peer);
  462 
  463     fail_if (peer_elem == NULL, "Could not retrieve peer %s", peer);
  464 
  465     sinkpad = gst_element_get_static_pad (peer_elem, "sink");
  466     gst_object_unref (peer_elem);
  467     fail_if (sinkpad == NULL, "Peer element did not have a 'sink' pad");
  468 
  469     fail_unless (peerpad == sinkpad,
  470         "Source src pad got connected to the wrong peer");
  471     gst_object_unref (sinkpad);
  472   }
  473 
  474   gst_object_unref (srcpad);
  475 
  476   gst_object_unref (src);
  477   gst_object_unref (sink);
  478 
  479   gst_element_set_state (pipe, GST_STATE_NULL);
  480   gst_object_unref (pipe);
  481 }
  482 
  483 GST_START_TEST (delayed_link)
  484 {
  485   fail_unless (gst_element_register (NULL, "parsetestelement",
  486           GST_RANK_NONE, GST_TYPE_PARSE_TEST_ELEMENT));
  487 
  488   /* This tests the delayed linking support in parse_launch by creating
  489    * a test element based on bin, which contains a fakesrc and a sometimes 
  490    * pad-template, and trying to link to a fakesink. When the bin transitions
  491    * to paused it adds a pad, which should get linked to the fakesink */
  492   run_delayed_test
  493       ("parsetestelement name=src ! fakesink silent=true name=sink", "sink",
  494       TRUE);
  495   /* FIXME: valgrind finds one element */
  496 
  497   /* Test, but this time specifying both pad names */
  498   run_delayed_test ("parsetestelement name=src .src ! "
  499       ".sink fakesink silent=true name=sink", "sink", TRUE);
  500   /* FIXME: valgrind finds one element */
  501 
  502   /* Now try with a caps filter, but not testing that
  503    * the peerpad == sinkpad, because the peer will actually
  504    * be a capsfilter */
  505   run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
  506       "fakesink silent=true name=sink", NULL, TRUE);
  507 
  508   /* Now try with mutually exclusive caps filters that 
  509    * will prevent linking, but only once gets around to happening -
  510    * ie, the pipeline should create ok but fail to change state */
  511   run_delayed_test ("parsetestelement name=src ! application/x-test-caps ! "
  512       "identity silent=true ! application/x-other-caps ! "
  513       "fakesink silent=true name=sink silent=true", NULL, FALSE);
  514 }
  515 
  516 GST_END_TEST;
  517 
  518 typedef struct _GstParseTestElement
  519 {
  520   GstBin parent;
  521 
  522   GstElement *fakesrc;
  523 } GstParseTestElement;
  524 
  525 typedef struct _GstParseTestElementClass
  526 {
  527   GstBinClass parent;
  528 } GstParseTestElementClass;
  529 
  530 static GstStaticPadTemplate test_element_pad_template =
  531 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
  532     GST_PAD_SOMETIMES, GST_STATIC_CAPS ("application/x-test-caps"));
  533 #define gst_parse_test_element_parent_class parent_class
  534 G_DEFINE_TYPE (GstParseTestElement, gst_parse_test_element, GST_TYPE_BIN);
  535 
  536 static GstStateChangeReturn
  537 gst_parse_test_element_change_state (GstElement * element,
  538     GstStateChange transition);
  539 
  540 static void
  541 gst_parse_test_element_class_init (GstParseTestElementClass * klass)
  542 {
  543   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
  544 
  545   gst_element_class_add_static_pad_template (gstelement_class,
  546       &test_element_pad_template);
  547 
  548   gst_element_class_set_metadata (gstelement_class,
  549       "Test element for parse launch tests", "Source",
  550       "Test element for parse launch tests in core",
  551       "GStreamer Devel <gstreamer-devel@lists.sf.net>");
  552 
  553   gstelement_class->change_state = gst_parse_test_element_change_state;
  554 }
  555 
  556 static void
  557 gst_parse_test_element_init (GstParseTestElement * src)
  558 {
  559   /* Create a fakesrc and add it to ourselves */
  560   src->fakesrc = gst_element_factory_make ("fakesrc", NULL);
  561   if (src->fakesrc)
  562     gst_bin_add (GST_BIN (src), src->fakesrc);
  563 }
  564 
  565 static GstStateChangeReturn
  566 gst_parse_test_element_change_state (GstElement * element,
  567     GstStateChange transition)
  568 {
  569   GstParseTestElement *src = (GstParseTestElement *) element;
  570 
  571   if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
  572     /* Add our pad */
  573     GstPad *pad;
  574     GstPad *ghost;
  575 
  576     if (src->fakesrc == NULL)
  577       return GST_STATE_CHANGE_FAILURE;
  578 
  579     pad = gst_element_get_static_pad (src->fakesrc, "src");
  580     if (pad == NULL)
  581       return GST_STATE_CHANGE_FAILURE;
  582 
  583     ghost = gst_ghost_pad_new ("src", pad);
  584     fail_if (ghost == NULL, "Failed to create ghost pad");
  585     /* activate and add */
  586     gst_pad_set_active (ghost, TRUE);
  587     gst_element_add_pad (GST_ELEMENT (src), ghost);
  588     gst_object_unref (pad);
  589   }
  590 
  591   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  592 }
  593 
  594 GST_START_TEST (test_missing_elements)
  595 {
  596   GstParseContext *ctx;
  597   GstElement *element;
  598   GError *err = NULL;
  599   gchar **arr;
  600 
  601   /* avoid misleading 'no such element' error debug messages when using cvs */
  602   if (!g_getenv ("GST_DEBUG"))
  603     gst_debug_set_default_threshold (GST_LEVEL_NONE);
  604 
  605   /* one missing element */
  606   ctx = gst_parse_context_new ();
  607   element = gst_parse_launch_full ("fakesrc ! coffeesink", ctx,
  608       GST_PARSE_FLAG_FATAL_ERRORS, &err);
  609   fail_unless (err != NULL, "expected error");
  610   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
  611   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
  612   arr = gst_parse_context_get_missing_elements (ctx);
  613   fail_unless (arr != NULL, "expected missing elements");
  614   fail_unless_equals_string (arr[0], "coffeesink");
  615   fail_unless (arr[1] == NULL);
  616   g_strfreev (arr);
  617   gst_parse_context_free (ctx);
  618   g_error_free (err);
  619   err = NULL;
  620 
  621   /* multiple missing elements */
  622   ctx = gst_parse_context_new ();
  623   element = gst_parse_launch_full ("fakesrc ! bogusenc ! identity ! goomux ! "
  624       "fakesink", ctx, GST_PARSE_FLAG_FATAL_ERRORS, &err);
  625   fail_unless (err != NULL, "expected error");
  626   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
  627   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
  628   arr = gst_parse_context_get_missing_elements (ctx);
  629   fail_unless (arr != NULL, "expected missing elements");
  630   fail_unless_equals_string (arr[0], "bogusenc");
  631   fail_unless_equals_string (arr[1], "goomux");
  632   fail_unless (arr[2] == NULL);
  633   g_strfreev (arr);
  634   gst_parse_context_free (ctx);
  635   g_error_free (err);
  636   err = NULL;
  637 
  638   /* multiple missing elements, different link pattern */
  639   ctx = gst_parse_context_new ();
  640   element = gst_parse_launch_full ("fakesrc ! bogusenc ! mux.sink "
  641       "blahsrc ! goomux name=mux ! fakesink   fakesrc ! goosink", ctx,
  642       GST_PARSE_FLAG_FATAL_ERRORS, &err);
  643   fail_unless (err != NULL, "expected error");
  644   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
  645   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
  646   arr = gst_parse_context_get_missing_elements (ctx);
  647   fail_unless (arr != NULL, "expected missing elements");
  648   fail_unless_equals_string (arr[0], "bogusenc");
  649   fail_unless_equals_string (arr[1], "blahsrc");
  650   fail_unless_equals_string (arr[2], "goomux");
  651   fail_unless_equals_string (arr[3], "goosink");
  652   fail_unless (arr[4] == NULL);
  653   g_strfreev (arr);
  654   gst_parse_context_free (ctx);
  655   g_error_free (err);
  656   err = NULL;
  657 }
  658 
  659 GST_END_TEST;
  660 
  661 GST_START_TEST (test_flags)
  662 {
  663   GstElement *element;
  664   GError *err = NULL;
  665 
  666   /* avoid misleading 'no such element' error debug messages when using cvs */
  667   if (!g_getenv ("GST_DEBUG"))
  668     gst_debug_set_default_threshold (GST_LEVEL_NONE);
  669 
  670   /* default behaviour is to return any already constructed bins/elements */
  671   element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL, 0, &err);
  672   fail_unless (err != NULL, "expected error");
  673   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
  674   fail_unless (element != NULL, "expected partial pipeline/element");
  675   g_error_free (err);
  676   err = NULL;
  677   gst_object_unref (element);
  678 
  679   /* test GST_PARSE_FLAG_FATAL_ERRORS */
  680   element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
  681       GST_PARSE_FLAG_FATAL_ERRORS, &err);
  682   fail_unless (err != NULL, "expected error");
  683   fail_unless_equals_int (err->code, GST_PARSE_ERROR_NO_SUCH_ELEMENT);
  684   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
  685   g_error_free (err);
  686   err = NULL;
  687 
  688   /* test GST_PARSE_FLAG_FATAL_ERRORS without GError */
  689   element = gst_parse_launch_full ("fakesrc ! coffeesink", NULL,
  690       GST_PARSE_FLAG_FATAL_ERRORS, NULL);
  691   fail_unless (element == NULL, "expected NULL return with FATAL_ERRORS");
  692 }
  693 
  694 GST_END_TEST;
  695 
  696 GST_START_TEST (test_parsing)
  697 {
  698   GstElement *pipeline;
  699 
  700   /* make sure we don't read beyond the end of the string */
  701   pipeline = gst_parse_launch_full ("filesrc location=x\\", NULL, 0, NULL);
  702   gst_object_unref (pipeline);
  703 }
  704 
  705 GST_END_TEST;
  706 
  707 static Suite *
  708 parse_suite (void)
  709 {
  710   Suite *s = suite_create ("Parse Launch syntax");
  711   TCase *tc_chain = tcase_create ("parselaunch");
  712 
  713   /* time out after 20s, not the default 3 */
  714   tcase_set_timeout (tc_chain, 20);
  715 
  716   suite_add_tcase (s, tc_chain);
  717   tcase_add_test (tc_chain, test_launch_lines);
  718   tcase_add_test (tc_chain, test_launch_lines2);
  719   tcase_add_test (tc_chain, expected_to_fail_pipes);
  720   tcase_add_test (tc_chain, leaking_fail_pipes);
  721   tcase_add_test (tc_chain, delayed_link);
  722   tcase_add_test (tc_chain, test_flags);
  723   tcase_add_test (tc_chain, test_missing_elements);
  724   tcase_add_test (tc_chain, test_parsing);
  725   return s;
  726 }
  727 
  728 GST_CHECK_MAIN (parse);