From fd30291ebc9ab3459e1396ca2ec204820e798a65 Mon Sep 17 00:00:00 2001
From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
Date: Thu, 18 Aug 2022 12:07:46 -0300
Subject: [PATCH] tests: add dummy plugin for daemon unit tests

The TestSuite plugin contains audio, video and chat handlers to
support toggling/untoogling tests.

GitLab: https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/745

Change-Id: I45f55127443a5c904b89066b6fe1ca102d37e361
---
 AutoAnswer/BotPeerChatSubscriber.h      |   2 -
 TestSuite/AudioHandlerTester.cpp        |  89 ++++++++
 TestSuite/AudioHandlerTester.h          |  50 +++++
 TestSuite/AudioSubscriberTester.cpp     |  65 ++++++
 TestSuite/AudioSubscriberTester.h       |  49 +++++
 TestSuite/CMakeLists.txt                |  91 ++++++++
 TestSuite/ChatHandlerTester.cpp         |  76 +++++++
 TestSuite/ChatHandlerTester.h           |  56 +++++
 TestSuite/ChatSubscriberTester.cpp      |  60 ++++++
 TestSuite/ChatSubscriberTester.h        |  48 +++++
 TestSuite/VideoHandlerTester.cpp        |  88 ++++++++
 TestSuite/VideoHandlerTester.h          |  50 +++++
 TestSuite/VideoSubscriberTester.cpp     |  66 ++++++
 TestSuite/VideoSubscriberTester.h       |  46 ++++
 TestSuite/build.sh                      | 267 ++++++++++++++++++++++++
 TestSuite/data/accountpreferences.json  |   9 +
 TestSuite/data/icon.png                 | Bin 0 -> 31362 bytes
 TestSuite/data/icon.svg                 |  30 +++
 TestSuite/data/locale/TestSuite_en.json |   8 +
 TestSuite/data/locale/TestSuite_fr.json |   8 +
 TestSuite/data/preferences.json         |   9 +
 TestSuite/main.cpp                      |  86 ++++++++
 TestSuite/manifest.json                 |   6 +
 TestSuite/package.json                  |  19 ++
 24 files changed, 1276 insertions(+), 2 deletions(-)
 create mode 100644 TestSuite/AudioHandlerTester.cpp
 create mode 100644 TestSuite/AudioHandlerTester.h
 create mode 100644 TestSuite/AudioSubscriberTester.cpp
 create mode 100644 TestSuite/AudioSubscriberTester.h
 create mode 100644 TestSuite/CMakeLists.txt
 create mode 100644 TestSuite/ChatHandlerTester.cpp
 create mode 100644 TestSuite/ChatHandlerTester.h
 create mode 100644 TestSuite/ChatSubscriberTester.cpp
 create mode 100644 TestSuite/ChatSubscriberTester.h
 create mode 100644 TestSuite/VideoHandlerTester.cpp
 create mode 100644 TestSuite/VideoHandlerTester.h
 create mode 100644 TestSuite/VideoSubscriberTester.cpp
 create mode 100644 TestSuite/VideoSubscriberTester.h
 create mode 100755 TestSuite/build.sh
 create mode 100644 TestSuite/data/accountpreferences.json
 create mode 100644 TestSuite/data/icon.png
 create mode 100644 TestSuite/data/icon.svg
 create mode 100644 TestSuite/data/locale/TestSuite_en.json
 create mode 100644 TestSuite/data/locale/TestSuite_fr.json
 create mode 100644 TestSuite/data/preferences.json
 create mode 100644 TestSuite/main.cpp
 create mode 100644 TestSuite/manifest.json
 create mode 100644 TestSuite/package.json

diff --git a/AutoAnswer/BotPeerChatSubscriber.h b/AutoAnswer/BotPeerChatSubscriber.h
index cac463b..70e1964 100644
--- a/AutoAnswer/BotPeerChatSubscriber.h
+++ b/AutoAnswer/BotPeerChatSubscriber.h
@@ -46,8 +46,6 @@ public:
                   std::string& peerId,
                   std::map<std::string, std::string>& sendMsg,
                   bool swarm);
-    void setAnswer(const std::string& textAnswer);
-    void setInText(const std::string& inText);
 
 protected:
     // Observer pattern
