[farsight2/master] Implement complete 2 person test

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:20:23 PST 2008


---
 tests/check/main/generic.c       |  112 ++++++++++++
 tests/check/main/generic.h       |   26 +++-
 tests/check/main/rtpconference.c |  370 ++++++++++++++++++++++++++++++++++----
 3 files changed, 472 insertions(+), 36 deletions(-)

diff --git a/tests/check/main/generic.c b/tests/check/main/generic.c
index 008242d..9001d4d 100644
--- a/tests/check/main/generic.c
+++ b/tests/check/main/generic.c
@@ -18,8 +18,120 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 
 
 #include "generic.h"
 
+#include <gst/check/gstcheck.h>
+#include <gst/farsight/fs-conference-iface.h>
 
+struct SimpleTestConference *
+setup_simple_conference (
+    gchar *conference_elem,
+    gchar *cname)
+{
+  struct SimpleTestConference *dat = g_new0 (struct SimpleTestConference, 1);
+  GError *error = NULL;
+
+  dat->pipeline = gst_pipeline_new ("pipeline");
+  fail_if (dat->pipeline == NULL);
+
+  dat->conference = gst_element_factory_make (conference_elem, NULL);
+  fail_if (dat->conference == NULL, "Could not build %s", conference_elem);
+  fail_unless (gst_bin_add (GST_BIN (dat->pipeline), dat->conference),
+      "Could not add conference to the pipeline");
+
+  dat->session = fs_conference_new_session (FS_CONFERENCE (dat->conference),
+      FS_MEDIA_TYPE_AUDIO, &error);
+  if (error)
+    fail ("Error while creating new session (%d): %s",
+        error->code, error->message);
+  fail_if (dat->session == NULL, "Could not make session, but no GError!");
+
+  dat->participant = fs_conference_new_participant (
+      FS_CONFERENCE (dat->conference), cname, &error);
+  if (error)
+    fail ("Error while creating new participant (%d): %s",
+        error->code, error->message);
+  fail_if (dat->session == NULL, "Could not make participant, but no GError!");
+
+  dat->stream = fs_session_new_stream (dat->session, dat->participant,
+      FS_DIRECTION_BOTH, "rawudp", 0, NULL, &error);
+  if (error)
+    fail ("Error while creating new stream (%d): %s",
+        error->code, error->message);
+  fail_if (dat->stream == NULL, "Could not make stream, but no GError!");
+
+  return dat;
+}
+
+
+void
+cleanup_simple_conference (struct SimpleTestConference *dat)
+{
+
+  g_object_unref (dat->stream);
+  g_object_unref (dat->session);
+  g_object_unref (dat->participant);
+  gst_object_unref (dat->pipeline);
+  g_free (dat);
+}
+
+
+void
+setup_fakesrc (struct SimpleTestConference *dat)
+{
+  GstElement *capsfilter = NULL;
+  GstCaps *caps = NULL;
+  GstPad *sinkpad = NULL, *srcpad = NULL;
+
+  g_debug ("Adding fakesrc");
+
+  capsfilter = gst_element_factory_make ("capsfilter", NULL);
+  fail_if (capsfilter == NULL, "Could not make capsfilter");
+  gst_bin_add (GST_BIN (dat->pipeline), capsfilter);
+
+  caps = gst_caps_new_simple ("audio/x-raw-int",
+      "rate", G_TYPE_INT, 8000,
+      "channels", G_TYPE_INT, 1,
+      NULL);
+
+  g_object_set (capsfilter, "caps", caps, NULL);
+
+  gst_caps_unref (caps);
+
+  g_object_get (dat->session, "sink-pad", &sinkpad, NULL);
+  fail_if (sinkpad == NULL, "Could not get session sinkpad");
+
+  srcpad = gst_element_get_static_pad (capsfilter, "src");
+
+  fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
+      "Could not link the capsfilter and the fsrtpconference");
+
+  gst_object_unref (sinkpad);
+  gst_object_unref (srcpad);
+
+  dat->fakesrc = gst_element_factory_make ("fakesrc", NULL);
+  fail_if (dat->fakesrc == NULL, "Could not make fakesrc");
+  gst_bin_add (GST_BIN (dat->pipeline), dat->fakesrc);
+
+  g_object_set (dat->fakesrc,
+      /* "num-buffers", 2000, */
+      "sizetype", 2,
+      "sizemax", 10,
+      "is-live", TRUE,
+      NULL);
+
+  fail_unless (gst_element_link_pads (dat->fakesrc, "src", capsfilter, "sink"),
+      "Could not link capsfilter to sink");
+
+  if (dat->started)
+  {
+    gst_element_set_state (dat->pipeline, GST_STATE_PLAYING);
+    dat->started = TRUE;
+  }
+
+}
diff --git a/tests/check/main/generic.h b/tests/check/main/generic.h
index 54d97a9..d431820 100644
--- a/tests/check/main/generic.h
+++ b/tests/check/main/generic.h
@@ -19,12 +19,32 @@
  */
 
 
