Blame tests/check/pipelines/tcp.c

Packit 971217
/* GStreamer
Packit 971217
 *
Packit 971217
 * Copyright (C) 2014 William Manley <will@williammanley.net>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include <gio/gio.h>
Packit 971217
#include <gst/check/gstcheck.h>
Packit 971217
#include <gst/app/gstappsink.h>
Packit 971217
#include <gst/app/gstappsrc.h>
Packit 971217
#include <gst/net/gstnetcontrolmessagemeta.h>
Packit 971217
Packit 971217
#ifdef HAVE_GIO_UNIX_2_0
Packit 971217
#include <gio/gunixfdmessage.h>
Packit 971217
#endif /*  HAVE_GIO_UNIX_2_0 */
Packit 971217
Packit 971217
#include <sys/types.h>
Packit 971217
#include <sys/stat.h>
Packit 971217
#include <sys/socket.h>
Packit 971217
#include <unistd.h>
Packit 971217
Packit 971217
static gboolean
Packit 971217
g_socketpair (GSocketFamily family, GSocketType type, GSocketProtocol protocol,
Packit 971217
    GSocket * gsv[2], GError ** error);
Packit 971217
Packit 971217
typedef struct
Packit 971217
{
Packit 971217
  GstElement *sink;
Packit 971217
  GstElement *src;
Packit 971217
Packit 971217
  GstPipeline *sink_pipeline;
Packit 971217
  GstPipeline *src_pipeline;
Packit 971217
  GstAppSrc *sink_src;
Packit 971217
  GstAppSink *src_sink;
Packit 971217
} SymmetryTest;
Packit 971217
Packit 971217
static void
Packit 971217
symmetry_test_setup (SymmetryTest * st, GstElement * sink, GstElement * src)
Packit 971217
{
Packit 971217
  GstCaps *caps;
Packit 971217
  st->sink = sink;
Packit 971217
  g_object_set (sink, "sync", FALSE, NULL);
Packit 971217
  st->src = src;
Packit 971217
Packit 971217
  st->sink_pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
Packit 971217
  st->src_pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
Packit 971217
Packit 971217
  st->sink_src = GST_APP_SRC (gst_element_factory_make ("appsrc", NULL));
Packit 971217
  fail_unless (st->sink_src != NULL);
Packit 971217
  caps = gst_caps_from_string ("application/x-gst-check");
Packit 971217
  gst_app_src_set_caps (st->sink_src, caps);
Packit 971217
  gst_caps_unref (caps);
Packit 971217
Packit 971217
  gst_bin_add_many (GST_BIN (st->sink_pipeline), GST_ELEMENT (st->sink_src),
Packit 971217
      st->sink, NULL);
Packit 971217
  fail_unless (gst_element_link_many (GST_ELEMENT (st->sink_src), st->sink,
Packit 971217
          NULL));
Packit 971217
Packit 971217
  st->src_sink = GST_APP_SINK (gst_element_factory_make ("appsink", NULL));
Packit 971217
  fail_unless (st->src_sink != NULL);
Packit 971217
  gst_bin_add_many (GST_BIN (st->src_pipeline), st->src,
Packit 971217
      GST_ELEMENT (st->src_sink), NULL);
Packit 971217
  fail_unless (gst_element_link_many (st->src, GST_ELEMENT (st->src_sink),
Packit 971217
          NULL));
Packit 971217
Packit 971217
  gst_element_set_state (GST_ELEMENT (st->sink_pipeline), GST_STATE_PLAYING);
Packit 971217
  gst_element_set_state (GST_ELEMENT (st->src_pipeline), GST_STATE_PLAYING);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
symmetry_test_teardown (SymmetryTest * st)
Packit 971217
{
Packit 971217
  fail_unless (gst_element_set_state (GST_ELEMENT (st->sink_pipeline),
Packit 971217
          GST_STATE_NULL) != GST_STATE_CHANGE_FAILURE);
Packit 971217
  fail_unless (gst_element_set_state (GST_ELEMENT (st->src_pipeline),
Packit 971217
          GST_STATE_NULL) != GST_STATE_CHANGE_FAILURE);
Packit 971217
Packit 971217
  gst_object_unref (st->sink_pipeline);
Packit 971217
  gst_object_unref (st->src_pipeline);
Packit 971217
Packit 971217
  memset (st, 0, sizeof (*st));
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
symmetry_test_assert_passthrough (SymmetryTest * st, GstBuffer * in)
Packit 971217
{
Packit 971217
  gpointer copy;
Packit 971217
  gsize data_size;
Packit 971217
  GstSample *out;
Packit 971217
Packit 971217
  gst_buffer_extract_dup (in, 0, -1, &copy, &data_size);
Packit 971217
Packit 971217
  fail_unless (gst_app_src_push_buffer (st->sink_src, in) == GST_FLOW_OK);
Packit 971217
  in = NULL;
Packit 971217
  out = gst_app_sink_pull_sample (st->src_sink);
Packit 971217
  fail_unless (out != NULL);
Packit 971217
Packit 971217
  fail_unless (gst_buffer_get_size (gst_sample_get_buffer (out)) == data_size);
Packit 971217
  fail_unless (gst_buffer_memcmp (gst_sample_get_buffer (out), 0, copy,
Packit 971217
          data_size) == 0);
Packit 971217
  g_free (copy);
Packit 971217
  gst_sample_unref (out);
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
g_socketpair (GSocketFamily family, GSocketType type, GSocketProtocol protocol,
Packit 971217
    GSocket * gsv[2], GError ** error)
Packit 971217
{
Packit 971217
  int ret;
Packit 971217
  int sv[2];
Packit 971217
Packit 971217
  ret = socketpair (family, type, protocol, sv);
Packit 971217
  if (ret != 0) {
Packit 971217
    g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "socketpair failed: %s",
Packit 971217
        g_strerror (errno));
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
  gsv[0] = g_socket_new_from_fd (sv[0], error);
Packit 971217
  if (gsv[0] == NULL) {
Packit 971217
    close (sv[0]);
Packit 971217
    close (sv[1]);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
  gsv[1] = g_socket_new_from_fd (sv[1], error);
Packit 971217
  if (gsv[1] == NULL) {
Packit 971217
    g_object_unref (gsv[0]);
Packit 971217
    gsv[0] = NULL;
Packit 971217
    close (sv[1]);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
setup_multisocketsink_and_socketsrc (SymmetryTest * st)
Packit 971217
{
Packit 971217
  GSocket *sockets[2] = { NULL, NULL };
Packit 971217
  GError *err = NULL;
Packit 971217
Packit 971217
  st->sink = gst_check_setup_element ("multisocketsink");
Packit 971217
  st->src = gst_check_setup_element ("socketsrc");
Packit 971217
Packit 971217
  fail_unless (g_socketpair (G_SOCKET_FAMILY_UNIX,
Packit 971217
          G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, sockets, &err));
Packit 971217
Packit 971217
  g_object_set (st->src, "socket", sockets[0], NULL);
Packit 971217
  g_object_unref (sockets[0]);
Packit 971217
  sockets[0] = NULL;
Packit 971217
Packit 971217
  symmetry_test_setup (st, st->sink, st->src);
Packit 971217
Packit 971217
  g_signal_emit_by_name (st->sink, "add", sockets[1], NULL);
Packit 971217
  g_object_unref (sockets[1]);
Packit 971217
  sockets[1] = NULL;
Packit 971217
}
Packit 971217
Packit 971217
GST_START_TEST (test_that_socketsrc_and_multisocketsink_are_symmetrical)
Packit 971217
{
Packit 971217
  SymmetryTest st = { 0 };
Packit 971217
  setup_multisocketsink_and_socketsrc (&st);
Packit 971217
  symmetry_test_assert_passthrough (&st,
Packit 971217
      gst_buffer_new_wrapped (g_strdup ("hello"), 5));
Packit 971217
  symmetry_test_teardown (&st);
Packit 971217
}
Packit 971217
Packit 971217
GST_END_TEST;
Packit 971217
Packit 971217
Packit 971217
GST_START_TEST (test_that_tcpclientsink_and_tcpserversrc_are_symmetrical)
Packit 971217
{
Packit 971217
  SymmetryTest st = { 0 };
Packit 971217
  GstElement *serversrc = gst_check_setup_element ("tcpserversrc");
Packit 971217
Packit 971217
  gst_element_set_state (serversrc, GST_STATE_PAUSED);
Packit 971217
  symmetry_test_setup (&st, gst_check_setup_element ("tcpclientsink"),
Packit 971217
      serversrc);
Packit 971217
Packit 971217
  symmetry_test_assert_passthrough (&st,
Packit 971217
      gst_buffer_new_wrapped (g_strdup ("hello"), 5));
Packit 971217
Packit 971217
  symmetry_test_teardown (&st);
Packit 971217
}
Packit 971217
Packit 971217
GST_END_TEST;
Packit 971217
Packit 971217
Packit 971217
GST_START_TEST (test_that_tcpserversink_and_tcpclientsrc_are_symmetrical)
Packit 971217
{
Packit 971217
  SymmetryTest st = { 0 };
Packit 971217
Packit 971217
  symmetry_test_setup (&st, gst_check_setup_element ("tcpserversink"),
Packit 971217
      gst_check_setup_element ("tcpclientsrc"));
Packit 971217
Packit 971217
  symmetry_test_assert_passthrough (&st,
Packit 971217
      gst_buffer_new_wrapped (g_strdup ("hello"), 5));
Packit 971217
  symmetry_test_teardown (&st);
Packit 971217
}
Packit 971217
Packit 971217
GST_END_TEST;
Packit 971217
Packit 971217
static void
Packit 971217
on_connection_closed (GstElement * socketsrc, gpointer user_data)
Packit 971217
{
Packit 971217
  GSocket *socket = (GSocket *) user_data;
Packit 971217
Packit 971217
  g_object_set (socketsrc, "socket", socket, NULL);
Packit 971217
}
Packit 971217
Packit 971217
GST_START_TEST (test_that_we_can_provide_new_socketsrc_sockets_during_signal)
Packit 971217
{
Packit 971217
  GSocket *sockets[4] = { NULL, NULL };
Packit 971217
Packit 971217
  GstPipeline *pipeline = NULL;
Packit 971217
  GstAppSink *appsink = NULL;
Packit 971217
  GstElement *socketsrc = NULL;
Packit 971217
  GstSample *sample = NULL;
Packit 971217
Packit 971217
  socketsrc = gst_check_setup_element ("socketsrc");
Packit 971217
Packit 971217
  fail_unless (g_socketpair (G_SOCKET_FAMILY_UNIX,
Packit 971217
          G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &sockets[0], NULL));
Packit 971217
Packit 971217
  fail_unless (g_socket_send (sockets[0], "hello", 5, NULL, NULL) == 5);
Packit 971217
  fail_unless (g_socket_shutdown (sockets[0], FALSE, TRUE, NULL));
Packit 971217
Packit 971217
  fail_unless (g_socketpair (G_SOCKET_FAMILY_UNIX,
Packit 971217
          G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &sockets[2], NULL));
Packit 971217
  fail_unless (g_socket_send (sockets[2], "goodbye", 7, NULL, NULL) == 7);
Packit 971217
  fail_unless (g_socket_shutdown (sockets[2], FALSE, TRUE, NULL));
Packit 971217
Packit 971217
  g_object_set (socketsrc, "socket", sockets[1], NULL);
Packit 971217
Packit 971217
  g_signal_connect (socketsrc, "connection-closed-by-peer",
Packit 971217
      G_CALLBACK (on_connection_closed), sockets[3]);
Packit 971217
Packit 971217
  pipeline = (GstPipeline *) gst_pipeline_new (NULL);
Packit 971217
  appsink = GST_APP_SINK (gst_check_setup_element ("appsink"));
Packit 971217
  gst_bin_add_many (GST_BIN (pipeline), socketsrc, GST_ELEMENT (appsink), NULL);
Packit 971217
  fail_unless (gst_element_link_many (socketsrc, GST_ELEMENT (appsink), NULL));
Packit 971217
Packit 971217
  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
Packit 971217
Packit 971217
  fail_unless ((sample = gst_app_sink_pull_sample (appsink)) != NULL);
Packit 971217
  gst_buffer_memcmp (gst_sample_get_buffer (sample), 0, "hello", 5);
Packit 971217
  gst_sample_unref (sample);
Packit 971217
Packit 971217
  fail_unless ((sample = gst_app_sink_pull_sample (appsink)) != NULL);
Packit 971217
  gst_buffer_memcmp (gst_sample_get_buffer (sample), 0, "goodbye", 7);
Packit 971217
  gst_sample_unref (sample);
Packit 971217
Packit 971217
  fail_unless (NULL == gst_app_sink_pull_sample (appsink));
Packit 971217
  fail_unless (gst_app_sink_is_eos (appsink));
Packit 971217
Packit 971217
  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
Packit 971217
  g_clear_object (&sockets[0]);
Packit 971217
  g_clear_object (&sockets[1]);
Packit 971217
  g_clear_object (&sockets[2]);
Packit 971217
  g_clear_object (&sockets[3]);
Packit 971217
  gst_object_unref (pipeline);
Packit 971217
}
Packit 971217
Packit 971217
GST_END_TEST
Packit 971217
#ifdef HAVE_GIO_UNIX_2_0
Packit 971217
static GSocketControlMessage *
Packit 971217
get_control_message_meta (GstBuffer * buf)
Packit 971217
{
Packit 971217
  GstMeta *meta;
Packit 971217
  gpointer iter_state = NULL;
Packit 971217
Packit 971217
  while ((meta = gst_buffer_iterate_meta (buf, &iter_state)) != NULL) {
Packit 971217
    if (meta->info->api == GST_NET_CONTROL_MESSAGE_META_API_TYPE)
Packit 971217
      return ((GstNetControlMessageMeta *) meta)->message;
Packit 971217
  }
Packit 971217
  fail ("Expected GSocketControlMessage attached to buffer");
Packit 971217
  return NULL;
Packit 971217
}
Packit 971217
Packit 971217
Packit 971217
GST_START_TEST (test_that_multisocketsink_and_socketsrc_preserve_meta)
Packit 971217
{
Packit 971217
  GstBuffer *buf;
Packit 971217
  GSocketControlMessage *msg;
Packit 971217
  SymmetryTest st = { 0 };
Packit 971217
  char tmpfilename[] = "/tmp/tcp-test.XXXXXX";
Packit 971217
  GstSample *out;
Packit 971217
  int orig_fd, *new_fds, new_fds_len;
Packit 971217
  struct stat orig_stat, new_stat;
Packit 971217
Packit 971217
  setup_multisocketsink_and_socketsrc (&st);
Packit 971217
Packit 971217
  orig_fd = mkstemp (tmpfilename);
Packit 971217
  fail_unless (orig_fd > 0);
Packit 971217
  fail_unless (unlink (tmpfilename) == 0);
Packit 971217
  fstat (orig_fd, &orig_stat);
Packit 971217
Packit 971217
  msg = g_unix_fd_message_new ();
Packit 971217
  fail_unless (g_unix_fd_message_append_fd ((GUnixFDMessage *) msg, orig_fd,
Packit 971217
          NULL));
Packit 971217
  close (orig_fd);
Packit 971217
  orig_fd = -1;
Packit 971217
Packit 971217
  buf = gst_buffer_new_wrapped (g_strdup ("hello"), 5);
Packit 971217
  gst_buffer_add_net_control_message_meta (buf, msg);
Packit 971217
  g_clear_object (&msg;;
Packit 971217
Packit 971217
  fail_unless (gst_app_src_push_buffer (st.sink_src, buf) == GST_FLOW_OK);
Packit 971217
  buf = NULL;
Packit 971217
Packit 971217
  out = gst_app_sink_pull_sample (st.src_sink);
Packit 971217
  fail_unless (out != NULL);
Packit 971217
Packit 971217
  fail_unless (gst_buffer_get_size (gst_sample_get_buffer (out)) == 5);
Packit 971217
  fail_unless (gst_buffer_memcmp (gst_sample_get_buffer (out), 0, "hello",
Packit 971217
          5) == 0);
Packit 971217
Packit 971217
  msg = get_control_message_meta (gst_sample_get_buffer (out));
Packit 971217
  fail_unless (g_socket_control_message_get_msg_type (msg) == SCM_RIGHTS);
Packit 971217
  new_fds = g_unix_fd_message_steal_fds ((GUnixFDMessage *) msg, &new_fds_len);
Packit 971217
  fail_unless (new_fds_len == 1);
Packit 971217
Packit 971217
  fstat (new_fds[0], &new_stat);
Packit 971217
  fail_unless (orig_stat.st_ino, new_stat.st_ino);
Packit 971217
Packit 971217
  close (new_fds[0]);
Packit 971217
  g_free (new_fds);
Packit 971217
Packit 971217
  gst_sample_unref (out);
Packit 971217
Packit 971217
  symmetry_test_teardown (&st);
Packit 971217
}
Packit 971217
Packit 971217
GST_END_TEST;
Packit 971217
#endif /* HAVE_GIO_UNIX_2_0 */
Packit 971217
Packit 971217
static Suite *
Packit 971217
socketintegrationtest_suite (void)
Packit 971217
{
Packit 971217
  Suite *s = suite_create ("socketintegrationtest");
Packit 971217
  TCase *tc_chain = tcase_create ("general");
Packit 971217
Packit 971217
  suite_add_tcase (s, tc_chain);
Packit 971217
  tcase_add_test (tc_chain,
Packit 971217
      test_that_socketsrc_and_multisocketsink_are_symmetrical);
Packit 971217
  tcase_add_test (tc_chain,
Packit 971217
      test_that_tcpclientsink_and_tcpserversrc_are_symmetrical);
Packit 971217
  tcase_add_test (tc_chain,
Packit 971217
      test_that_tcpserversink_and_tcpclientsrc_are_symmetrical);
Packit 971217
  tcase_add_test (tc_chain,
Packit 971217
      test_that_we_can_provide_new_socketsrc_sockets_during_signal);
Packit 971217
#ifdef HAVE_GIO_UNIX_2_0
Packit 971217
  tcase_add_test (tc_chain,
Packit 971217
      test_that_multisocketsink_and_socketsrc_preserve_meta);
Packit 971217
#endif /* HAVE_GIO_UNIX_2_0 */
Packit 971217
Packit 971217
  return s;
Packit 971217
}
Packit 971217
Packit 971217
GST_CHECK_MAIN (socketintegrationtest);