diff --git a/configure.ac b/configure.ac index 582b4e339112eb5b4947bf5ac0634b9755199ef9..3ee14ce5bb71621d6d98855855e78f4f710b4a73 100644 --- a/configure.ac +++ b/configure.ac @@ -382,7 +382,7 @@ AS_IF([test "x$with_dbus" = "xyes"], [ AS_IF([test "x$CLANG" = "xyes"], [ AC_MSG_ERROR([dbus does not compile when clang is used, rerun with --without-dbus]) ]); - AM_CONDITIONAL(RING_DBUS, true)], + AM_CONDITIONAL(RING_DBUS, true)],TESTS= $(check_PROGRAMS) AM_CONDITIONAL(RING_DBUS, false)); dnl Ring name service is default-enabled @@ -731,6 +731,9 @@ AC_CONFIG_FILES([Makefile \ ringtones/Makefile \ test/Makefile\ test/sip/Makefile \ + test/base64/Makefile \ + test/media/Makefile \ + test/media/video/Makefile \ man/Makefile \ doc/Makefile \ doc/doxygen/Makefile]) diff --git a/test/.gitignore b/test/.gitignore index 7e563b8b3023b7b9cc879c0052dfcc26b9f82505..c2cf4ab8ed024de43caa1930d0177807f24f5b54 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,2 +1,7 @@ +*.o + +# test result files *.log *.trs + +.dirstamp diff --git a/test/Makefile.am b/test/Makefile.am index 10991115e819f782edc973c3ebfd12e7ce5c71d9..2a232630106fe296c98ab70a229e1460ebeddff4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1 +1,3 @@ SUBDIRS=sip +SUBDIRS+=base64 +SUBDIRS+=media diff --git a/test/base64/.gitignore b/test/base64/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..633b4680f72aed4dd53d3107a94c9f10fccd79f1 --- /dev/null +++ b/test/base64/.gitignore @@ -0,0 +1,10 @@ +*.o + +# test result files +*.log +*.trs + +#test binaries +sip + +base64 diff --git a/test/base64/Makefile.am b/test/base64/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..f7cc7239d6ab87ce17330a59104478479dde75b1 --- /dev/null +++ b/test/base64/Makefile.am @@ -0,0 +1,41 @@ +include $(top_srcdir)/globals.mk + +AM_CXXFLAGS=-I$(top_srcdir)/src/media/video -I$(top_srcdir)/src +check_PROGRAMS= + +# +# base64 testsuite +# +check_PROGRAMS+= base64 +base64_SOURCES= base64.cpp +base64_LDADD= $(CPPUNIT_LIBS) $(top_builddir)/src/libring.la + +# +# video_input testsuite +# +#check_PROGRAMS+= test_video_input +#test_video_input_SOURCES= media/video/test_video_input.cpp media/video/test_video_input.h +#test_video_input_LDADD= $(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS) + +################## +# EXCLUDED_TEST SUITES # +################## +# test_video_rtp +# reason: compilation fails +# test_video_rtp.cpp:38:19: error: no matching function for call to ‘ring::video::VideoRtpSession::start()’ +# +# test_video_rtp_SOURCES= media/video/test_video_rtp.cpp +# test_video_rtp_LDADD= $(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS) +# +# +# test_shm (compilation fails, include file not in repository?) +# reason: compilation fails, include file not in repository: +# test_video_input.cpp.cpp:21:22: fatal error: shm_sink.h: No such file or directory +# +# if HAVE_LINUX +# test_shm_SOURCES= media/video/test_shm.cpp media/video/shm_src.cpp media/video/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 + +TESTS= $(check_PROGRAMS) diff --git a/test/base64/base64.cpp b/test/base64/base64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ad6e7c7f8010db1e81869a71819bc3125541b07 --- /dev/null +++ b/test/base64/base64.cpp @@ -0,0 +1,53 @@ +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#include "test_runner.hpp" +#include "base64.h" + +namespace ring_test { + class Base64Test : public CppUnit::TestFixture { + public: + static std::string name() { return "base64"; } + + private: + void encodingTest(); + void decodingTestSuccess(); + void decodingTestFail(); + + CPPUNIT_TEST_SUITE(Base64Test); + CPPUNIT_TEST(encodingTest); + CPPUNIT_TEST(decodingTestSuccess); + CPPUNIT_TEST(decodingTestFail); + CPPUNIT_TEST_SUITE_END(); + + const std::vector<uint8_t> test_bytes = { 23, 45, 67, 87, 89, 34, 2, 45, 9, 10 }; + const std::string test_base64 = "Fy1DV1kiAi0JCg=="; + const std::string test_invalid_base64 = "ERSAÄÖöädt4-++asd=="; + }; + + CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Base64Test, Base64Test::name()); + + void Base64Test::encodingTest() + { + const std::string output = ring::base64::encode(test_bytes); + CPPUNIT_ASSERT(test_base64.compare(output) == 0); + } + + void Base64Test::decodingTestSuccess() + { + const std::vector<uint8_t> output = ring::base64::decode(test_base64); + CPPUNIT_ASSERT(std::equal(test_bytes.begin(), test_bytes.end(), output.begin())); + } + + void Base64Test::decodingTestFail() + { + // Currently, the input is not validated, i.e. the function most not throw an + // exception if decoding fails to make sure calling code not expecting any + // is no broken. (Some validation should be implemented sometimes later, though. + ring::base64::decode(test_invalid_base64); + CPPUNIT_ASSERT(true); + } +} // namespace tests + +RING_TEST_RUNNER(ring_test::Base64Test::name()) diff --git a/test/base64/test_runner.hpp b/test/base64/test_runner.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0762b5764c12a48107b295ac7028afb4c0330d71 --- /dev/null +++ b/test/base64/test_runner.hpp @@ -0,0 +1,19 @@ +#include <iostream> + +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/CompilerOutputter.h> + +#define RING_TEST_RUNNER(suite_name) \ +int main() \ +{ \ + CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(suite_name); \ + CppUnit::Test *suite = registry.makeTest(); \ + if(suite->countTestCases() == 0) { \ + std::cout << "No test cases specified for suite \"" << suite_name << "\"\n"; \ + return 1; \ + } \ + CppUnit::TextUi::TestRunner runner; \ + runner.addTest(suite); \ + return runner.run() ? 0 : 1; \ +} diff --git a/test/media/Makefile.am b/test/media/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..32b8fca2afa1146a4095afa18ed7b2d56fa2afbe --- /dev/null +++ b/test/media/Makefile.am @@ -0,0 +1,3 @@ +include $(top_srcdir)/globals.mk + +SUBDIRS= video diff --git a/test/media/video/.gitignore b/test/media/video/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2e3b6e6e04753de26f70bdf06f1ea54c778eec83 --- /dev/null +++ b/test/media/video/.gitignore @@ -0,0 +1 @@ +test_video_input diff --git a/test/media/video/Makefile.am b/test/media/video/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..7e83dcda42f9f876f2a2186cbf7d13cf01760cfb --- /dev/null +++ b/test/media/video/Makefile.am @@ -0,0 +1,11 @@ +include $(top_srcdir)/globals.mk + +check_PROGRAMS= +# +# video_input testsuite +# +check_PROGRAMS+= test_video_input +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) + +TESTS= $(check_PROGRAMS) diff --git a/test/media/video/README b/test/media/video/README new file mode 100644 index 0000000000000000000000000000000000000000..9ef0c4f1e81db2960330be48b5138435024a50d5 --- /dev/null +++ b/test/media/video/README @@ -0,0 +1 @@ +c++ shm_src.cpp shmclient.cpp -o shmclient `pkg-config --cflags --libs clutter-1.0` -lrt -pthread -O2 diff --git a/test/media/video/test_video_input.cpp b/test/media/video/test_video_input.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d089ae8dd52e4ecbfb16a158e1c95f5bde5cabb6 --- /dev/null +++ b/test/media/video/test_video_input.cpp @@ -0,0 +1,47 @@ +/* + * 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 "media/video/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; +} diff --git a/test/media/video/test_video_input.h b/test/media/video/test_video_input.h new file mode 100644 index 0000000000000000000000000000000000000000..aeeb2acd3cd4cf1e9ca9b4abcf993e85cad28d75 --- /dev/null +++ b/test/media/video/test_video_input.h @@ -0,0 +1,33 @@ +/* + * 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_ diff --git a/test/sip/.gitignore b/test/sip/.gitignore index d0cf867da6b545ec0e6dcd9e9b781952efdb4c16..508976e42163e5fee85a0b9c7e7b1627ada5f147 100644 --- a/test/sip/.gitignore +++ b/test/sip/.gitignore @@ -1,8 +1,4 @@ -*.o - -# test result files -*.log -*.trs - #test binaries sip + +dring-sample.yml.bak diff --git a/test/sip/Makefile.am b/test/sip/Makefile.am index 01bc4887e0bf5bce6971530579035f1bbdacd263..73a2d3a4fb603e76b7b6d29c468e80271cde99f7 100644 --- a/test/sip/Makefile.am +++ b/test/sip/Makefile.am @@ -1,8 +1,8 @@ # Rules for the test code (use `make check` to execute) -include ../../globals.mk +include $(top_srcdir)/globals.mk TESTS = sip check_PROGRAMS = $(TESTS) -sip_LDADD = ./../../src/libring.la +sip_LDADD = $(top_builddir)/src/libring.la sip_SOURCES = sip.cpp test_SIP.h test_SIP.cpp ../../manager.h sip_CXXFLAGS = $(CPPUNIT_CFLAGS) sip_LDFLAGS = $(CPPUNIT_LIBS) -ldl diff --git a/test/sip/test_SIP.cpp b/test/sip/test_SIP.cpp index 411c2ae74b317de45e63da1ca4b6f7687b12dea2..c5bede3ce2aa9f24f6618bbc0daa4132ea12c1f8 100644 --- a/test/sip/test_SIP.cpp +++ b/test/sip/test_SIP.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2004-2017 Savoir-Faire Linux Inc. * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * Author: Olivier Gregoire <olivier.gregoire@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 @@ -124,283 +125,212 @@ test_SIP::tearDown() std::cout << "test_SIP: Error from system call, killall sipp" << ", ret=" << ret << '\n'; + Manager::instance().callFactory.clear(); } void test_SIP::testSimpleOutgoingIpCall() { - // start a user agent server waiting for a call - auto t = sippThread("sipp -sn uas -i 127.0.0.1 -p 5068 -m 1 -bg"); + std::cout << ">>>> test simple outgoing IP call <<<< " << '\n'; - std::string testaccount("IP2IP"); - std::string testcallnumber("sip:test@127.0.0.1:5068"); - std::string testcallid; // returned by outgoingCall() + CPPUNIT_ASSERT(Manager::instance().callFactory.empty()); - CPPUNIT_ASSERT(!Manager::instance().hasCurrentCall()); + // start a user agent server waiting for a call + auto t = sippThread("sipp -sn uas -i 127.0.0.1 -p 5068 -m 1 -bg"); - // start a new call sending INVITE message to sipp instance - testcallid = Manager::instance().outgoingCall(testaccount, testcallnumber); - - // wait for receiving 180 and 200 message from peer - std::this_thread::sleep_for(std::chrono::seconds(2)); // should be enough - - auto call = Manager::instance().getCallFromCallID(testcallid); - CPPUNIT_ASSERT(call); - - // check call state - auto state = call->getStateStr(); - std::cout << ">>>> call state is now " << state << '\n'; - CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); - - Manager::instance().hangupCall(testcallid); - - // check call state - state = call->getStateStr(); - std::cout << ">>>> call state is now " << state << '\n'; - CPPUNIT_ASSERT(state == DRing::Call::StateEvent::OVER); - - // Call must not not be available (except for thus how already own a pointer like us) - CPPUNIT_ASSERT(not Manager::instance().getCallFromCallID(testcallid)); -} - -#if 0 -void test_SIP::testSimpleIncomingIpCall() -{ - pthread_t thethread; - - // command to be executed by the thread, user agent client which initiate a call and hangup - std::string command("sipp -sn uac 127.0.0.1 -i 127.0.0.1 -p 5062 -m 1i -bg"); - - int rc = pthread_create(&thethread, NULL, sippThread, &command); - - if (rc) - std::cout << "test_SIP: ERROR; return code from pthread_create()" << std::endl; - - // sleep a while to make sure that sipp insdtance is initialized and sflphoned received - // the incoming invite. - sleep(2); - - // gtrab call id from sipvoiplink - SIPVoIPLink& siplink = SIPVoIPLink::instance(); - - CPPUNIT_ASSERT(siplink.sipCallMap_.size() == 1); - SipCallMap::iterator iterCallId = siplink.sipCallMap_.begin(); - std::string testcallid = iterCallId->first; - - // Answer this call - CPPUNIT_ASSERT(Manager::instance().answerCall(testcallid)); - - sleep(1); - - rc = pthread_join(thethread, NULL); - - if (rc) - std::cout << "test_SIP: ERROR; return code from pthread_join(): " << rc << std::endl; - else - std::cout << "test_SIP: completed join with thread" << std::endl; -} -#endif - -void -test_SIP::testTwoOutgoingIpCall() -{ - // This scenario expect to be put on hold before hangup - auto firstCallThread = sippThread("sipp -sf tools/sippxml/test_1.xml -i 127.0.0.1 -p 5062 -m 1"); - // The second call uses the default user agent scenario - auto secondCallThread = sippThread("sipp -sn uas -i 127.0.0.1 -p 5064 -m 1"); - - sleep(1); - - auto testAccount = "IP2IP"; - auto firstCallNumber = "sip:test@127.0.0.1:5062"; - auto secondCallNumber = "sip:test@127.0.0.1:5064"; + std::string testaccount("IP2IP"); + std::string testcallnumber("sip:test@127.0.0.1:5068"); + std::string testcallid; // returned by outgoingCall() CPPUNIT_ASSERT(!Manager::instance().hasCurrentCall()); // start a new call sending INVITE message to sipp instance - // this call should be put on hold when making the second call - auto firstCallId = Manager::instance().outgoingCall(testAccount, firstCallNumber); + testcallid = Manager::instance().outgoingCall(testaccount, testcallnumber); + + // wait for receiving 180 and 200 message from peer + std::this_thread::sleep_for(std::chrono::seconds(1)); // should be enough - // must sleep here until receiving 180 and 200 message from peer - sleep(1); + auto call = Manager::instance().getCallFromCallID(testcallid); + CPPUNIT_ASSERT(call); - auto secondCallId = Manager::instance().outgoingCall(testAccount, secondCallNumber); + // check call state + auto state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); - sleep(1); + // hangup call + std::cout << ">>>> hangup the call " << '\n'; + Manager::instance().hangupCall(testcallid); + state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::OVER); - Manager::instance().hangupCall(firstCallId); - Manager::instance().hangupCall(secondCallId); + // Call must not not be available (except for thus how already own a pointer like us) + CPPUNIT_ASSERT(not Manager::instance().getCallFromCallID(testcallid)); } -#if 0 -void test_SIP::testTwoIncomingIpCall() -{ - pthread_mutex_init(&count_mutex, NULL); - pthread_cond_init(&count_nb_thread, NULL); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); +void +test_SIP::testSimpleIncomingIpCall() +{ + std::cout << ">>>> test simple incomming IP call <<<< " << '\n'; - // the first call is supposed to be put on hold when answering teh second incoming call - std::string firstCallCommand("sipp -sf tools/sippxml/test_2.xml 127.0.0.1 -i 127.0.0.1 -p 5064 -m 1 > testfile1.txt -bg"); + CPPUNIT_ASSERT(Manager::instance().callFactory.empty()); // command to be executed by the thread, user agent client which initiate a call and hangup - std::string secondCallCommand("sipp -sn uac 127.0.0.1 -i 127.0.0.1 -p 5062 -m 1 -d 250 > testfile2.txt -bg"); + sippThread("sipp -sn uac 127.0.0.1 -i 127.0.0.1 -p 5062 -m 1 -bg"); - pthread_t firstCallThread; - int rc = pthread_create(&firstCallThread, &attr, sippThreadWithCount, &firstCallCommand); - - if (rc) - std::cout << "test_SIP: ERROR; return code from pthread_create()" << std::endl; - - // sleep a while to make sure that sipp insdtance is initialized and sflphoned received + // sleep a while to make sure that sipp insdtance is initialized and dring received // the incoming invite. - sleep(1); - - // gtrab call id from sipvoiplink - SIPVoIPLink& sipLink = SIPVoIPLink::instance(); - - CPPUNIT_ASSERT(sipLink.sipCallMap_.size() == 1); - SipCallMap::iterator iterCallId = sipLink.sipCallMap_.begin(); - std::string firstCallID = iterCallId->first; + std::this_thread::sleep_for(std::chrono::seconds(1)); // Answer this call - CPPUNIT_ASSERT(Manager::instance().answerCall(firstCallID)); + const auto& calls = Manager::instance().callFactory.getAllCalls(); + const auto call = *calls.cbegin(); + CPPUNIT_ASSERT(Manager::instance().answerCall(call->getCallId())); + + // hangup this call + Manager::instance().hangupCall(call->getCallId()); + auto state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::OVER); +} - sleep(1); - pthread_t secondCallThread; - rc = pthread_create(&secondCallThread, &attr, sippThread, &secondCallCommand); +void +test_SIP::testMultipleIncomingIpCall(){ + std::cout << ">>>> test multiple incoming IP call <<<< " << '\n'; - if (rc) - std::cout << "test_SIP: Error; return code from pthread_create()" << std::endl; + CPPUNIT_ASSERT(Manager::instance().callFactory.empty()); - sleep(1); + // this value change the number of outgoing call we do + int numberOfCall =5; - CPPUNIT_ASSERT(sipLink.sipCallMap_.size() == 2); - iterCallId = sipLink.sipCallMap_.begin(); + for(int i = 0; i < numberOfCall; i++){ + // start a user agent server waiting for a call + sippThread("sipp -sf sippxml/test_2.xml 127.0.0.1 -i 127.0.0.1 -p 506"+std::to_string(i+1)+" -m 1 -bg"); - if (iterCallId->first == firstCallID) - ++iterCallId; + // sleep a while to make sure that sipp insdtance is initialized and dring received + // the incoming invite. + std::this_thread::sleep_for(std::chrono::seconds(3)); - std::string secondCallID(iterCallId->first); + const auto& calls = Manager::instance().callFactory.getAllCalls(); + const auto call = *calls.cbegin(); + auto state = call->getStateStr(); + std::cout << ">>>> current call (call number: "+std::to_string(i)+") state:" << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::INCOMING); //TODO this state is sometime HOLD - CPPUNIT_ASSERT(Manager::instance().answerCall(secondCallID)); + // Answer this call + CPPUNIT_ASSERT(Manager::instance().answerCall(call->getCallId())); - sleep(2); + state = call->getStateStr(); + std::cout << ">>>> current call (call number: "+std::to_string(i)+") state:" << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); - pthread_mutex_lock(&count_mutex); + Manager::instance().onHoldCall(call->getCallId()); + state = call->getStateStr(); + std::cout << ">>>> current call (call number: "+std::to_string(i)+") state:" << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::HOLD); + } + +} - while (counter > 0) - pthread_cond_wait(&count_nb_thread, &count_mutex); - pthread_mutex_unlock(&count_mutex); +void +test_SIP::testMultipleOutgoingIpCall() +{ + std::cout << ">>>> test multiple outgoing IP call <<<< " << '\n'; + + CPPUNIT_ASSERT(Manager::instance().callFactory.empty()); + + // this value change the number of outgoing call we do + int numberOfCall =5; + + //setup of the calls + std::string callNumber("sip:test@127.0.0.1:5061"); + std::string testaccount("IP2IP"); + std::string callID[numberOfCall]; + + for(int i = 0; i < numberOfCall; i++){ + // start a user agent server waiting for a call + sippThread("sipp -sn uas -i 127.0.0.1 -p 5061 -m "+std::to_string(numberOfCall)+" -bg"); + + callID[i] = Manager::instance().outgoingCall(testaccount, callNumber); + auto newCall = Manager::instance().getCallFromCallID(callID[i]); + CPPUNIT_ASSERT(newCall); + + // wait for receiving 180 and 200 message from peer + std::this_thread::sleep_for(std::chrono::seconds(1)); // should be enough + + auto state = newCall->getStateStr(); + std::cout << ">>>> current call (call number: "+std::to_string(i)+") state:" << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); + + // test the changement of calls states after doing a new call + if(i){ + for(int j = 0; j<i; j++){ + auto oldCall = Manager::instance().getCallFromCallID(callID[j]); + CPPUNIT_ASSERT(oldCall); + auto oldState = oldCall->getStateStr(); + std::cout << ">>>> old call (call number: "+std::to_string(j)+") state:" << oldState << '\n'; + CPPUNIT_ASSERT(oldState == DRing::Call::StateEvent::HOLD); + } + } + } - pthread_mutex_destroy(&count_mutex); - pthread_cond_destroy(&count_nb_thread); + //hangup all calls + for(int i = 0; i < numberOfCall; i++){ + auto call = Manager::instance().getCallFromCallID(callID[i]); + Manager::instance().hangupCall(callID[i]); + auto state = call->getStateStr(); + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::OVER); + } } -#endif void test_SIP::testHoldIpCall() { + std::cout << ">>>> test hold IP call <<<< " << '\n'; + + CPPUNIT_ASSERT(Manager::instance().callFactory.empty()); + auto testAccount = "IP2IP"; auto testCallNumber = "sip:test@127.0.0.1:5062"; - auto callThread = sippThread("sipp -sf tools/sippxml/test_3.xml -i 127.0.0.1 -p 5062 -m 1 -bg"); + auto callThread = sippThread("sipp -sf sippxml/test_3.xml -i 127.0.0.1 -p 5062 -m 1 -bg"); auto testCallId = Manager::instance().outgoingCall(testAccount, testCallNumber); + auto call = Manager::instance().getCallFromCallID(testCallId); - sleep(1); + std::this_thread::sleep_for(std::chrono::seconds(2)); + + auto state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); Manager::instance().onHoldCall(testCallId); - sleep(1); + state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::HOLD); Manager::instance().offHoldCall(testCallId); - sleep(1); + state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::CURRENT); Manager::instance().hangupCall(testCallId); + state = call->getStateStr(); + std::cout << ">>>> call state is now " << state << '\n'; + CPPUNIT_ASSERT(state == DRing::Call::StateEvent::OVER); } -#if 0 + void test_SIP::testSIPURI() { + std::cout << ">>>> test SIPURI <<<< " << '\n'; + std::string foo("<sip:17771234567@callcentric.com>"); sip_utils::stripSipUriPrefix(foo); CPPUNIT_ASSERT(foo == "17771234567"); } -#endif - -#if 0 -void test_SIP::testParseDisplayName() -{ - // 1st element is input, 2nd is expected output - const char *test_set[][2] = { - {"\nFrom: \"A. G. Bell\" <sip:agb@bell-telephone.com> ;tag=a48s", "A. G. Bell"}, - {"\nFrom: \"A. G. Bell2\" <sip:agb@bell-telephone.com> ;tag=a48s\r\nOtherLine: \"bla\"\r\n", "A. G. Bell2"}, - {"\nf: Anonymous <sip:c8oqz84zk7z@privacy.org>;tag=hyh8", "Anonymous"}, - {"\nFrom: \"Alejandro Perez\" <sip:1111@10.0.0.1>;tag=3a7516a63bdbo0", "Alejandro Perez"}, - {"\nFrom: \"Malformed <sip:1111@10.0.0.1>;tag=3a6a63bdbo0", ""}, - {"\nTo: <sip:1955@10.0.0.1>;tag=as6fbade41", ""}, - {"\nFrom: \"1000\" <sip:1000@sip.example.es>;tag=as775338f3", "1000"}, - {"\nFrom: 1111_9532323 <sip:1111_9532323@sip.example.es>;tag=caa3a61", "1111_9532323"}, - {"\nFrom: \"4444_953111111\" <sip:4444_111111@sip.example.es>;tag=2b00632co0", "4444_953111111"}, - {"\nFrom: <sip:6926666@4.4.4.4>;tag=4421-D9700", ""}, - {"\nFrom: <sip:pinger@sipwise.local>;tag=01f516a4", ""}, - {"\nFrom: sip:pinger@sipwise.local;tag=01f516a4", ""}, - {"\nFrom: ", ""}, - {"\nFrom: \"\xb1""Alejandro P\xc3\xa9rez\" <sip:1111@10.0.0.1>;tag=3a7516a63bdbo0", "\xef\xbf\xbd""Alejandro P\xc3\xa9rez"}, - {"\nFrom: \"Alejandro P\xc3\xa9rez\" <sip:1111@10.0.0.1>;tag=3a7516a63bdbo0", "Alejandro P\xc3\xa9rez"}, - {"\nFrom: sip:+1212555@server.example.com;tag=887s", ""}}; - - for (const auto &t : test_set) { - const std::string str(sip_utils::parseDisplayName(t[0])); - CPPUNIT_ASSERT_MESSAGE(std::string("\"") + str + "\" should be \"" + - t[1] + "\", input on next line: " + t[0], - str == t[1]); - } -} -#endif - -#if 0 -void test_SIP::testIncomingIpCallSdp() -{ - // command to be executed by the thread, user agent client which initiate a call and hangup - std::string command("sipp -sf tools/sippxml/test_4.xml 127.0.0.1 -i 127.0.0.1 -p 5062 -m 1i -bg"); - - pthread_t thethread; - int rc = pthread_create(&thethread, NULL, sippThread, (void *)(&command)); - - if (rc) - std::cout << "test_SIP: ERROR; return code from pthread_create()" << std::endl; - - // sleep a while to make sure that sipp insdtance is initialized and sflphoned received - // the incoming invite. - sleep(2); - - // gtrab call id from sipvoiplink - SIPVoIPLink& siplink = SIPVoIPLink::instance(); - - CPPUNIT_ASSERT(siplink.sipCallMap_.size() == 1); - SipCallMap::iterator iterCallId = siplink.sipCallMap_.begin(); - std::string testcallid = iterCallId->first; - - // TODO: hmmm, should IP2IP call be stored in call list.... - CPPUNIT_ASSERT(Manager::instance().getCallList().empty()); - - // Answer this call - CPPUNIT_ASSERT(Manager::instance().answerCall(testcallid)); - - - sleep(1); - - rc = pthread_join(thethread, NULL); - - if (rc) - std::cout << "test_SIP: ERROR; return code from pthread_join(): " << rc << std::endl; - else - std::cout << "test_SIP: completed join with thread" << std::endl; -} -#endif diff --git a/test/sip/test_SIP.h b/test/sip/test_SIP.h index 7cbb3c908fc161b6b21519809339a303ec185999..8ad13c611f7c77b3f9617e0393df12e1dad63f16 100644 --- a/test/sip/test_SIP.h +++ b/test/sip/test_SIP.h @@ -2,6 +2,7 @@ * Copyright (C) 2004-2017 Savoir-Faire Linux Inc. * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * Author: Olivier Gregoire <olivier.gregoire@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 @@ -28,6 +29,7 @@ // Application import #include "manager.h" + #include "sip/sipvoiplink.h" #include "sip/sip_utils.h" @@ -80,33 +82,35 @@ public: void tearDown(); private: + // Create a simple IP call and test his state void testSimpleOutgoingIpCall(void); - //void testSimpleIncomingIpCall(void); + // Receive a new incoming call and test his state + void testSimpleIncomingIpCall(void); - void testTwoOutgoingIpCall(void); + // Test with multiple outgoing calls + void testMultipleOutgoingIpCall(void); - //void testTwoIncomingIpCall(void); + // TODO this test bug, the new calls are sometimes + // put in hold + void testMultipleIncomingIpCall(void); + // Test the hold state void testHoldIpCall(void); - //void testIncomingIpCallSdp(void); - - //void testSIPURI(); + void testSIPURI(void); - //void testParseDisplayName(); /** - * Use cppunit library macros to add unit test the factory + * Use cppunit library macros to add unit test to the factory */ CPPUNIT_TEST_SUITE(test_SIP); + CPPUNIT_TEST ( testSIPURI ); + /*CPPUNIT_TEST ( testHoldIpCall ); CPPUNIT_TEST ( testSimpleOutgoingIpCall ); - //CPPUNIT_TEST ( testParseDisplayName ); - //CPPUNIT_TEST ( testSimpleIncomingIpCall ); - //CPPUNIT_TEST ( testTwoOutgoingIpCall ); - //CPPUNIT_TEST ( testTwoIncomingIpCall ); - //CPPUNIT_TEST ( testHoldIpCall ); - //CPPUNIT_TEST ( testIncomingIpCallSdp ); + CPPUNIT_TEST ( testMultipleOutgoingIpCall ); + CPPUNIT_TEST ( testSimpleIncomingIpCall );*/ + //CPPUNIT_TEST ( testMultipleIncomingIpCall ); CPPUNIT_TEST_SUITE_END(); RAIIThread eventLoop_;