Commit 36558a6d authored by Guillaume Roguez's avatar Guillaume Roguez

tests: add sipp test

Original tests taken from the 1.4.0 version.
Modified to keep only a working base.

[guillaume: ci msg modified for clarifications]
[guillaume: fix configure.ac bad insertion]

Change-Id: I0d7f848ccbbd3a7a0d832cead6d8e01b01e91b24
Reviewed-by: Guillaume Roguez's avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 3e4fa65d
......@@ -6,7 +6,7 @@ SOURCES=
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src ringtones man $(TESTS_DIR) doc bin
SUBDIRS = src ringtones man $(TESTS_DIR) doc bin test
EXTRA_DIST = m4/libtool.m4 \
m4/lt~obsolete.m4 \
......
......@@ -699,6 +699,7 @@ AS_IF([test "x$enable_debug" = "xyes"],
dnl What Makefiles to generate
#TODO: split this list across where the relevant check is performed
AC_CONFIG_FILES([Makefile \
bin/Makefile \
......@@ -725,10 +726,11 @@ AC_CONFIG_FILES([Makefile \
src/media/video/androidvideo/Makefile \
src/media/video/osxvideo/Makefile \
src/media/video/winvideo/Makefile \
src/media/video/test/Makefile \
src/security/Makefile \
src/upnp/Makefile \
ringtones/Makefile \
test/Makefile\
test/sip/Makefile \
man/Makefile \
doc/Makefile \
doc/doxygen/Makefile])
......
include $(top_srcdir)/globals.mk
SUBDIRS= test
if HAVE_LINUX
if HAVE_ANDROID
SUBDIRS+= \
SUBDIRS= \
androidvideo
else
SUBDIRS+= \
SUBDIRS= \
v4l2
endif
endif
if HAVE_OSX
SUBDIRS+= \
SUBDIRS= \
osxvideo
endif
if HAVE_WIN32
SUBDIRS+= \
SUBDIRS= \
winvideo
endif
......
test_thread
test_v4l2
test_video_endpoint
test_video_rtp
test_video_preview
include $(top_srcdir)/globals.mk
TESTS=test_shm test_video_input test_video_rtp
check_PROGRAMS=test_video_rtp test_video_input test_shm
test_video_rtp_SOURCES=test_video_rtp.cpp
test_video_rtp_LDADD=$(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS)
test_video_input_SOURCES=test_video_input.cpp test_video_input.h
test_video_input_LDADD=$(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS)
if HAVE_LINUX
test_shm_SOURCES=test_shm.cpp shm_src.cpp shm_src.h
test_shm_LDADD=$(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS) -lrt
test_shm_CXXFLAGS=$(AM_CXXFLAGS)
endif
AM_CXXFLAGS=-I$(top_srcdir)/src/media/video -I$(top_srcdir)/src
c++ shm_src.cpp shmclient.cpp -o shmclient `pkg-config --cflags --libs clutter-1.0` -lrt -pthread -O2
# disables audio
ffmpeg -f video4linux2 -i /dev/video0 -srcw 320 -srch 240 -an -r 30 -vprofile baseline -level 13 -vb 400000 -vcodec libx264 -payload_type 109 -preset veryfast -tune zerolatency -f rtp rtp://192.168.50.116:2228
/*
* Copyright (C) 2012-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* Portions derived from GStreamer:
* Copyright (C) <2009> Collabora Ltd
* @author: Olivier Crete <olivier.crete@collabora.co.uk
* Copyright (C) <2009> Nokia Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "shm_src.h"
#include "../shm_header.h"
#include <sys/mman.h>
#include <fcntl.h>
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cassert>
SHMSrc::SHMSrc(const std::string &shm_name) :
shm_name_(shm_name),
fd_(-1),
shm_area_(static_cast<SHMHeader*>(MAP_FAILED)),
shm_area_len_(0),
buffer_gen_(0)
{}
bool
SHMSrc::start()
{
if (fd_ != -1) {
std::cerr << "fd must be -1" << std::endl;
return false;
}
fd_ = shm_open(shm_name_.c_str(), O_RDWR, 0);
if (fd_ < 0) {
std::cerr << "could not open shm area \"" << shm_name_ << "\", shm_open failed" << std::endl;
perror(strerror(errno));
return false;
}
shm_area_len_ = sizeof(SHMHeader);
shm_area_ = static_cast<SHMHeader*>(mmap(NULL, shm_area_len_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0));
if (shm_area_ == MAP_FAILED) {
std::cerr << "Could not map shm area, mmap failed" << std::endl;
return false;
}
return true;
}
bool
SHMSrc::stop()
{
if (fd_ >= 0)
close(fd_);
fd_ = -1;
if (shm_area_ != MAP_FAILED)
munmap(shm_area_, shm_area_len_);
shm_area_len_ = 0;
shm_area_ = static_cast<SHMHeader*>(MAP_FAILED);
return true;
}
bool
SHMSrc::resize_area()
{
while ((sizeof(SHMHeader) + shm_area_->buffer_size) > shm_area_len_) {
size_t new_size = sizeof(SHMHeader) + shm_area_->buffer_size;
shm_unlock();
if (munmap(shm_area_, shm_area_len_)) {
std::cerr << "Could not unmap shared area" << std::endl;
perror(strerror(errno));
return false;
}
shm_area_ = static_cast<SHMHeader*>(mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0));
shm_area_len_ = new_size;
if (!shm_area_) {
shm_area_ = 0;
std::cerr << "Could not remap shared area" << std::endl;
return false;
}
shm_area_len_ = new_size;
shm_lock();
}
return true;
}
void SHMSrc::render(char *dest, size_t len)
{
shm_lock();
while (buffer_gen_ == shm_area_->buffer_gen) {
shm_unlock();
std::cerr << "Waiting for next buffer" << std::endl;;
sem_wait(&shm_area_->notification);
shm_lock();
}
if (!resize_area())
return;
std::cerr << "Reading from buffer!" << std::endl;
memcpy(dest, shm_area_->data, len);
buffer_gen_ = shm_area_->buffer_gen;
shm_unlock();
}
void SHMSrc::shm_lock()
{
sem_wait(&shm_area_->mutex);
}
void SHMSrc::shm_unlock()
{
sem_post(&shm_area_->mutex);
}
/*
* Copyright (C) 2012-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* Portions derived from GStreamer:
* Copyright (C) <2009> Collabora Ltd
* @author: Olivier Crete <olivier.crete@collabora.co.uk
* Copyright (C) <2009> Nokia Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef SHM_SRC_H_
#define SHM_SRC_H_
#include <string>
#include "../../noncopyable.h"
class SHMHeader;
// Example Shared memory source, only useful for testing
// as far as the daemon is concerned
class SHMSrc {
public:
SHMSrc(const std::string &shm_name);
virtual ~SHMSrc() {};
bool start();
bool stop();
bool resize_area();
void render(char *data, size_t len);
protected:
void shm_lock();
void shm_unlock();
std::string shm_name_;
int fd_;
SHMHeader *shm_area_;
size_t shm_area_len_;
unsigned buffer_gen_;
private:
NON_COPYABLE(SHMSrc);
};
#endif // SHM_SRC_H_
/*
* Copyright (C) 2011-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cstdio>
#include <cstdlib>
#include "shm_src.h"
#include "../shm_header.h"
#include "../../noncopyable.h"
#include <sys/mman.h>
#include <iostream>
#include <clutter/clutter.h>
class ClutterSHMSrc : public SHMSrc {
public:
ClutterSHMSrc(const std::string &name,
unsigned width,
unsigned height,
ClutterActor *texture) :
SHMSrc(name),
width_(width),
height_(height),
texture_(texture)
{
printf("Creating source with name:%s width:%d height:%d texture:%p\n", name.c_str(), width, height, texture);
}
void render_to_texture()
{
if (shm_area_ == MAP_FAILED) {
g_print("shm_area is MAP FAILED!\n");
return;
}
shm_lock();
while (buffer_gen_ == shm_area_->buffer_gen) {
shm_unlock();
sem_wait(&shm_area_->notification);
shm_lock();
}
if (!resize_area()) {
g_print("could not resize area\n");
return;
}
clutter_actor_set_size(texture_, width_, height_);
const int BPP = 4;
const int ROW_STRIDE = BPP * width_;
/* update the clutter texture */
clutter_texture_set_from_rgb_data(CLUTTER_TEXTURE(texture_),
reinterpret_cast<const unsigned char *>(shm_area_->data),
TRUE,
width_,
height_,
ROW_STRIDE,
BPP,
CLUTTER_TEXTURE_RGB_FLAG_BGR,
NULL);
buffer_gen_ = shm_area_->buffer_gen;
shm_unlock();
}
private:
NON_COPYABLE(ClutterSHMSrc);
unsigned width_;
unsigned height_;
ClutterActor *texture_;
};
gboolean updateTexture(gpointer data)
{
ClutterSHMSrc *src = static_cast<ClutterSHMSrc *>(data);
src->render_to_texture();
return TRUE;
}
int main(int argc, char *argv[])
{
if (argc < 4) {
printf("Usage: ./shmclient <shm_filename> <width> <height>\n");
return 1;
}
/* Initialize Clutter */
if (clutter_init(NULL, NULL) != CLUTTER_INIT_SUCCESS)
return 1;
/* Get the default stage */
ClutterActor *stage = clutter_stage_get_default();
const int width = atoi(argv[2]);
const int height = atoi(argv[3]);
clutter_actor_set_size(stage, width, height);
ClutterActor *texture = clutter_texture_new();
clutter_stage_set_title(CLUTTER_STAGE(stage), "Client");
/* Add ClutterTexture to the stage */
clutter_container_add(CLUTTER_CONTAINER(stage), texture, NULL);
ClutterSHMSrc src(argv[1], width, height, texture);
if (not src.start()) {
printf("Could not start SHM source\n");
return 1;
}
/* frames are read and saved here */
g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 30, updateTexture, &src, NULL);
clutter_actor_show_all(stage);
/* main loop */
clutter_main();
src.stop();
return 0;
}
/*
* Copyright (C) 2012-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "shm_sink.h"
#include "shm_src.h"
#include <thread>
#include <signal.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <atomic>
#include <cstring>
#include <cassert>
static std::atomic<bool> done(false);
static void
signal_handler(int /*sig*/)
{
done = true;
}
static const char test_data[] = "abcdefghijklmnopqrstuvwxyz";
static void
sink_thread()
{
ring::video::SHMSink sink("bob");;
if (!sink.start())
return;
std::vector<unsigned char> test_vec(test_data, test_data + sizeof(test_data) / sizeof(test_data[0]));
while (!done) {
sink.render(test_vec);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
sink.stop();
std::cerr << std::endl;
std::cerr << "Exitting sink thread" << std::endl;
}
static void
run_client()
{
SHMSrc src("bob");;
bool started = false;
while (not done and not started) {
sleep(1);
if (src.start())
started = true;
}
// we get here if the above loop was interupted by our signal handler
if (!started)
return;
// initialize destination string to 0's
std::vector<char> dest(sizeof(test_data), 0);
const std::vector<char> test_data_str(test_data, test_data + sizeof(test_data));
assert(test_data_str.size() == 27);
assert(dest.size() == test_data_str.size());
while (not done and dest != test_data_str) {
src.render(dest.data(), dest.size());
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
src.stop();
std::cerr << "Got characters, exitting client process" << std::endl;
}
static void
run_daemon()
{
std::thread bob(sink_thread);
/* Wait for child process. */
int status;
int pid;
if ((pid = wait(&status)) == -1) {
perror("wait error");
} else {
// Check status.
if (WIFSIGNALED(status) != 0)
std::cout << "Child process ended because of signal " <<
WTERMSIG(status) << std::endl;
else if (WIFEXITED(status) != 0)
std::cout << "Child process ended normally; status = " <<
WEXITSTATUS(status) << std::endl;
else
std::cout << "Child process did not end normally" << std::endl;
}
std::cout << "Finished waiting for child" << std::endl;
done = true;
// wait for thread
bob.join();
}
int main()
{
signal(SIGINT, signal_handler);
pid_t pid = fork();
if (pid < 0) {
std::cerr << "Failed to fork" << std::endl;
return 1;
} else if (pid == 0) {
// child code only
run_client();
} else {
// parent code only
run_daemon();
}
return 0;
}
/*
* Copyright (C) 2011-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "test_video_input.h"
#include "video_input.h"
#include "media_const.h"
#include <map>
#include <string>
namespace ring { namespace video { namespace test {
void VideoInputTest::testInput()
{
static const std::string sep = DRing::Media::VideoProtocolPrefix::SEPARATOR;
std::string resource = DRing::Media::VideoProtocolPrefix::DISPLAY + sep + std::string(getenv("DISPLAY") ? : ":0.0");
VideoInput video;
video.switchInput(resource);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}}} // namespace ring::video::test
int main ()
{
for (int i = 0; i < 20; ++i) {
ring::video::test::VideoInputTest test;
test.testInput();
}
return 0;
}
/*
* Copyright (C) 2011-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _VIDEO_INPUT_TEST_
#define _VIDEO_INPUT_TEST_
namespace ring { namespace video { namespace test {
class VideoInputTest {
public:
void testInput();
};
}}} // namespace ring::video::test
#endif // _VIDEO_INPUT_TEST_
*.o
# test result files
*.log
*.trs
#test binaries
sip
# Rules for the test code (use `make check` to execute)
include ../../globals.mk
TESTS = sip
check_PROGRAMS = $(TESTS)
sip_LDADD = ./../../src/libring.la
sip_SOURCES = sip.cpp test_SIP.h test_SIP.cpp ../../manager.h
sip_CXXFLAGS = $(CPPUNIT_CFLAGS)
sip_LDFLAGS = $(CPPUNIT_LIBS) -ldl
<
/*
* Copyright (C) 2011-2017 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
* Author: Julien Bonjean <julien.bonjean@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -16,28 +15,42 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include "test_SIP.h"
#include "video_rtp_session.h"
#include "video_device_monitor.h"
#include <cppunit/CompilerOutputter.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TextTestRunner.h>
#include <cppunit/ui/text/TestRunner.h>
#include "ip_utils.h"
#include <unistd.h> // for sleep
int main ()
int main(int argc, char* argv[])
{
ring::video::VideoDeviceMonitor monitor;
ring::video::VideoRtpSession session("test", monitor.getDeviceParams(monitor.getDefaultDevice()));
ring::MediaDescription local {};
local.addr = {AF_INET};
local.addr.setPort(12345);
session.updateMedia(local, ring::MediaDescription{});
// Get the top level suite from the registry
CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
// Adds the test to the list of test to run
CppUnit::TextUi::TestRunner runner;
runner.addTest( suite );
session.start();
sleep(5);
session.stop();
// Change the default outputter to a compiler error format outputter
runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(),
std::cerr ) );
// Run the tests.
bool wasSucessful = runner.run();
return 0;
// Return error code 1 if the one of test failed.
return wasSucessful ? 0 : 1;