From f9f610c3cb6be372ddd3221bc9aa5baf485d7faf Mon Sep 17 00:00:00 2001 From: Ji-hoon Lee Date: Fri, 24 Sep 2021 16:59:40 +0900 Subject: [PATCH] Add tests for verifying the behavior of CWakeupManager To make sure the modification made to CWakeupManager would not cause any unexpected side-effect especially on the observer modules, added tests for checking the behavioral correctness of each operations. [==========] Running 10 tests from 1 test suite. [----------] Global test environment set-up. [----------] 10 tests from DefaultFixture [ RUN ] DefaultFixture.SettingValueObserverCalledWhenLanguageChanges [ OK ] DefaultFixture.SettingValueObserverCalledWhenLanguageChanges (2 ms) [ RUN ] DefaultFixture.SettingValueObserverCalledWhenAssistantAdded [ OK ] DefaultFixture.SettingValueObserverCalledWhenAssistantAdded (2 ms) [ RUN ] DefaultFixture.SettingValueObserverCalledWhenAssistantDeleted [ OK ] DefaultFixture.SettingValueObserverCalledWhenAssistantDeleted (2 ms) [ RUN ] DefaultFixture.WakeupEventNotTriggeredWhenInactiveMode [ OK ] DefaultFixture.WakeupEventNotTriggeredWhenInactiveMode (1 ms) [ RUN ] DefaultFixture.WakeupEventTriggeredWhenVoiceKeyGetsPressed [ OK ] DefaultFixture.WakeupEventTriggeredWhenVoiceKeyGetsPressed (1 ms) [ RUN ] DefaultFixture.AudioDataReceivedWhenVoiceKeyGetsPressed [ OK ] DefaultFixture.AudioDataReceivedWhenVoiceKeyGetsPressed (12 ms) [ RUN ] DefaultFixture.FinishAudioDataReceivedWhenStoppedBeforeReleasingWithInterval [ OK ] DefaultFixture.FinishAudioDataReceivedWhenStoppedBeforeReleasingWithInterval (604 ms) [ RUN ] DefaultFixture.FinishAudioDataReceivedWhenStoppedBeforeReleasingWithoutInterval [ OK ] DefaultFixture.FinishAudioDataReceivedWhenStoppedBeforeReleasingWithoutInterval (303 ms) [ RUN ] DefaultFixture.FinishAudioDataReceivedOnResultBeforeReleasingWithInterval [ OK ] DefaultFixture.FinishAudioDataReceivedOnResultBeforeReleasingWithInterval (607 ms) [ RUN ] DefaultFixture.FinishAudioDataReceivedOnResultBeforeReleasingWithoutInterval [ OK ] DefaultFixture.FinishAudioDataReceivedOnResultBeforeReleasingWithoutInterval (303 ms) [----------] 10 tests from DefaultFixture (1837 ms total) [----------] Global test environment tear-down [==========] 10 tests from 1 test suite ran. (1837 ms total) [ PASSED ] 10 tests. Change-Id: I95054494410f2583874e94cd48277cc205dc1353 --- tests/utc/CMakeLists.txt | 1 + tests/utc/wakeup-manager/CMakeLists.txt | 95 +++++++++++ tests/utc/wakeup-manager/test_main.cpp | 276 ++++++++++++++++++++++++++++++++ tests/utc/wakeup-manager/ttpo.xml | 27 ++++ 4 files changed, 399 insertions(+) create mode 100644 tests/utc/wakeup-manager/CMakeLists.txt create mode 100644 tests/utc/wakeup-manager/test_main.cpp create mode 100644 tests/utc/wakeup-manager/ttpo.xml diff --git a/tests/utc/CMakeLists.txt b/tests/utc/CMakeLists.txt index 33c0a69..4c20d2c 100644 --- a/tests/utc/CMakeLists.txt +++ b/tests/utc/CMakeLists.txt @@ -7,3 +7,4 @@ ADD_SUBDIRECTORY(service-main) ADD_SUBDIRECTORY(preference-manager-vconf) ADD_SUBDIRECTORY(package-update-monitor) ADD_SUBDIRECTORY(wakeup-policy-default) +ADD_SUBDIRECTORY(wakeup-manager) diff --git a/tests/utc/wakeup-manager/CMakeLists.txt b/tests/utc/wakeup-manager/CMakeLists.txt new file mode 100644 index 0000000..4075250 --- /dev/null +++ b/tests/utc/wakeup-manager/CMakeLists.txt @@ -0,0 +1,95 @@ +# THIS FILE WAS GENERATED BY THE TIZEN TDD-PROJECT OUTLINER. +# IT IS NOT RECOMMENDED TO MODIFY THIS FILE SINCE THE +# MODIFICATION CAN BE OVERWRITTEN BY THE GENERATION TOOL. + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(ttpo-project CXX C) + +LINK_DIRECTORIES(${CMAKE_BINARY_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) + +SET(TTPO_SRCS + test_main.cpp + ../../../plugins/wakeup-manager/src/wakeup_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_audio_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_engine_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_settings.cpp + ../../../plugins/wakeup-manager/src/dependency_resolver.cpp + ../../../plugins/wakeup-manager/src/assistant_config_manager.cpp + ../../../plugins/wakeup-manager/src/heap_tracer.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy_default.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy_external.cpp + ../../../plugins/wakeup-manager/src/wakeup_manager_wrapper.cpp +) + +SET(TTPO_PKGS + gmock + dlog + ecore + vconf + pkgmgr-info + capi-media-audio-io + capi-appfw-application + capi-appfw-preference +) + +SET(TTPO_INCLUDES + ../../../inc// + ../../../plugins/wakeup-manager/inc// +) + +SET(TTPO_CFLAGS + -Wno-format-truncation +) + +SET(TTPO_WRAPPERS + "-Wl,\ +--wrap=ecore_main_loop_thread_safe_call_async" +) + +SET(TTPO_LDFLAGS +) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++14") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -O0") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TTPO_CFLAGS}") +SET(EXTRA_LDFLAGS "${TTPO_LDFLAGS}") + +# Find Packages +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + ${TTPO_PKGS} +) + +INCLUDE_DIRECTORIES(${TTPO_INCLUDES}) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") +ENDFOREACH(flag) + +FIND_PACKAGE(GTest REQUIRED) +INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS}) +LINK_DIRECTORIES(${GTEST_LIBRARY_DIRS}) + +SET(TTPO_EXECUTABLE test-wakeup-manager) +ADD_EXECUTABLE( + ${TTPO_EXECUTABLE} + ${TTPO_SRCS} +) + +TARGET_LINK_LIBRARIES(${TTPO_EXECUTABLE} ${pkgs_LDFLAGS}) +if(NOT "${EXTRA_LDFLAGS}" STREQUAL " ") + TARGET_LINK_LIBRARIES(${TTPO_EXECUTABLE} ${EXTRA_LDFLAGS}) +endif() +TARGET_LINK_LIBRARIES(${TTPO_EXECUTABLE} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) + +SET_TARGET_PROPERTIES(${TTPO_EXECUTABLE} PROPERTIES + COMPILE_FLAGS "-fPIE" + LINK_FLAGS "${TTPO_WRAPPERS}") +ADD_TEST(NAME ${TTPO_EXECUTABLE} COMMAND ${TTPO_EXECUTABLE}) + +# REPLACE THE TARGET INSTALL DESTINATION AS NEEDED (default : bin) +INSTALL(TARGETS ${TTPO_EXECUTABLE} DESTINATION bin) \ No newline at end of file diff --git a/tests/utc/wakeup-manager/test_main.cpp b/tests/utc/wakeup-manager/test_main.cpp new file mode 100644 index 0000000..46b38f2 --- /dev/null +++ b/tests/utc/wakeup-manager/test_main.cpp @@ -0,0 +1,276 @@ +#include +#include +#include + +#include "wakeup_manager.h" + +using namespace multiassistant::wakeup; + +extern "C" { +/* Add wrapper functions here with __wrap_ and __real prefix +Example : + +int __real_vconf_get_int(const char *in_key, int *intval); +int __wrap_vconf_get_int(const char *in_key, int *intval) +{ + if (strcmp(in_key, "TestKey") == 0) + return 0; + + return __real_vconf_get_int(in_key, intval); +} +*/ +void __wrap_ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, void *data) {} + +} + +class CMockWakeupEventObserver : public IWakeupEventObserver +{ +public: + CMockWakeupEventObserver() { + ON_CALL(*this, on_streaming_audio_data).WillByDefault( + [this](mas_speech_streaming_event_e event, void* buffer, unsigned int len) { + if (event == MAS_SPEECH_STREAMING_EVENT_FINISH) ++mFinishedReceived; + ++mStreamingAudioCount; + }); + } + MOCK_METHOD(void, on_wakeup, (mas_wakeup_event_info wakeup_info), (override)); + MOCK_METHOD(void, on_streaming_audio_data, + (mas_speech_streaming_event_e event, void* buffer, unsigned int len), (override)); + MOCK_METHOD(void, on_audio_streaming_data_section, (ma_audio_streaming_data_section_e section), (override)); + MOCK_METHOD(void, on_wakeup_engine_command, + (mas_wakeup_engine_command_target_e target, const char* name, const char* command), (override)); + MOCK_METHOD(void, on_wakeup_service_state_changed, (ma_service_state_e state), (override)); + MOCK_METHOD(void, on_voice_key_status_changed, (ma_voice_key_status_e status), (override)); + + std::atomic_uint mStreamingAudioCount{0}; + std::atomic_uint mFinishedReceived{0}; +}; + +class CMockSettingValueObserver : public ISettingValueObserver +{ +public: + MOCK_METHOD(void, on_value_changed, (), (override)); +}; + +class DefaultFixture : public testing::Test +{ +public: + DefaultFixture() { + } + virtual ~DefaultFixture() { + } + void SetUp() override { + mWakeupManager.initialize(); + } + void TearDown() override { + mWakeupManager.deinitialize(); + } + + /* Using NiceMock to ignore uninterested method calls to on_wakeup_service_state_changed() */ + testing::NiceMock mWakeupEventObserver; + CMockSettingValueObserver mSettingValueObserver; + CWakeupManager mWakeupManager{&mWakeupEventObserver, &mSettingValueObserver}; +}; + +TEST_F(DefaultFixture, SettingValueObserverCalledWhenLanguageChanges) { + EXPECT_CALL(mSettingValueObserver, on_value_changed()) + .Times(testing::Exactly(1)); + + CWakeupSettings* settings = mWakeupManager.get_wakeup_settings(); + auto observer = settings->get_observers().at(0); + + observer->on_voice_input_language_changed("ko-KR"); +} + +TEST_F(DefaultFixture, SettingValueObserverCalledWhenAssistantAdded) { + EXPECT_CALL(mSettingValueObserver, on_value_changed()) + .Times(testing::Exactly(1)); + + CWakeupSettings* settings = mWakeupManager.get_wakeup_settings(); + auto observer = settings->get_observers().at(0); + + observer->on_assistant_enabled_info_changed("Bixby", true); +} + +TEST_F(DefaultFixture, SettingValueObserverCalledWhenAssistantDeleted) { + EXPECT_CALL(mSettingValueObserver, on_value_changed()) + .Times(testing::Exactly(1)); + + CWakeupSettings* settings = mWakeupManager.get_wakeup_settings(); + auto observer = settings->get_observers().at(0); + + observer->on_assistant_enabled_info_changed("Bixby", false); +} + +TEST_F(DefaultFixture, WakeupEventNotTriggeredWhenInactiveMode) { + EXPECT_CALL(mWakeupEventObserver, on_wakeup(testing::_)) + .Times(0); + EXPECT_CALL(mWakeupEventObserver, on_voice_key_status_changed(testing::_)) + .Times(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_INACTIVE); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); +} + +TEST_F(DefaultFixture, WakeupEventTriggeredWhenVoiceKeyGetsPressed) { + EXPECT_CALL(mWakeupEventObserver, on_wakeup(testing::_)) + .Times(testing::Exactly(1)); + EXPECT_CALL(mWakeupEventObserver, on_voice_key_status_changed(MA_VOICE_KEY_STATUS_PRESSED)) + .Times(testing::Exactly(1)); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); +} + +TEST_F(DefaultFixture, AudioDataReceivedWhenVoiceKeyGetsPressed) { + EXPECT_CALL(mWakeupEventObserver, + on_streaming_audio_data(MAS_SPEECH_STREAMING_EVENT_START, testing::_, testing::_)) + .Times(testing::Exactly(1)); + EXPECT_CALL(mWakeupEventObserver, + on_streaming_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, testing::_, testing::_)) + .Times(testing::Exactly(3)); + EXPECT_CALL(mWakeupEventObserver, + on_streaming_audio_data(MAS_SPEECH_STREAMING_EVENT_FINISH, testing::_, testing::_)) + .Times(testing::Exactly(1)); + + const std::chrono::seconds interval(3); + auto last = std::chrono::steady_clock::now(); + + const int len = 10; + unsigned char buffer[len]; + + mWakeupEventObserver.mStreamingAudioCount.store(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); + mWakeupManager.start_streaming_utterance_data(); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_START, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_FINISH, buffer, len); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_RELEASED, nullptr, 0); + + /* Wait for all audio data gets received, at most 3 seconds */ + while (mWakeupEventObserver.mStreamingAudioCount.load() < 5) { + auto now = std::chrono::steady_clock::now(); + if (now - last > interval) break; + } + mWakeupManager.stop_streaming_utterance_data(); +} + +TEST_F(DefaultFixture, FinishAudioDataReceivedWhenStoppedBeforeReleasingWithInterval) { + const std::chrono::seconds interval(3); + auto last = std::chrono::steady_clock::now(); + + const int len = 10; + unsigned char buffer[len]; + + mWakeupEventObserver.mFinishedReceived.store(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); + mWakeupManager.start_streaming_utterance_data(); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_START, buffer, len); + this_thread::sleep_for(chrono::milliseconds(300)); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.stop_streaming_utterance_data(); + + /* Wait for FINISH audio data gets received, at most 3 seconds */ + while (mWakeupEventObserver.mFinishedReceived.load() == 0) { + auto now = std::chrono::steady_clock::now(); + if (now - last > interval) break; + } + + this_thread::sleep_for(chrono::milliseconds(300)); + ASSERT_EQ(mWakeupEventObserver.mFinishedReceived.load(), 1); +} + +TEST_F(DefaultFixture, FinishAudioDataReceivedWhenStoppedBeforeReleasingWithoutInterval) { + const std::chrono::seconds interval(3); + auto last = std::chrono::steady_clock::now(); + + const int len = 10; + unsigned char buffer[len]; + + mWakeupEventObserver.mFinishedReceived.store(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_START, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.start_streaming_utterance_data(); + mWakeupManager.stop_streaming_utterance_data(); + + /* Wait for FINISH audio data gets received, at most 3 seconds */ + while (mWakeupEventObserver.mFinishedReceived.load() == 0) { + auto now = std::chrono::steady_clock::now(); + if (now - last > interval) break; + } + + this_thread::sleep_for(chrono::milliseconds(300)); + ASSERT_EQ(mWakeupEventObserver.mFinishedReceived.load(), 1); +} + +TEST_F(DefaultFixture, FinishAudioDataReceivedOnResultBeforeReleasingWithInterval) { + const std::chrono::seconds interval(3); + auto last = std::chrono::steady_clock::now(); + + const int len = 10; + unsigned char buffer[len]; + + mWakeupEventObserver.mFinishedReceived.store(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); + mWakeupManager.start_streaming_utterance_data(); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_START, buffer, len); + this_thread::sleep_for(chrono::milliseconds(300)); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.update_recognition_result(std::string(), 0); + + /* Wait for FINISH audio data gets received, at most 3 seconds */ + while (mWakeupEventObserver.mFinishedReceived.load() == 0) { + auto now = std::chrono::steady_clock::now(); + if (now - last > interval) break; + } + + this_thread::sleep_for(chrono::milliseconds(300)); + ASSERT_EQ(mWakeupEventObserver.mFinishedReceived.load(), 1); +} + +TEST_F(DefaultFixture, FinishAudioDataReceivedOnResultBeforeReleasingWithoutInterval) { + const std::chrono::seconds interval(3); + auto last = std::chrono::steady_clock::now(); + + const int len = 10; + unsigned char buffer[len]; + + mWakeupEventObserver.mFinishedReceived.store(0); + + mWakeupManager.change_manager_state(WAKEUP_MANAGER_STATE_LISTENING); + mWakeupManager.process_plugin_event(MAS_PLUGIN_EVENT_VOICE_KEY_PRESSED, nullptr, 0); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_START, buffer, len); + mWakeupManager.feed_audio_data(MAS_SPEECH_STREAMING_EVENT_CONTINUE, buffer, len); + mWakeupManager.start_streaming_utterance_data(); + mWakeupManager.update_recognition_result(std::string(), 0); + + /* Wait for FINISH audio data gets received, at most 3 seconds */ + while (mWakeupEventObserver.mFinishedReceived.load() == 0) { + auto now = std::chrono::steady_clock::now(); + if (now - last > interval) break; + } + + this_thread::sleep_for(chrono::milliseconds(300)); + ASSERT_EQ(mWakeupEventObserver.mFinishedReceived.load(), 1); +} + +/* Uncomment the below piece of code if you need your own main() */ +/* +int main(int argc, char** argv) { + std::cout << "Starting tests" << std::endl; + testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} +*/ diff --git a/tests/utc/wakeup-manager/ttpo.xml b/tests/utc/wakeup-manager/ttpo.xml new file mode 100644 index 0000000..85209a9 --- /dev/null +++ b/tests/utc/wakeup-manager/ttpo.xml @@ -0,0 +1,27 @@ + + + test_main.cpp + ../../../plugins/wakeup-manager/src/wakeup_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_audio_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_engine_manager.cpp + ../../../plugins/wakeup-manager/src/wakeup_settings.cpp + ../../../plugins/wakeup-manager/src/dependency_resolver.cpp + ../../../plugins/wakeup-manager/src/assistant_config_manager.cpp + ../../../plugins/wakeup-manager/src/heap_tracer.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy_default.cpp + ../../../plugins/wakeup-manager/src/wakeup_policy_external.cpp + ../../../plugins/wakeup-manager/src/wakeup_manager_wrapper.cpp + ../../../inc/ + ../../../plugins/wakeup-manager/inc/ + gmock + dlog + ecore + vconf + pkgmgr-info + capi-media-audio-io + capi-appfw-application + capi-appfw-preference + ecore_main_loop_thread_safe_call_async + -Wno-format-truncation + -- 2.7.4