diff --git a/TestSuite/AudioHandlerTester.cpp b/TestSuite/AudioHandlerTester.cpp
new file mode 100644
index 0000000..4b6b73a
--- /dev/null
+++ b/TestSuite/AudioHandlerTester.cpp
@@ -0,0 +1,89 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "AudioHandlerTester.h"
+
+#include "pluglog.h"
+#include <string_view>
+
+const char sep = separator();
+const std::string TAG = "AudioHandlerTester";
+
+#define NAME "AudioHandlerTester"
+
+namespace jami {
+
+AudioHandlerTester::AudioHandlerTester(std::string&& datapath)
+    : datapath_ {datapath}
+{
+    setId(datapath_);
+    mAS = std::make_shared<AudioSubscriberTester>();
+}
+
+void
+AudioHandlerTester::notifyAVFrameSubject(const StreamData& data, jami::avSubjectPtr subject)
+{
+    if (!mAS)
+        return;
+    std::ostringstream oss;
+    std::string_view direction = data.direction ? "Receive" : "Preview";
+    oss << "NEW SUBJECT: [" << data.id << "," << direction << "]" << std::endl;
+    bool preferredStreamDirection = false; // false for output; true for input
+    oss << "preferredStreamDirection " << preferredStreamDirection << std::endl;
+    if (data.type == StreamType::audio && !data.direction
+        && data.direction == preferredStreamDirection) {
+        subject->attach(mAS.get()); // your image
+        oss << "got my sent audio attached" << std::endl;
+        attached_ = '1';
+    } else if (data.type == StreamType::audio && data.direction
+               && data.direction == preferredStreamDirection) {
+        subject->attach(mAS.get()); // the image you receive from others on the call
+        oss << "got received audio attached" << std::endl;
+        attached_ = '1';
+    }
+
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+std::map<std::string, std::string>
+AudioHandlerTester::getCallMediaHandlerDetails()
+{
+    return {{"name", NAME},
+            {"iconPath", datapath_ + sep + "icon.svg"},
+            {"pluginId", id()},
+            {"attached", attached_},
+            {"dataType", "0"}};
+}
+
+void
+AudioHandlerTester::detach()
+{
+    attached_ = '0';
+    mAS->detach();
+}
+
+AudioHandlerTester::~AudioHandlerTester()
+{
+    std::ostringstream oss;
+    oss << " ~AudioHandlerTester from TestSuite Plugin" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+    detach();
+}
+} // namespace jami
diff --git a/TestSuite/AudioHandlerTester.h b/TestSuite/AudioHandlerTester.h
new file mode 100644
index 0000000..c31a430
--- /dev/null
+++ b/TestSuite/AudioHandlerTester.h
@@ -0,0 +1,50 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+#include "AudioSubscriberTester.h"
+
+#include "plugin/jamiplugin.h"
+#include "plugin/mediahandler.h"
+
+using avSubjectPtr = std::weak_ptr<jami::Observable<AVFrame*>>;
+
+namespace jami {
+
+class AudioHandlerTester : public CallMediaHandler
+{
+public:
+    AudioHandlerTester(std::string&& dataPath);
+    ~AudioHandlerTester();
+
+    virtual void notifyAVFrameSubject(const StreamData& data, avSubjectPtr subject) override;
+    virtual std::map<std::string, std::string> getCallMediaHandlerDetails() override;
+    virtual void detach() override;
+    virtual void setPreferenceAttribute(const std::string& key, const std::string& value) override {}
+    virtual bool preferenceMapHasKey(const std::string& key) override { return false; }
+
+    std::shared_ptr<AudioSubscriberTester> mAS{};
+
+private:
+    const std::string datapath_;
+    std::string attached_ {'0'};
+};
+} // namespace jami
diff --git a/TestSuite/AudioSubscriberTester.cpp b/TestSuite/AudioSubscriberTester.cpp
new file mode 100644
index 0000000..52f4afb
--- /dev/null
+++ b/TestSuite/AudioSubscriberTester.cpp
@@ -0,0 +1,65 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "AudioSubscriberTester.h"
+
+#include <pluglog.h>
+
+const std::string TAG = "AudioHandlerTester";
+const char sep = separator();
+
+namespace jami {
+
+AudioSubscriberTester::~AudioSubscriberTester()
+{
+    std::ostringstream oss;
+    oss << "~AudioSubscriberTester" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+AudioSubscriberTester::attached(Observable<AVFrame*>* observable)
+{
+    std::ostringstream oss;
+    oss << "::Attached ! " << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+    observable_ = observable;
+}
+
+void
+AudioSubscriberTester::detached(Observable<AVFrame*>*)
+{
+    observable_ = nullptr;
+    std::ostringstream oss;
+    oss << "::Detached()" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+AudioSubscriberTester::detach()
+{
+    if (observable_) {
+        std::ostringstream oss;
+        oss << "::Calling detach()" << std::endl;
+        Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+        observable_->detach(this);
+    }
+}
+} // namespace jami
diff --git a/TestSuite/AudioSubscriberTester.h b/TestSuite/AudioSubscriberTester.h
new file mode 100644
index 0000000..83e1bfa
--- /dev/null
+++ b/TestSuite/AudioSubscriberTester.h
@@ -0,0 +1,49 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+#include <observer.h>
+
+namespace jami {
+
+class AudioSubscriberTester : public Observer<AVFrame*>
+{
+public:
+    AudioSubscriberTester() {}
+    ~AudioSubscriberTester();
+
+    virtual void update(Observable<AVFrame*>*, AVFrame* const&) override {}
+    virtual void attached(Observable<AVFrame*>*) override;
+    virtual void detached(Observable<AVFrame*>*) override;
+
+    void detach();
+
+private:
+    // Observer pattern
+    Observable<AVFrame*>* observable_{};
+
+    // Data
+    std::string path_;
+};
+} // namespace jami
diff --git a/TestSuite/CMakeLists.txt b/TestSuite/CMakeLists.txt
new file mode 100644
index 0000000..51f516f
--- /dev/null
+++ b/TestSuite/CMakeLists.txt
@@ -0,0 +1,91 @@
+cmake_minimum_required(VERSION 3.10)
+
+# set the project name
+set (ProjectName TestSuite)
+set (Version 1.0.0)
+
+project(${ProjectName} VERSION ${Version})
+
+set (DAEMON ${PROJECT_SOURCE_DIR}/../../daemon)
+set (JPL_FILE_NAME ${ProjectName}.jpl)
+set (DAEMON_SRC ${DAEMON}/src)
+set (CONTRIB_PATH ${DAEMON}/contrib)
+set (PLUGINS_LIB ${PROJECT_SOURCE_DIR}/../lib)
+set (JPL_DIRECTORY ${PROJECT_BINARY_DIR}/jpl)
+set (LIBS_DIR ${PROJECT_SOURCE_DIR}/../contrib/Libs)
+
+if(WIN32)
+    message(OS:\  WINDOWS\ ${CMAKE_SYSTEM_PROCESSOR})
+    if (NOT ${CMAKE_CL_64})
+        message( FATAL_ERROR "\nUse CMake only for x64 Windows" )
+    endif()
+    set (CONTRIB_PLATFORM_CURT x64)
+    set (CONTRIB_PLATFORM ${CONTRIB_PLATFORM_CURT}-windows)
+    set (LIBRARY_FILE_NAME ${ProjectName}.dll)
+    set (FFMPEG ${CONTRIB_PATH}/build/ffmpeg/Build/win32/x64)
+else()
+    message( FATAL_ERROR "\nUse CMake only for Windows! For linux or Android (linux host), use our bash scripts." )
+endif()
+
+message(Building:\   ${ProjectName}\   ${Version})
+message(Build\ path:\ ${PROJECT_BINARY_DIR})
+message(JPL\ assembling\ path:\ ${JPL_DIRECTORY})
+message(JPL\ path:\ ${JPL_DIRECTORY}/../../../build/${ProjectName}/${JPL_FILE_NAME})
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+
+set(plugin_SRC AudioHandlerTester.cpp
+               AudioSubscriberTester.cpp
+               VideoHandlerTester.cpp
+               VideoSubscriberTester.cpp
+               ChatHandlerTester.cpp
+               ChatSubscriberTester.cpp
+               main.cpp
+               )
+
+set(plugin_HDR AudioHandlerTester.h
+               AudioSubscriberTester.h
+               VideoHandlerTester.h
+               VideoSubscriberTester.h
+               ChatHandlerTester.h
+               ChatSubscriberTester.h
+               ./../lib/pluglog.h
+               )
+
+add_library(${ProjectName} SHARED ${plugin_SRC}
+                                  ${plugin_HDR}
+                                  )
+
+target_include_directories(${ProjectName} PUBLIC ${PROJECT_BINARY_DIR}
+                                                 ${PROJECT_SOURCE_DIR}
+                                                 ${PLUGINS_LIB}
+                                                 ${DAEMON_SRC}
+                                                 ${CONTRIB_PATH}
+                                                 ${CONTRIB_PATH}/build/fmt/include
+                                                 ${FFMPEG}/include
+                                                 )
+target_link_directories(${ProjectName} PUBLIC ${CONTRIB_PATH}
+                                        ${FFMPEG}/bin
+                                        ${CONTRIB_PATH}/build/fmt/msvc/Release
+                                        )
+
+target_link_libraries(${ProjectName} PUBLIC avutil)
+
+add_custom_command(
+    TARGET ${ProjectName}
+    PRE_BUILD
+    COMMAND python ${PROJECT_SOURCE_DIR}/../SDK/jplManipulation.py --preassemble --plugin=${ProjectName}
+    COMMENT "Assembling Plugin files"
+)
+
+add_custom_command(
+    TARGET ${ProjectName}
+    POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/Release/${ProjectName}.lib ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+    COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/Release/${LIBRARY_FILE_NAME} ${JPL_DIRECTORY}/lib/${CONTRIB_PLATFORM}
+    COMMAND python ${PROJECT_SOURCE_DIR}/../SDK/jplManipulation.py --assemble --plugin=${ProjectName}
+    COMMENT "Generating JPL archive"
+)
diff --git a/TestSuite/ChatHandlerTester.cpp b/TestSuite/ChatHandlerTester.cpp
new file mode 100644
index 0000000..f1b1907
--- /dev/null
+++ b/TestSuite/ChatHandlerTester.cpp
@@ -0,0 +1,76 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "ChatHandlerTester.h"
+
+#include "pluglog.h"
+
+const char sep = separator();
+const std::string TAG = "ChatHandlerTester";
+
+#define NAME "ChatHandlerTester"
+
+namespace jami {
+
+ChatHandlerTester::ChatHandlerTester(std::string&& dataPath)
+    : datapath_ {dataPath}
+{
+    setId(datapath_);
+    mCS_ = std::make_shared<ChatSubscriberTester>();
+}
+
+void
+ChatHandlerTester::notifyChatSubject(std::pair<std::string, std::string>& subjectConnection,
+                                     chatSubjectPtr subject)
+{
+    if (mCS_ && subjects.find(subject) == subjects.end()) {
+        std::ostringstream oss;
+        oss << "NEW SUBJECT: account = " << subjectConnection.first
+            << " peer = " << subjectConnection.second << std::endl;
+        Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+        subject->attach(mCS_.get());
+        subjects.insert(subject);
+    }
+}
+
+std::map<std::string, std::string>
+ChatHandlerTester::getChatHandlerDetails()
+{
+    return {{"name", NAME}, {"iconPath", datapath_ + sep + "icon.svg"}, {"pluginId", id()}};
+}
+
+void
+ChatHandlerTester::detach(chatSubjectPtr subject)
+{
+    auto it = subjects.find(subject);
+    if (it != subjects.end()) {
+        subject->detach(mCS_.get());
+        subjects.erase(it);
+    }
+}
+
+ChatHandlerTester::~ChatHandlerTester()
+{
+    const auto copy = subjects;
+    for (const auto& subject : copy) {
+        detach(subject);
+    }
+}
+} // namespace jami
diff --git a/TestSuite/ChatHandlerTester.h b/TestSuite/ChatHandlerTester.h
new file mode 100644
index 0000000..8357ef7
--- /dev/null
+++ b/TestSuite/ChatHandlerTester.h
@@ -0,0 +1,56 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+#include "ChatSubscriberTester.h"
+
+#include "plugin/jamiplugin.h"
+#include "plugin/chathandler.h"
+
+#include <string>
+#include <map>
+#include <memory>
+#include <set>
+
+using chatSubjectPtr = std::shared_ptr<jami::PublishObservable<jami::pluginMessagePtr>>;
+
+namespace jami {
+
+class ChatHandlerTester : public jami::ChatHandler
+{
+public:
+    ChatHandlerTester(std::string&& dataPath);
+    ~ChatHandlerTester();
+
+    void notifyChatSubject(std::pair<std::string, std::string>& subjectConnection,
+                           chatSubjectPtr subject) override;
+    std::map<std::string, std::string> getChatHandlerDetails() override;
+    void detach(chatSubjectPtr subject) override;
+    void setPreferenceAttribute(const std::string& key, const std::string& value) override {}
+    bool preferenceMapHasKey(const std::string& key) override { return false; }
+
+    std::shared_ptr<ChatSubscriberTester> mCS_ {};
+
+private:
+    const std::string datapath_;
+    std::set<chatSubjectPtr> subjects;
+};
+} // namespace jami
diff --git a/TestSuite/ChatSubscriberTester.cpp b/TestSuite/ChatSubscriberTester.cpp
new file mode 100644
index 0000000..7ee5ab5
--- /dev/null
+++ b/TestSuite/ChatSubscriberTester.cpp
@@ -0,0 +1,60 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "ChatSubscriberTester.h"
+#include "pluglog.h"
+
+const std::string TAG = "ChatHandlerTester";
+
+namespace jami {
+
+ChatSubscriberTester::~ChatSubscriberTester()
+{
+    std::ostringstream oss;
+    oss << "~ChatSubscriberTester" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+ChatSubscriberTester::attached(Observable<pluginMessagePtr>* observable)
+{
+    if (observables_.find(observable) == observables_.end()) {
+        std::ostringstream oss;
+        oss << "::Attached ! " << std::endl;
+        Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+        observables_.insert(observable);
+        isAttached = true;
+    }
+}
+
+void
+ChatSubscriberTester::detached(Observable<pluginMessagePtr>* observable)
+{
+    auto it = observables_.find(observable);
+    if (it != observables_.end()) {
+        observables_.erase(it);
+        std::ostringstream oss;
+        oss << "::Detached()" << std::endl;
+        Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+        if (observables_.empty())
+            isAttached = false;
+    }
+}
+} // namespace jami
diff --git a/TestSuite/ChatSubscriberTester.h b/TestSuite/ChatSubscriberTester.h
new file mode 100644
index 0000000..f93e38d
--- /dev/null
+++ b/TestSuite/ChatSubscriberTester.h
@@ -0,0 +1,48 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+#include "observer.h"
+
+#include "plugin/streamdata.h"
+#include "plugin/jamiplugin.h"
+#include "plugin/chathandler.h"
+
+#include <map>
+#include <set>
+
+namespace jami {
+
+class ChatSubscriberTester : public Observer<pluginMessagePtr>
+{
+public:
+    ChatSubscriberTester() {}
+    ~ChatSubscriberTester();
+    virtual void update(Observable<pluginMessagePtr>*, pluginMessagePtr const&) override {}
+    virtual void attached(Observable<pluginMessagePtr>*) override;
+    virtual void detached(Observable<pluginMessagePtr>*) override;
+
+protected:
+    // Observer pattern
+    std::set<Observable<pluginMessagePtr>*> observables_;
+    bool isAttached {false};
+};
+} // namespace jami
diff --git a/TestSuite/VideoHandlerTester.cpp b/TestSuite/VideoHandlerTester.cpp
new file mode 100644
index 0000000..1029161
--- /dev/null
+++ b/TestSuite/VideoHandlerTester.cpp
@@ -0,0 +1,88 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "VideoHandlerTester.h"
+
+#include "pluglog.h"
+#include <string_view>
+
+const char sep = separator();
+const std::string TAG = "VideoHandlerTester";
+
+#define NAME "VideoHandlerTester"
+
+namespace jami {
+
+VideoHandlerTester::VideoHandlerTester(std::string&& datapath)
+    : datapath_ {datapath}
+{
+    setId(datapath_);
+    mVS = std::make_shared<VideoSubscriberTester>();
+}
+
+void
+VideoHandlerTester::notifyAVFrameSubject(const StreamData& data, jami::avSubjectPtr subject)
+{
+    std::ostringstream oss;
+    std::string_view direction = data.direction ? "Receive" : "Preview";
+    oss << "NEW SUBJECT: [" << data.id << "," << direction << "]" << std::endl;
+
+    bool preferredStreamDirection = false; // false for output; true for input
+    oss << "preferredStreamDirection " << preferredStreamDirection << std::endl;
+    if (data.type == StreamType::video && !data.direction
+        && data.direction == preferredStreamDirection) {
+        subject->attach(mVS.get()); // your image
+        oss << "got my sent image attached" << std::endl;
+        attached_ = "1";
+    } else if (data.type == StreamType::video && data.direction
+               && data.direction == preferredStreamDirection) {
+        subject->attach(mVS.get()); // the image you receive from others on the call
+        oss << "got received image attached" << std::endl;
+        attached_ = "1";
+    }
+
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+std::map<std::string, std::string>
+VideoHandlerTester::getCallMediaHandlerDetails()
+{
+    return {{"name", NAME},
+            {"iconPath", datapath_ + sep + "icon.svg"},
+            {"pluginId", id()},
+            {"attached", attached_},
+            {"dataType", "1"}};
+}
+
+void
+VideoHandlerTester::detach()
+{
+    attached_ = "0";
+    mVS->detach();
+}
+
+VideoHandlerTester::~VideoHandlerTester()
+{
+    std::ostringstream oss;
+    oss << " ~VideoHandlerTester from TestSuite Plugin" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+    detach();
+}
+} // namespace jami
diff --git a/TestSuite/VideoHandlerTester.h b/TestSuite/VideoHandlerTester.h
new file mode 100644
index 0000000..b5a57e7
--- /dev/null
+++ b/TestSuite/VideoHandlerTester.h
@@ -0,0 +1,50 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+#include "VideoSubscriberTester.h"
+#include "plugin/jamiplugin.h"
+#include "plugin/mediahandler.h"
+
+using avSubjectPtr = std::weak_ptr<jami::Observable<AVFrame*>>;
+
+namespace jami {
+
+class VideoHandlerTester : public jami::CallMediaHandler
+{
+public:
+    VideoHandlerTester(std::string&& dataPath);
+    ~VideoHandlerTester();
+
+    virtual void notifyAVFrameSubject(const StreamData& data, avSubjectPtr subject) override;
+    virtual std::map<std::string, std::string> getCallMediaHandlerDetails() override;
+
+    virtual void detach() override;
+    virtual void setPreferenceAttribute(const std::string& key, const std::string& value) override {}
+    virtual bool preferenceMapHasKey(const std::string& key) override { return false; }
+
+    std::shared_ptr<VideoSubscriberTester> mVS{};
+
+private:
+    const std::string datapath_;
+    std::string attached_ {"0"};
+};
+} // namespace jami
diff --git a/TestSuite/VideoSubscriberTester.cpp b/TestSuite/VideoSubscriberTester.cpp
new file mode 100644
index 0000000..d428a84
--- /dev/null
+++ b/TestSuite/VideoSubscriberTester.cpp
@@ -0,0 +1,66 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 "VideoSubscriberTester.h"
+
+#include <pluglog.h>
+#include <stdio.h>
+
+const std::string TAG = "VideoHandlerTester";
+const char sep = separator();
+
+namespace jami {
+
+VideoSubscriberTester::~VideoSubscriberTester()
+{
+    std::ostringstream oss;
+    oss << "~VideoSubscriberTester" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+VideoSubscriberTester::attached(jami::Observable<AVFrame*>* observable)
+{
+    std::ostringstream oss;
+    oss << "::Attached ! " << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+    observable_ = observable;
+}
+
+void
+VideoSubscriberTester::detached(jami::Observable<AVFrame*>*)
+{
+    observable_ = nullptr;
+    std::ostringstream oss;
+    oss << "::Detached()" << std::endl;
+    Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+}
+
+void
+VideoSubscriberTester::detach()
+{
+    if (observable_) {
+        std::ostringstream oss;
+        oss << "::Calling detach()" << std::endl;
+        Plog::log(Plog::LogPriority::INFO, TAG, oss.str());
+        observable_->detach(this);
+    }
+}
+} // namespace jami
diff --git a/TestSuite/VideoSubscriberTester.h b/TestSuite/VideoSubscriberTester.h
new file mode 100644
index 0000000..49d5ca7
--- /dev/null
+++ b/TestSuite/VideoSubscriberTester.h
@@ -0,0 +1,46 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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.
+ */
+
+#pragma once
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+#include <observer.h>
+
+namespace jami {
+
+class VideoSubscriberTester : public jami::Observer<AVFrame*>
+{
+public:
+    VideoSubscriberTester() {}
+    ~VideoSubscriberTester();
+
+    virtual void update(jami::Observable<AVFrame*>*, AVFrame* const&) override {}
+    virtual void attached(jami::Observable<AVFrame*>*) override;
+    virtual void detached(jami::Observable<AVFrame*>*) override;
+
+    void detach();
+
+private:
+    // Observer pattern
+    Observable<AVFrame*>* observable_{};
+};
+} // namespace jami
diff --git a/TestSuite/build.sh b/TestSuite/build.sh
new file mode 100755
index 0000000..881221a
--- /dev/null
+++ b/TestSuite/build.sh
@@ -0,0 +1,267 @@
+#! /bin/bash
+# Build the plugin for the project
+set -e
+export OSTYPE
+ARCH=$(uname -m)
+EXTRAPATH=''
+# Flags:
+
+# -p: number of processors to use
+# -c: Runtime plugin cpu/gpu setting.
+# -t: target platform.
+
+
+if [ -z "${DAEMON}" ]; then
+    DAEMON="./../../daemon"
+    echo "DAEMON not provided, building with ${DAEMON}"
+fi
+
+PLUGIN_NAME="TestSuite"
+JPL_FILE_NAME="${PLUGIN_NAME}.jpl"
+SO_FILE_NAME="lib${PLUGIN_NAME}.so"
+DAEMON_SRC="${DAEMON}/src"
+CONTRIB_PATH="${DAEMON}/contrib"
+PLUGINS_LIB="../lib"
+LIBS_DIR="./../contrib/Libs"
+PLATFORM=$(uname)
+
+if [ "${PLATFORM}" = "Linux" ]; then
+    PLATFORM="linux-gnu"
+    CONTRIB_PLATFORM_CURT=${ARCH}
+    echo "Building with ${PLATFORM}"
+elif [ "${PLATFORM}" = "Darwin" ]; then
+    PLATFORM="darwin"
+    SO_FILE_NAME="lib${PLUGIN_NAME}.dylib"
+    alias nproc='sysctl -n hw.logicalcpu'
+    CONTRIB_PLATFORM_CURT=${ARCH}-apple
+    CONTRIB_PLATFORM_EXTRA=$(uname -r)
+    echo "Building with ${PLATFORM}"
+fi
+
+while getopts t:c:p OPT; do
+  case "$OPT" in
+    t)
+      PLATFORM="${OPTARG}"
+    ;;
+    c)
+      PROCESSOR="${OPTARG}"
+    ;;
+    p)
+    ;;
+    \?)
+      exit 1
+    ;;
+  esac
+done
+
+if [ "${PLATFORM}" = "linux-gnu" ] || [ "${PLATFORM}" = "redhat-linux" ]
+then
+    python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+
+    CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
+
+    # Compile
+    clang++ -std=c++17 -shared -fPIC \
+    -Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
+    -Wall -Wextra \
+    -Wno-unused-variable \
+    -Wno-unused-function \
+    -Wno-unused-parameter \
+    -I"." \
+    -I"${DAEMON_SRC}" \
+    -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \
+    -I"${PLUGINS_LIB}" \
+    AudioHandlerTester.cpp \
+    AudioSubscriberTester.cpp \
+    VideoHandlerTester.cpp \
+    VideoSubscriberTester.cpp \
+    ChatHandlerTester.cpp \
+    ChatSubscriberTester.cpp \
+    main.cpp \
+    -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/" \
+    -l:libavutil.a \
+    -lva \
+    -o "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+
+elif [ "${PLATFORM}" = "darwin" ]
+then
+    python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+
+    CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
+
+    # Compile
+    clang++ -std=c++17 -shared -fPIC \
+    -Wl,-no_compact_unwind -Wl,-framework,CoreFoundation \
+    -Wl,-framework,Security -Wl,-framework,VideoToolbox \
+    -Wl,-framework,CoreMedia -Wl,-framework,CoreVideo \
+    -Wl,-framework,OpenCl -Wl,-framework,Accelerate \
+    -Wl,-rpath,"\${ORIGIN}" \
+    -Wall -Wextra \
+    -Wno-unused-variable \
+    -Wno-unused-function \
+    -Wno-unused-parameter \
+    -I"." \
+    -I"${DAEMON_SRC}" \
+    -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}/include" \
+    -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}/include/opencv4" \
+    -I"${PLUGINS_LIB}" \
+    AudioHandlerTester.cpp \
+    AudioSubscriberTester.cpp \
+    VideoHandlerTester.cpp \
+    VideoSubscriberTester.cpp \
+    ChatHandlerTester.cpp \
+    ChatSubscriberTester.cpp \
+    main.cpp \
+    -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}/lib/" \
+    -lavutil \
+    -lvpx -lx264 -lbz2 -liconv -lz -lspeex -lopus \
+    -o "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+
+    install_name_tool -id "@loader_path/${SO_FILE_NAME}" "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+
+    if [ -n "${APPLE_SIGN_CERTIFICATE}" ]; then
+      codesign --force --verify --timestamp -o runtime --sign "${APPLE_SIGN_CERTIFICATE}"  "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+      ditto -c -k --rsrc "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}" "build-local/${SO_FILE_NAME}.zip"
+      LIBRARYNAME=${PLUGIN_NAME} sh ./../notarize.sh
+      cd ..
+      ditto -x -k "build-local/${SO_FILE_NAME}.zip" "build-local/notarized"
+      cp "build-local/notarized/${SO_FILE_NAME}" "build-local/jpl/lib/${CONTRIB_PLATFORM}/${SO_FILE_NAME}"
+    fi
+
+elif [ "${PLATFORM}" = "android" ]
+then
+    python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM}
+
+    if [ -z "$ANDROID_NDK" ]; then
+            ANDROID_NDK="/home/${USER}/Android/Sdk/ndk/21.1.6352462"
+        echo "ANDROID_NDK not provided, building with ${ANDROID_NDK}"
+    fi
+
+    #=========================================================
+    #    Check if the ANDROID_ABI was provided
+    #    if not, set default
+    #=========================================================
+    if [ -z "$ANDROID_ABI" ]; then
+        ANDROID_ABI="armeabi-v7a arm64-v8a x86_64"
+        echo "ANDROID_ABI not provided, building for ${ANDROID_ABI}"
+    fi
+
+    buildlib() {
+        echo "$CURRENT_ABI"
+
+        #=========================================================
+        #    ANDROID TOOLS
+        #=========================================================
+        export HOST_TAG=linux-x86_64
+        export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_TAG
+
+        if [ "$CURRENT_ABI" = armeabi-v7a ]
+        then
+        export AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
+        export AS=$TOOLCHAIN/bin/arm-linux-androideabi-as
+        export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang
+        export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang++
+        export LD=$TOOLCHAIN/bin/arm-linux-androideabi-ld
+        export RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
+        export STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip
+        export ANDROID_SYSROOT=${DAEMON}/../client-android/android-toolchain-21-arm/sysroot
+
+        elif [ "$CURRENT_ABI" = arm64-v8a ]
+        then
+        export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
+        export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
+        export CC=$TOOLCHAIN/bin/aarch64-linux-android21-clang
+        export CXX=$TOOLCHAIN/bin/aarch64-linux-android21-clang++
+        export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
+        export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
+        export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip
+        export ANDROID_SYSROOT=${DAEMON}/../client-android/android-toolchain-21-arm64/sysroot
+
+        elif [ "$CURRENT_ABI" = x86_64 ]
+        then
+        export AR=$TOOLCHAIN/bin/x86_64-linux-android-ar
+        export AS=$TOOLCHAIN/bin/x86_64-linux-android-as
+        export CC=$TOOLCHAIN/bin/x86_64-linux-android21-clang
+        export CXX=$TOOLCHAIN/bin/x86_64-linux-android21-clang++
+        export LD=$TOOLCHAIN/bin/x86_64-linux-android-ld
+        export RANLIB=$TOOLCHAIN/bin/x86_64-linux-android-ranlib
+        export STRIP=$TOOLCHAIN/bin/x86_64-linux-android-strip
+        export ANDROID_SYSROOT=${DAEMON}/../client-android/android-toolchain-21-x86_64/sysroot
+
+        else
+        echo "ABI NOT OK" >&2
+        exit 1
+        fi
+
+        #=========================================================
+        #    CONTRIBS
+        #=========================================================
+        if [ "$CURRENT_ABI" = armeabi-v7a ]
+        then
+        CONTRIB_PLATFORM=arm-linux-androideabi
+
+        elif [ "$CURRENT_ABI" = arm64-v8a ]
+        then
+        CONTRIB_PLATFORM=aarch64-linux-android
+
+        elif [ "$CURRENT_ABI" = x86_64 ]
+        then
+        CONTRIB_PLATFORM=x86_64-linux-android
+        fi
+
+        #NDK SOURCES FOR cpufeatures
+        NDK_SOURCES=${ANDROID_NDK}/sources/android
+
+        #=========================================================
+        #    LD_FLAGS
+        #=========================================================
+        if [ "$CURRENT_ABI" = armeabi-v7a ]
+        then
+        export EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -L${ANDROID_SYSROOT}/usr/lib/arm-linux-androideabi -L${ANDROID_SYSROOT}/usr/lib/arm-linux-androideabi/21"
+        elif [ "$CURRENT_ABI" = arm64-v8a ]
+        then
+        export EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -L${ANDROID_SYSROOT}/usr/lib/aarch64-linux-android -L${ANDROID_SYSROOT}/usr/lib/aarch64-linux-android/21"
+        elif [ "$CURRENT_ABI" = x86_64 ]
+        then
+        export EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -L${ANDROID_SYSROOT}/usr/lib/x86_64-linux-android -L${ANDROID_SYSROOT}/usr/lib/x86_64-linux-android/21"
+        fi
+
+        #=========================================================
+        #    Compile the plugin
+        #=========================================================
+
+        # Create so destination folder
+        $CXX --std=c++17 -O3 -g -fPIC \
+        -Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
+        -shared \
+        -Wall -Wextra \
+        -Wno-unused-variable \
+        -Wno-unused-function \
+        -Wno-unused-parameter \
+        -I"." \
+        -I"${DAEMON_SRC}" \
+        -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \
+        -I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include/opencv4" \
+        -I"${PLUGINS_LIB}" \
+        AudioHandlerTester.cpp \
+        AudioSubscriberTester.cpp \
+        VideoHandlerTester.cpp \
+        VideoSubscriberTester.cpp \
+        ChatHandlerTester.cpp \
+        ChatSubscriberTester.cpp \
+        main.cpp \
+        -L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/" \
+        -lavutil \
+        -llog -lz \
+        --sysroot=$ANDROID_SYSROOT \
+        -o "build-local/jpl/lib/$CURRENT_ABI/${SO_FILE_NAME}"
+    }
+
+    # Build the so
+    for i in ${ANDROID_ABI}; do
+        CURRENT_ABI=$i
+        buildlib
+    done
+fi
+
+python3 ./../SDK/jplManipulation.py --assemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM} --extraPath=${EXTRAPATH}
diff --git a/TestSuite/data/accountpreferences.json b/TestSuite/data/accountpreferences.json
new file mode 100644
index 0000000..e1d4b8e
--- /dev/null
+++ b/TestSuite/data/accountpreferences.json
@@ -0,0 +1,9 @@
+[
+    {
+        "type": "EditText",
+        "key": "textAccountPreference",
+        "title": "{{text_translatable2}}",
+        "summary": "{{summary_translatable2}}",
+        "defaultValue": "{{default_translatable2}}"
+    }
+]
\ No newline at end of file
diff --git a/TestSuite/data/icon.png b/TestSuite/data/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..437e40834746471d23081d0643d6f6f59b648c1c
GIT binary patch
literal 31362
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