-#include <gst/gst.h>
-
 #ifndef __GENERIC_H__
 #define __GENERIC_H__
 
-GstElement *setup_pipeline (gchar *conference_elem);
+#include <gst/gst.h>
+#include <gst/farsight/fs-conference-iface.h>
+
+struct SimpleTestConference {
+  GstElement *pipeline;
+  GstElement *conference;
+  FsSession *session;
+  FsParticipant *participant;
+  FsStream *stream;
+  GstElement *fakesrc;
+
+  gint buffer_count;
+
+  gboolean started;
+};
+
+struct SimpleTestConference *setup_simple_conference (
+    gchar *conference_elem,
+    gchar *cname);
+
+void setup_fakesrc (struct SimpleTestConference *dat);
+
+void cleanup_simple_conference (struct SimpleTestConference *dat);
 
 
 #endif /* __GENERIC_H__ */
diff --git a/tests/check/main/rtpconference.c b/tests/check/main/rtpconference.c
index 3c70674..417ce7d 100644
--- a/tests/check/main/rtpconference.c
+++ b/tests/check/main/rtpconference.c
@@ -27,55 +27,353 @@
 
 #include "generic.h"
 
+struct SimpleTestConference *dat1 = NULL;
+struct SimpleTestConference *dat2 = NULL;
+GMainLoop *loop;
+
+
 GST_START_TEST (test_rtpconference_new)
 {
-  GstElement *pipeline = gst_pipeline_new ("pipeline");
-  GstElement *conference = NULL;
-  FsSession *session;
-  FsParticipant *participant;
-  FsStream *stream;
+  struct SimpleTestConference *dat = NULL;
+  guint id = 999;
+  GList *local_codecs = NULL;
+  FsMediaType *media_type;
+  GstPad *sinkpad = NULL;
+  gchar *str;
+
+  dat = setup_simple_conference ("fsrtpconference", "bob at 127.0.0.1");
+
+  g_object_get (dat->session,
+      "id", &id,
+      "local-codecs", &local_codecs,
+      "media-type", &media_type,
+      "sink-pad", &sinkpad,
+      NULL);
+
+  fail_unless (id == 1, "The id of the first session should be 1 not %d", id);
+  fail_if (local_codecs == NULL, "Local codecs should not be NULL");
+  fail_unless (media_type == FS_MEDIA_TYPE_AUDIO, "Media type isnt audio,"
+      " its %d", media_type);
+  fail_if (sinkpad == NULL, "Sink pad should not be null");
+  str = g_strdup_printf ("sink_%d", id);
+  fail_unless (!strcmp (str, GST_OBJECT_NAME (sinkpad)), "Sink pad is %s"
+      " instead of being %d", GST_OBJECT_NAME (sinkpad), str);
+  g_free (str);
+
+  cleanup_simple_conference (dat);
+}
+GST_END_TEST;
+
+static gboolean
+_simple_bus_callback (GstBus *bus, GstMessage *message, gpointer user_data)
+{
+
+  switch (GST_MESSAGE_TYPE (message))
+  {
+    case GST_MESSAGE_ELEMENT:
+      if (gst_implements_interface_check (GST_MESSAGE_SRC (message),
+              FS_TYPE_CONFERENCE))
+      {
+        const GValue *errorvalue, *debugvalue;
+        gint errno;
+
+        gst_structure_get_int (message->structure, "error-no", &errno);
+        errorvalue = gst_structure_get_value (message->structure, "error-msg");
+        debugvalue = gst_structure_get_value (message->structure, "debug-msg");
+
+        fail ("Error on BUS (%d) %s .. %s", errno,
+            g_value_get_string (errorvalue),
+            g_value_get_string (debugvalue));
+      }
+
+      break;
+    case GST_MESSAGE_ERROR:
+      {
+        GError *error = NULL;
+        gchar *debug = NULL;
+        gst_message_parse_error (message, &error, &debug);
+
+        fail ("Got an error on the BUS (%d): %s (%s)", error->code,
+            error->message, debug);
+        g_error_free (error);
+        g_free (debug);
+      }
+      break;
+    case GST_MESSAGE_WARNING:
+      {
+        GError *error = NULL;
+        gchar *debug = NULL;
+        gst_message_parse_warning (message, &error, &debug);
+
+        g_debug ("Got a warning on the BUS (%d): %s (%s)", error->code,
+            error->message, debug);
+        g_error_free (error);
+        g_free (debug);
+      }
+      break;
+    default:
+      break;
+  }
+
+  return TRUE;
+}
+
+static void
+_simple_send_codec_changed (FsSession *session, gpointer user_data)
+{
+  FsCodec *codec = NULL;
+  gchar *str = NULL;
+
+  g_object_get (session, "current-send-codec", &codec, NULL);
+  fail_if (codec == NULL, "Could not get new send codec");
+
+  str = fs_codec_to_string (codec);
+  g_debug ("New send codec: %s", str);
+  g_free (str);
+
+  fs_codec_destroy (codec);
+}
+
+static void
+_handoff_handler (GstElement *element, GstBuffer *buffer, GstPad *pad,
+  gpointer user_data)
+{
+  struct SimpleTestConference *dat = user_data;
+
+  g_debug ("Buffer");
+
+  dat->buffer_count++;
+
+  /*
+  fail_if (dat->buffer_count > 20,
+    "Too many buffers %d > 20", dat->buffer_count);
+  */
+
+  if (dat->buffer_count >= 20) {
+    /* TEST OVER */
+    g_main_loop_quit (loop);
+  }
+}
+
+static void
+_src_pad_added (FsStream *self, GstPad *pad, FsCodec *codec, gpointer user_data)
+{
+  struct SimpleTestConference *dat = user_data;
+  GstElement *fakesink = gst_element_factory_make ("fakesink", NULL);
+  GstPad *fakesink_pad = NULL;
+  GstPadLinkReturn ret;
+
+  g_assert (fakesink);
+
+  g_object_set (fakesink,
+      "signal-handoffs", TRUE,
+      "sync", TRUE,
+      "async", TRUE,
+      NULL);
+
+  g_signal_connect (fakesink, "handoff", G_CALLBACK (_handoff_handler), dat);
+
+  gst_bin_add (GST_BIN (dat->pipeline), fakesink);
+
+  fakesink_pad = gst_element_get_static_pad (fakesink, "sink");
+  ret = gst_pad_link (pad, fakesink_pad);
+  gst_object_unref (fakesink_pad);
+
+  fail_if (GST_PAD_LINK_FAILED(ret), "Could not link fakesink");
+
+  fail_if (gst_element_set_state (fakesink, GST_STATE_PLAYING) ==
+      GST_STATE_CHANGE_FAILURE, "Could not set the fakesink to playing");
+
+  g_debug ("Added Fakesink");
+}
+
+
+static void
+_new_active_candidate_pair (FsStream *stream, FsCandidate *local,
+    FsCandidate *remote, gpointer user_data)
+{
+  struct SimpleTestConference *dat = user_data;
+
+  fail_if (local == NULL, "Local candidate NULL");
+  fail_if (remote == NULL, "Remote candidate NULL");
+
+  if (local->component_id != 1)
+    return;
+
+  if (!dat->fakesrc)
+    setup_fakesrc (dat);
+}
+
+
+void
+rtpconference_simple_connect_signals (struct SimpleTestConference *dat)
+{
+  GstBus *bus = NULL;
+
+  bus = gst_element_get_bus (dat->pipeline);
+  gst_bus_add_watch (bus, _simple_bus_callback, dat);
+  gst_object_unref (bus);
+
+  g_signal_connect (dat->session, "send-codec-changed",
+      G_CALLBACK (_simple_send_codec_changed), dat);
+
+  g_signal_connect (dat->stream, "src-pad-added", G_CALLBACK (_src_pad_added),
+      dat);
+
+  g_signal_connect (dat->stream, "new-active-candidate-pair",
+      G_CALLBACK (_new_active_candidate_pair), dat);
+}
+
+
+static gboolean
+_start_pipeline (gpointer user_data)
+{
+  struct SimpleTestConference *dat = user_data;
+
+  g_debug ("Starting pipeline");
+
+  fail_if (gst_element_set_state (dat->pipeline, GST_STATE_PLAYING) ==
+    GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing");
+
+    dat->started = TRUE;
+
+  return FALSE;
+}
+
+static void
+_new_negotiated_codecs (FsSession *session, gpointer user_data)
+{
+  GList *codecs = NULL;
   GError *error = NULL;
 
-  conference = gst_element_factory_make ("fsrtpconference", NULL);
-  fail_if (conference == NULL, "Could not buld fsrtpconference");
-  fail_unless (gst_bin_add (GST_BIN (pipeline), conference),
-      "Could not add conference to the pipeline");
+  g_debug ("New negotiated codecs");
 
-  session = fs_conference_new_session (FS_CONFERENCE (conference),
-      FS_MEDIA_TYPE_AUDIO, &error);
-  if (error)
-    fail ("Error while creating new session (%d): %s",
-        error->code, error->message);
-  fail_if (session == NULL, "Could not make session, but no GError!");
+  fail_if (session != dat2->session, "Got signal from the wrong object");
+
+  g_object_get (dat2->session, "negotiated-codecs", &codecs, NULL);
+  fail_if (codecs == NULL, "Could not get the negotiated codecs");
 
-  participant = fs_conference_new_participant (FS_CONFERENCE (conference),
-      "bob at 127.0.0.1", &error);
-  if (error)
-    fail ("Error while creating new participant (%d): %s",
-        error->code, error->message);
-  fail_if (session == NULL, "Could not make participant, but no GError!");
 
-  stream = fs_session_new_stream (session, participant, FS_DIRECTION_NONE,
-      "rawudp", 0, NULL, &error);
+  if (!fs_stream_set_remote_codecs (dat1->stream, codecs, &error))
+  {
+    if (error)
+      fail ("Could not set the remote codecs on dat1 (%d): %s", error->code,
+          error->message);
+    else
+      fail ("Could not set the remote codecs on dat1"
+          " and we DID not get a GError!!");
+  }
+
+  fs_codec_list_destroy (codecs);
+}
+
+
+static void
+_new_local_candidate (FsStream *stream, FsCandidate *candidate,
+    gpointer user_data)
+{
+  struct SimpleTestConference *other_dat = user_data;
+  gboolean ret;
+  GError *error = NULL;
+
+  g_debug ("New local candidate");
+
+  ret = fs_stream_add_remote_candidate (other_dat->stream, candidate, &error);
+
   if (error)
-    fail ("Error while creating new stream (%d): %s",
-        error->code, error->message);
-  fail_if (session == NULL, "Could not make stream, but no GError!");
-
-  g_object_unref (stream);
-  g_object_unref (session);
-  g_object_unref (participant);
-  gst_object_unref (pipeline);
+    fail ("Error while adding candidate: (%s:%d) %s",
+      g_quark_to_string (error->domain), error->code, error->message);
+
+  fail_unless(ret == TRUE, "No detailed error from add_remote_candidate");
+
+}
+
+void
+set_local_codecs (void)
+{
+  GList *local_codecs = NULL;
+  GList *filtered_codecs = NULL;
+  GList *item = NULL;
+  GError *error = NULL;
+
+  g_object_get (dat1->session, "local-codecs", &local_codecs, NULL);
+
+  fail_if (local_codecs == NULL, "Could not get the local codecs");
+
+  for (item = g_list_first (local_codecs); item; item = g_list_next (item))
+  {
+    FsCodec *codec = item->data;
+    if (codec->id == 0 || codec->id == 8)
+      filtered_codecs = g_list_append (filtered_codecs, codec);
+  }
+
+  fail_if (filtered_codecs == NULL, "PCMA and PCMU are not in the codecs"
+      " you must install gst-plugins-good");
+
+
+  if (!fs_stream_set_remote_codecs (dat2->stream, filtered_codecs, &error))
+  {
+    if (error)
+      fail ("Could not set the remote codecs on dat2 (%d): %s", error->code,
+          error->message);
+    else
+      fail ("Could not set the remote codecs on dat2"
+          " and we DID not get a GError!!");
+  }
+
+  g_list_free (filtered_codecs);
+  fs_codec_list_destroy (local_codecs);
+}
+
+
+GST_START_TEST (test_rtpconference_simple)
+{
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  dat1 = setup_simple_conference ("fsrtpconference", "tester at TesterTop3");
+  dat2 = setup_simple_conference ("fsrtpconference", "tester at TesterTop3");
+
+  rtpconference_simple_connect_signals (dat1);
+  rtpconference_simple_connect_signals (dat2);
+
+  g_idle_add (_start_pipeline, dat1);
+  g_idle_add (_start_pipeline, dat2);
+
+  g_signal_connect (dat2->session, "new-negotiated-codecs",
+      G_CALLBACK (_new_negotiated_codecs), NULL);
+
+  set_local_codecs ();
+
+  g_signal_connect (dat1->stream, "new-local-candidate",
+      G_CALLBACK (_new_local_candidate), dat2);
+  g_signal_connect (dat2->stream, "new-local-candidate",
+      G_CALLBACK (_new_local_candidate), dat1);
+
+  g_main_loop_run (loop);
+
+  gst_element_set_state (dat1->pipeline, GST_STATE_NULL);
+  gst_element_set_state (dat2->pipeline, GST_STATE_NULL);
+
+  cleanup_simple_conference (dat1);
+  cleanup_simple_conference (dat2);
+
+  g_main_loop_unref (loop);
 }
 GST_END_TEST;
 
 
 
 static Suite *
-rawudptransmitter_suite (void)
+fsrtpconference_suite (void)
 {
   Suite *s = suite_create ("fsrtpconference");
   TCase *tc_chain;
+  GLogLevelFlags fatal_mask;
+
+  fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+  fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+  g_log_set_always_fatal (fatal_mask);
 
 
   tc_chain = tcase_create ("fsrtpconfence_base");
@@ -84,8 +382,14 @@ rawudptransmitter_suite (void)
   suite_add_tcase (s, tc_chain);
 
 
+  tc_chain = tcase_create ("fsrtpconfence_simple");
+  tcase_set_timeout (tc_chain, 10);
+  tcase_add_test (tc_chain, test_rtpconference_simple);
+  suite_add_tcase (s, tc_chain);
+
+
   return s;
 }
 
 
-GST_CHECK_MAIN (rawudptransmitter);
+GST_CHECK_MAIN (fsrtpconference);
-- 
1.5.6.5




More information about the farsight-commits mailing list