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 &registry = 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_;