literal 0
HcmV?d00001

diff --git a/TestSuite/data/icon.svg b/TestSuite/data/icon.svg
new file mode 100644
index 0000000..4ced6a7
--- /dev/null
+++ b/TestSuite/data/icon.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>O</title>
+    <defs>
+        <linearGradient x1="50.001267%" y1="120.94311%" x2="50.001267%" y2="-257.222291%" id="linearGradient-1">
+            <stop stop-color="#EFB000" offset="0%"></stop>
+            <stop stop-color="#F1B904" offset="2.798313%"></stop>
+            <stop stop-color="#F6CF0E" offset="11.34%"></stop>
+            <stop stop-color="#FAE016" offset="21.42%"></stop>
+            <stop stop-color="#FDEB1B" offset="33.9%"></stop>
+            <stop stop-color="#FFF21E" offset="51.4%"></stop>
+            <stop stop-color="#FFF41F" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="49.9829639%" y1="-278.222509%" x2="49.9829639%" y2="99.9773676%" id="linearGradient-2">
+            <stop stop-color="#EFB000" offset="80.23%"></stop>
+            <stop stop-color="#F6CD0D" offset="85.32%"></stop>
+            <stop stop-color="#FBE317" offset="90.44%"></stop>
+            <stop stop-color="#FEF01D" offset="95.41%"></stop>
+            <stop stop-color="#FFF41F" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="O" fill-rule="nonzero">
+            <g transform="translate(2.000000, 0.000000)" id="Path">
+                <path d="M295.571429,152.285714 C295.571429,152.214286 295.571429,152.142857 295.571429,152.071429 C295.571429,150.428571 295.571429,148.714286 295.5,146.928571 C295.5,146.214286 295.5,145.428571 295.5,144.714286 L295.428571,144.714286 C293.857143,105.928571 280.071429,50.7142857 210.642857,15.1428571 C135.928571,-23.0714286 70.0714286,23.3571429 70.0714286,23.3571429 C70.1428571,23.3571429 70.1428571,23.3571429 70.2142857,23.3571429 C110.857143,16.2857143 172.357143,46.8571429 206.285714,90.9285714 C211.571429,97.7857143 216.214286,104.928571 219.928571,112.357143 C226.214286,124.642857 228.928571,136.214286 229.428571,146.642857 C229.428571,147.071429 229.5,147.571429 229.5,148 C229.571429,151.357143 229.5,154.714286 229.142857,157.857143 L229.142857,157.857143 C227.357143,176.214286 219,194.071429 205,208.142857 C173.428571,239.642857 121.142857,240.142857 89.5714286,208.571429 L89.4285714,209.142857 C123.357143,253.214286 184.857143,283.785714 225.5,276.714286 C235.071429,270.785714 244.071429,263.785714 252.357143,255.5 C279.428571,228.428571 293.714286,193.428571 295.357143,157.928571 L295.5,157.928571 C295.571429,156.428571 295.571429,154.928571 295.571429,153.428571 C295.571429,153 295.571429,152.642857 295.571429,152.285714 Z" fill="url(#linearGradient-1)"></path>
+                <path d="M225.5,276.642857 C184.857143,283.714286 123.357143,253.142857 89.4285714,209.071429 C84.1428571,202.214286 79.5,195.071429 75.7857143,187.642857 C69.5,175.357143 66.7857143,163.785714 66.2857143,153.357143 C66.2857143,152.928571 66.2142857,152.428571 66.2142857,152 C66.1428571,148.642857 66.2142857,145.285714 66.5714286,142.142857 L66.5714286,142.142857 C68.3571429,123.785714 76.7142857,105.928571 90.7142857,91.8571429 C122.285714,60.3571429 174.571429,59.8571429 206.142857,91.4285714 L206.285714,90.8571429 C172.357143,46.8571429 110.857143,16.2857143 70.2142857,23.3571429 C60.6428571,29.2857143 51.6428571,36.2857143 43.3571429,44.5714286 C16.2857143,71.6428571 2,106.642857 0.357142857,142.142857 L0.214285714,142.142857 C0.142857143,143.642857 0.142857143,145.142857 0.142857143,146.642857 C0.142857143,147 0.142857143,147.357143 0.142857143,147.714286 C0.142857143,147.785714 0.142857143,147.857143 0.142857143,147.928571 C0.142857143,149.571429 0.142857143,151.285714 0.214285714,153.071429 C0.214285714,153.785714 0.214285714,154.571429 0.285714286,155.285714 L0.357142857,155.285714 C1.92857143,194.071429 15.7142857,249.285714 85.1428571,284.857143 C159.857143,323.142857 225.714286,276.714286 225.714286,276.714286 C225.571429,276.642857 225.571429,276.642857 225.5,276.642857 Z" fill="url(#linearGradient-2)"></path>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/TestSuite/data/locale/TestSuite_en.json b/TestSuite/data/locale/TestSuite_en.json
new file mode 100644
index 0000000..866f977
--- /dev/null
+++ b/TestSuite/data/locale/TestSuite_en.json
@@ -0,0 +1,8 @@
+{
+    "text_translatable1": "text one in english",
+    "text_translatable2": "text two in english",
+    "summary_translatable1": "summary one in english",
+    "summary_translatable2": "summary two in english",
+    "default_translatable1": "default one in english",
+    "default_translatable2": "default two in english"
+}
diff --git a/TestSuite/data/locale/TestSuite_fr.json b/TestSuite/data/locale/TestSuite_fr.json
new file mode 100644
index 0000000..c292bca
--- /dev/null
+++ b/TestSuite/data/locale/TestSuite_fr.json
@@ -0,0 +1,8 @@
+{
+    "text_translatable1": "text un en français",
+    "text_translatable2": "text deux en français",
+    "summary_translatable1": "summary un en français",
+    "summary_translatable2": "summary deux en français",
+    "default_translatable1": "default un en français",
+    "default_translatable2": "default deux en français"
+}
diff --git a/TestSuite/data/preferences.json b/TestSuite/data/preferences.json
new file mode 100644
index 0000000..d6a496d
--- /dev/null
+++ b/TestSuite/data/preferences.json
@@ -0,0 +1,9 @@
+[
+    {
+        "type": "EditText",
+        "key": "textGlobalPreference",
+        "title": "{{text_translatable1}}",
+        "summary": "{{summary_translatable1}}",
+        "defaultValue": "{{default_translatable1}}"
+    }
+]
\ No newline at end of file
diff --git a/TestSuite/main.cpp b/TestSuite/main.cpp
new file mode 100644
index 0000000..cca526c
--- /dev/null
+++ b/TestSuite/main.cpp
@@ -0,0 +1,86 @@
+/**
+ *  Copyright (C) 2020-2021 Savoir-faire Linux Inc.
+ *
+ *  Author: Aline Gondim Santos <aline.gondimsantos@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 <iostream>
+#include <string.h>
+#include <thread>
+#include <memory>
+#include <plugin/jamiplugin.h>
+
+#include "AudioHandlerTester.h"
+#include "VideoHandlerTester.h"
+#include "ChatHandlerTester.h"
+
+#ifdef WIN32
+#define EXPORT_PLUGIN __declspec(dllexport)
+#else
+#define EXPORT_PLUGIN
+#endif
+
+#define TestSuite_VERSION_MAJOR 1
+#define TestSuite_VERSION_MINOR 0
+#define TestSuite_VERSION_PATCH 0
+
+extern "C" {
+void
+pluginExit(void)
+{}
+
+EXPORT_PLUGIN JAMI_PluginExitFunc
+JAMI_dynPluginInit(const JAMI_PluginAPI* api)
+{
+    std::cout << "*******************" << std::endl;
+    std::cout << "**   TestSuite   **" << std::endl;
+    std::cout << "*******************" << std::endl << std::endl;
+    std::cout << "Version " << TestSuite_VERSION_MAJOR << "." << TestSuite_VERSION_MINOR << "."
+              << TestSuite_VERSION_PATCH << std::endl;
+
+    // If invokeService doesn't return an error
+    if (api) {
+        std::string dataPath;
+        api->invokeService(api, "getPluginDataPath", &dataPath);
+
+        auto fmpAudio
+            = std::make_unique<jami::AudioHandlerTester>(std::move(dataPath));
+        if (api->manageComponent(api,
+                                 "CallMediaHandlerManager",
+                                 fmpAudio.release())) {
+            return nullptr;
+        }
+
+        auto fmpVideo
+            = std::make_unique<jami::VideoHandlerTester>(std::move(dataPath));
+        if (api->manageComponent(api,
+                                 "CallMediaHandlerManager",
+                                 fmpVideo.release())) {
+            return nullptr;
+        }
+
+        auto fmpChat
+            = std::make_unique<jami::ChatHandlerTester>(std::move(dataPath));
+        if (api->manageComponent(api,
+                                 "ChatHandlerManager",
+                                 fmpChat.release())) {
+            return nullptr;
+        }
+    }
+    return pluginExit;
+}
+}
diff --git a/TestSuite/manifest.json b/TestSuite/manifest.json
new file mode 100644
index 0000000..5ff8a07
--- /dev/null
+++ b/TestSuite/manifest.json
@@ -0,0 +1,6 @@
+{
+    "name": "TestSuite",
+    "description": "TestSuite is a empty process plugin conceived for use in the daemon unit tests.",
+    "version": "1.0.0",
+    "iconPath" : "icon.svg"
+}
\ No newline at end of file
diff --git a/TestSuite/package.json b/TestSuite/package.json
new file mode 100644
index 0000000..f4ad235
--- /dev/null
+++ b/TestSuite/package.json
@@ -0,0 +1,19 @@
+{
+    "name": "TestSuite",
+    "version": "1.0.0",
+    "extractLibs": false,
+    "deps": [
+        "fmt",
+        "ffmpeg"
+    ],
+    "defines": [],
+    "custom_scripts": {
+        "pre_build": [
+            "mkdir msvc"
+        ],
+        "build": [
+            "cmake --build ./msvc --config Release"
+        ],
+        "post_build": []
+    }
+}
\ No newline at end of file
-- 
GitLab