AutoAnswer: add process test
GitLab: https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/745
Change-Id: I54e5df2ffa44e779f52e5b404898c91d280ac1f6
diff --git a/AutoAnswer/.gitignore b/AutoAnswer/.gitignore
new file mode 100644
index 0000000..0924e88
--- /dev/null
+++ b/AutoAnswer/.gitignore
@@ -0,0 +1,2 @@
+/AutoAnswer
+AutoAnswer*
diff --git a/AutoAnswer/BotChatHandler.cpp b/AutoAnswer/BotChatHandler.cpp
index 6a03179..c877e37 100644
--- a/AutoAnswer/BotChatHandler.cpp
+++ b/AutoAnswer/BotChatHandler.cpp
@@ -72,7 +72,8 @@
BotChatHandler::~BotChatHandler()
{
- for (const auto& subject : subjects) {
+ const auto copy = subjects;
+ for (const auto& subject : copy) {
detach(subject);
}
}
diff --git a/AutoAnswer/BotPeerChatSubscriber.cpp b/AutoAnswer/BotPeerChatSubscriber.cpp
index 19760f5..8f2475a 100644
--- a/AutoAnswer/BotPeerChatSubscriber.cpp
+++ b/AutoAnswer/BotPeerChatSubscriber.cpp
@@ -60,6 +60,10 @@
else if (message->data.at("type") == "text/plain" && message->data.at("body") == input) {
sendMsg["type"] = "text/plain";
sendMsg["body"] = answer;
+#ifdef __DEBUG__
+ Plog::log(Plog::LogPriority::INFO, TAG, "input " + message->data.at("body"));
+ Plog::log(Plog::LogPriority::INFO, TAG, "ouput " + answer);
+#endif
}
if (!sendMsg.empty()) {
sendText(message->accountId, message->peerId, sendMsg, message->isSwarm);
@@ -106,6 +110,8 @@
sendMsg,
true);
botAnswer->isSwarm = swarm;
+#ifndef __DEBUG__
api_->invokeService(api_, "sendTextMessage", botAnswer.get());
+#endif
}
} // namespace jami
diff --git a/AutoAnswer/CMakeLists.txt b/AutoAnswer/CMakeLists.txt
index a0db3f1..eb06399 100644
--- a/AutoAnswer/CMakeLists.txt
+++ b/AutoAnswer/CMakeLists.txt
@@ -33,24 +33,39 @@
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")
+
+if(TESTPROCESS)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D__DEBUG__ /MD")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /D__DEBUG__ /MD")
+else()
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MD")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
+endif()
set(plugin_SRC BotChatHandler.cpp
BotPeerChatSubscriber.cpp
PluginPreferenceHandler.cpp
main.cpp
+ ./../lib/common.cpp
)
set(plugin_HDR BotChatHandler.h
BotPeerChatSubscriber.h
PluginPreferenceHandler.h
./../lib/pluglog.h
+ ./../lib/common.h
)
-add_library(${ProjectName} SHARED ${plugin_SRC}
+if(TESTPROCESS)
+ add_executable(${ProjectName} ${plugin_SRC}
${plugin_HDR}
)
+else()
+ add_library(${ProjectName} SHARED ${plugin_SRC}
+ ${plugin_HDR}
+ )
+endif()
+
target_include_directories(${ProjectName} PUBLIC ${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}
@@ -58,23 +73,35 @@
${DAEMON_SRC}
${CONTRIB_PATH}
${CONTRIB_PATH}/build/fmt/include
+ ${CONTRIB_PATH}/build/yaml-cpp/include
)
target_link_directories(${ProjectName} PUBLIC ${CONTRIB_PATH}
${CONTRIB_PATH}/build/fmt/msvc/Release
+ ${CONTRIB_PATH}/build/yaml-cpp/msvc/Release
)
-add_custom_command(
- TARGET ${ProjectName}
- PRE_BUILD
- COMMAND python ${PROJECT_SOURCE_DIR}/../SDK/jplManipulation.py --preassemble --plugin=${ProjectName}
- COMMENT "Assembling Plugin files"
-)
+target_link_libraries(${ProjectName} PUBLIC libyaml-cppmd)
-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"
-)
+if(TESTPROCESS)
+ add_custom_command(
+ TARGET ${ProjectName}
+ PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/testPreferences.yml ${PROJECT_BINARY_DIR}/
+ )
+else()
+ 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"
+ )
+endif()
diff --git a/AutoAnswer/build.sh b/AutoAnswer/build.sh
index 5af8d21..8b136ec 100755
--- a/AutoAnswer/build.sh
+++ b/AutoAnswer/build.sh
@@ -6,10 +6,10 @@
EXTRAPATH=''
# Flags:
-# -p: number of processors to use
+# -p: number of processors to use.
# -c: Runtime plugin cpu/gpu setting.
# -t: target platform.
-
+# -d: debug program.
if [ -z "${DAEMON}" ]; then
DAEMON="./../../daemon"
@@ -36,8 +36,11 @@
echo "Building with ${PLATFORM}"
fi
-while getopts t:c:p OPT; do
+while getopts t:c:p:d OPT; do
case "$OPT" in
+ d)
+ DEBUG=true
+ ;;
t)
PLATFORM="${OPTARG}"
;;
@@ -54,34 +57,48 @@
if [ "${PLATFORM}" = "linux-gnu" ] || [ "${PLATFORM}" = "redhat-linux" ] || [ "${PLATFORM}" = "Darwin" ]
then
- python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
-
CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-${PLATFORM}
OUTPUTFOLDER=${CONTRIB_PLATFORM}
if [ "${PLATFORM}" = "Darwin" ]; then
CONTRIB_PLATFORM=${CONTRIB_PLATFORM}${CONTRIB_PLATFORM_EXTRA}
fi
+ if [ ${DEBUG} ]; then
+ OUTPUT="${PLUGIN_NAME}"
+ CLANG_OPTS="-g -fsanitize=address"
+ EXTRA_DEBUG_LIBRARIES="-lyaml-cpp"
+ EXTRA_DEFINES="-D__DEBUG__"
+ else
+ python3 ./../SDK/jplManipulation.py --preassemble --plugin=${PLUGIN_NAME}
+ CLANG_OPTS="-O3 -shared"
+ OUTPUT="build-local/jpl/lib/${OUTPUTFOLDER}/${SO_FILE_NAME}"
+ fi
+
# Compile
- clang++ -std=c++17 -shared -fPIC \
+ clang++ -std=c++17 -fPIC ${CLANG_OPTS} \
-Wl,-rpath,"\${ORIGIN}" \
-Wall -Wextra \
- -Wno-unused-variable \
- -Wno-unused-function \
-Wno-unused-parameter \
+ ${EXTRA_DEFINES} \
-I"." \
-I"${DAEMON_SRC}" \
-I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \
-I"${PLUGINS_LIB}" \
+ ./../lib/common.cpp \
PluginPreferenceHandler.cpp \
BotChatHandler.cpp \
BotPeerChatSubscriber.cpp \
main.cpp \
-L"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/" \
- -o "build-local/jpl/lib/${OUTPUTFOLDER}/${SO_FILE_NAME}"
+ ${EXTRA_DEBUG_LIBRARIES} \
+ -o "${OUTPUT}"
if [ "${PLATFORM}" = "Darwin" ]; then
- install_name_tool -id "@loader_path/${SO_FILE_NAME}" "build-local/jpl/lib/${OUTPUTFOLDER}/${SO_FILE_NAME}"
+ if [ ! ${DEBUG} ]; then
+ install_name_tool -id "@loader_path/${PLUGIN_NAME}" "${OUTPUT}"
+ else
+ install_name_tool -id "@loader_path/${SO_FILE_NAME}" "${OUTPUT}"
+ fi
fi
if [ -n "${APPLE_SIGN_CERTIFICATE}" ]; then
@@ -199,8 +216,6 @@
-Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \
-shared \
-Wall -Wextra \
- -Wno-unused-variable \
- -Wno-unused-function \
-Wno-unused-parameter \
-I"." \
-I"${DAEMON_SRC}" \
@@ -223,4 +238,6 @@
done
fi
-python3 ./../SDK/jplManipulation.py --assemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM} --extraPath=${EXTRAPATH}
+if [ ! ${DEBUG} ]; then
+ python3 ./../SDK/jplManipulation.py --assemble --plugin=${PLUGIN_NAME} --distribution=${PLATFORM} --extraPath=${EXTRAPATH}
+fi
diff --git a/AutoAnswer/main.cpp b/AutoAnswer/main.cpp
index ff4d180..dfed25f 100644
--- a/AutoAnswer/main.cpp
+++ b/AutoAnswer/main.cpp
@@ -26,6 +26,13 @@
#include "plugin/jamiplugin.h"
#include "BotChatHandler.h"
+#ifdef __DEBUG__
+#include <common.h>
+#include <assert.h>
+#include <yaml-cpp/yaml.h>
+#include <fstream>
+#endif
+
#ifdef WIN32
#define EXPORT_PLUGIN __declspec(dllexport)
#else
@@ -80,3 +87,85 @@
return pluginExit;
}
}
+
+#ifdef __DEBUG__
+
+int
+main ()
+{
+ std::cout << "********************************" << std::endl;
+ std::cout << "** AutoAnswer Debug Version **" << std::endl;
+ std::cout << "********************************" << std::endl;
+ std::cout << "Version " << AutoAnswer_VERSION_MAJOR << "." << AutoAnswer_VERSION_MINOR << "."
+ << AutoAnswer_VERSION_PATCH << std::endl << std::endl;
+
+
+#ifdef _WIN32
+ std::ifstream file = std::ifstream(string_utils::to_wstring("testPreferences.yml"));
+#else
+ std::ifstream file = std::ifstream("testPreferences.yml", std::ios_base::in);
+#endif
+
+ assert(file.is_open());
+ YAML::Node node = YAML::Load(file);
+
+ assert(node.IsMap());
+ std::map<std::string, std::map<std::string, std::string>> preferences;
+ preferences["default"] = {};
+ for (const auto& kv : node) {
+ preferences["default"][kv.first.as<std::string>()] = kv.second.as<std::string>();
+ std::cout << "Key: " << kv.first.as<std::string>() << "; Value: " << kv.second.as<std::string>() << std::endl;
+ }
+
+ std::string dataPath = "tester";
+
+ auto fmpPluginPreferenceHandler
+ = std::make_unique<jami::PluginPreferenceHandler>(nullptr, std::move(preferences), dataPath);
+
+ auto fmpBotChatHandler
+ = std::make_unique<jami::BotChatHandler>(nullptr,
+ std::move(dataPath),
+ fmpPluginPreferenceHandler.get());
+
+ auto subject = std::make_shared<jami::PublishObservable<jami::pluginMessagePtr>>();
+ std::pair<std::string, std::string> subjectConnection("origin", "destiny");
+ fmpBotChatHandler->notifyChatSubject(subjectConnection, subject);
+
+ // Only test for swarm
+
+ // Valid Sender, Receiver, direction and message
+ std::cout << "Test 1" << std::endl << "Should print input/output" << std::endl;
+ std::map<std::string, std::string> sendMsg = {{"type", "text/plain"}, {"body", preferences["default"]["inText"]}};
+ jami::pluginMessagePtr jamiMsg = std::make_shared<JamiMessage>("origin",
+ "destiny",
+ true,
+ sendMsg,
+ false);
+ jamiMsg->isSwarm = true;
+ subject->publish(jamiMsg);
+
+
+ // Valid Sender, Receiver and message but not direction
+ std::cout << "Test 2" << std::endl << "Should NOT print input/output" << std::endl;
+ jamiMsg.reset(new JamiMessage("origin",
+ "destiny",
+ false,
+ sendMsg,
+ false));
+ jamiMsg->isSwarm = true;
+ subject->publish(jamiMsg);
+
+ // Invalid Sender, Receiver, direction and message
+ std::cout << "Test 3" << std::endl << "Should NOT print input/output" << std::endl;
+ sendMsg["body"] = preferences["default"]["invalid"];
+ jamiMsg.reset(new JamiMessage("destiny",
+ "origin",
+ true,
+ sendMsg,
+ false));
+ jamiMsg->isSwarm = true;
+ subject->publish(jamiMsg);
+
+ return 0;
+}
+#endif
diff --git a/AutoAnswer/package.json b/AutoAnswer/package.json
index 3161df3..a1dee2f 100644
--- a/AutoAnswer/package.json
+++ b/AutoAnswer/package.json
@@ -3,9 +3,12 @@
"version": "2.0.0",
"extractLibs": false,
"deps": [
- "fmt"
+ "fmt",
+ "yaml-cpp"
],
- "defines": [],
+ "defines": [
+ "TESTPROCESS=False"
+ ],
"custom_scripts": {
"pre_build": [
"mkdir msvc"
diff --git a/AutoAnswer/testPreferences.yml b/AutoAnswer/testPreferences.yml
new file mode 100644
index 0000000..5b0283d
--- /dev/null
+++ b/AutoAnswer/testPreferences.yml
@@ -0,0 +1,3 @@
+answer: "Occupied"
+inText: "Trigger"
+invalid: "invalid message"
diff --git a/GreenScreen/pluginProcessor.cpp b/GreenScreen/pluginProcessor.cpp
index 737ebfe..52b7d17 100644
--- a/GreenScreen/pluginProcessor.cpp
+++ b/GreenScreen/pluginProcessor.cpp
@@ -29,24 +29,7 @@
#include <pluglog.h>
#ifdef WIN32
-#include <WTypes.h>
-
-namespace string_utils {
-std::wstring
-to_wstring(const std::string& str) {
- int codePage = CP_UTF8;
- int srcLength = (int) str.length();
- int requiredSize = MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, nullptr, 0);
- if (!requiredSize) {
- throw std::runtime_error("Can't convert string to wstring");
- }
- std::wstring result((size_t) requiredSize, 0);
- if (!MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, &(*result.begin()), requiredSize)) {
- throw std::runtime_error("Can't convert string to wstring");
- }
- return result;
-}
-} // namespace string_utils
+#include <common.h>
#endif
const char sep = separator();
diff --git a/lib/common.cpp b/lib/common.cpp
new file mode 100644
index 0000000..2047278
--- /dev/null
+++ b/lib/common.cpp
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2022 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 "common.h"
+
+#ifdef WIN32
+#include <WTypes.h>
+#include <stdexcept>
+
+namespace string_utils {
+std::wstring
+to_wstring(const std::string& str) {
+ int codePage = CP_UTF8;
+ int srcLength = (int) str.length();
+ int requiredSize = MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, nullptr, 0);
+ if (!requiredSize) {
+ throw std::runtime_error("Can't convert string to wstring");
+ }
+ std::wstring result((size_t) requiredSize, 0);
+ if (!MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, &(*result.begin()), requiredSize)) {
+ throw std::runtime_error("Can't convert string to wstring");
+ }
+ return result;
+}
+} // namespace string_utils
+#endif // WIN32
diff --git a/lib/common.h b/lib/common.h
new file mode 100644
index 0000000..f0543d0
--- /dev/null
+++ b/lib/common.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifdef WIN32
+
+#include <string>
+
+namespace string_utils {
+std::wstring to_wstring(const std::string& str);
+} // namespace string_utils
+#endif // WIN32
+#endif // COMMON_H