diff --git a/CMakeLists.txt b/CMakeLists.txt index 941910620b..fdecfb3381 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -404,7 +404,7 @@ endif() if(PLUGIN_NETWORKMANAGER) include(l1networkmanager.cmake) add_subdirectory(NetworkManager) - add_subdirectory(Tests/L1Tests) + # add_subdirectory(Tests/L1Tests) endif() if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) diff --git a/NetworkManager/Tests/.clang-format b/NetworkManager/Tests/.clang-format new file mode 100644 index 0000000000..423360be10 --- /dev/null +++ b/NetworkManager/Tests/.clang-format @@ -0,0 +1,108 @@ +--- +Language: Cpp +# BasedOnStyle: WebKit +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: All +BreakBeforeBraces: WebKit +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeCategories: + - Regex: '^"config\.h"' + Priority: -1 + # The main header for a source file automatically gets category 0 + - Regex: '.*' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... diff --git a/NetworkManager/Tests/L1Tests/.lcovrc_l1 b/NetworkManager/Tests/L1Tests/.lcovrc_l1 new file mode 100644 index 0000000000..879fe2ce58 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/.lcovrc_l1 @@ -0,0 +1,181 @@ +# +# /etc/lcovrc - system-wide defaults for LCOV +# +# To change settings for a single user, place a customized copy of this file +# at location ~/.lcovrc +# + +# Specify an external style sheet file (same as --css-file option of genhtml) +#genhtml_css_file = gcov.css + +# Specify coverage rate limits (in %) for classifying file entries +# HI: hi_limit <= rate <= 100 graph color: green +# MED: med_limit <= rate < hi_limit graph color: orange +# LO: 0 <= rate < med_limit graph color: red +genhtml_hi_limit = 75 +genhtml_med_limit = 50 + +# Width of line coverage field in source code view +genhtml_line_field_width = 12 + +# Width of branch coverage field in source code view +genhtml_branch_field_width = 16 + +# Width of overview image (used by --frames option of genhtml) +genhtml_overview_width = 80 + +# Resolution of overview navigation: this number specifies the maximum +# difference in lines between the position a user selected from the overview +# and the position the source code window is scrolled to (used by --frames +# option of genhtml) +genhtml_nav_resolution = 4 + +# Clicking a line in the overview image should show the source code view at +# a position a bit further up so that the requested line is not the first +# line in the window. This number specifies that offset in lines (used by +# --frames option of genhtml) +genhtml_nav_offset = 10 + +# Do not remove unused test descriptions if non-zero (same as +# --keep-descriptions option of genhtml) +genhtml_keep_descriptions = 0 + +# Do not remove prefix from directory names if non-zero (same as --no-prefix +# option of genhtml) +genhtml_no_prefix = 0 + +# Do not create source code view if non-zero (same as --no-source option of +# genhtml) +genhtml_no_source = 0 + +# Replace tabs with number of spaces in source view (same as --num-spaces +# option of genhtml) +genhtml_num_spaces = 8 + +# Highlight lines with converted-only data if non-zero (same as --highlight +# option of genhtml) +genhtml_highlight = 0 + +# Include color legend in HTML output if non-zero (same as --legend option of +# genhtml) +genhtml_legend = 0 + +# Use FILE as HTML prolog for generated pages (same as --html-prolog option of +# genhtml) +#genhtml_html_prolog = FILE + +# Use FILE as HTML epilog for generated pages (same as --html-epilog option of +# genhtml) +#genhtml_html_epilog = FILE + +# Use custom filename extension for pages (same as --html-extension option of +# genhtml) +#genhtml_html_extension = html + +# Compress all generated html files with gzip. +#genhtml_html_gzip = 1 + +# Include sorted overview pages (can be disabled by the --no-sort option of +# genhtml) +genhtml_sort = 1 + +# Include function coverage data display (can be disabled by the +# --no-func-coverage option of genhtml) +#genhtml_function_coverage = 1 + +# Include branch coverage data display (can be disabled by the +# --no-branch-coverage option of genhtml) +#genhtml_branch_coverage = 1 + +# Specify the character set of all generated HTML pages +genhtml_charset=UTF-8 + +# Allow HTML markup in test case description text if non-zero +genhtml_desc_html=0 + +# Specify the precision for coverage rates +#genhtml_precision=1 + +# Show missed counts instead of hit counts +#genhtml_missed=1 + +# Demangle C++ symbols +#genhtml_demangle_cpp=1 + +# Name of the tool used for demangling C++ function names +#genhtml_demangle_cpp_tool = c++filt + +# Specify extra parameters to be passed to the demangling tool +#genhtml_demangle_cpp_params = "" + +# Location of the gcov tool (same as --gcov-info option of geninfo) +#geninfo_gcov_tool = gcov + +# Adjust test names to include operating system information if non-zero +#geninfo_adjust_testname = 0 + +# Calculate checksum for each source code line if non-zero (same as --checksum +# option of geninfo if non-zero, same as --no-checksum if zero) +#geninfo_checksum = 1 + +# Specify whether to capture coverage data for external source files (can +# be overridden by the --external and --no-external options of geninfo/lcov) +#geninfo_external = 1 + +# Enable libtool compatibility mode if non-zero (same as --compat-libtool option +# of geninfo if non-zero, same as --no-compat-libtool if zero) +#geninfo_compat_libtool = 0 + +# Use gcov's --all-blocks option if non-zero +#geninfo_gcov_all_blocks = 1 + +# Specify compatiblity modes (same as --compat option of geninfo). +#geninfo_compat = libtool=on, hammer=auto, split_crc=auto + +# Adjust path to source files by removing or changing path components that +# match the specified pattern (Perl regular expression format) +#geninfo_adjust_src_path = /tmp/build => /usr/src + +# Specify if geninfo should try to automatically determine the base-directory +# when collecting coverage data. +geninfo_auto_base = 1 + +# Use gcov intermediate format? Valid values are 0, 1, auto +geninfo_intermediate = auto + +# Specify if exception branches should be excluded from branch coverage. +geninfo_no_exception_branch = 0 + +# Directory containing gcov kernel files +# lcov_gcov_dir = /proc/gcov + +# Location of the insmod tool +lcov_insmod_tool = /sbin/insmod + +# Location of the modprobe tool +lcov_modprobe_tool = /sbin/modprobe + +# Location of the rmmod tool +lcov_rmmod_tool = /sbin/rmmod + +# Location for temporary directories +lcov_tmp_dir = /tmp + +# Show full paths during list operation if non-zero (same as --list-full-path +# option of lcov) +lcov_list_full_path = 0 + +# Specify the maximum width for list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_width = 80 + +# Specify the maximum percentage of file names which may be truncated when +# choosing a directory prefix in list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_truncate_max = 20 + +# Specify if function coverage data should be collected and processed. +lcov_function_coverage = 1 + +# Specify if branch coverage data should be collected and processed. +lcov_branch_coverage = 0 diff --git a/NetworkManager/Tests/L1Tests/CMakeLists.txt b/NetworkManager/Tests/L1Tests/CMakeLists.txt new file mode 100755 index 0000000000..98f7235b17 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/CMakeLists.txt @@ -0,0 +1,200 @@ +# # If not stated otherwise in this file or this component's LICENSE file the +# # following copyright and licenses apply: +# # +# # Copyright 2020 RDK Management +# # +# # Licensed under the Apache License, Version 2.0 (the "License"); +# # you may not use this file except in compliance with the License. +# # You may obtain a copy of the License at +# # +# # http://www.apache.org/licenses/LICENSE-2.0 +# # +# # Unless required by applicable law or agreed to in writing, software +# # distributed under the License is distributed on an "AS IS" BASIS, +# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# # See the License for the specific language governing permissions and +# # limitations under the License. + +# cmake_minimum_required(VERSION 3.8) +# project(RdkServicesL1Test) + +# set(CMAKE_CXX_STANDARD 11) + +# find_package(${NAMESPACE}Plugins REQUIRED) + +# include(FetchContent) +# FetchContent_Declare( +# googletest +# URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip +# ) +# FetchContent_MakeAvailable(googletest) +# file(GLOB TESTS tests/test_Network.cpp) +# add_executable(${PROJECT_NAME} +# ${TESTS} +# ../mocks/Rfc.cpp +# ../mocks/Iarm.cpp +# ../mocks/RBus.cpp +# ../mocks/MotionDetection.cpp +# ../mocks/Telemetry.cpp +# ../mocks/Udev.cpp +# ../mocks/devicesettings.cpp +# ../mocks/HdmiCec.cpp +# ../mocks/thunder/Module.cpp +# ../mocks/Wraps.cpp +# ../mocks/Dobby.cpp +# ../mocks/rdkshell.cpp +# ../mocks/opkgMock.cpp +# ../mocks/WpaCtrl.cpp +# ) + +# set_source_files_properties( +# tests/test_DeviceAudioCapabilities.cpp +# tests/test_DeviceVideoCapabilities.cpp +# tests/test_SystemServices.cpp +# tests/test_Warehouse.cpp +# tests/test_HdmiCec.cpp +# tests/test_HdmiCec2.cpp +# tests/test_HdmiCecSource.cpp +# tests/test_FrontPanel.cpp +# tests/test_HdmiCecSink.cpp +# PROPERTIES COMPILE_FLAGS "-fexceptions") + +# include_directories(../../LocationSync +# ../../SecurityAgent +# ../../DeviceIdentification +# ../../DeviceDiagnostics +# ../../FrameRate +# ../../AVInput +# ../../Telemetry +# ../../ScreenCapture +# ../../DataCapture +# ../../UsbAccess +# ../../Timer +# ../../LoggingPreferences +# ../../UserPreferences +# ../../Messenger +# ../../DeviceInfo +# ../../helpers +# ../../SystemServices +# ../../HdmiInput +# ../../HdcpProfile +# ../../Network +# ../../WifiManager +# ../../TraceControl +# ../../Warehouse +# ../../ActivityMonitor +# ../../MotionDetection +# ../../CompositeInput +# ../../OCIContainer +# ../../HdmiCec +# ../../HdmiCec_2 +# ../../HdmiCecSource +# ../../XCast +# ../../FrontPanel +# ../../HdmiCecSink +# ../../RDKShell +# ../../MaintenanceManager +# ../../Packager +# ../../TextToSpeech +# ../../SystemAudioPlayer +# ../../Miracast/common +# ../../Miracast/MiracastService +# ../../Miracast/MiracastService/P2P +# ../../Miracast/MiracastPlayer +# ../../Miracast/MiracastPlayer/RTSP +# ) +# link_directories(../../LocationSync +# ../../SecurityAgent +# ../../DeviceIdentification +# ../../DeviceDiagnostics +# ../../FrameRate +# ../../AVInput +# ../../Telemetry +# ../../ScreenCapture +# ../../DataCapture +# ../../UsbAccess +# ../../Timer +# ../../LoggingPreferences +# ../../SystemServices +# ../../UserPreferences +# ../../Messenger +# ../../DeviceInfo +# ../../HdmiInput +# ../../HdcpProfile +# ../../Network +# ../../WifiManager +# ../../TraceControl +# ../../Warehouse +# ../../ActivityMonitor +# ../../MotionDetection +# ../../CompositeInput +# ../../OCIContainer +# ../../HdmiCec +# ../../HdmiCec_2 +# ../../HdmiCecSource +# ../../XCast +# ../../FrontPanel +# ../../HdmiCecSink +# ../../RDKShell +# ../../MaintenanceManager +# ../../Packager +# ../../TextToSpeech +# ../../SystemAudioPlayer +# ../../Miracast +# ) + +# target_link_libraries(${PROJECT_NAME} +# gmock_main +# ${NAMESPACE}Plugins::${NAMESPACE}Plugins +# ${NAMESPACE}DataCapture +# ${NAMESPACE}DeviceDiagnostics +# ${NAMESPACE}LocationSync +# ${NAMESPACE}SecurityAgent +# ${NAMESPACE}DeviceIdentification +# ${NAMESPACE}FrameRate +# ${NAMESPACE}AVInput +# ${NAMESPACE}ScreenCapture +# ${NAMESPACE}Telemetry +# ${NAMESPACE}UsbAccess +# ${NAMESPACE}Timer +# ${NAMESPACE}LoggingPreferences +# ${NAMESPACE}SystemServices +# ${NAMESPACE}UserPreferences +# ${NAMESPACE}Messenger +# ${NAMESPACE}DeviceInfo +# ${NAMESPACE}HdmiInput +# ${NAMESPACE}HdcpProfile +# ${NAMESPACE}Network +# ${NAMESPACE}WifiManager +# ${NAMESPACE}TraceControl +# ${NAMESPACE}Warehouse +# ${NAMESPACE}ActivityMonitor +# ${NAMESPACE}MotionDetection +# ${NAMESPACE}CompositeInput +# ${NAMESPACE}OCIContainer +# ${NAMESPACE}HdmiCec +# ${NAMESPACE}HdmiCec_2 +# ${NAMESPACE}HdmiCecSource +# ${NAMESPACE}XCast +# ${NAMESPACE}FrontPanel +# ${NAMESPACE}HdmiCecSink +# ${NAMESPACE}RDKShell +# ${NAMESPACE}MaintenanceManager +# ${NAMESPACE}Packager +# ${NAMESPACE}TextToSpeech +# ${NAMESPACE}SystemAudioPlayer +# ${NAMESPACE}MiracastService +# ${NAMESPACE}MiracastPlayer +# ) + +# target_include_directories(${PROJECT_NAME} +# PUBLIC +# $ +# $ +# ../mocks +# ../mocks/devicesettings +# ../mocks/thunder +# ${CMAKE_CURRENT_SOURCE_DIR}/../../OCIContainer/stubs +# ) + +# install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/NetworkManager/Tests/L1Tests/README.md b/NetworkManager/Tests/L1Tests/README.md new file mode 100755 index 0000000000..551d048414 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/README.md @@ -0,0 +1,66 @@ +# Unit Tests # + +## How to run locally ## + +Install [act](https://github.com/nektos/act) and docker: + +##### Ubuntu ##### + +```shell script +curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash +sudo apt update +sudo apt -y install docker.io +``` + +##### macOS ##### + +```shell script +brew install act +brew install --cask docker +``` + +Create a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). + +Invoke the workflow: + +```shell script +act -W .github/workflows/l1-tests.yml -s GITHUB_TOKEN=[token] +``` + +`-r, --reuse` to reuse the container. + +Get a bash shell in the container, if needed: + +```shell script +docker ps +docker exec -it /bin/bash +``` + +## FAQ ## + +1. The commands to build and run tests are in [l1-tests.yml](../.github/workflows/l1-tests.yml). + For the queries on syntax please refer to the [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions). + +2. External dependencies need to be mocked. + For each external header, add one into the [l1tests.cmake](../l1tests.cmake) (preserve the original path parts, if needed). + For each external declaration, add one into the [mocks folder](./mocks). + For the queries on mocks please refer to the [gMock Cookbook](http://google.github.io/googletest/gmock_cook_book.html). + +3. For the queries on how to write tests please refer to the [GoogleTest User’s Guide](https://google.github.io/googletest/). + Common recommendations: + - Tests should be fast. + - Tests should be independent and repeatable. + - Find the smallest piece of logic you can test, isolate it from other parts. + - Use One-Assert-per-Test and Arrange-Act-Assert patterns. + If two or more tests operate on similar data, use a test fixture. + - Having more constraints than necessary is bad. + If a test over-specifies, it doesn’t leave enough freedom to the implementation. + Use `ON_CALL` by default, and only use `EXPECT_CALL` when intend to verify that the call is made. + +4. Before review: + - Enable [ClangFormat](./.clang-format) and make sure the tests code is formatted. + - Make sure the code builds without warnings. + - At the bottom of the workflow summary page on GitHub, there is a section with artifacts. + Artifacts include coverage report and valgrind log. + They help to understand how much code is covered by tests and whether there are memory leaks. + Make sure you check both. \ No newline at end of file diff --git a/NetworkManager/Tests/L1Tests/tests/test_AVInput.cpp b/NetworkManager/Tests/L1Tests/tests/test_AVInput.cpp new file mode 100755 index 0000000000..6fde932441 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_AVInput.cpp @@ -0,0 +1,93 @@ +#include + +#include "AVInput.h" + +#include "HdmiInputMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class AVInputTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + AVInputTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~AVInputTest() = default; +}; + +class AVInputDsTest : public AVInputTest { +protected: + HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; + + AVInputDsTest() + : AVInputTest() + { + p_hdmiInputImplMock = new NiceMock ; + device::HdmiInput::setImpl(p_hdmiInputImplMock); + } + virtual ~AVInputDsTest() override + { + device::HdmiInput::setImpl(nullptr); + if (p_hdmiInputImplMock != nullptr) + { + delete p_hdmiInputImplMock; + p_hdmiInputImplMock = nullptr; + } + } +}; + +TEST_F(AVInputTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("numberOfInputs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("currentVideoMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("contentProtected"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEdid2AllmSupport"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEdid2AllmSupport"))); +} + +TEST_F(AVInputTest, contentProtected) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("contentProtected"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"isContentProtected\":true,\"success\":true}")); +} + +TEST_F(AVInputDsTest, numberOfInputs) +{ + ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) + .WillByDefault(::testing::Return(1)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("numberOfInputs"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"numberOfInputs\":1,\"success\":true}")); +} + +TEST_F(AVInputDsTest, currentVideoMode) +{ + ON_CALL(*p_hdmiInputImplMock, getCurrentVideoMode()) + .WillByDefault(::testing::Return(string("unknown"))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("currentVideoMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"currentVideoMode\":\"unknown\",\"success\":true}")); +} + +TEST_F(AVInputDsTest, getEdid2AllmSupport) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEdid2AllmSupport"), _T("{\"portId\": \"0\",\"allmSupport\":true}"), response)); + EXPECT_EQ(response, string("{\"allmSupport\":true,\"success\":true}")); +} + + +TEST_F(AVInputDsTest, setEdid2AllmSupport) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEdid2AllmSupport"), _T("{\"portId\": \"0\",\"allmSupport\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + diff --git a/NetworkManager/Tests/L1Tests/tests/test_ActivityMonitor.cpp b/NetworkManager/Tests/L1Tests/tests/test_ActivityMonitor.cpp new file mode 100755 index 0000000000..ae9ce3ef0b --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_ActivityMonitor.cpp @@ -0,0 +1,230 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include + +#include "ActivityMonitor.h" + +#include "FactoriesImplementation.h" +#include "ServiceMock.h" +#include "IarmBusMock.h" +#include +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string regFile = _T("/opt/waylandregistry.conf"); +const uint8_t regFileData[] = "{\"waylandapps\":[{\"name\" : \"memcheck-amd64-\",\"binary\" : \"/usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-%\"}]}"; +} + +class ActivityMonitorTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + ActivityMonitorTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~ActivityMonitorTest() override + { + plugin->Deinitialize(nullptr); + } +}; + +TEST_F(ActivityMonitorTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disableMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getApplicationMemoryUsage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getAllMemoryUsage"))); +} + +TEST_F(ActivityMonitorTest, enableMonitoringEmptyConfig) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("enableMonitoring"), _T("{\"config\":[],\"memoryIntervalSeconds\":\"0\", \"cpuIntervalSeconds\":\"0\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("enableMonitoring"), _T("{\"config\":[{\"appPid\": 6763, \"memoryThresholdMB\": 10,\"cpuThresholdPercent\": 50,\"cpuThresholdSeconds\": 2}],\"memoryIntervalSeconds\":\"0\", \"cpuIntervalSeconds\":\"0\"}"), response)); +} + +TEST_F(ActivityMonitorTest, getAllMemoryUsage) +{ + //Add version info + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\n"; + fileVer.close(); + + //Add Apps registry file + Core::File fileApps(regFile); + fileApps.Create(); + fileApps.Write(regFileData, sizeof(regFileData)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAllMemoryUsage"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"freeMemoryMB\":[0-9]+," + "\"applicationMemory\":" + "\\[(\\{" + "\"appPid\":[0-9]+," + "\"appName\":\"memcheck-amd64-\"," + "\"memoryMB\":[0-9]+" + "\\},{0,}){0,}\\]," + "\"success\":true" + "\\}")); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); + + // Delete Apps registry file + fileApps.Destroy(); +} + +class ActivityMonitorEventTest : public ActivityMonitorTest { +protected: + ServiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + + ActivityMonitorEventTest() + : ActivityMonitorTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~ActivityMonitorEventTest() override + { + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +/** + * freezes and log flooding without valgrind + */ +TEST_F(ActivityMonitorEventTest, DISABLED_enableMonitoringWithConfig) +{ + //Add version info + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\n"; + fileVer.close(); + + //Add Apps registry file + Core::File fileApps(regFile); + fileApps.Create(); + fileApps.Write(regFileData, sizeof(regFileData)); + + Core::Event memoryThresholdEvent(false, true); + Core::Event cpuThresholdEvent(false, true); + handler.Subscribe(0, _T("onMemoryThreshold"), _T("org.rdk.ActivityMonitor"), message); + handler.Subscribe(0, _T("onCPUThreshold"), _T("org.rdk.ActivityMonitor"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.ActivityMonitor.onMemoryThreshold\"," + "\"params\":" + "\\{" + "\"appPid\":[0-9]+," + "\"threshold\":\"exceeded\"," + "\"memoryMB\":[0-9]+" + "\\}" + "\\}"))); + + memoryThresholdEvent.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.ActivityMonitor.onCPUThreshold\"," + "\"params\":" + "\\{" + "\"appPid\":[0-9]+," + "\"threshold\":\"exceeded\"," + "\"cpuPercent\":[0-9]+" + "\\}" + "\\}"))); + + cpuThresholdEvent.SetEvent(); + return Core::ERROR_NONE; + })); + + //Monitor own PID + unsigned int ownPID = static_cast(getpid()); + + string monitorString = "{\"config\":[{\"appPid\":" + std::to_string(ownPID) + ", \"memoryThresholdMB\": 1,\"cpuThresholdPercent\": 1,\"cpuThresholdSeconds\": 2}],\"memoryIntervalSeconds\":\"0.02\", \"cpuIntervalSeconds\":\"0.02\"}"; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableMonitoring"), monitorString, response)); + + string AppPID = "{\"pid\":" + std::to_string(ownPID) + "}"; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getApplicationMemoryUsage"), AppPID, response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"applicationMemory\":" + "\\{" + "\"appPid\":[0-9]+," + "\"appName\":\"memcheck-amd64-\"," + "\"memoryMB\":[0-9]+" + "\\}," + "\"success\":true" + "\\}")); + + //Wait for events to occur + EXPECT_EQ(Core::ERROR_NONE, memoryThresholdEvent.Lock()); + EXPECT_EQ(Core::ERROR_NONE, cpuThresholdEvent.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("disableMonitoring"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); + + // Delete Apps registry file + fileApps.Destroy(); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_CompositeInput.cpp b/NetworkManager/Tests/L1Tests/tests/test_CompositeInput.cpp new file mode 100755 index 0000000000..aa21b480e9 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_CompositeInput.cpp @@ -0,0 +1,366 @@ +#include +#include "CompositeInput.h" +#include "FactoriesImplementation.h" +#include "CompositeInputMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" + +using namespace WPEFramework; +using ::testing::NiceMock; +using ::testing::Eq; + +class CompositeInputTest : public ::testing::Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + CompositeInputTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~CompositeInputTest() + { + } +}; + +class CompositeInputDsTest : public CompositeInputTest { +protected: + CompositeInputImplMock *p_compositeInputImplMock = nullptr ; + + CompositeInputDsTest() + : CompositeInputTest() + { + p_compositeInputImplMock = new NiceMock ; + device::CompositeInput::setImpl(p_compositeInputImplMock); + } + virtual ~CompositeInputDsTest() override + { + device::CompositeInput::setImpl(nullptr); + if (p_compositeInputImplMock != nullptr) + { + delete p_compositeInputImplMock; + p_compositeInputImplMock = nullptr; + } + } +}; + +class CompositeInputInitializedTest : public CompositeInputTest { +protected: + NiceMock iarmBusImplMock; + IARM_EventHandler_t dsCompositeEventHandler; + IARM_EventHandler_t dsCompositeStatusEventHandler; + IARM_EventHandler_t dsCompositeSignalStatusEventHandler; + + CompositeInputInitializedTest() + : CompositeInputTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsCompositeEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsCompositeStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsCompositeSignalStatusEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~CompositeInputInitializedTest() override + { + plugin->Deinitialize(nullptr); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + + +class CompositeInputInitializedEventTest : public CompositeInputInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + CompositeInputInitializedEventTest() + : CompositeInputInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~CompositeInputInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class CompositeInputInitializedEventDsTest : public CompositeInputInitializedEventTest { +protected: + CompositeInputImplMock *p_compositeInputImplMock = nullptr ; + + CompositeInputInitializedEventDsTest() + : CompositeInputInitializedEventTest() + { + p_compositeInputImplMock = new NiceMock ; + device::CompositeInput::setImpl(p_compositeInputImplMock); + } + + virtual ~CompositeInputInitializedEventDsTest() override + { + device::CompositeInput::setImpl(nullptr); + if (p_compositeInputImplMock != nullptr) + { + delete p_compositeInputImplMock; + p_compositeInputImplMock = nullptr; + } + } +}; + +TEST_F(CompositeInputTest, RegisteredMethods) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCompositeInputDevices"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startCompositeInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopCompositeInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); +} + +TEST_F(CompositeInputDsTest, getCompositeInputDevices) +{ + ON_CALL(*p_compositeInputImplMock, getNumberOfInputs()) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_compositeInputImplMock, isPortConnected(::testing::_)) + .WillByDefault(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCompositeInputDevices"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}],\"success\":true}")); +} + +TEST_F(CompositeInputDsTest, startCompositeInputInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startCompositeInput"), _T("{\"portId\": \"b\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(CompositeInputDsTest, startCompositeInput) +{ + EXPECT_CALL(*p_compositeInputImplMock, selectPort(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](int8_t Port) { + + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startCompositeInput"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(CompositeInputDsTest, setVideoRectangleInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": \"b\",\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(CompositeInputDsTest, setVideoRectangle) +{ + EXPECT_CALL(*p_compositeInputImplMock, scaleVideo(::testing::_,::testing::_,::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](int32_t x, int32_t y, int32_t width, int32_t height) { + + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": 0,\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(CompositeInputInitializedEventDsTest, onDevicesChanged) +{ + ASSERT_TRUE(dsCompositeEventHandler != nullptr); + ON_CALL(*p_compositeInputImplMock, getNumberOfInputs()) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_compositeInputImplMock, isPortConnected(::testing::_)) + .WillByDefault(::testing::Return(true)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onDevicesChanged.onDevicesChanged\",\"params\":{\"devices\":[{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}]}}"))); + + return Core::ERROR_NONE; + })); + + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_connect.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_connect.isPortConnected = true; + handler.Subscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); + + dsCompositeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, &eventData , 0); + + handler.Unsubscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); +} + +TEST_F(CompositeInputInitializedEventDsTest, onInputStatusChangeOn) +{ + ASSERT_TRUE(dsCompositeStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_status.isPresented = true; + handler.Subscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); + dsCompositeStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS , &eventData , 0); + handler.Unsubscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onInputStatusChangeOff) +{ + ASSERT_TRUE(dsCompositeStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_status.isPresented = false; + handler.Subscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); + dsCompositeStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onSignalChangedStable) +{ + ASSERT_TRUE(dsCompositeSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_STABLE; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsCompositeSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS , &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onSignalChangedNoSignal) +{ + ASSERT_TRUE(dsCompositeSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_NOSIGNAL; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsCompositeSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onSignalChangedUnstable) +{ + ASSERT_TRUE(dsCompositeSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_UNSTABLE; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsCompositeSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onSignalChangedNotSupported) +{ + ASSERT_TRUE(dsCompositeSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_NOTSUPPORTED; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsCompositeSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(CompositeInputInitializedEventDsTest, onSignalChangedDefault) +{ + ASSERT_TRUE(dsCompositeSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"cvbsin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.composite_in_sig_status.port =dsCOMPOSITE_IN_PORT_0; + eventData.data.composite_in_sig_status.status = dsCOMP_IN_SIGNAL_STATUS_MAX; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsCompositeSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DataCapture.cpp b/NetworkManager/Tests/L1Tests/tests/test_DataCapture.cpp new file mode 100755 index 0000000000..58c3511b28 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DataCapture.cpp @@ -0,0 +1,329 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include + +#include +#include + +#include "DataCapture.h" +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" + +using ::testing::NiceMock; + +namespace { +const std::string iarmName = _T("Thunder_Plugins"); +constexpr const char answer[16] = "TESTING STREAM!"; + +void runSocket(std::promise ready, const std::string& fileName) +{ + auto sd = socket(AF_UNIX, SOCK_STREAM, 0); + + struct sockaddr_un serveraddr; + memset(&serveraddr, 0, sizeof(serveraddr)); + serveraddr.sun_family = AF_UNIX; + memcpy(serveraddr.sun_path, fileName.c_str(), fileName.size() + 1); + + ASSERT_FALSE(bind(sd, (struct sockaddr*)&serveraddr, SUN_LEN(&serveraddr)) < 0); + ASSERT_FALSE(listen(sd, 10) < 0); + ready.set_value(true); + + auto sd2 = accept(sd, NULL, NULL); + + write(sd2, answer, 16); + + close(sd2); + close(sd); + unlink(fileName.c_str()); +} + +void runServer(std::promise ready) +{ + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + ASSERT_TRUE(sockfd != -1); + + sockaddr_in sockaddr; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = INADDR_ANY; + sockaddr.sin_port = htons(9999); + + ASSERT_FALSE(bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0); + ASSERT_FALSE(listen(sockfd, 10) < 0); + ready.set_value(true); + + auto addrlen = sizeof(sockaddr); + const int connection = accept(sockfd, (struct sockaddr*)&sockaddr, (socklen_t*)&addrlen); + ASSERT_FALSE(connection < 0); + + char buffer[2048]; + ASSERT_TRUE(read(connection, buffer, 2048) > 0); + // Expect we got correct message + EXPECT_TRUE(strstr(buffer, answer) != nullptr); + + // Return the simplest response + std::string response = "HTTP/1.1 200\n\rContent-Length: 0"; + send(connection, response.c_str(), response.size(), 0); + + close(connection); + close(sockfd); +} +} + +using testing::_; +using testing::AtLeast; +using testing::NiceMock; +using testing::Return; +using testing::Test; + +using namespace WPEFramework; + +class DataCaptureTest : public Test { +protected: + Core::ProxyType dataCapture_; + Core::JSONRPC::Connection connection_; + Core::JSONRPC::Handler& handler_; + + DataCaptureTest() + : dataCapture_(Core::ProxyType::Create()) + , connection_(1, 0) + , handler_(*dataCapture_) + { + } + virtual ~DataCaptureTest() = default; +}; + +class DataCaptureInitializedTest : public DataCaptureTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + + DataCaptureInitializedTest() + : DataCaptureTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + + EXPECT_EQ(string(""), dataCapture_->Initialize(nullptr)); + } + virtual ~DataCaptureInitializedTest() override + { + dataCapture_->Deinitialize(nullptr); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + } +}; + +class DataCaptureInitializedEnableAudioCaptureTest : public DataCaptureInitializedTest { +protected: + DataCaptureInitializedEnableAudioCaptureTest() + : DataCaptureInitializedTest() + { + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_OPEN) == 0) { + auto* param = static_cast(arg); + param->session_id = 10; + param->result = 0; + } else if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_GET_OUTPUT_PROPS) == 0) { + auto* param = static_cast(arg); + param->details.arg_output_props.output.max_buffer_duration = 6; + param->result = 0; + } else if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_SET_OUTPUT_PROPERTIES) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } else if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_GET_AUDIO_PROPS) == 0) { + auto* param = static_cast(arg); + audiocapturemgr::audio_properties_ifce_t answer; + answer.format = acmFormate16BitStereo; + answer.sampling_frequency = acmFreqe48000; + param->details.arg_audio_properties = answer; + param->result = 0; + } else if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_START) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } + return IARM_RESULT_SUCCESS; + }); + + string response; + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("enableAudioCapture"), _T("{\"bufferMaxDuration\":6}"), response)); + EXPECT_EQ(response, _T("{\"error\":0,\"success\":true}")); + } + virtual ~DataCaptureInitializedEnableAudioCaptureTest() override = default; +}; + +class DataCaptureInitializedEnableAudioCaptureEventTest : public DataCaptureInitializedEnableAudioCaptureTest { +protected: + ServiceMock service_; + Core::JSONRPC::Message message_; + FactoriesImplementation factoriesImplementation_; + PluginHost::IDispatcher* dispatcher; + + DataCaptureInitializedEnableAudioCaptureEventTest() + : DataCaptureInitializedEnableAudioCaptureTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation_); + + dispatcher = static_cast( + dataCapture_->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service_); + } + virtual ~DataCaptureInitializedEnableAudioCaptureEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(DataCaptureTest, ShouldRegisterMethod) +{ + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("enableAudioCapture"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getAudioClip"))); +} + +TEST_F(DataCaptureTest, ShouldReturnErrorWhenParamsAreEmpty) +{ + string response; + EXPECT_EQ(Core::ERROR_GENERAL, handler_.Invoke(connection_, _T("enableAudioCapture"), _T(""), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler_.Invoke(connection_, _T("getAudioClip"), _T(""), response)); +} + +TEST_F(DataCaptureInitializedEnableAudioCaptureTest, ShouldTurnOnAudioCapture) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_REQUEST_SAMPLE) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } + return IARM_RESULT_SUCCESS; + }); + + string response; + EXPECT_EQ(Core::ERROR_NONE, + handler_.Invoke(connection_, + _T("getAudioClip"), + _T("{\"clipRequest\":{\"stream\":\"primary\",\"url\":\"https://192.168.0.1\",\"duration\":8,\"captureMode\":\"preCapture\"}}"), + response)); + EXPECT_EQ(response, _T("{\"error\":0,\"success\":true}")); +} + +TEST_F(DataCaptureInitializedEnableAudioCaptureTest, ShouldTurnOffAudioCapture) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_STOP) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } else if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_CLOSE) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } + return IARM_RESULT_SUCCESS; + }); + + string response; + // Turn off audio capture + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("enableAudioCapture"), _T("{\"bufferMaxDuration\":0}"), response)); + EXPECT_EQ(response, _T("{\"error\":0,\"success\":true}")); +} + +/** + * fails without valgrind + * 2022-12-22T13:10:14.1251887Z Expected equality of these values: +2022-12-22T13:10:14.1252364Z text +2022-12-22T13:10:14.1254516Z Which is: "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.dataCapture.onAudioClipReady\",\"params\":{\"fileName\":\"dataLocator123\",\"status\":false,\"message\":\"Upload Failed: 7:'Couldn't connect to server'\"}}" +2022-12-22T13:10:14.1256178Z string("{" "\"jsonrpc\":\"2.0\"," "\"method\":\"org.rdk.dataCapture.onAudioClipReady\"," "\"params\":{\"fileName\":\"dataLocator123\",\"status\":true,\"message\":\"Success\"}" "}") +2022-12-22T13:10:14.1257672Z Which is: "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.dataCapture.onAudioClipReady\",\"params\":{\"fileName\":\"dataLocator123\",\"status\":true,\"message\":\"Success\"}}" + */ +TEST_F(DataCaptureInitializedEnableAudioCaptureEventTest, DISABLED_ShouldUploadData) +{ + constexpr const char dataLocator[] = "dataLocator123"; + constexpr const char owner[] = "DataCaptureTest"; + + std::promise serverReady; + auto serverReadyFuture = serverReady.get_future(); + std::thread serverThread(runServer, std::move(serverReady)); + + std::promise socketReady; + auto socketReadyFuture = socketReady.get_future(); + std::thread socketThread(runSocket, std::move(socketReady), std::string(dataLocator)); + + // Wait for server and socket thread + serverReadyFuture.wait(); + socketReadyFuture.wait(); + + handler_.Subscribe(0, _T("onAudioClipReady"), _T("org.rdk.dataCapture"), message_); + + EXPECT_CALL(service_, Submit) + .WillOnce( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.dataCapture.onAudioClipReady\"," + "\"params\":{\"fileName\":\"dataLocator123\",\"status\":true,\"message\":\"Success\"}" + "}"))); + + return Core::ERROR_NONE; + }); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARMBUS_AUDIOCAPTUREMGR_REQUEST_SAMPLE) == 0) { + auto* param = static_cast(arg); + param->result = 0; + } + return IARM_RESULT_SUCCESS; + }); + + // setup http://127.0.0.1:9999 as url + string response; + EXPECT_EQ(Core::ERROR_NONE, + handler_.Invoke(connection_, + _T("getAudioClip"), + _T("{\"clipRequest\":{\"stream\":\"primary\",\"url\":\"http://127.0.0.1:9999\",\"duration\":8,\"captureMode\":\"preCapture\"}}"), + response)); + EXPECT_EQ(response, _T("{\"error\":0,\"success\":true}")); + + // Trigger event, curl message will be check by server thread + iarmbus_notification_payload_t data; + strncpy(data.dataLocator, dataLocator, sizeof(data.dataLocator)); + dataCapture_->eventHandler(owner, DATA_CAPTURE_IARM_EVENT_AUDIO_CLIP_READY, static_cast(&data), sizeof(data)); + + handler_.Unsubscribe(0, _T("onAudioClipReady"), _T("org.rdk.dataCapture"), message_); + + serverThread.join(); + socketThread.join(); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceAudioCapabilities.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceAudioCapabilities.cpp new file mode 100755 index 0000000000..f087ff394f --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceAudioCapabilities.cpp @@ -0,0 +1,257 @@ +#include + +#include "Implementation/DeviceAudioCapabilities.h" + +#include "AudioOutputPortMock.h" +#include "HostMock.h" +#include "IarmBusMock.h" +#include "ManagerMock.h" + +#include "exception.hpp" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class DeviceAudioCapabilitiesTest : public ::testing::Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + Core::ProxyType deviceAudioCapabilities; + Exchange::IDeviceAudioCapabilities* interface; + + DeviceAudioCapabilitiesTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_managerImplMock = new NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + EXPECT_CALL(*p_managerImplMock, Initialize()) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Return()); + + deviceAudioCapabilities = Core::ProxyType::Create(); + + interface = static_cast( + deviceAudioCapabilities->QueryInterface(Exchange::IDeviceAudioCapabilities::ID)); + } + + virtual ~DeviceAudioCapabilitiesTest() + { + interface->Release(); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +class DeviceAudioCapabilitiesDsTest : public DeviceAudioCapabilitiesTest { +protected: + HostImplMock *p_hostImplMock = nullptr ; + AudioOutputPortMock *p_audioOutputPortMock = nullptr ; + + DeviceAudioCapabilitiesDsTest() + : DeviceAudioCapabilitiesTest() + { + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + p_audioOutputPortMock = new NiceMock ; + device::AudioOutputPort::setImpl(p_audioOutputPortMock); + } + virtual ~DeviceAudioCapabilitiesDsTest() override + { + device::AudioOutputPort::setImpl(nullptr); + if (p_audioOutputPortMock != nullptr) + { + delete p_audioOutputPortMock; + p_audioOutputPortMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +TEST_F(DeviceAudioCapabilitiesDsTest, SupportedAudioPorts) +{ + device::AudioOutputPort audioOutputPort; + RPC::IStringIterator* supportedAudioPorts = nullptr; + string audioPort(_T("HDMI0")); + string element; + + ON_CALL(*p_audioOutputPortMock, getName()) + .WillByDefault(::testing::ReturnRef(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPorts()) + .WillByDefault(::testing::Return(device::List({ audioOutputPort }))); + + EXPECT_EQ(Core::ERROR_NONE, interface->SupportedAudioPorts(supportedAudioPorts)); + ASSERT_TRUE(supportedAudioPorts != nullptr); + ASSERT_TRUE(supportedAudioPorts->Next(element)); + EXPECT_EQ(element, audioPort); + + supportedAudioPorts->Release(); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, AudioCapabilities_noParam) +{ + device::AudioOutputPort audioOutputPort; + Exchange::IDeviceAudioCapabilities::IAudioCapabilityIterator* audioCapabilities = nullptr; + string audioPort(_T("HDMI0")); + Exchange::IDeviceAudioCapabilities::AudioCapability element; + + ON_CALL(*p_audioOutputPortMock, getAudioCapabilities(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int* capabilities) { + ASSERT_TRUE(capabilities != nullptr); + EXPECT_EQ(*capabilities, dsAUDIOSUPPORT_NONE); + *capabilities = dsAUDIOSUPPORT_ATMOS | dsAUDIOSUPPORT_DDPLUS; + })); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, interface->AudioCapabilities(string(), audioCapabilities)); + ASSERT_TRUE(audioCapabilities != nullptr); + ASSERT_TRUE(audioCapabilities->Next(element)); + EXPECT_EQ(element, Exchange::IDeviceAudioCapabilities::AudioCapability::ATMOS); + ASSERT_TRUE(audioCapabilities->Next(element)); + EXPECT_EQ(element, Exchange::IDeviceAudioCapabilities::AudioCapability::DDPLUS); + + audioCapabilities->Release(); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, MS12Capabilities_noParam) +{ + device::AudioOutputPort audioOutputPort; + Exchange::IDeviceAudioCapabilities::IMS12CapabilityIterator* ms12Capabilities = nullptr; + string audioPort(_T("HDMI0")); + Exchange::IDeviceAudioCapabilities::MS12Capability element; + + ON_CALL(*p_audioOutputPortMock, getMS12Capabilities(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int* capabilities) { + ASSERT_TRUE(capabilities != nullptr); + EXPECT_EQ(*capabilities, dsMS12SUPPORT_NONE); + *capabilities = dsMS12SUPPORT_DolbyVolume | dsMS12SUPPORT_InteligentEqualizer; + })); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, interface->MS12Capabilities(string(), ms12Capabilities)); + ASSERT_TRUE(ms12Capabilities != nullptr); + ASSERT_TRUE(ms12Capabilities->Next(element)); + EXPECT_EQ(element, Exchange::IDeviceAudioCapabilities::MS12Capability::DOLBYVOLUME); + ASSERT_TRUE(ms12Capabilities->Next(element)); + EXPECT_EQ(element, Exchange::IDeviceAudioCapabilities::MS12Capability::INTELIGENTEQUALIZER); + + ms12Capabilities->Release(); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, SupportedMS12AudioProfiles_noParam) +{ + device::AudioOutputPort audioOutputPort; + RPC::IStringIterator* supportedMS12AudioProfiles = nullptr; + string audioPort(_T("HDMI0")); + string audioPortMS12AudioProfile(_T("Movie")); + string element; + + ON_CALL(*p_audioOutputPortMock, getMS12AudioProfileList()) + .WillByDefault(::testing::Return(std::vector({ audioPortMS12AudioProfile }))); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, interface->SupportedMS12AudioProfiles(string(), supportedMS12AudioProfiles)); + ASSERT_TRUE(supportedMS12AudioProfiles != nullptr); + ASSERT_TRUE(supportedMS12AudioProfiles->Next(element)); + EXPECT_EQ(element, audioPortMS12AudioProfile); + + supportedMS12AudioProfiles->Release(); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, SupportedAudioPorts_exception) +{ + RPC::IStringIterator* supportedAudioPorts = nullptr; + + ON_CALL(*p_hostImplMock, getAudioOutputPorts()) + .WillByDefault(::testing::Invoke( + [&]() -> device::List { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->SupportedAudioPorts(supportedAudioPorts)); + EXPECT_EQ(supportedAudioPorts, nullptr); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, AudioCapabilities_HDMI0_exception) +{ + Exchange::IDeviceAudioCapabilities::IAudioCapabilityIterator* audioCapabilities = nullptr; + + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::AudioOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->AudioCapabilities(string(_T("HDMI0")), audioCapabilities)); + EXPECT_EQ(audioCapabilities, nullptr); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, MS12Capabilities_HDMI0_exception) +{ + Exchange::IDeviceAudioCapabilities::IMS12CapabilityIterator* ms12Capabilities = nullptr; + + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::AudioOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->MS12Capabilities(string(_T("HDMI0")), ms12Capabilities)); + EXPECT_EQ(ms12Capabilities, nullptr); +} + +TEST_F(DeviceAudioCapabilitiesDsTest, SupportedMS12AudioProfiles_HDMI0_exception) +{ + RPC::IStringIterator* supportedMS12AudioProfiles = nullptr; + + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::AudioOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->SupportedMS12AudioProfiles(string(_T("HDMI0")), supportedMS12AudioProfiles)); + EXPECT_EQ(supportedMS12AudioProfiles, nullptr); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceDiagnostics.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceDiagnostics.cpp new file mode 100755 index 0000000000..eedebcb130 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceDiagnostics.cpp @@ -0,0 +1,89 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" + +#include "DeviceDiagnostics.h" + +using namespace WPEFramework; + +class DeviceDiagnosticsTest : public ::testing::Test { +protected: + Core::ProxyType deviceDiagnostic_; + Core::JSONRPC::Handler& handler_; + string response; + Core::JSONRPC::Connection connection_; + + DeviceDiagnosticsTest() + : deviceDiagnostic_(Core::ProxyType::Create()) + , handler_(*deviceDiagnostic_) + , connection_(1, 0) + { + } +}; + +TEST_F(DeviceDiagnosticsTest, RegisterMethod) +{ + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getConfiguration"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getAVDecoderStatus"))); +} + +/** + * fails without valgrind + * 2022-12-22T13:10:15.1620146Z Value of: bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0 +2022-12-22T13:10:15.1620468Z Actual: true +2022-12-22T13:10:15.1620732Z Expected: false +2022-12-22T13:10:15.1635528Z [ FAILED ] DeviceDiagnosticsTest.getConfiguration (9 ms) + */ +TEST_F(DeviceDiagnosticsTest, DISABLED_getConfiguration) +{ + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + ASSERT_TRUE(sockfd != -1); + sockaddr_in sockaddr; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = INADDR_ANY; + sockaddr.sin_port = htons(10999); + ASSERT_FALSE(bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0); + ASSERT_FALSE(listen(sockfd, 10) < 0); + + std::thread thread = std::thread([&]() { + auto addrlen = sizeof(sockaddr); + const int connection = accept(sockfd, (struct sockaddr*)&sockaddr, (socklen_t*)&addrlen); + ASSERT_FALSE(connection < 0); + char buffer[2048] = { 0 }; + ASSERT_TRUE(read(connection, buffer, 2048) > 0); + EXPECT_EQ(string(buffer), string(_T("POST / HTTP/1.1\r\nHost: 127.0.0.1:10999\r\nAccept: */*\r\nContent-Length: 31\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n{\"paramList\":[{\"name\":\"test\"}]}"))); + std::string response = _T("HTTP/1.1 200\n\rContent-type: application/json\n\r{\"paramList\":[\"Device.X_CISCO_COM_LED.RedPwm\":123],\"success\":true}"); + send(connection, response.c_str(), response.size(), 0); + close(connection); + }); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("getConfiguration"), _T("{\"names\":[\"test\"]}"), response)); + EXPECT_EQ(response, _T("{\"paramList\":[\"Device.X_CISCO_COM_LED.RedPwm\":123],\"success\":true}")); + + thread.join(); + + close(sockfd); +} + +TEST_F(DeviceDiagnosticsTest, getAVDecoderStatus) +{ + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("getAVDecoderStatus"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"avDecoderStatus\":\"IDLE\",\"success\":true}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceIdentification.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceIdentification.cpp new file mode 100755 index 0000000000..7fc8b1b908 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceIdentification.cpp @@ -0,0 +1,107 @@ +#include + +#include "DeviceIdentification.h" + +#include "COMLinkMock.h" +#include "ServiceMock.h" +#include "SystemInfo.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string testArchitecture = _T("testArchitecture"); +const string testChipset = _T("testChipset"); +const string testFirmwareVersion = _T("testFirmwareVersion"); +const string testId = _T("testIdentity"); +const string deviceId = _T("WPEdGVzdElkZW50aXR5"); +} + +namespace WPEFramework { +namespace Plugin { + class DeviceImplementation : public PluginHost::ISubSystem::IIdentifier { + public: + virtual ~DeviceImplementation() = default; + + string Architecture() const override { return testArchitecture; } + string Chipset() const override { return testChipset; } + string FirmwareVersion() const override { return testFirmwareVersion; } + uint8_t Identifier(const uint8_t length, uint8_t buffer[]) const override + { + ::memcpy(buffer, testId.c_str(), testId.length()); + + return testId.length(); + } + + BEGIN_INTERFACE_MAP(DeviceImplementation) + INTERFACE_ENTRY(PluginHost::ISubSystem::IIdentifier) + END_INTERFACE_MAP + }; + + SERVICE_REGISTRATION(DeviceImplementation, 1, 0); +} +} + +class DeviceIdentificationTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + DeviceIdentificationTest() + : plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + } + virtual ~DeviceIdentificationTest() + { + } +}; + +class DeviceIdentificationInitializedTest : public DeviceIdentificationTest { +protected: + Core::Sink> subSystem; + NiceMock service; + NiceMock comLinkMock; + + DeviceIdentificationInitializedTest() + : DeviceIdentificationTest() + { + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\n" + " \"root\":{\n" + " \"outofprocess\":false\n" + " }\n" + "}")); + ON_CALL(service, SubSystems()) + .WillByDefault(::testing::Invoke( + [&]() { + PluginHost::ISubSystem* result = (&subSystem); + result->AddRef(); + return result; + })); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~DeviceIdentificationInitializedTest() override + { + plugin->Deinitialize(&service); + } +}; + +TEST_F(DeviceIdentificationInitializedTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("deviceidentification"))); +} + +TEST_F(DeviceIdentificationInitializedTest, deviceidentification) +{ + EXPECT_TRUE(subSystem.Get(PluginHost::ISubSystem::IDENTIFIER) != nullptr); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("deviceidentification"), _T(""), response)); + EXPECT_EQ(response, _T("{\"firmwareversion\":\"testFirmwareVersion\",\"chipset\":\"testChipset\",\"deviceid\":\"WPEdGVzdElkZW50aXR5\"}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceInfo.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfo.cpp new file mode 100755 index 0000000000..498ff55a4a --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfo.cpp @@ -0,0 +1,82 @@ +#include + +#include "Implementation/DeviceInfo.h" + +#include "IarmBusMock.h" + +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class DeviceInfoTest : public ::testing::Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + Core::ProxyType deviceInfoImplementation; + Exchange::IDeviceInfo* interface; + + DeviceInfoTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + deviceInfoImplementation = Core::ProxyType::Create(); + + interface = static_cast( + deviceInfoImplementation->QueryInterface(Exchange::IDeviceInfo::ID)); + } + virtual ~DeviceInfoTest() + { + interface->Release(); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +TEST_F(DeviceInfoTest, Make) +{ + std::ofstream file("/etc/device.properties"); + file << "MFG_NAME=Pace"; + file.close(); + + string make; + EXPECT_EQ(Core::ERROR_NONE, interface->Make(make)); + EXPECT_EQ(make, _T("Pace")); +} + +TEST_F(DeviceInfoTest, Model) +{ + std::ofstream file("/etc/device.properties"); + file << "FRIENDLY_ID=\"Pace Xi5\""; + file.close(); + + string model; + EXPECT_EQ(Core::ERROR_NONE, interface->Model(model)); + EXPECT_EQ(model, _T("Pace Xi5")); +} + +TEST_F(DeviceInfoTest, DeviceType) +{ + std::ofstream file("/etc/authService.conf"); + file << "deviceType=IpStb"; + file.close(); + + string deviceType; + EXPECT_EQ(Core::ERROR_NONE, interface->DeviceType(deviceType)); + EXPECT_EQ(deviceType, _T("IpStb")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoJsonRpc.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoJsonRpc.cpp new file mode 100755 index 0000000000..b512131de1 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoJsonRpc.cpp @@ -0,0 +1,438 @@ +#include + +#include "DeviceInfo.h" + +#include "AudioOutputPortMock.h" +#include "HostMock.h" +#include "IarmBusMock.h" +#include "ManagerMock.h" +#include "ServiceMock.h" +#include "VideoOutputPortConfigMock.h" +#include "VideoOutputPortMock.h" +#include "VideoOutputPortTypeMock.h" +#include "VideoResolutionMock.h" + +#include "SystemInfo.h" + +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string webPrefix = _T("/Service/DeviceInfo"); +} + +class DeviceInfoJsonRpcTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + DeviceInfoJsonRpcTest() + : plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + } + virtual ~DeviceInfoJsonRpcTest() = default; +}; + +class DeviceInfoJsonRpcInitializedTest : public DeviceInfoJsonRpcTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + NiceMock service; + Core::Sink> subSystem; + + DeviceInfoJsonRpcInitializedTest() + : DeviceInfoJsonRpcTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_managerImplMock = new NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\"root\":{\"mode\":\"Off\"}}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, SubSystems()) + .WillByDefault(::testing::Invoke( + [&]() { + PluginHost::ISubSystem* result = (&subSystem); + result->AddRef(); + return result; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~DeviceInfoJsonRpcInitializedTest() override + { + plugin->Deinitialize(&service); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + } +}; + +class DeviceInfoJsonRpcInitializedDsTest : public DeviceInfoJsonRpcInitializedTest { +protected: + HostImplMock *p_hostImplMock = nullptr ; + AudioOutputPortMock *p_audioOutputPortMock = nullptr ; + VideoResolutionMock *p_videoResolutionMock = nullptr ; + VideoOutputPortMock *p_videoOutputPortMock = nullptr ; + + DeviceInfoJsonRpcInitializedDsTest() + : DeviceInfoJsonRpcInitializedTest() + { + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + p_audioOutputPortMock = new NiceMock ; + device::AudioOutputPort::setImpl(p_audioOutputPortMock); + + p_videoResolutionMock = new NiceMock ; + device::VideoResolution::setImpl(p_videoResolutionMock); + p_videoOutputPortMock = new NiceMock ; + device::VideoOutputPort::setImpl(p_videoOutputPortMock); + } + virtual ~DeviceInfoJsonRpcInitializedDsTest() override + { + device::AudioOutputPort::setImpl(nullptr); + if (p_audioOutputPortMock != nullptr) + { + delete p_audioOutputPortMock; + p_audioOutputPortMock = nullptr; + } + device::VideoResolution::setImpl(nullptr); + if (p_videoResolutionMock != nullptr) + { + delete p_videoResolutionMock; + p_videoResolutionMock = nullptr; + } + device::VideoOutputPort::setImpl(nullptr); + if (p_videoOutputPortMock != nullptr) + { + delete p_videoOutputPortMock; + p_videoOutputPortMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +class DeviceInfoJsonRpcInitializedDsVideoOutputTest : public DeviceInfoJsonRpcInitializedDsTest { +protected: + VideoOutputPortConfigImplMock *p_videoOutputPortConfigImplMock = nullptr ; + VideoOutputPortTypeMock *p_videoOutputPortTypeMock = nullptr ; + + DeviceInfoJsonRpcInitializedDsVideoOutputTest() + : DeviceInfoJsonRpcInitializedDsTest() + { + p_videoOutputPortConfigImplMock = new NiceMock ; + device::VideoOutputPortConfig::setImpl(p_videoOutputPortConfigImplMock); + p_videoOutputPortTypeMock = new NiceMock ; + device::VideoOutputPortType::setImpl(p_videoOutputPortTypeMock); + } + virtual ~DeviceInfoJsonRpcInitializedDsVideoOutputTest() override + { + device::VideoOutputPortType::setImpl(nullptr); + if (p_videoOutputPortTypeMock != nullptr) + { + delete p_videoOutputPortTypeMock; + p_videoOutputPortTypeMock = nullptr; + } + device::VideoOutputPortConfig::setImpl(nullptr); + if (p_videoOutputPortConfigImplMock != nullptr) + { + delete p_videoOutputPortConfigImplMock; + p_videoOutputPortConfigImplMock = nullptr; + } + } +}; + +TEST_F(DeviceInfoJsonRpcTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("socketinfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addresses"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("systeminfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("firmwareversion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("serialnumber"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("modelid"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("make"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("modelname"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("devicetype"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("distributorid"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("supportedaudioports"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("supportedvideodisplays"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("hostedid"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("defaultresolution"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("supportedresolutions"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("supportedhdcp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("audiocapabilities"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("ms12capabilities"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("supportedms12audioprofiles"))); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, systeminfo) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("systeminfo"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"version\":\"#\"," + "\"uptime\":[0-9]+," + "\"totalram\":[0-9]+," + "\"freeram\":[0-9]+," + "\"totalswap\":[0-9]+," + "\"freeswap\":[0-9]+," + "\"devicename\":\".+\"," + "\"cpuload\":\"[0-9]+\"," + "\"cpuloadavg\":" + "\\{" + "\"avg1min\":[0-9]+," + "\"avg5min\":[0-9]+," + "\"avg15min\":[0-9]+" + "\\}," + "\"serialnumber\":\".+\"," + "\"time\":\".+\"" + "\\}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, addresses) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("addresses"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\[" + "(\\{" + "\"name\":\"[^\"]+\"," + "\"mac\":\"[^\"]+\"" + "(,\"ip\":\\[(\"[^\"]+\",{0,1}){1,}\\]){0,1}" + "\\},{0,1}){0,}" + "\\]")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, socketinfo) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("socketinfo"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"runs\":[0-9]+\\}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, firmwareversion) +{ + std::ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\nSDK_VERSION=17.3\nMEDIARITE=8.3.53\nYOCTO_VERSION=dunfell\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("firmwareversion"), _T(""), response)); + EXPECT_EQ(response, _T("{\"imagename\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\",\"sdk\":\"17.3\",\"mediarite\":\"8.3.53\",\"yocto\":\"dunfell\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, make) +{ + std::ofstream file("/etc/device.properties"); + file << "MFG_NAME=Pace\nFRIENDLY_ID=\"Pace Xi5\"\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("make"), _T(""), response)); + EXPECT_EQ(response, _T("{\"make\":\"pace\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, modelname) +{ + std::ofstream file("/etc/device.properties"); + file << "MFG_NAME=Pace\nFRIENDLY_ID=\"Pace Xi5\"\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("modelname"), _T(""), response)); + EXPECT_EQ(response, _T("{\"model\":\"Pace Xi5\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedTest, devicetype) +{ + std::ofstream file("/etc/authService.conf"); + file << "deviceType=IpStb"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("devicetype"), _T(""), response)); + EXPECT_EQ(response, _T("{\"devicetype\":\"IpStb\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, supportedaudioports) +{ + device::AudioOutputPort audioOutputPort; + string audioPort(_T("HDMI0")); + + ON_CALL(*p_audioOutputPortMock, getName()) + .WillByDefault(::testing::ReturnRef(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPorts()) + .WillByDefault(::testing::Return(device::List({ audioOutputPort }))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("supportedaudioports"), _T(""), response)); + EXPECT_EQ(response, _T("{\"supportedAudioPorts\":[\"HDMI0\"]}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, supportedvideodisplays) +{ + device::VideoOutputPort videoOutputPort; + string videoPort(_T("HDMI0")); + + ON_CALL(*p_videoOutputPortMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPorts()) + .WillByDefault(::testing::Return(device::List({ videoOutputPort }))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("supportedvideodisplays"), _T(""), response)); + EXPECT_EQ(response, _T("{\"supportedVideoDisplays\":[\"HDMI0\"]}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, hostedid) +{ + ON_CALL(*p_hostImplMock, getHostEDID(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector& edid) { + edid = { 't', 'e', 's', 't' }; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("hostedid"), _T(""), response)); + EXPECT_EQ(response, _T("{\"EDID\":\"dGVzdA==\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, defaultresolution) +{ + device::VideoOutputPort videoOutputPort; + device::VideoResolution videoResolution; + string videoPort(_T("HDMI0")); + string videoPortDefaultResolution(_T("1080p")); + + ON_CALL(*p_videoResolutionMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPortDefaultResolution)); + ON_CALL(*p_videoOutputPortMock, getDefaultResolution()) + .WillByDefault(::testing::ReturnRef(videoResolution)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("defaultresolution"), _T(""), response)); + EXPECT_EQ(response, _T("{\"defaultResolution\":\"1080p\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsVideoOutputTest, supportedresolutions) +{ + device::VideoOutputPort videoOutputPort; + device::VideoOutputPortType videoOutputPortType; + device::VideoResolution videoResolution; + string videoPort(_T("HDMI0")); + string videoPortSupportedResolution(_T("1080p")); + + ON_CALL(*p_videoResolutionMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPortSupportedResolution)); + ON_CALL(*p_videoOutputPortTypeMock, getSupportedResolutions()) + .WillByDefault(::testing::Return(device::List({ videoResolution }))); + ON_CALL(*p_videoOutputPortTypeMock, getId()) + .WillByDefault(::testing::Return(0)); + ON_CALL(*p_videoOutputPortMock, getType()) + .WillByDefault(::testing::ReturnRef(videoOutputPortType)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPortType(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPortType)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("supportedresolutions"), _T(""), response)); + EXPECT_EQ(response, _T("{\"supportedResolutions\":[\"1080p\"]}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsVideoOutputTest, supportedhdcp) +{ + device::VideoOutputPort videoOutputPort; + string videoPort(_T("HDMI0")); + + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("supportedhdcp"), _T(""), response)); + EXPECT_EQ(response, _T("{\"supportedHDCPVersion\":\"2.2\"}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, audiocapabilities) +{ + device::AudioOutputPort audioOutputPort; + + string audioPort(_T("HDMI0")); + + ON_CALL(*p_audioOutputPortMock, getAudioCapabilities(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int* capabilities) { + ASSERT_TRUE(capabilities != nullptr); + EXPECT_EQ(*capabilities, dsAUDIOSUPPORT_NONE); + *capabilities = dsAUDIOSUPPORT_ATMOS | dsAUDIOSUPPORT_DD | dsAUDIOSUPPORT_DDPLUS | dsAUDIOSUPPORT_DAD | dsAUDIOSUPPORT_DAPv2 | dsAUDIOSUPPORT_MS12; + })); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("audiocapabilities"), _T(""), response)); + EXPECT_EQ(response, _T("{\"AudioCapabilities\":[\"ATMOS\",\"DOLBY DIGITAL\",\"DOLBY DIGITAL PLUS\",\"Dual Audio Decode\",\"DAPv2\",\"MS12\"]}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, ms12capabilities) +{ + device::AudioOutputPort audioOutputPort; + + string audioPort(_T("HDMI0")); + + ON_CALL(*p_audioOutputPortMock, getMS12Capabilities(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int* capabilities) { + ASSERT_TRUE(capabilities != nullptr); + EXPECT_EQ(*capabilities, dsMS12SUPPORT_NONE); + *capabilities = dsMS12SUPPORT_DolbyVolume | dsMS12SUPPORT_InteligentEqualizer | dsMS12SUPPORT_DialogueEnhancer; + })); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ms12capabilities"), _T(""), response)); + EXPECT_EQ(response, _T("{\"MS12Capabilities\":[\"Dolby Volume\",\"Inteligent Equalizer\",\"Dialogue Enhancer\"]}")); +} + +TEST_F(DeviceInfoJsonRpcInitializedDsTest, supportedms12audioprofiles) +{ + device::AudioOutputPort audioOutputPort; + + string audioPort(_T("HDMI0")); + string audioPortMS12AudioProfile(_T("Movie")); + + ON_CALL(*p_audioOutputPortMock, getMS12AudioProfileList()) + .WillByDefault(::testing::Return(std::vector({ audioPortMS12AudioProfile }))); + ON_CALL(*p_hostImplMock, getDefaultAudioPortName()) + .WillByDefault(::testing::Return(audioPort)); + ON_CALL(*p_hostImplMock, getAudioOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(audioOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("supportedms12audioprofiles"), _T(""), response)); + EXPECT_EQ(response, _T("{\"supportedMS12AudioProfiles\":[\"Movie\"]}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoWeb.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoWeb.cpp new file mode 100755 index 0000000000..f94f1976f9 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceInfoWeb.cpp @@ -0,0 +1,241 @@ +#include + +#include "DeviceInfo.h" + +#include "IarmBusMock.h" +#include "ManagerMock.h" +#include "ServiceMock.h" + +#include "FactoriesImplementation.h" +#include "SystemInfo.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string webPrefix = _T("/Service/DeviceInfo"); +} + +class DeviceInfoWebTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + PluginHost::IWeb* interface; + + DeviceInfoWebTest() + : plugin(Core::ProxyType::Create()) + { + interface = static_cast(plugin->QueryInterface(PluginHost::IWeb::ID)); + } + virtual ~DeviceInfoWebTest() + { + interface->Release(); + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +class DeviceInfoWebInitializedTest : public DeviceInfoWebTest { +protected: + NiceMock factoriesImplementation; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + NiceMock service; + Core::Sink> subSystem; + + DeviceInfoWebInitializedTest() + : DeviceInfoWebTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_managerImplMock = new NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\"root\":{\"mode\":\"Off\"}}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, SubSystems()) + .WillByDefault(::testing::Invoke( + [&]() { + PluginHost::ISubSystem* result = (&subSystem); + result->AddRef(); + return result; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~DeviceInfoWebInitializedTest() override + { + plugin->Deinitialize(&service); + + PluginHost::IFactories::Assign(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + } +}; + +TEST_F(DeviceInfoWebInitializedTest, httpGet) +{ + Web::Request request; + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix; + + auto response = interface->Process(request); + ASSERT_TRUE(response.IsValid()); + + EXPECT_EQ(response->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(response->Message, "OK"); + EXPECT_EQ(response->ContentType, Web::MIMETypes::MIME_JSON); + + auto body = response->Body>(); + ASSERT_TRUE(body.IsValid()); + + string bodyStr; + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"addresses\":" + "\\[" + "(\\{" + "\"name\":\"[^\"]+\"," + "\"mac\":\"[^\"]+\"" + "(,\"ip\":\\[(\"[^\"]+\",{0,1}){1,}\\]){0,1}" + "\\},{0,1}){0,}" + "\\]," + "\"systeminfo\":" + "\\{" + "\"version\":\"#\"," + "\"uptime\":[0-9]+," + "\"totalram\":[0-9]+," + "\"freeram\":[0-9]+," + "\"totalswap\":[0-9]+," + "\"freeswap\":[0-9]+," + "\"devicename\":\".+\"," + "\"cpuload\":\"[0-9]+\"," + "\"cpuloadavg\":" + "\\{" + "\"avg1min\":[0-9]+," + "\"avg5min\":[0-9]+," + "\"avg15min\":[0-9]+" + "\\}," + "\"serialnumber\":\".+\"," + "\"time\":\".+\"" + "\\}," + "\"sockets\":" + "\\{\"runs\":[0-9]+\\}" + "\\}")); +} + +TEST_F(DeviceInfoWebInitializedTest, httpGetAdresses) +{ + Web::Request request; + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix + _T("/Adresses"); + + auto response = interface->Process(request); + ASSERT_TRUE(response.IsValid()); + + EXPECT_EQ(response->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(response->Message, "OK"); + EXPECT_EQ(response->ContentType, Web::MIMETypes::MIME_JSON); + + auto body = response->Body>(); + ASSERT_TRUE(body.IsValid()); + + string bodyStr; + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"addresses\":" + "\\[" + "(\\{" + "\"name\":\"[^\"]+\"," + "\"mac\":\"[^\"]+\"" + "(,\"ip\":\\[(\"[^\"]+\",{0,1}){1,}\\]){0,1}" + "\\},{0,1}){0,}" + "\\]" + "\\}")); +} + +TEST_F(DeviceInfoWebInitializedTest, httpGetSystem) +{ + Web::Request request; + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix + _T("/System"); + + auto response = interface->Process(request); + ASSERT_TRUE(response.IsValid()); + + EXPECT_EQ(response->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(response->Message, "OK"); + EXPECT_EQ(response->ContentType, Web::MIMETypes::MIME_JSON); + + auto body = response->Body>(); + ASSERT_TRUE(body.IsValid()); + + string bodyStr; + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"systeminfo\":" + "\\{" + "\"version\":\"#\"," + "\"uptime\":[0-9]+," + "\"totalram\":[0-9]+," + "\"freeram\":[0-9]+," + "\"totalswap\":[0-9]+," + "\"freeswap\":[0-9]+," + "\"devicename\":\".+\"," + "\"cpuload\":\"[0-9]+\"," + "\"cpuloadavg\":" + "\\{" + "\"avg1min\":[0-9]+," + "\"avg5min\":[0-9]+," + "\"avg15min\":[0-9]+" + "\\}," + "\"serialnumber\":\".+\"," + "\"time\":\".+\"" + "\\}" + "\\}")); +} + +TEST_F(DeviceInfoWebInitializedTest, httpGetSockets) +{ + Web::Request request; + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix + _T("/Sockets"); + + auto response = interface->Process(request); + ASSERT_TRUE(response.IsValid()); + + EXPECT_EQ(response->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(response->Message, "OK"); + EXPECT_EQ(response->ContentType, Web::MIMETypes::MIME_JSON); + + auto body = response->Body>(); + ASSERT_TRUE(body.IsValid()); + + string bodyStr; + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"sockets\":" + "\\{\"runs\":[0-9]+\\}" + "\\}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_DeviceVideoCapabilities.cpp b/NetworkManager/Tests/L1Tests/tests/test_DeviceVideoCapabilities.cpp new file mode 100755 index 0000000000..43818dce9c --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_DeviceVideoCapabilities.cpp @@ -0,0 +1,312 @@ +#include + +#include "Implementation/DeviceVideoCapabilities.h" + +#include "HostMock.h" +#include "IarmBusMock.h" +#include "ManagerMock.h" +#include "VideoOutputPortConfigMock.h" +#include "VideoOutputPortMock.h" +#include "VideoOutputPortTypeMock.h" +#include "VideoResolutionMock.h" + +#include "exception.hpp" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class DeviceVideoCapabilitiesTest : public ::testing::Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + Core::ProxyType deviceVideoCapabilities; + Exchange::IDeviceVideoCapabilities* interface; + + DeviceVideoCapabilitiesTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_managerImplMock = new NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + EXPECT_CALL(*p_managerImplMock, Initialize()) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Return()); + + deviceVideoCapabilities = Core::ProxyType::Create(); + + interface = static_cast( + deviceVideoCapabilities->QueryInterface(Exchange::IDeviceVideoCapabilities::ID)); + } + virtual ~DeviceVideoCapabilitiesTest() + { + interface->Release(); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +class DeviceVideoCapabilitiesDsTest : public DeviceVideoCapabilitiesTest { +protected: + HostImplMock *p_hostImplMock = nullptr ; + VideoOutputPortConfigImplMock *p_videoOutputPortConfigImplMock = nullptr ; + VideoOutputPortTypeMock *p_videoOutputPortTypeMock = nullptr ; + VideoOutputPortMock *p_videoOutputPortMock = nullptr ; + VideoResolutionMock *p_videoResolutionMock = nullptr ; + + DeviceVideoCapabilitiesDsTest() + : DeviceVideoCapabilitiesTest() + { + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + + p_videoOutputPortConfigImplMock = new NiceMock ; + device::VideoOutputPortConfig::setImpl(p_videoOutputPortConfigImplMock); + + p_videoOutputPortTypeMock = new NiceMock ; + device::VideoOutputPortType::setImpl(p_videoOutputPortTypeMock); + + p_videoResolutionMock = new NiceMock ; + device::VideoResolution::setImpl(p_videoResolutionMock); + + p_videoOutputPortMock = new NiceMock ; + device::VideoOutputPort::setImpl(p_videoOutputPortMock); + } + virtual ~DeviceVideoCapabilitiesDsTest() override + { + device::VideoResolution::setImpl(nullptr); + if (p_videoResolutionMock != nullptr) + { + delete p_videoResolutionMock; + p_videoResolutionMock = nullptr; + } + device::VideoOutputPortType::setImpl(nullptr); + if (p_videoOutputPortTypeMock != nullptr) + { + delete p_videoOutputPortTypeMock; + p_videoOutputPortTypeMock = nullptr; + } + device::VideoOutputPort::setImpl(nullptr); + if (p_videoOutputPortMock != nullptr) + { + delete p_videoOutputPortMock; + p_videoOutputPortMock = nullptr; + } + device::VideoOutputPortConfig::setImpl(nullptr); + if (p_videoOutputPortConfigImplMock != nullptr) + { + delete p_videoOutputPortConfigImplMock; + p_videoOutputPortConfigImplMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedVideoDisplays) +{ + device::VideoOutputPort videoOutputPort; + RPC::IStringIterator* supportedVideoDisplays = nullptr; + string videoPort(_T("HDMI0")); + string element; + + ON_CALL(*p_videoOutputPortMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPorts()) + .WillByDefault(::testing::Return(device::List({ videoOutputPort }))); + + EXPECT_EQ(Core::ERROR_NONE, interface->SupportedVideoDisplays(supportedVideoDisplays)); + ASSERT_TRUE(supportedVideoDisplays != nullptr); + ASSERT_TRUE(supportedVideoDisplays->Next(element)); + EXPECT_EQ(element, videoPort); + + supportedVideoDisplays->Release(); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, HostEDID) +{ + string edid; + + ON_CALL(*p_hostImplMock, getHostEDID(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector& edid) { + edid = { 't', 'e', 's', 't' }; + })); + + EXPECT_EQ(Core::ERROR_NONE, interface->HostEDID(edid)); + EXPECT_EQ(edid, _T("dGVzdA==")); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, DefaultResolution_noParam) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + device::VideoResolution videoResolution; + string videoPort(_T("HDMI0")); + string videoPortDefaultResolution(_T("1080p")); + string defaultResolution; + + ON_CALL(*p_videoResolutionMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPortDefaultResolution)); + ON_CALL(*p_videoOutputPortMock, getDefaultResolution()) + .WillByDefault(::testing::ReturnRef(videoResolution)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, interface->DefaultResolution(string(), defaultResolution)); + EXPECT_EQ(defaultResolution, videoPortDefaultResolution); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedResolutions_noParam) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + device::VideoOutputPortType videoOutputPortType; + device::VideoResolution videoResolution; + RPC::IStringIterator* supportedResolutions = nullptr; + string videoPort(_T("HDMI0")); + string videoPortSupportedResolution(_T("1080p")); + string element; + + ON_CALL(*p_videoResolutionMock, getName()) + .WillByDefault(::testing::ReturnRef(videoPortSupportedResolution)); + ON_CALL(*p_videoOutputPortTypeMock, getSupportedResolutions()) + .WillByDefault(::testing::Return(device::List({ videoResolution }))); + ON_CALL(*p_videoOutputPortTypeMock, getId()) + .WillByDefault(::testing::Return(0)); + ON_CALL(*p_videoOutputPortMock, getType()) + .WillByDefault(::testing::ReturnRef(videoOutputPortType)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPortType(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPortType)); + + EXPECT_EQ(Core::ERROR_NONE, interface->SupportedResolutions(string(), supportedResolutions)); + ASSERT_TRUE(supportedResolutions != nullptr); + ASSERT_TRUE(supportedResolutions->Next(element)); + EXPECT_EQ(element, videoPortSupportedResolution); + + supportedResolutions->Release(); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedHdcp_noParam) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + string videoPort(_T("HDMI0")); + auto supportedHDCPVersion = Exchange::IDeviceVideoCapabilities::CopyProtection::HDCP_UNAVAILABLE; + + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + + EXPECT_EQ(Core::ERROR_NONE, interface->SupportedHdcp(string(), supportedHDCPVersion)); + EXPECT_EQ(supportedHDCPVersion, Exchange::IDeviceVideoCapabilities::CopyProtection::HDCP_22); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedVideoDisplays_exception) +{ + RPC::IStringIterator* supportedVideoDisplays = nullptr; + + ON_CALL(*p_hostImplMock, getVideoOutputPorts()) + .WillByDefault(::testing::Invoke( + [&]() -> device::List { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->SupportedVideoDisplays(supportedVideoDisplays)); + EXPECT_EQ(supportedVideoDisplays, nullptr); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, HostEDID_exception) +{ + string edid; + + ON_CALL(*p_hostImplMock, getHostEDID(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector& edid) { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->HostEDID(edid)); + EXPECT_EQ(edid, string()); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, DefaultResolution_HDMI0_exception) +{ + string defaultResolution; + + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::VideoOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->DefaultResolution(string(_T("HDMI0")), defaultResolution)); + EXPECT_EQ(defaultResolution, string()); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedResolutions_HDMI0_exception) +{ + RPC::IStringIterator* supportedResolutions = nullptr; + + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::VideoOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->SupportedResolutions(string(_T("HDMI0")), supportedResolutions)); + EXPECT_EQ(supportedResolutions, nullptr); +} + +TEST_F(DeviceVideoCapabilitiesDsTest, SupportedHdcp_HDMI0_exception) +{ + auto supportedHDCPVersion = Exchange::IDeviceVideoCapabilities::CopyProtection::HDCP_UNAVAILABLE; + + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::VideoOutputPort& { + EXPECT_EQ(name, _T("HDMI0")); + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, interface->SupportedHdcp(string(_T("HDMI0")), supportedHDCPVersion)); + EXPECT_EQ(supportedHDCPVersion, Exchange::IDeviceVideoCapabilities::CopyProtection::HDCP_UNAVAILABLE); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_FirmwareVersion.cpp b/NetworkManager/Tests/L1Tests/tests/test_FirmwareVersion.cpp new file mode 100755 index 0000000000..3d14c675c8 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_FirmwareVersion.cpp @@ -0,0 +1,78 @@ +#include + +#include "Implementation/FirmwareVersion.h" + +#include + +using namespace WPEFramework; + +class FirmwareVersionTest : public ::testing::Test { +protected: + Core::ProxyType firmwareVersion; + Exchange::IFirmwareVersion* interface; + + FirmwareVersionTest() + : firmwareVersion(Core::ProxyType::Create()) + { + interface = static_cast( + firmwareVersion->QueryInterface(Exchange::IFirmwareVersion::ID)); + } + virtual ~FirmwareVersionTest() + { + interface->Release(); + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +TEST_F(FirmwareVersionTest, Imagename) +{ + std::ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + file.close(); + + string imagename; + EXPECT_EQ(Core::ERROR_NONE, interface->Imagename(imagename)); + EXPECT_EQ(imagename, _T("PX051AEI_VBN_2203_sprint_20220331225312sdy_NG")); +} + +TEST_F(FirmwareVersionTest, Sdk) +{ + std::ofstream file("/version.txt"); + file << "SDK_VERSION=17.3"; + file.close(); + + string sdk; + EXPECT_EQ(Core::ERROR_NONE, interface->Sdk(sdk)); + EXPECT_EQ(sdk, _T("17.3")); +} + +TEST_F(FirmwareVersionTest, Mediarite) +{ + std::ofstream file("/version.txt"); + file << "MEDIARITE=8.3.53"; + file.close(); + + string mediarite; + EXPECT_EQ(Core::ERROR_NONE, interface->Mediarite(mediarite)); + EXPECT_EQ(mediarite, _T("8.3.53")); +} + +TEST_F(FirmwareVersionTest, Yocto) +{ + std::ofstream file("/version.txt"); + file << "YOCTO_VERSION=dunfell"; + file.close(); + + string yocto; + EXPECT_EQ(Core::ERROR_NONE, interface->Yocto(yocto)); + EXPECT_EQ(yocto, _T("dunfell")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_FrameRate.cpp b/NetworkManager/Tests/L1Tests/tests/test_FrameRate.cpp new file mode 100755 index 0000000000..682ba7fb9f --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_FrameRate.cpp @@ -0,0 +1,269 @@ +#include + +#include "FrameRate.h" + +#include "FactoriesImplementation.h" +#include "HostMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "VideoDeviceMock.h" +#include "devicesettings.h" +#include "dsMgr.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class FrameRateTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + FrameRateTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~FrameRateTest() = default; +}; + +class FrameRateInitializedTest : public FrameRateTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + IARM_EventHandler_t FrameRatePreChange; + IARM_EventHandler_t FrameRatePostChange; + + FrameRateInitializedTest() + : FrameRateTest() + { + p_iarmBusImplMock = new NiceMock ; + + IarmBus::setImpl(p_iarmBusImplMock); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_PRECHANGE)) { + FrameRatePreChange = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_POSTCHANGE)) { + FrameRatePostChange = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~FrameRateInitializedTest() override + { + plugin->Deinitialize(nullptr); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class FrameRateInitializedEventTest : public FrameRateInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + FrameRateInitializedEventTest() + : FrameRateInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~FrameRateInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class FrameRateDsTest : public FrameRateTest { +protected: + HostImplMock *p_hostImplMock = nullptr; + VideoDeviceMock *p_videoDeviceMock = nullptr; + + FrameRateDsTest() + : FrameRateTest() + { + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + + device::VideoDevice videoDevice; + p_videoDeviceMock = new NiceMock ; + device::VideoDevice::setImpl(p_videoDeviceMock); + + ON_CALL(*p_hostImplMock, getVideoDevices()) + .WillByDefault(::testing::Return(device::List({ videoDevice }))); + } + virtual ~FrameRateDsTest() override + { + device::VideoDevice::setImpl(nullptr); + if (p_videoDeviceMock != nullptr) + { + delete p_videoDeviceMock; + p_videoDeviceMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +TEST_F(FrameRateTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setCollectionFrequency"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startFpsCollection"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopFpsCollection"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("updateFps"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFrmMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFrmMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDisplayFrameRate"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDisplayFrameRate"))); +} + +TEST_F(FrameRateTest, setCollectionFrequency_startFpsCollection_stopFpsCollection_updateFps) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setCollectionFrequency"), _T("{\"frequency\":1000}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startFpsCollection"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopFpsCollection"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updateFps"), _T("{\"newFpsValue\":60}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * Segmentation fault without valgrind + */ +TEST_F(FrameRateDsTest, DISABLED_setFrmMode) +{ + ON_CALL(*p_videoDeviceMock, setFRFMode(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int param) { + EXPECT_EQ(param, 0); + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFrmMode"), _T("{\"frmmode\":0}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * Segmentation fault without valgrind + */ +TEST_F(FrameRateDsTest, DISABLED_getFrmMode) +{ + ON_CALL(*p_videoDeviceMock, getFRFMode(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int* param) { + *param = 0; + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFrmMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"auto-frm-mode\":0,\"success\":true}")); +} + +/** + * Segmentation fault without valgrind + */ +TEST_F(FrameRateDsTest, DISABLED_setDisplayFrameRate) +{ + ON_CALL(*p_videoDeviceMock, setDisplayframerate(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* param) { + EXPECT_EQ(param, string("3840x2160px48")); + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setDisplayFrameRate"), _T("{\"framerate\":\"3840x2160px48\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * Segmentation fault without valgrind + */ +TEST_F(FrameRateDsTest, DISABLED_getDisplayFrameRate) +{ + ON_CALL(*p_videoDeviceMock, getCurrentDisframerate(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](char* param) { + string framerate("3840x2160px48"); + ::memcpy(param, framerate.c_str(), framerate.length()); + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDisplayFrameRate"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"framerate\":\"3840x2160px48\",\"success\":true}")); +} + +TEST_F(FrameRateInitializedEventTest, onDisplayFrameRateChanging) +{ + ASSERT_TRUE(FrameRatePreChange != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onDisplayFrameRateChanging.onDisplayFrameRateChanging\"," + "\"params\":{\"displayFrameRate\":\"3840x2160px48\"}" + "}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + strcpy(eventData.data.DisplayFrameRateChange.framerate,"3840x2160px48"); + + ASSERT_TRUE(FrameRatePreChange != nullptr); + handler.Subscribe(0, _T("onDisplayFrameRateChanging"), _T("client.events.onDisplayFrameRateChanging"), message); + FrameRatePreChange(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_PRECHANGE, &eventData , sizeof(eventData)); + handler.Unsubscribe(0, _T("onDisplayFrameRateChanging"), _T("client.events.onDisplayFrameRateChanging"), message); +} + +TEST_F(FrameRateInitializedEventTest, onDisplayFrameRateChanged) +{ + ASSERT_TRUE(FrameRatePostChange != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onDisplayFrameRateChanged.onDisplayFrameRateChanged\"," + "\"params\":{\"displayFrameRate\":\"3840x2160px48\"}" + "}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + strcpy(eventData.data.DisplayFrameRateChange.framerate,"3840x2160px48"); + + ASSERT_TRUE(FrameRatePostChange != nullptr); + handler.Subscribe(0, _T("onDisplayFrameRateChanged"), _T("client.events.onDisplayFrameRateChanged"), message); + FrameRatePostChange(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_POSTCHANGE, &eventData , sizeof(eventData)); + handler.Unsubscribe(0, _T("onDisplayFrameRateChanged"), _T("client.events.onDisplayFrameRateChanged"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_FrontPanel.cpp b/NetworkManager/Tests/L1Tests/tests/test_FrontPanel.cpp new file mode 100755 index 0000000000..a90e4319ae --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_FrontPanel.cpp @@ -0,0 +1,700 @@ +#include + +#include "FrontPanel.h" +#include "frontpanel.h" + + +#include "FactoriesImplementation.h" + +#include "FrontPanelIndicatorMock.h" +#include "FrontPanelTextDisplayMock.h" +#include "FrontPanelConfigMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "ColorMock.h" + +using namespace WPEFramework; + +using testing::Eq; + +class FrontPanelTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + FrontPanelTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~FrontPanelTest() = default; +}; + +class FrontPanelDsTest : public FrontPanelTest { +protected: + testing::NiceMock frontPanelIndicatorMock; + testing::NiceMock frontPanelTextDisplayIndicatorMock; + FrontPanelConfigMock *p_frontPanelConfigImplMock = nullptr; + FrontPanelTextDisplayMock *p_frontPanelTextDisplayMock = nullptr; + FrontPanelDsTest() + : FrontPanelTest() + { + device::FrontPanelIndicator::getInstance().impl = &frontPanelIndicatorMock; + p_frontPanelConfigImplMock = new testing::NiceMock ; + device::FrontPanelConfig::setImpl(p_frontPanelConfigImplMock); + p_frontPanelTextDisplayMock = new testing::NiceMock ; + device::FrontPanelTextDisplay::setImpl(p_frontPanelTextDisplayMock); + device::FrontPanelTextDisplay::getInstance().FrontPanelIndicator::impl = &frontPanelTextDisplayIndicatorMock; + + } + virtual ~FrontPanelDsTest() override + { + device::FrontPanelIndicator::getInstance().impl = nullptr; + device::FrontPanelTextDisplay::getInstance().FrontPanelIndicator::impl = nullptr; + if (p_frontPanelTextDisplayMock != nullptr) + { + delete p_frontPanelTextDisplayMock; + p_frontPanelTextDisplayMock = nullptr; + } + if (p_frontPanelConfigImplMock != nullptr) + { + delete p_frontPanelConfigImplMock; + p_frontPanelConfigImplMock = nullptr; + } + + } +}; + +class FrontPanelInitializedTest : public FrontPanelTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + FrontPanelConfigMock *p_frontPanelConfigImplMock = nullptr; + FrontPanelTextDisplayMock *p_frontPanelTextDisplayMock = nullptr; + + IARM_EventHandler_t dsPanelEventHandler; + testing::NiceMock frontPanelIndicatorMock; + testing::NiceMock frontPanelTextDisplayIndicatorMock; + + IARM_EventHandler_t dsFrontPanelModeChange; + + FrontPanelInitializedTest() + : FrontPanelTest() + { + + p_iarmBusImplMock = new testing::NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_frontPanelConfigImplMock = new testing::NiceMock ; + device::FrontPanelConfig::setImpl(p_frontPanelConfigImplMock); + + device::FrontPanelIndicator::getInstance().impl = &frontPanelIndicatorMock; + device::FrontPanelTextDisplay::getInstance().FrontPanelIndicator::impl = &frontPanelTextDisplayIndicatorMock; + + p_frontPanelTextDisplayMock = new testing::NiceMock ; + device::FrontPanelTextDisplay::setImpl(p_frontPanelTextDisplayMock); + + //Needs to be set at initiative time, as the function gets called when FrontPanel is intialized. + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(*p_frontPanelConfigImplMock, getIndicators()) + .WillByDefault(::testing::Return(device::List({ device::FrontPanelIndicator::getInstance() }))); + + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + EXPECT_TRUE(handler != nullptr); + dsFrontPanelModeChange = handler; + } + + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~FrontPanelInitializedTest() override + { + device::FrontPanelIndicator::getInstance().impl = nullptr; + device::FrontPanelTextDisplay::getInstance().FrontPanelIndicator::impl = nullptr; + + + plugin->Deinitialize(nullptr); + //Clearing out out of scope variables, and setting initDone to 0. + Plugin::CFrontPanel::initDone = 0; + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::FrontPanelTextDisplay::setImpl(nullptr); + if (p_frontPanelTextDisplayMock != nullptr) + { + delete p_frontPanelTextDisplayMock; + p_frontPanelTextDisplayMock = nullptr; + } + device::FrontPanelConfig::setImpl(nullptr); + if (p_frontPanelConfigImplMock != nullptr) + { + delete p_frontPanelConfigImplMock; + p_frontPanelConfigImplMock = nullptr; + } + } +}; + +class FrontPanelInitializedEventTest : public FrontPanelInitializedTest { +protected: + testing::NiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + FrontPanelInitializedEventTest() + : FrontPanelInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~FrontPanelInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class FrontPanelInitializedEventDsTest : public FrontPanelInitializedEventTest { +protected: + + ColorMock *p_colorImplMock = nullptr ; + + FrontPanelInitializedEventDsTest() + : FrontPanelInitializedEventTest() + { + p_colorImplMock = new testing::NiceMock ; + device::FrontPanelIndicator::Color::setImpl(p_colorImplMock); + + //Variable that needs to be set is set through this call + IARM_Bus_PWRMgr_EventData_t eventData; + eventData.data.state.newState =IARM_BUS_PWRMGR_POWERSTATE_ON; + eventData.data.state.curState =IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + dsFrontPanelModeChange(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, &eventData , 0); + } + + virtual ~FrontPanelInitializedEventDsTest() override + { + device::FrontPanelIndicator::Color::setImpl(nullptr); + if (p_colorImplMock != nullptr) + { + delete p_colorImplMock; + p_colorImplMock = nullptr; + } + } +}; + +TEST_F(FrontPanelTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setBrightness"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getBrightness"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("powerLedOn"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("powerLedOff"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setClockBrightness"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getClockBrightness"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFrontPanelLights"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPreferences"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setPreferences"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLED"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setBlink"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("set24HourClock"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("is24HourClock"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setClockTestPattern"))); +} + +TEST_F(FrontPanelInitializedEventDsTest, setBrightnessWIndex) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("Power")); + + + EXPECT_CALL(frontPanelIndicatorMock, setBrightness(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](int brightness, bool toPersist) { + EXPECT_EQ(brightness, 1); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBrightness"), _T("{\"brightness\": 1,\"index\": \"power_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(FrontPanelInitializedEventDsTest, setBrightnessClock) +{ + ON_CALL(*p_frontPanelTextDisplayMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelTextDisplay& { + EXPECT_EQ("Text", name); + return device::FrontPanelTextDisplay::getInstance(); + })); + + + + ON_CALL(*p_frontPanelConfigImplMock, getIndicators()) + .WillByDefault(::testing::Return(device::List({device::FrontPanelIndicator::getInstance()}))); + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("red")); + + EXPECT_CALL(*p_frontPanelTextDisplayMock, setTextBrightness(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](int brightness) { + EXPECT_EQ(brightness, 1); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBrightness"), _T("{\"brightness\": 1,\"index\": \"clock_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, setBrightness) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("Power")); + + EXPECT_CALL(frontPanelIndicatorMock, setBrightness(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](int brightness, bool toPersist) { + EXPECT_EQ(brightness, 1); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBrightness"), _T("{\"brightness\": 1}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, getBrightnessWIndex) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + ON_CALL(frontPanelIndicatorMock, getBrightness(::testing::_)) + .WillByDefault(::testing::Return(50)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getBrightness"), _T("{\"index\": \"power_led\"}"), response)); + EXPECT_EQ(response, string("{\"brightness\":50,\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, getBrightnessOtherName) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("other", name); + return device::FrontPanelIndicator::getInstance(); + })); + ON_CALL(frontPanelIndicatorMock, getBrightness(::testing::_)) + .WillByDefault(::testing::Return(50)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getBrightness"), _T("{\"index\": \"other\"}"), response)); + EXPECT_EQ(response, string("{\"brightness\":50,\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, getBrightnessWIndexClock) +{ + + ON_CALL(*p_frontPanelTextDisplayMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelTextDisplay& { + EXPECT_EQ("Text", name); + return device::FrontPanelTextDisplay::getInstance(); + })); + + + ON_CALL(*p_frontPanelTextDisplayMock, getTextBrightness()) + .WillByDefault(::testing::Return(50)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getBrightness"), _T("{\"index\": \"clock_led\"}"), response)); + EXPECT_EQ(response, string("{\"brightness\":50,\"success\":true}")); +} + + +TEST_F(FrontPanelInitializedEventDsTest, getBrightness) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + ON_CALL(frontPanelIndicatorMock, getBrightness(::testing::_)) + .WillByDefault(::testing::Return(50)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getBrightness"), _T(""), response)); + EXPECT_EQ(response, string("{\"brightness\":50,\"success\":true}")); +} +TEST_F(FrontPanelInitializedEventDsTest, getClockBrightness) +{ + + ON_CALL(*p_frontPanelTextDisplayMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelTextDisplay& { + EXPECT_EQ("Text", name); + return device::FrontPanelTextDisplay::getInstance(); + })); + + ON_CALL(*p_frontPanelTextDisplayMock, getTextBrightness()) + .WillByDefault(::testing::Return(50)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getClockBrightness"), _T(""), response)); + EXPECT_EQ(response, string("{\"brightness\":50,\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, setClockBrightness) +{ + + ON_CALL(*p_frontPanelTextDisplayMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelTextDisplay& { + EXPECT_EQ("Text", name); + return device::FrontPanelTextDisplay::getInstance(); + })); + + + ON_CALL(*p_frontPanelConfigImplMock, getIndicators()) + .WillByDefault(::testing::Return(device::List({device::FrontPanelIndicator::getInstance()}))); + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("red")); + + EXPECT_CALL(*p_frontPanelTextDisplayMock, setTextBrightness(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](int brightness) { + EXPECT_EQ(brightness, 1); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setClockBrightness"), _T("{\"brightness\": 1}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, getFrontPanelLights) +{ + ON_CALL(*p_frontPanelConfigImplMock, getIndicators()) + .WillByDefault(::testing::Return(device::List({ device::FrontPanelIndicator::getInstance() }))); + + ON_CALL(frontPanelIndicatorMock, getBrightnessLevels(::testing::_,::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int &levels,int &min,int &max) { + levels=1; + min=0; + max=2; + })); + ON_CALL(frontPanelTextDisplayIndicatorMock, getBrightnessLevels(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int& levels, int& min, int& max) { + levels = 1; + min = 0; + max = 2; + })); + + ON_CALL(*p_frontPanelConfigImplMock, getTextDisplays()) + .WillByDefault(::testing::Return(device::List({ device::FrontPanelTextDisplay::getInstance() }))); + ON_CALL(frontPanelTextDisplayIndicatorMock, getName()) + .WillByDefault(::testing::Return("Text")); + ON_CALL(*p_colorImplMock, getName()) + .WillByDefault(::testing::Return("white")); + + int test = 0; + + ON_CALL(*p_frontPanelConfigImplMock, getTextDisplay(test)) + .WillByDefault(::testing::ReturnRef(device::FrontPanelTextDisplay::getInstance())); + + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("Power")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFrontPanelLights"), _T(""), response)); + EXPECT_EQ(response, string("{\"supportedLights\":[\"power_led\",\"clock_led\"],\"supportedLightsInfo\":{\"power_led\":{\"range\":\"boolean\",\"min\":0,\"max\":2,\"colorMode\":0},\"clock_led\":{\"range\":\"boolean\",\"min\":0,\"max\":2,\"colorMode\":0}},\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, getPreferences) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPreferences"), _T("{\"preferences\":{\"test\": true}}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPreferences"), _T(""), response)); + EXPECT_EQ(response, string("{\"preferences\":{\"test\":true},\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, is24HourClock) +{ + + std::string test = "Text"; + ON_CALL(*p_frontPanelConfigImplMock, getTextDisplay(test)) + .WillByDefault(::testing::ReturnRef(device::FrontPanelTextDisplay::getInstance())); + ON_CALL(*p_frontPanelTextDisplayMock, getCurrentTimeFormat()) + .WillByDefault(::testing::Return(dsFPD_TIME_12_HOUR)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("is24HourClock"), _T(""), response)); + EXPECT_EQ(response, string("{\"is24Hour\":false,\"success\":true}")); + + ON_CALL(*p_frontPanelTextDisplayMock, getCurrentTimeFormat()) + .WillByDefault(::testing::Return(dsFPD_TIME_24_HOUR)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("is24HourClock"), _T(""), response)); + EXPECT_EQ(response, string("{\"is24Hour\":true,\"success\":true}")); + +} + +TEST_F(FrontPanelInitializedEventDsTest, powerLedOffPower) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + + EXPECT_CALL(frontPanelIndicatorMock, setState(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](bool state) { + EXPECT_EQ(state, false); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOff"), _T("{\"index\": \"power_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(FrontPanelInitializedEventDsTest, powerLedOffData) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Message", name); + return device::FrontPanelIndicator::getInstance(); + })); + + + EXPECT_CALL(frontPanelIndicatorMock, setState(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](bool state) { + EXPECT_EQ(state, false); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOff"), _T("{\"index\": \"data_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(FrontPanelInitializedEventDsTest, powerLedOffRecord) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Record", name); + return device::FrontPanelIndicator::getInstance(); + })); + + + EXPECT_CALL(frontPanelIndicatorMock, setState(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](bool state) { + EXPECT_EQ(state, false); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOff"), _T("{\"index\": \"record_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, powerLedOnPower) +{ + + ON_CALL(*p_frontPanelConfigImplMock, getIndicators()) + .WillByDefault(::testing::Return(device::List({device::FrontPanelIndicator::getInstance()}))); + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("red")); + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOn"), _T("{\"index\": \"power_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Record", name); + return device::FrontPanelIndicator::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOn"), _T("{\"index\": \"record_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Message", name); + return device::FrontPanelIndicator::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("powerLedOn"), _T("{\"index\": \"data_led\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + +} + +TEST_F(FrontPanelInitializedEventDsTest, set24HourClock) +{ + std::string test = "Text"; + + ON_CALL(*p_frontPanelConfigImplMock, getTextDisplay(test)) + .WillByDefault(::testing::ReturnRef(device::FrontPanelTextDisplay::getInstance())); + ON_CALL(*p_frontPanelTextDisplayMock, getCurrentTimeFormat()) + .WillByDefault(::testing::Return(dsFPD_TIME_24_HOUR)); + EXPECT_CALL(*p_frontPanelTextDisplayMock, setTimeFormat(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const int iTimeFormat) { + EXPECT_EQ(iTimeFormat, dsFPD_TIME_24_HOUR); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("set24HourClock"), _T("{\"is24Hour\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(FrontPanelInitializedEventDsTest, setBlink) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(frontPanelIndicatorMock, getBrightness(::testing::_)) + .WillByDefault(::testing::Return(50)); + ON_CALL(*p_frontPanelTextDisplayMock, getTextBrightness()) + .WillByDefault(::testing::Return(50)); + + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("Power")); + + EXPECT_CALL(frontPanelIndicatorMock, setColorInt(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t color, bool persist) { + EXPECT_EQ(color, 131586); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBlink"), _T("{\"blinkInfo\": {\"ledIndicator\": \"power_led\", \"iterations\": 10, \"pattern\": [{\"brightness\": 50, \"duration\": 100, \"red\": 2, \"green\":2, \"blue\":2}]}}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, setClockTestPattern) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(*p_colorImplMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator::Color& { + EXPECT_EQ("red", name); + return device::FrontPanelIndicator::Color::getInstance(); + })); + + std::string test = "Text"; + + ON_CALL(*p_frontPanelConfigImplMock, getTextDisplay(test)) + .WillByDefault(::testing::ReturnRef(device::FrontPanelTextDisplay::getInstance())); + ON_CALL(*p_frontPanelTextDisplayMock, getTextBrightness()) + .WillByDefault(::testing::Return(100)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setClockTestPattern"), _T("{\"show\": true, \"timeInterval\": 4}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setClockTestPattern"), _T("{\"show\": false, \"timeInterval\": 4}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(FrontPanelInitializedEventDsTest, setLEDMode1) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + ON_CALL(frontPanelIndicatorMock, getName()) + .WillByDefault(::testing::Return("Power")); + + EXPECT_CALL(frontPanelIndicatorMock, setColorInt(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t color, bool toPersist) { + EXPECT_EQ(color, 0); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLED"), _T("{\"ledIndicator\": \"power_led\", \"brightness\": 50, \"red\": 0, \"green\": 0, \"blue\":0}"), response)); + + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(FrontPanelInitializedEventDsTest, setLEDMode2) +{ + + ON_CALL(frontPanelIndicatorMock, getInstanceString) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::FrontPanelIndicator& { + EXPECT_EQ("Power", name); + return device::FrontPanelIndicator::getInstance(); + })); + + EXPECT_CALL(frontPanelIndicatorMock, setColorInt(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t color, bool toPersist) { + EXPECT_EQ(color, 66051); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLED"), _T("{\"ledIndicator\": \"power_led\", \"brightness\": 50, \"red\": 1, \"green\": 2, \"blue\":3}"), response)); + + EXPECT_EQ(response, string("{\"success\":true}")); +} + + diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdcpProfile.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdcpProfile.cpp new file mode 100755 index 0000000000..e72311f9e0 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdcpProfile.cpp @@ -0,0 +1,427 @@ +#include + +#include "HdcpProfile.h" + +#include "FactoriesImplementation.h" +#include "HostMock.h" +#include "ManagerMock.h" +#include "VideoOutputPortConfigMock.h" +#include "VideoOutputPortMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "dsMgr.h" +#include "dsDisplay.h" +#include "pwrMgr.h" +using namespace WPEFramework; + +using ::testing::NiceMock; + +class HDCPProfileTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + Core::JSONRPC::Message message; + + HDCPProfileTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~HDCPProfileTest() = default; + +}; + +class HDCPProfileDsTest : public HDCPProfileTest { +protected: + HostImplMock *p_hostImplMock = nullptr ; + VideoOutputPortConfigImplMock *p_videoOutputPortConfigImplMock = nullptr ; + VideoOutputPortMock *p_videoOutputPortMock = nullptr ; + + HDCPProfileDsTest() + : HDCPProfileTest() + { + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + p_videoOutputPortConfigImplMock = new NiceMock ; + device::VideoOutputPortConfig::setImpl(p_videoOutputPortConfigImplMock); + p_videoOutputPortMock = new NiceMock ; + device::VideoOutputPort::setImpl(p_videoOutputPortMock); + } + virtual ~HDCPProfileDsTest() override + { + device::VideoOutputPort::setImpl(nullptr); + if (p_videoOutputPortMock != nullptr) + { + delete p_videoOutputPortMock; + p_videoOutputPortMock = nullptr; + } + device::VideoOutputPortConfig::setImpl(nullptr); + if (p_videoOutputPortConfigImplMock != nullptr) + { + delete p_videoOutputPortConfigImplMock; + p_videoOutputPortConfigImplMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +class HDCPProfileEventTest : public HDCPProfileDsTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HDCPProfileEventTest() + : HDCPProfileDsTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~HDCPProfileEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class HDCPProfileEventIarmTest : public HDCPProfileEventTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + IARM_EventHandler_t dsHdmiEventHandler; + + HDCPProfileEventIarmTest() + : HDCPProfileEventTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_managerImplMock = new NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + EXPECT_CALL(*p_managerImplMock, Initialize()) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Return()); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG)) { + dsHdmiEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDCP_STATUS)) { + dsHdmiEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + + virtual ~HDCPProfileEventIarmTest() override + { + plugin->Deinitialize(&service); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + } +}; + +TEST_F(HDCPProfileTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHDCPStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSettopHDCPSupport"))); +} + +TEST_F(HDCPProfileDsTest, getHDCPStatus_isConnected_false) +{ + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(false)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPStatus()) + .WillByDefault(::testing::Return(dsHDCP_STATUS_UNPOWERED)); + ON_CALL(*p_videoOutputPortMock, isContentProtected()) + .WillByDefault(::testing::Return(0)); + ON_CALL(*p_videoOutputPortMock, getHDCPReceiverProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_MAX)); + ON_CALL(*p_videoOutputPortMock, getHDCPCurrentProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_MAX)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHDCPStatus"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"HDCPStatus\":" + "\\{" + "\"isConnected\":false," + "\"isHDCPCompliant\":false," + "\"isHDCPEnabled\":false," + "\"hdcpReason\":0," + "\"supportedHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"receiverHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"currentHDCPVersion\":\"[1-2]+.[1-4]\"" + "\\}," + "\"success\":true" + "\\}"))); +} + +TEST_F(HDCPProfileDsTest, getHDCPStatus_isConnected_true) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPStatus()) + .WillByDefault(::testing::Return(dsHDCP_STATUS_AUTHENTICATED)); + ON_CALL(*p_videoOutputPortMock, isContentProtected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPReceiverProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPCurrentProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHDCPStatus"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"HDCPStatus\":" + "\\{" + "\"isConnected\":true," + "\"isHDCPCompliant\":true," + "\"isHDCPEnabled\":true," + "\"hdcpReason\":2," + "\"supportedHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"receiverHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"currentHDCPVersion\":\"[1-2]+.[1-4]\"" + "\\}," + "\"success\":true" + "\\}"))); +} + +TEST_F(HDCPProfileDsTest, getSettopHDCPSupport_Hdcp_v1x) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_1X)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSettopHDCPSupport"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"supportedHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"isHDCPSupported\":true," + "\"success\":true" + "\\}"))); +} + +TEST_F(HDCPProfileDsTest, getSettopHDCPSupport_Hdcp_v2x) +{ + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSettopHDCPSupport"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"supportedHDCPVersion\":\"[1-2]+.[1-4]\"," + "\"isHDCPSupported\":true," + "\"success\":true" + "\\}"))); +} + +TEST_F(HDCPProfileEventIarmTest, onDisplayConnectionChanged) +{ + ASSERT_TRUE(dsHdmiEventHandler != nullptr); + + Core::Event onDisplayConnectionChanged(false, true); + + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPStatus()) + .WillByDefault(::testing::Return(dsHDCP_STATUS_AUTHENTICATED)); + ON_CALL(*p_videoOutputPortMock, isContentProtected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPReceiverProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPCurrentProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + //EXPECT_EQ(text, string(_T(""))); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onDisplayConnectionChanged\"," + "\"params\":" + "\\{\"HDCPStatus\":" + "\\{" + "\"isConnected\":true," + "\"isHDCPCompliant\":true," + "\"isHDCPEnabled\":true," + "\"hdcpReason\":2," + "\"supportedHDCPVersion\":\"2.2\"," + "\"receiverHDCPVersion\":\"2.2\"," + "\"currentHDCPVersion\":\"2.2\"" + "\\}" + "\\}" + "\\}"))); + + onDisplayConnectionChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_hpd.event = dsDISPLAY_EVENT_CONNECTED; + dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onDisplayConnectionChanged.Lock()); + + handler.Unsubscribe(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); +} + +TEST_F(HDCPProfileEventIarmTest, onHdmiOutputHDCPStatusEvent) +{ + ASSERT_TRUE(dsHdmiEventHandler != nullptr); + + Core::Event onDisplayConnectionChanged(false, true); + + NiceMock videoOutputPortMock; + device::VideoOutputPort videoOutputPort; + + string videoPort(_T("HDMI0")); + + ON_CALL(*p_hostImplMock, getDefaultVideoPortName()) + .WillByDefault(::testing::Return(videoPort)); + ON_CALL(*p_videoOutputPortConfigImplMock, getPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(videoOutputPort)); + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPStatus()) + .WillByDefault(::testing::Return(dsHDCP_STATUS_AUTHENTICATED)); + ON_CALL(*p_videoOutputPortMock, isContentProtected()) + .WillByDefault(::testing::Return(true)); + ON_CALL(*p_videoOutputPortMock, getHDCPReceiverProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + ON_CALL(*p_videoOutputPortMock, getHDCPCurrentProtocol()) + .WillByDefault(::testing::Return(dsHDCP_VERSION_2X)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onDisplayConnectionChanged\"," + "\"params\":" + "\\{\"HDCPStatus\":" + "\\{" + "\"isConnected\":true," + "\"isHDCPCompliant\":true," + "\"isHDCPEnabled\":true," + "\"hdcpReason\":2," + "\"supportedHDCPVersion\":\"2.2\"," + "\"receiverHDCPVersion\":\"2.2\"," + "\"currentHDCPVersion\":\"2.2\"" + "\\}" + "\\}" + "\\}"))); + + onDisplayConnectionChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0) { + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + return IARM_RESULT_SUCCESS; + }); + + handler.Subscribe(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_hdcp.hdcpStatus = dsDISPLAY_HDCPPROTOCOL_CHANGE; + dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDCP_STATUS, &eventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onDisplayConnectionChanged.Lock()); + + handler.Unsubscribe(0, _T("onDisplayConnectionChanged"), _T("client.events"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdmiCec.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdmiCec.cpp new file mode 100755 index 0000000000..c3b4610b56 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdmiCec.cpp @@ -0,0 +1,302 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "HdmiCec.h" + +#include "FactoriesImplementation.h" + + +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "devicesettings.h" +#include "HdmiCecMock.h" +using namespace WPEFramework; +using ::testing::NiceMock; + +class HdmiCecTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + HdmiCecTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~HdmiCecTest() = default; +}; +class HdmiCecDsTest : public HdmiCecTest { +protected: + LibCCECImplMock *p_libCCECImplMock = nullptr ; + ConnectionImplMock *p_connectionImplMock = nullptr ; + HdmiCecDsTest() + : HdmiCecTest() + { + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + + p_connectionImplMock = new testing::NiceMock ; + Connection::setImpl(p_connectionImplMock); + + } + virtual ~HdmiCecDsTest() override + { + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + Connection::setImpl(nullptr); + if (p_connectionImplMock != nullptr) + { + delete p_connectionImplMock; + p_connectionImplMock = nullptr; + } + } +}; + +class HdmiCecInitializedTest : public HdmiCecTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + IARM_EventHandler_t cecMgrEventHandler; + IARM_EventHandler_t dsHdmiEventHandler; + LibCCECImplMock *p_libCCECImplMock = nullptr ; + ConnectionImplMock *p_connectionImplMock = nullptr ; + + HdmiCecInitializedTest() + : HdmiCecTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + + p_connectionImplMock = new testing::NiceMock ; + Connection::setImpl(p_connectionImplMock); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_STATUS_UPDATED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + } + + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + + //Setenable needs to run firzt, as it turns everything on, locally. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + } + virtual ~HdmiCecInitializedTest() override + { + + plugin->Deinitialize(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + Connection::setImpl(nullptr); + if (p_connectionImplMock != nullptr) + { + delete p_connectionImplMock; + p_connectionImplMock = nullptr; + } + //Turning off HdmiCec. otherwise we get segementation faults as things memory early while threads are still running + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + } +}; +class HdmiCecInitializedEventTest : public HdmiCecInitializedTest { +protected: + testing::NiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HdmiCecInitializedEventTest() + : HdmiCecInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~HdmiCecInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + } +}; + +TEST_F(HdmiCecTest, RegisteredMethods) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCECAddresses"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getActiveSourceStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceList"))); + +} + +TEST_F(HdmiCecDsTest, getEnabledFalse) +{ + //Without setting cecEnable to true. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"success\":true}")); +} + + +TEST_F(HdmiCecInitializedTest, getEnabledTrue) +{ + //Get enabled just checks if CEC is on, which is a global variable. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + +} + +TEST_F(HdmiCecInitializedTest, getActiveSourceStatusTrue) +{ + //ActiveSource is a local variable, no mocked functions to check. + //Calling the sendMessage() function with the proper message sets ActiveSource to true. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendMessage"), _T("{\"message\": \"P4IwAA==\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":true,\"success\":true}")); + + +} +TEST_F(HdmiCecInitializedTest, getActiveSourceStatusFalse) +{ + //ActiveSource is a local variable, no mocked functions to check. + //Active source is false by default. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":false,\"success\":true}")); +} + +TEST_F(HdmiCecInitializedTest, getCECAddress) +{ + EXPECT_CALL(*p_libCCECImplMock, getPhysicalAddress(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t *physAddress) { + *physAddress = (uint32_t)12345; + })); + ASSERT_TRUE(cecMgrEventHandler != nullptr); + IARM_Bus_CECMgr_Status_Updated_Param_t eventData; + + //Active Source Status update sets the address/logical address and what not to non-default values + eventData.logicalAddress = 5; + + cecMgrEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_STATUS_UPDATED, &eventData , 0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCECAddresses"), _T(""), response)); + EXPECT_EQ(response, string(_T("{\"CECAddresses\":{\"physicalAddress\":12345,\"logicalAddress\":5,\"deviceType\":\"Audio System\"},\"success\":true}"))); + +} + +TEST_F(HdmiCecInitializedEventTest, cecAddressesChanged) +{ + EXPECT_CALL(*p_libCCECImplMock, getPhysicalAddress(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t *physAddress) { + *physAddress = (uint32_t)1234; + })); + ASSERT_TRUE(dsHdmiEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.HdmiCec.cecAddressesChanged\",\"params\":{\"CECAddresses\":{\"physicalAddress\":1234}}}"))); + + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_hpd.event = 0; + handler.Subscribe(0, _T("cecAddressesChanged"), _T("org.rdk.HdmiCec"), message); + dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, &eventData , 0); + handler.Unsubscribe(0, _T("cecAddressesChanged"), _T("org.rdk.HdmiCec"), message); +} + +TEST_F(HdmiCecInitializedTest, getDeviceList) +{ + int iCounter = 0; + //Checking to see if one of the values has been filled in (as the rest get filled in at the same time, and waiting if its not. + while ((!Plugin::HdmiCec::_instance->deviceList[0].m_isOSDNameUpdated) && (iCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + const char* val = "TEST"; + OSDName name = OSDName(val); + SetOSDName osdName = SetOSDName(name); + + Header header; + header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using + + VendorID vendor(1,2,3); + DeviceVendorID vendorid(vendor); + + plugin->process(osdName, header); //calls the process that sets osdName for LogicalAddress = 1 + plugin->process(vendorid, header); //calls the process that sets vendorID for LogicalAddress = 1 + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceList"), _T(""), response)); + + EXPECT_EQ(response, string(_T("{\"numberofdevices\":14,\"deviceList\":[{\"logicalAddress\":1,\"osdName\":\"TEST\",\"vendorID\":\"123\"},{\"logicalAddress\":2,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":3,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":4,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":5,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":6,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":7,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":8,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":9,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":10,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":11,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":12,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":13,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":14,\"osdName\":\"NA\",\"vendorID\":\"000\"}],\"success\":true}"))); + + +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdmiCec2.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdmiCec2.cpp new file mode 100755 index 0000000000..5852829a1c --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdmiCec2.cpp @@ -0,0 +1,654 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "HdmiCec.h" +#include "HdmiCec_2.h" + +#include "FactoriesImplementation.h" + + +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "devicesettings.h" +#include "HdmiCecMock.h" +#include "DisplayMock.h" +#include "VideoOutputPortMock.h" +#include "HostMock.h" +#include "ManagerMock.h" + + + +using namespace WPEFramework; + +using namespace WPEFramework; + +class HdmiCec_2Test : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + HdmiCec_2Test() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~HdmiCec_2Test() = default; +}; +class HdmiCec_2DsTest : public HdmiCec_2Test { +protected: + LibCCECImplMock *p_libCCECImplMock = nullptr ; + ConnectionImplMock *p_connectionImplMock = nullptr ; + HdmiCec_2DsTest() + : HdmiCec_2Test() + { + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + } + virtual ~HdmiCec_2DsTest() override + { + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + } +}; + +class HdmiCec_2InitializedTest : public HdmiCec_2Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ManagerImplMock *p_managerImplMock = nullptr ; + HostImplMock *p_hostImplMock = nullptr ; + LibCCECImplMock *p_libCCECImplMock = nullptr ; + ConnectionImplMock *p_connectionImplMock = nullptr ; + VideoOutputPortMock *p_videoOutputPortMock = nullptr ; + MessageEncoderMock *p_messageEncoderMock = nullptr ; + + IARM_EventHandler_t cecMgrEventHandler; + IARM_EventHandler_t dsHdmiEventHandler; + IARM_EventHandler_t pwrMgrEventHandler; + + DisplayMock *p_displayMock = nullptr ; + + HdmiCec_2InitializedTest() + : HdmiCec_2Test() + { + p_iarmBusImplMock = new testing::NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_hostImplMock = new testing::NiceMock ; + device::Host::setImpl(p_hostImplMock); + + p_managerImplMock = new testing::NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + + p_messageEncoderMock = new testing::NiceMock ; + MessageEncoder::setImpl(p_messageEncoderMock); + + p_connectionImplMock = new testing::NiceMock ; + Connection::setImpl(p_connectionImplMock); + + p_videoOutputPortMock = new testing::NiceMock ; + device::VideoOutputPort::setImpl(p_videoOutputPortMock); + + p_displayMock = new testing::NiceMock ; + device::Display::setImpl(p_displayMock); + + //OnCall required for intialize to run properly + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(device::VideoOutputPort::getInstance())); + + ON_CALL(*p_videoOutputPortMock, getDisplay()) + .WillByDefault(::testing::ReturnRef(device::Display::getInstance())); + + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(true)); + + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::ReturnRef(CECFrame::getInstance())); + + ON_CALL(*p_displayMock, getEDIDBytes(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector &edidVec2) { + edidVec2 = std::vector({ 't', 'e', 's', 't' }); + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_STATUS_UPDATED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + } + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + EXPECT_TRUE(handler != nullptr); + pwrMgrEventHandler = handler; + } + + return IARM_RESULT_SUCCESS; + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0) { + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + return IARM_RESULT_SUCCESS; + }); + + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + //Set enabled needs to be + ON_CALL(*p_libCCECImplMock, getLogicalAddress(::testing::_)) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_connectionImplMock, open()) + .WillByDefault(::testing::Return()); + ON_CALL(*p_connectionImplMock, addFrameListener(::testing::_)) + .WillByDefault(::testing::Return()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + } + virtual ~HdmiCec_2InitializedTest() override + { + int lCounter = 0; + while ((Plugin::HdmiCec_2::_instance->deviceList[0].m_isOSDNameUpdated) && (lCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + lCounter ++; + } + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + plugin->Deinitialize(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + device::Display::setImpl(nullptr); + if (p_displayMock != nullptr) + { + delete p_displayMock; + p_displayMock = nullptr; + } + device::VideoOutputPort::setImpl(nullptr); + if (p_videoOutputPortMock != nullptr) + { + delete p_videoOutputPortMock; + p_videoOutputPortMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + Connection::setImpl(nullptr); + if (p_connectionImplMock != nullptr) + { + delete p_connectionImplMock; + p_connectionImplMock = nullptr; + } + MessageEncoder::setImpl(nullptr); + if (p_messageEncoderMock != nullptr) + { + delete p_messageEncoderMock; + p_messageEncoderMock = nullptr; + } + + } +}; +class HdmiCec_2InitializedEventTest : public HdmiCec_2InitializedTest { +protected: + testing::NiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HdmiCec_2InitializedEventTest() + : HdmiCec_2InitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~HdmiCec_2InitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + } +}; + +TEST_F(HdmiCec_2Test, RegisteredMethods) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getActiveSourceStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceList"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOSDName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOTPEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVendorId"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("performOTPAction"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendKeyPressEvent"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendStandbyMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOSDName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOTPEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVendorId"))); + +} + +TEST_F(HdmiCec_2DsTest, getEnabledFalse) +{ + //Without setting cecEnable to true. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"success\":true}")); +} + + +TEST_F(HdmiCec_2InitializedTest, getEnabledTrue) +{ + //Get enabled just checks if CEC is on, which is a global variable. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + +} + +TEST_F(HdmiCec_2InitializedTest, getActiveSourceStatusTrue) +{ + //SetsOTP to on. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + //Sets Activesource to true + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("performOTPAction"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":true,\"success\":true}")); + + +} +TEST_F(HdmiCec_2InitializedTest, getActiveSourceStatusFalse) +{ + //ActiveSource is a local variable, no mocked functions to check. + //Active source is false by default. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":false,\"success\":true}")); +} + + +TEST_F(HdmiCec_2InitializedTest, getDeviceList) +{ + int iCounter = 0; + //Checking to see if one of the values has been filled in (as the rest get filled in at the same time, and waiting if its not. + while ((!Plugin::HdmiCec_2::_instance->deviceList[0].m_isOSDNameUpdated) && (iCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + const char* val = "TEST"; + OSDName name = OSDName(val); + SetOSDName osdName = SetOSDName(name); + + Header header; + header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using + + VendorID vendor(1,2,3); + DeviceVendorID vendorid(vendor); + + Plugin::HdmiCec_2Processor proc(Connection::getInstance()); + + proc.process(osdName, header); //calls the process that sets osdName for LogicalAddress = 1 + proc.process(vendorid, header); //calls the process that sets vendorID for LogicalAddress = 1 + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceList"), _T(""), response)); + + EXPECT_EQ(response, string(_T("{\"numberofdevices\":14,\"deviceList\":[{\"logicalAddress\":1,\"osdName\":\"TEST\",\"vendorID\":\"123\"},{\"logicalAddress\":2,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":3,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":4,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":5,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":6,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":7,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":8,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":9,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":10,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":11,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":12,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":13,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":14,\"osdName\":\"NA\",\"vendorID\":\"000\"}],\"success\":true}"))); + + +} + + +TEST_F(HdmiCec_2InitializedTest, getOTPEnabled) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOTPEnabled"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + +} + + + +TEST_F(HdmiCec_2InitializedTest, sendStandbyMessage) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendStandbyMessage"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCec_2InitializedTest, setOSDName) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOSDName"), _T("{\"name\": \"Sky Tv\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOSDName"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"name\":\"Sky Tv\",\"success\":true}")); + + + +} +TEST_F(HdmiCec_2InitializedTest, setVendorId) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVendorId"), _T("{\"vendorid\": \"0x0019FB\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVendorId"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"vendorid\":\"019fb\",\"success\":true}")); + + +} +TEST_F(HdmiCec_2InitializedTest, setOTPEnabled) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEventUp) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_VOLUME_UP ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 65}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent2) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_VOLUME_DOWN ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 66}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent3) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_MUTE ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 67}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent4) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_UP ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 1}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent5) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_DOWN ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 2}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent6) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_LEFT ); + return CECFrame::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 3}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent7) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_RIGHT ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 4}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent8) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_SELECT ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 0}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent9) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_HOME ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 9}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent10) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_BACK ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 13}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent11) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_0 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 32}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent12) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_1 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 33}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent13) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_2 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 34}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent14) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_3 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 35}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent15) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_4 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 36}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent16) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_5 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 37}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent17) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_6 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 38}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent18) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_7 ); + return CECFrame::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 39}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent19) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_8 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 40}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCec_2InitializedTest, sendKeyPressEvent20) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_9 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 41}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSink.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSink.cpp new file mode 100755 index 0000000000..89e7023ef9 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSink.cpp @@ -0,0 +1,397 @@ +#include +#include "HdmiCecSink.h" +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "devicesettings.h" +#include "HdmiCec.h" +#include "HdmiCecMock.h" +#include "WrapsMock.h" +#include "RfcApiMock.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +class HdmiCecSinkTest : public ::testing::Test { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ConnectionImplMock *p_connectionImplMock = nullptr ; + MessageEncoderMock *p_messageEncoderMock = nullptr ; + LibCCECImplMock *p_libCCECImplMock = nullptr ; + RfcApiImplMock *p_rfcApiImplMock = nullptr ; + WrapsImplMock *p_wrapsImplMock = nullptr ; + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + NiceMock rfcApiImplMock; + NiceMock wrapsImplMock; + IARM_EventHandler_t pwrMgrModeChangeEventHandler; + IARM_EventHandler_t dsHdmiEventHandler; + IARM_EventHandler_t dsHdmiCecSinkEventHandler; + string response; + + HdmiCecSinkTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + + p_messageEncoderMock = new testing::NiceMock ; + MessageEncoder::setImpl(p_messageEncoderMock); + + p_connectionImplMock = new testing::NiceMock ; + Connection::setImpl(p_connectionImplMock); + + p_rfcApiImplMock = new testing::NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + + p_wrapsImplMock = new testing::NiceMock ; + Wraps::setImpl(p_wrapsImplMock); /*Set up mock for fopen; + to use the mock implementation/the default behavior of the fopen function from Wraps class.*/ + + ON_CALL(*p_connectionImplMock, poll(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const LogicalAddress &from, const Throw_e &doThrow) { + throw CECNoAckException(); + })); + + EXPECT_CALL(*p_libCCECImplMock, getPhysicalAddress(::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](uint32_t *physAddress) { + *physAddress = (uint32_t)0x12345678; + })); + + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::ReturnRef(CECFrame::getInstance())); + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::ReturnRef(CECFrame::getInstance())); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + EXPECT_TRUE(handler != nullptr); + pwrMgrModeChangeEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + } + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiCecSinkEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + ON_CALL(*p_connectionImplMock, open()) + .WillByDefault(::testing::Return()); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + + virtual ~HdmiCecSinkTest() override + { + plugin->Deinitialize(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + Connection::setImpl(nullptr); + if (p_connectionImplMock != nullptr) + { + delete p_connectionImplMock; + p_connectionImplMock = nullptr; + } + MessageEncoder::setImpl(nullptr); + if (p_messageEncoderMock != nullptr) + { + delete p_messageEncoderMock; + p_messageEncoderMock = nullptr; + } + + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + } +}; + +class HdmiCecSinkDsTest : public HdmiCecSinkTest { +protected: + string response; + + HdmiCecSinkDsTest(): HdmiCecSinkTest() + { + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0) { + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + if (strcmp(methodName, IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs) == 0) { + auto* param = static_cast(arg); + param->result = dsERR_NONE; + param->numHdmiInputs = 3; + } + if (strcmp(methodName, IARM_BUS_DSMGR_API_dsHdmiInGetStatus) == 0) { + auto* param = static_cast(arg); + param->result = dsERR_NONE; + param->status.isPortConnected[1] = 1; + } + if (strcmp(methodName, IARM_BUS_DSMGR_API_dsGetHDMIARCPortId) == 0) { + auto* param = static_cast(arg); + param->portId = 1; + } + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + } + virtual ~HdmiCecSinkDsTest() override { + } +}; + +class HdmiCecSinkInitializedEventTest : public HdmiCecSinkDsTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HdmiCecSinkInitializedEventTest(): HdmiCecSinkDsTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~HdmiCecSinkInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + } +}; + +class HdmiCecSinkInitializedEventDsTest : public HdmiCecSinkInitializedEventTest { +protected: + HdmiCecSinkInitializedEventDsTest(): HdmiCecSinkInitializedEventTest() + { + } + virtual ~HdmiCecSinkInitializedEventDsTest() override + { + } +}; + +TEST_F(HdmiCecSinkTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOSDName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVendorId"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVendorId"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setActivePath"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setRoutingChange"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceList"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getActiveSource"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setActiveSource"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getActiveRoute"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMenuLanguage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("requestActiveSource"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setupARCRouting"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("requestShortAudioDescriptor"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendStandbyMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendAudioDevicePowerOnMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendKeyPressEvent"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendGetAudioStatusMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getAudioDeviceConnectedStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("requestAudioDevicePowerStatus"))); +} + +TEST_F(HdmiCecSinkDsTest, setOSDNameParamMissing) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setOSDName"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, getOSDName) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOSDName"), _T("{\"name\":\"CECTEST\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOSDName"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"name\":\"CECTEST\",\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, setVendorIdParamMissing) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVendorId"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, getVendorId) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVendorId"), _T("{\"vendorid\":\"0x0019FF\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVendorId"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"vendorid\":\"019ff\",\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, setActivePathMissingParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setActivePath"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, setActivePath) +{ + EXPECT_CALL(*p_connectionImplMock, sendTo(::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](const LogicalAddress &to, const CECFrame &frame, int timeout) { + EXPECT_EQ(to.toInt(), LogicalAddress::BROADCAST); + EXPECT_GT(timeout, 0); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setActivePath"), _T("{\"activePath\":\"2.0.0.0\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, setRoutingChangeInvalidParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setRoutingChange"), _T("{\"oldPort\":\"HDMI0\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, setRoutingChange) +{ + std::this_thread::sleep_for(std::chrono::seconds(30)); + + EXPECT_CALL(*p_connectionImplMock, sendTo(::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](const LogicalAddress &to, const CECFrame &frame, int timeout) { + EXPECT_EQ(to.toInt(), LogicalAddress::BROADCAST); + EXPECT_GT(timeout, 0); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setRoutingChange"), _T("{\"oldPort\":\"HDMI0\",\"newPort\":\"TV\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, setMenuLanguageInvalidParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setMenuLanguage"), _T("{\"language\":""}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, setMenuLanguage) +{ + EXPECT_CALL(*p_connectionImplMock, sendTo(::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](const LogicalAddress &to, const CECFrame &frame, int timeout) { + EXPECT_LE(to.toInt(), LogicalAddress::BROADCAST); + EXPECT_GT(timeout, 0); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setMenuLanguage"), _T("{\"language\":\"english\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, setupARCRoutingInvalidParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setupARCRouting"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, setupARCRouting) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setupARCRouting"), _T("{\"enabled\":\"true\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSinkDsTest, sendKeyPressEventMissingParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": }"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiCecSinkDsTest, sendKeyPressEvent) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 65}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSinkInitializedEventDsTest, onHdmiOutputHDCPStatusEvent) +{ + ASSERT_TRUE(dsHdmiEventHandler != nullptr); + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_connect.port =dsHDMI_IN_PORT_1; + eventData.data.hdmi_in_connect.isPortConnected = true; + + handler.Subscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); + dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &eventData , 0); + handler.Unsubscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); +} + +TEST_F(HdmiCecSinkInitializedEventDsTest, powerModeChange) +{ + ASSERT_TRUE(pwrMgrModeChangeEventHandler != nullptr); + + IARM_Bus_PWRMgr_EventData_t eventData; + eventData.data.state.newState =IARM_BUS_PWRMGR_POWERSTATE_ON; + eventData.data.state.curState =IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + + pwrMgrModeChangeEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, &eventData , 0); +} + +TEST_F(HdmiCecSinkInitializedEventDsTest, HdmiCecEnableStatus) +{ + ASSERT_TRUE(dsHdmiCecSinkEventHandler != nullptr); + IARM_Bus_CECMgr_Status_Updated_Param_t eventData; + dsHdmiCecSinkEventHandler(IARM_BUS_CECMGR_NAME, IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED, &eventData , 0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); +} + +TEST_F(HdmiCecSinkTest, DISABLED_getCecVersion) +{ + /*EXPECT_CALL(rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + EXPECT_EQ(string(pcCallerID), string("HdmiCecSink")); + EXPECT_EQ(string(pcParameterName), string("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion")); + strncpy(pstParamData->value, "1.4", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + }));*/ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCecVersion"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"CECVersion\":\"1.4\",\"success\":true}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSource.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSource.cpp new file mode 100755 index 0000000000..5449d8fc2d --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdmiCecSource.cpp @@ -0,0 +1,655 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "HdmiCec.h" +#include "HdmiCecSource.h" + +#include "FactoriesImplementation.h" + + +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "devicesettings.h" +#include "HdmiCecMock.h" +#include "DisplayMock.h" +#include "VideoOutputPortMock.h" +#include "HostMock.h" +#include "ManagerMock.h" + + + +using namespace WPEFramework; + +using namespace WPEFramework; + +class HdmiCecSourceTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + HdmiCecSourceTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~HdmiCecSourceTest() = default; +}; +class HdmiCecSourceDsTest : public HdmiCecSourceTest { +protected: + LibCCECImplMock *p_libCCECImplMock = nullptr ; + + HdmiCecSourceDsTest() + : HdmiCecSourceTest() + { + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + } + virtual ~HdmiCecSourceDsTest() override + { + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + } +}; + +class HdmiCecSourceInitializedTest : public HdmiCecSourceTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + IARM_EventHandler_t cecMgrEventHandler; + IARM_EventHandler_t dsHdmiEventHandler; + IARM_EventHandler_t pwrMgrEventHandler; + LibCCECImplMock *p_libCCECImplMock = nullptr ; + + ManagerImplMock *p_managerImplMock = nullptr ; + HostImplMock *p_hostImplMock = nullptr ; + + ConnectionImplMock *p_connectionImplMock = nullptr ; + VideoOutputPortMock *p_videoOutputPortMock = nullptr ; + + MessageEncoderMock *p_messageEncoderMock = nullptr ; + DisplayMock *p_displayMock = nullptr ; + + HdmiCecSourceInitializedTest() + : HdmiCecSourceTest() + { + p_iarmBusImplMock = new testing::NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_hostImplMock = new testing::NiceMock ; + device::Host::setImpl(p_hostImplMock); + + p_managerImplMock = new testing::NiceMock ; + device::Manager::setImpl(p_managerImplMock); + + p_libCCECImplMock = new testing::NiceMock ; + LibCCEC::setImpl(p_libCCECImplMock); + + p_messageEncoderMock = new testing::NiceMock ; + MessageEncoder::setImpl(p_messageEncoderMock); + + p_connectionImplMock = new testing::NiceMock ; + Connection::setImpl(p_connectionImplMock); + + p_videoOutputPortMock = new testing::NiceMock ; + device::VideoOutputPort::setImpl(p_videoOutputPortMock); + + p_displayMock = new testing::NiceMock ; + device::Display::setImpl(p_displayMock); + + //OnCall required for intialize to run properly + ON_CALL(*p_hostImplMock, getVideoOutputPort(::testing::_)) + .WillByDefault(::testing::ReturnRef(device::VideoOutputPort::getInstance())); + + ON_CALL(*p_videoOutputPortMock, getDisplay()) + .WillByDefault(::testing::ReturnRef(device::Display::getInstance())); + + ON_CALL(*p_videoOutputPortMock, isDisplayConnected()) + .WillByDefault(::testing::Return(true)); + + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::ReturnRef(CECFrame::getInstance())); + + ON_CALL(*p_displayMock, getEDIDBytes(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector &edidVec2) { + edidVec2 = std::vector({ 't', 'e', 's', 't' }); + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_CECMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_CECMGR_EVENT_STATUS_UPDATED)) { + EXPECT_TRUE(handler != nullptr); + cecMgrEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + } + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + EXPECT_TRUE(handler != nullptr); + pwrMgrEventHandler = handler; + } + + return IARM_RESULT_SUCCESS; + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0) { + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + return IARM_RESULT_SUCCESS; + }); + + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + //Set enabled needs to be + ON_CALL(*p_libCCECImplMock, getLogicalAddress(::testing::_)) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_connectionImplMock, open()) + .WillByDefault(::testing::Return()); + ON_CALL(*p_connectionImplMock, addFrameListener(::testing::_)) + .WillByDefault(::testing::Return()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + } + virtual ~HdmiCecSourceInitializedTest() override + { + int lCounter = 0; + while ((Plugin::HdmiCecSource::_instance->deviceList[0].m_isOSDNameUpdated) && (lCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + lCounter ++; + } + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + plugin->Deinitialize(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + LibCCEC::setImpl(nullptr); + if (p_libCCECImplMock != nullptr) + { + delete p_libCCECImplMock; + p_libCCECImplMock = nullptr; + } + Connection::setImpl(nullptr); + if (p_connectionImplMock != nullptr) + { + delete p_connectionImplMock; + p_connectionImplMock = nullptr; + } + MessageEncoder::setImpl(nullptr); + if (p_messageEncoderMock != nullptr) + { + delete p_messageEncoderMock; + p_messageEncoderMock = nullptr; + } + device::Display::setImpl(nullptr); + if (p_displayMock != nullptr) + { + delete p_displayMock; + p_displayMock = nullptr; + } + device::VideoOutputPort::setImpl(nullptr); + if (p_videoOutputPortMock != nullptr) + { + delete p_videoOutputPortMock; + p_videoOutputPortMock = nullptr; + } + device::Manager::setImpl(nullptr); + if (p_managerImplMock != nullptr) + { + delete p_managerImplMock; + p_managerImplMock = nullptr; + } + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; +class HdmiCecSourceInitializedEventTest : public HdmiCecSourceInitializedTest { +protected: + testing::NiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HdmiCecSourceInitializedEventTest() + : HdmiCecSourceInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~HdmiCecSourceInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + } +}; + +TEST_F(HdmiCecSourceTest, RegisteredMethods) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getActiveSourceStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceList"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOSDName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOTPEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVendorId"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("performOTPAction"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendKeyPressEvent"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("sendStandbyMessage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOSDName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOTPEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVendorId"))); + +} + +TEST_F(HdmiCecSourceDsTest, getEnabledFalse) +{ + //Without setting cecEnable to true. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"success\":true}")); +} + + +TEST_F(HdmiCecSourceInitializedTest, getEnabledTrue) +{ + //Get enabled just checks if CEC is on, which is a global variable. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnabled"), _T(""), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + +} + +TEST_F(HdmiCecSourceInitializedTest, getActiveSourceStatusTrue) +{ + //SetsOTP to on. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + //Sets Activesource to true + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("performOTPAction"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":true,\"success\":true}")); + + +} +TEST_F(HdmiCecSourceInitializedTest, getActiveSourceStatusFalse) +{ + //ActiveSource is a local variable, no mocked functions to check. + //Active source is false by default. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getActiveSourceStatus"), _T(""), response)); + EXPECT_EQ(response, string("{\"status\":false,\"success\":true}")); +} + + +TEST_F(HdmiCecSourceInitializedTest, getDeviceList) +{ + int iCounter = 0; + //Checking to see if one of the values has been filled in (as the rest get filled in at the same time, and waiting if its not. + while ((!Plugin::HdmiCecSource::_instance->deviceList[0].m_isOSDNameUpdated) && (iCounter < (2*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + const char* val = "TEST"; + OSDName name = OSDName(val); + SetOSDName osdName = SetOSDName(name); + + Header header; + header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using + + VendorID vendor(1,2,3); + DeviceVendorID vendorid(vendor); + + Plugin::HdmiCecSourceProcessor proc(Connection::getInstance()); + + proc.process(osdName, header); //calls the process that sets osdName for LogicalAddress = 1 + proc.process(vendorid, header); //calls the process that sets vendorID for LogicalAddress = 1 + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceList"), _T(""), response)); + + EXPECT_EQ(response, string(_T("{\"numberofdevices\":14,\"deviceList\":[{\"logicalAddress\":1,\"osdName\":\"TEST\",\"vendorID\":\"123\"},{\"logicalAddress\":2,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":3,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":4,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":5,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":6,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":7,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":8,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":9,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":10,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":11,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":12,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":13,\"osdName\":\"NA\",\"vendorID\":\"000\"},{\"logicalAddress\":14,\"osdName\":\"NA\",\"vendorID\":\"000\"}],\"success\":true}"))); + + +} + + +TEST_F(HdmiCecSourceInitializedTest, getOTPEnabled) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOTPEnabled"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + +} + + + +TEST_F(HdmiCecSourceInitializedTest, sendStandbyMessage) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendStandbyMessage"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiCecSourceInitializedTest, setOSDName) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOSDName"), _T("{\"name\": \"Sky Tv\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOSDName"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"name\":\"Sky Tv\",\"success\":true}")); + + + +} +TEST_F(HdmiCecSourceInitializedTest, setVendorId) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVendorId"), _T("{\"vendorid\": \"0x0019FB\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVendorId"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"vendorid\":\"019fb\",\"success\":true}")); + + +} +TEST_F(HdmiCecSourceInitializedTest, setOTPEnabled) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOTPEnabled"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + + + +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEventUp) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_VOLUME_UP ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 65}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent2) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_VOLUME_DOWN ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 66}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent3) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_MUTE ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 67}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent4) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_UP ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 1}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent5) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_DOWN ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 2}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent6) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_LEFT ); + return CECFrame::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 3}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent7) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_RIGHT ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 4}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent8) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_SELECT ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 0}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent9) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_HOME ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 9}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent10) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_BACK ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 13}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent11) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_0 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 32}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent12) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_1 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 33}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent13) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_2 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 34}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent14) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_3 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 35}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent15) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_4 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 36}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent16) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_5 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 37}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent17) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_6 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 38}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent18) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_7 ); + return CECFrame::getInstance(); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 39}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent19) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_8 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 40}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} +TEST_F(HdmiCecSourceInitializedTest, sendKeyPressEvent20) +{ + ON_CALL(*p_messageEncoderMock, encode(::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const UserControlPressed& m) -> CECFrame& { + EXPECT_EQ(m.uiCommand.toInt(),UICommand::UI_COMMAND_NUM_9 ); + return CECFrame::getInstance(); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("sendKeyPressEvent"), _T("{\"logicalAddress\": 0, \"keyCode\": 41}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + diff --git a/NetworkManager/Tests/L1Tests/tests/test_HdmiInput.cpp b/NetworkManager/Tests/L1Tests/tests/test_HdmiInput.cpp new file mode 100755 index 0000000000..fb59306b9f --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_HdmiInput.cpp @@ -0,0 +1,812 @@ +#include + +#include "HdmiInput.h" + +#include "FactoriesImplementation.h" + +#include "HdmiInputMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" + +#include "dsMgr.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class HdmiInputTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Handler& handlerV2; + Core::JSONRPC::Connection connection; + string response; + + HdmiInputTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , handlerV2(*(plugin->GetHandler(2))) + , connection(1, 0) + { + } + virtual ~HdmiInputTest() = default; +}; + +class HdmiInputDsTest : public HdmiInputTest { +protected: + HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; + + HdmiInputDsTest() + : HdmiInputTest() + { + p_hdmiInputImplMock = new NiceMock ; + device::HdmiInput::setImpl(p_hdmiInputImplMock); + } + virtual ~HdmiInputDsTest() override + { + device::HdmiInput::setImpl(nullptr); + if (p_hdmiInputImplMock != nullptr) + { + delete p_hdmiInputImplMock; + p_hdmiInputImplMock = nullptr; + } + } +}; + +class HdmiInputInitializedTest : public HdmiInputTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + IARM_EventHandler_t dsHdmiEventHandler; + IARM_EventHandler_t dsHdmiStatusEventHandler; + IARM_EventHandler_t dsHdmiSignalStatusEventHandler; + IARM_EventHandler_t dsHdmiVideoModeEventHandler; + IARM_EventHandler_t dsHdmiGameFeatureStatusEventHandler; + + // NiceMock service; + ServiceMock service; + + HdmiInputInitializedTest() + : HdmiInputTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return nullptr; + })); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiSignalStatusEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiVideoModeEventHandler = handler; + } + if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiGameFeatureStatusEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~HdmiInputInitializedTest() override + { + plugin->Deinitialize(&service); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + + +class HdmiInputInitializedEventTest : public HdmiInputInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + HdmiInputInitializedEventTest() + : HdmiInputInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~HdmiInputInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class HdmiInputInitializedEventDsTest : public HdmiInputInitializedEventTest { +protected: + HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; + + HdmiInputInitializedEventDsTest() + : HdmiInputInitializedEventTest() + { + p_hdmiInputImplMock = new NiceMock ; + device::HdmiInput::setImpl(p_hdmiInputImplMock); + } + + virtual ~HdmiInputInitializedEventDsTest() override + { + device::HdmiInput::setImpl(nullptr); + if (p_hdmiInputImplMock != nullptr) + { + delete p_hdmiInputImplMock; + p_hdmiInputImplMock = nullptr; + } + } +}; + +TEST_F(HdmiInputTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHDMIInputDevices"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("writeEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("readEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getRawHDMISPD"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMISPD"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setEdidVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getEdidVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startHdmiInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopHdmiInput"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSupportedGameFeatures"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHdmiGameFeatureStatus"))); + + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMIInputDevices"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("writeEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("readEDID"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("startHdmiInput"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("stopHdmiInput"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setVideoRectangle"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getSupportedGameFeatures"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHdmiGameFeatureStatus"))); +} + +TEST_F(HdmiInputDsTest, getHDMIInputDevices) +{ + + ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) + .WillByDefault(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHDMIInputDevices"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}],\"success\":true}")); +} + + +TEST_F(HdmiInputDsTest, writeEDIDEmpty) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("writeEDID"), _T("{\"message\": \"message\"}"), response)); + EXPECT_EQ(response, string("")); +} + + +TEST_F(HdmiInputDsTest, writeEDID) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("writeEDID"), _T("{\"deviceId\": 0, \"message\": \"message\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiInputDsTest, writeEDIDInvalid) +{ + ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector &edidVec2) { + edidVec2 = std::vector({ 't', 'e', 's', 't' }); + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": \"b\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, readEDID) +{ + ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector &edidVec2) { + edidVec2 = std::vector({ 't', 'e', 's', 't' }); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": 0}"), response)); + EXPECT_EQ(response, string("{\"EDID\":\"dGVzdA==\",\"success\":true}")); +} + +TEST_F(HdmiInputDsTest, getRawHDMISPD) +{ + ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector& edidVec2) { + edidVec2 = { 't', 'e', 's', 't' }; + })); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":0}"), response)); + EXPECT_EQ(response, string("{\"HDMISPD\":\"dGVzdA\",\"success\":true}")); +} +TEST_F(HdmiInputDsTest, getRawHDMISPDInvalid) +{ + ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector& edidVec2) { + edidVec2 = { 't', 'e', 's', 't' }; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":\"b\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, getHDMISPD) +{ + ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector& edidVec2) { + edidVec2 = {'0','1','2','n', 'p', '1','2','3','4','5','6','7',0,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',0,'q','r'}; + })); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":0}"), response)); + EXPECT_EQ(response, string("{\"HDMISPD\":\"Packet Type:30,Version:49,Length:50,vendor name:1234567,product des:abcdefghijklmno,source info:71\",\"success\":true}")); +} +TEST_F(HdmiInputDsTest, getHDMISPDInvalid) +{ + ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, std::vector& edidVec2) { + edidVec2 = {'0','1','2','n', 'p', '0'}; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":\"b\"}"), response)); + EXPECT_EQ(response, string("")); +} + + +TEST_F(HdmiInputDsTest, setEdidVersionInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, setEdidVersion14) +{ + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI1.4\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiInputDsTest, setEdidVersion20) +{ + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI2.0\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +TEST_F(HdmiInputDsTest, setEdidVersionEmpty) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, getEdidVersionInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); + EXPECT_EQ(response, string("")); +} +TEST_F(HdmiInputDsTest, getEdidVersionVer14) +{ + ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iPort, int *edidVersion) { + *edidVersion = 0; + })); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI1.4\",\"success\":true}")); +} +TEST_F(HdmiInputDsTest, getEdidVersionVer20) +{ + ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iPort, int *edidVersion) { + *edidVersion = 1; + })); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI2.0\",\"success\":true}")); +} + +TEST_F(HdmiInputDsTest, startHdmiInputInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"b\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, startHdmiInput) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + + +TEST_F(HdmiInputDsTest, stopHdmiInput) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(HdmiInputDsTest, setVideoRectangleInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": \"b\",\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, setVideoRectangle) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": 0,\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + + +TEST_F(HdmiInputDsTest, getSupportedGameFeatures) +{ + ON_CALL(*p_hdmiInputImplMock, getSupportedGameFeatures(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](std::vector &supportedFeatures) { + supportedFeatures = {"ALLM"}; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedGameFeatures"), _T("{\"supportedGameFeatures\": \"ALLM\"}"), response)); + EXPECT_EQ(response, string("{\"supportedGameFeatures\":[\"ALLM\"],\"success\":true}")); +} + + +TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidPort) +{ + ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, bool *allm) { + *allm = true; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"b\",\"gameFeature\": \"ALLM\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatus) +{ + ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, bool *allm) { + *allm = true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"ALLM\"}"), response)); + EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); +} +TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidFeature) +{ + ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) + .WillByDefault(::testing::Invoke( + [&](int iport, bool *allm) { + *allm = true; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"Invalid\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(HdmiInputInitializedEventDsTest, onDevicesChanged) +{ + ASSERT_TRUE(dsHdmiEventHandler != nullptr); + ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) + .WillByDefault(::testing::Return(1)); + ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) + .WillByDefault(::testing::Return(true)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onDevicesChanged.onDevicesChanged\",\"params\":{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}]}}"))); + + return Core::ERROR_NONE; + })); + + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_connect.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_connect.isPortConnected = true; + handler.Subscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); + + dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &eventData , 0); + + handler.Unsubscribe(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); +} + +TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOn) +{ + ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\",\"plane\":0}}"))); + return Core::ERROR_NONE; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_status.isPresented = true; + handler.Subscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); + dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOff) +{ + ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\",\"plane\":-1}}"))); + return Core::ERROR_NONE; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_status.isPresented = false; + handler.Subscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); + dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedStable) +{ + ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_STABLE; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNoSignal) +{ + ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedUnstable) +{ + ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_UNSTABLE; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNotSupported) +{ + ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedDefault) +{ + ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_MAX; + handler.Subscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); + dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); + handler.Unsubscribe(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); +} + +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate1) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1001}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1920x1080; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_59dot94; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate2) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":480,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x480; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_24; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate3) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":576,\"progressive\":false,\"frameRateN\":25000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x576; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_25; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate4) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":3840,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_3840x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_30; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate5) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":50000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_50; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate6) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_60; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate7) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1001}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_23dot98; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate8) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate9) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1280,\"height\":720,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdateDefault) +{ + ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); + return Core::ERROR_NONE; + })); + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_MAX; + eventData.data.hdmi_in_video_mode.resolution.interlaced = true; + eventData.data.hdmi_in_video_mode.resolution.frameRate= dsVIDEO_FRAMERATE_MAX; + handler.Subscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); + dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); + handler.Unsubscribe(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); +} +TEST_F(HdmiInputInitializedEventDsTest, hdmiGameFeatureStatusUpdate) +{ + ASSERT_TRUE(dsHdmiGameFeatureStatusEventHandler != nullptr); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.hdmiGameFeatureStatusUpdate.hdmiGameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"ALLM\",\"mode\":true}}"))); + + return Core::ERROR_NONE; + })); + + + IARM_Bus_DSMgr_EventData_t eventData; + eventData.data.hdmi_in_allm_mode.port =dsHDMI_IN_PORT_0; + eventData.data.hdmi_in_allm_mode.allm_mode = true; + handler.Subscribe(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); + + dsHdmiGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, &eventData , 0); + + handler.Unsubscribe(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_JSON.cpp b/NetworkManager/Tests/L1Tests/tests/test_JSON.cpp new file mode 100755 index 0000000000..86fc3602e2 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_JSON.cpp @@ -0,0 +1,283 @@ +#include + +#include "Module.h" + +using namespace WPEFramework; + +TEST(JSONTest, EMPTY) +{ + JsonObject object; + EXPECT_FALSE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::EMPTY, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("null"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +/** + * FIXME + * | ===== $$ [6755]: ASSERT [JSON.h:138] (loaded <= payload) + */ +TEST(JSONTest, DOUBLE) +{ + JsonObject object; + object[_T("key")] = 1.2345; + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::DOUBLE, object[_T("key")].Content()); + // EXPECT_EQ(0, object[_T("key")].Number()); + // EXPECT_EQ(1.2345f, object[_T("key")].Float()); + // EXPECT_EQ(1.2345, object[_T("key")].Double()); + EXPECT_EQ(_T("1.2345"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +/** + * FIXME + * | ===== $$ [6755]: ASSERT [JSON.h:138] (loaded <= payload) + */ +TEST(JSONTest, FLOAT) +{ + JsonObject object; + object[_T("key")] = 1.2345f; + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::FLOAT, object[_T("key")].Content()); + // EXPECT_EQ(0, object[_T("key")].Number()); + // EXPECT_EQ(1.2345f, object[_T("key")].Float()); + // EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("1.2345"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +/** + * FIXME + * 1.2345 is deserialized to NUMBER 1 ??? + */ +TEST(JSONTest, FloatingPointDeserialized) +{ + JsonObject object; + object.FromString(_T("{\"key\":1.2345}")); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::NUMBER, object[_T("key")].Content()); + EXPECT_EQ(1, object[_T("key")].Number()); + EXPECT_EQ(1.0f, object[_T("key")].Float()); + EXPECT_EQ(1, object[_T("key")].Double()); + EXPECT_EQ(_T("1.2345"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, NUMBER) +{ + JsonObject object; + object[_T("key")] = 12345; + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::NUMBER, object[_T("key")].Content()); + EXPECT_EQ(12345, object[_T("key")].Number()); + EXPECT_EQ(12345.0f, object[_T("key")].Float()); + EXPECT_EQ(12345.0, object[_T("key")].Double()); + EXPECT_EQ(_T("12345"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, NumberAsStringDeserialized) +{ + JsonObject object; + object.FromString(_T("{\"key\":\"12345\"}")); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::STRING, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("12345"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, BOOLEAN) +{ + JsonObject object; + object[_T("key")] = true; + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::BOOLEAN, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("true"), object[_T("key")].String()); + EXPECT_EQ(true, object[_T("key")].Boolean()); +} + +TEST(JSONTest, BooleanTrueAsStringDeserialized) +{ + JsonObject object; + object.FromString(_T("{\"key\":\"true\"}")); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::STRING, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("true"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, BooleanFalseAsStringDeserialized) +{ + JsonObject object; + object.FromString(_T("{\"key\":\"false\"}")); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::STRING, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("false"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, STRING) +{ + JsonObject object; + object[_T("key")] = _T("value"); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::STRING, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("value"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, ARRAY) +{ + JsonObject object; + object[_T("key")] = JsonArray(); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::ARRAY, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("[]"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, OBJECT) +{ + JsonObject object; + object[_T("key")] = JsonObject(); + EXPECT_TRUE(object.HasLabel(_T("key"))); + EXPECT_EQ(Core::JSON::Variant::type::OBJECT, object[_T("key")].Content()); + EXPECT_EQ(0, object[_T("key")].Number()); + EXPECT_EQ(0.0f, object[_T("key")].Float()); + EXPECT_EQ(0.0, object[_T("key")].Double()); + EXPECT_EQ(_T("{}"), object[_T("key")].String()); + EXPECT_EQ(false, object[_T("key")].Boolean()); +} + +TEST(JSONTest, solidus_JsonObject_FromString) +{ + const string example = _T("{\"url\":\"http://example.com\"}"); + const string exampleEscaped = _T("{\"url\":\"http:\\/\\/example.com\"}"); + JsonObject jsonObject; + jsonObject.FromString(example); + EXPECT_EQ(string(_T("http://example.com")), jsonObject[_T("url")].String()); + string cString; + jsonObject.ToString(cString); + EXPECT_EQ(exampleEscaped, cString); +} + +TEST(JSONTest, solidus_JsonObject_FromString_Escaped) +{ + const string example = _T("{\"url\":\"http://example.com\"}"); + const string exampleEscaped = _T("{\"url\":\"http:\\/\\/example.com\"}"); + JsonObject jsonObject; + jsonObject.FromString(exampleEscaped); + EXPECT_EQ(string(_T("http://example.com")), jsonObject[_T("url")].String()); + string cString; + jsonObject.ToString(cString); + EXPECT_EQ(exampleEscaped, cString); +} + +TEST(JSONTest, solidus_JSON_String_FromString) +{ + const string example = _T("http://example.com"); + const string exampleEscapedQuoted = _T("\"http:\\/\\/example.com\""); + Core::JSON::String jsonString; + jsonString.FromString(example); + EXPECT_EQ(example, jsonString.Value()); + string cString; + jsonString.ToString(cString); + EXPECT_EQ(exampleEscapedQuoted, cString); +} + +TEST(JSONTest, solidus_JSON_String_FromString_Escaped) +{ + const string example = _T("http://example.com"); + const string exampleEscaped = _T("http:\\/\\/example.com"); + const string exampleEscapedQuoted = _T("\"http:\\/\\/example.com\""); + Core::JSON::String jsonString; + jsonString.FromString(exampleEscaped); + EXPECT_EQ(example, jsonString.Value()); + string cString; + jsonString.ToString(cString); + EXPECT_EQ(exampleEscapedQuoted, cString); +} + +class Payload : public Core::JSON::Container { +public: + Payload() + : Core::JSON::Container() + { + Add(_T("url"), &URL); + } + + Core::JSON::String URL; +}; + +TEST(JSONTest, JSONContainerFromString) +{ + const string example = _T("http://example.com"); + const string exampleContainer = _T("{\"url\":\"http://example.com\"}"); + Payload payload; + EXPECT_TRUE(payload.FromString(exampleContainer)); + EXPECT_TRUE(payload.URL.IsSet()); + EXPECT_EQ(example, payload.URL.Value()); +} + +TEST(JSONTest, JSONContainerFromStringEmpty) +{ + const string example = _T(""); + const string exampleContainer = _T("{}"); + Payload payload; + EXPECT_FALSE(payload.FromString(exampleContainer)); + EXPECT_FALSE(payload.URL.IsSet()); + EXPECT_EQ(example, payload.URL.Value()); +} + +TEST(JSONTest, JSONContainerFromStringExtra) +{ + const string example = _T("http://example.com"); + const string exampleContainer = _T("{\"url\":\"http://example.com\",\"hash\":\"7c35a3ce607a14953f070f0f83b5d74c2296ef93\"}"); + Payload payload; + EXPECT_TRUE(payload.FromString(exampleContainer)); + EXPECT_TRUE(payload.URL.IsSet()); + EXPECT_EQ(example, payload.URL.Value()); +} + +TEST(JSONTest, JSONContainerFromStringDifferent) +{ + const string example = _T(""); + const string exampleContainer = _T("{\"hash\":\"7c35a3ce607a14953f070f0f83b5d74c2296ef93\"}"); + Payload payload; + EXPECT_TRUE(payload.FromString(exampleContainer)); + EXPECT_FALSE(payload.URL.IsSet()); + EXPECT_EQ(example, payload.URL.Value()); +} + +TEST(JSONTest, JSONContainerFromStringWrong) +{ + const string example = _T("http://example.com"); + Payload payload; + EXPECT_FALSE(payload.FromString(example)); + EXPECT_FALSE(payload.URL.IsSet()); + payload.URL = example; + EXPECT_TRUE(payload.URL.IsSet()); + EXPECT_EQ(example, payload.URL.Value()); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_LocationSync.cpp b/NetworkManager/Tests/L1Tests/tests/test_LocationSync.cpp new file mode 100755 index 0000000000..93adf122fd --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_LocationSync.cpp @@ -0,0 +1,216 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include + +#include "LocationSync.h" + +#include "FactoriesImplementation.h" +#include "ServiceMock.h" +#include "SystemInfo.h" +#include "WorkerPoolImplementation.h" + +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string webPrefix = _T("/Service/LocationSync"); +} + +namespace { +class SystemInfoMock : public SystemInfo { +public: + virtual ~SystemInfoMock() = default; + MOCK_METHOD(void, Set, (const subsystem type, WPEFramework::Core::IUnknown* information), (override)); +}; +} + +class LocationSyncTest : public ::testing::Test { +protected: + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + NiceMock service; + Core::Sink> subSystem; + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + Core::JSONRPC::Message message; + string response; + PluginHost::IDispatcher* dispatcher; + + LocationSyncTest() + : workerPool(Core::ProxyType::Create( + 5, Core::Thread::DefaultStackSize(), 16)) + , plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + PluginHost::IFactories::Assign(&factoriesImplementation); + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\n" + "\"interval\":10,\n" + "\"retries\":20,\n" + "\"source\":\"http://jsonip.metrological.com/?maf=true\"\n" + "}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, SubSystems()) + .WillByDefault(::testing::Invoke( + [&]() { + PluginHost::ISubSystem* result = (&subSystem); + result->AddRef(); + return result; + })); + ON_CALL(subSystem, Set(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const PluginHost::ISubSystem::subsystem type, WPEFramework::Core::IUnknown* information) { + subSystem.SystemInfo::Set(type, information); + })); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~LocationSyncTest() + { + dispatcher->Deactivate(); + dispatcher->Release(); + + plugin.Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(LocationSyncTest, activate_locationchange_location_deactivate) +{ + Core::Event locationchange(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"LocationSync.locationchange\"," + "\"params\":\"\"" + "}"))); + + locationchange.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("locationchange"), _T("LocationSync"), message); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, locationchange.Lock(100000)); // 100s + + EXPECT_TRUE(subSystem.Get(PluginHost::ISubSystem::LOCATION) != nullptr); + EXPECT_TRUE(subSystem.Get(PluginHost::ISubSystem::INTERNET) != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("location"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"city\":\".*\"," + "\"country\":\".*\"," + "\"region\":\".*\"," + "\"timezone\":\".+\"," + "\"publicip\":\".+\"" + "\\}")); + + handler.Unsubscribe(0, _T("locationchange"), _T("LocationSync"), message); + + plugin->Deinitialize(&service); +} + +TEST_F(LocationSyncTest, activate_sync_deactivate) +{ + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_INPROGRESS, handler.Invoke(connection, _T("sync"), _T("{}"), response)); + + plugin->Deinitialize(&service); +} + +TEST_F(LocationSyncTest, activateWithIncorrectUrl) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\n" + "\"interval\":10,\n" + "\"retries\":20,\n" + "\"source\":\"http://0.0.0.0\"\n" + "}")); + + EXPECT_EQ(string("URL for retrieving location is incorrect !!!"), plugin->Initialize(&service)); +} + +TEST_F(LocationSyncTest, activateWithUnreachableHost_location_deactivate) +{ + Core::Event location(false, true); + Core::Event internet(false, true); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\n" + "\"interval\":1,\n" + "\"retries\":1,\n" + "\"source\":\"http://jsonip.metrological.com:1234/?maf=true\"\n" + "}")); + EXPECT_CALL(subSystem, Set(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const PluginHost::ISubSystem::subsystem type, WPEFramework::Core::IUnknown* information) { + subSystem.SystemInfo::Set(type, information); + if (type == PluginHost::ISubSystem::LOCATION) { + location.SetEvent(); + } else if (type == PluginHost::ISubSystem::INTERNET) { + internet.SetEvent(); + } + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, location.Lock(100000)); // 100s + EXPECT_EQ(Core::ERROR_NONE, internet.Lock(100000)); // 100s + + EXPECT_TRUE(subSystem.Get(PluginHost::ISubSystem::LOCATION) != nullptr); + EXPECT_TRUE(subSystem.Get(PluginHost::ISubSystem::INTERNET) != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("location"), _T(""), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"city\":\"\"," + "\"country\":\"\"," + "\"region\":\"\"," + "\"timezone\":\"\"," + "\"publicip\":\"\"" + "\\}")); + + plugin->Deinitialize(&service); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_LoggingPreferences.cpp b/NetworkManager/Tests/L1Tests/tests/test_LoggingPreferences.cpp new file mode 100755 index 0000000000..73f2c157ac --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_LoggingPreferences.cpp @@ -0,0 +1,230 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" + +#include "LoggingPreferences.h" + +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "sysMgr.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class LoggingPreferencesTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + LoggingPreferencesTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~LoggingPreferencesTest() = default; +}; + +class LoggingPreferencesInitializedTest : public LoggingPreferencesTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + + LoggingPreferencesInitializedTest() + : LoggingPreferencesTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~LoggingPreferencesInitializedTest() override + { + plugin->Deinitialize(nullptr); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + } +}; + +class LoggingPreferencesInitializedEventTest : public LoggingPreferencesInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + LoggingPreferencesInitializedEventTest() + : LoggingPreferencesInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~LoggingPreferencesInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(LoggingPreferencesTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isKeystrokeMaskEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setKeystrokeMaskEnabled"))); +} + +TEST_F(LoggingPreferencesTest, paramsMissing) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{}"), response)); +} + +TEST_F(LoggingPreferencesInitializedTest, getKeystrokeMask) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref) == 0) { + auto* param = static_cast(arg); + param->logStatus = 1; //Setting 1 returns response as false + } + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isKeystrokeMaskEnabled"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"keystrokeMaskEnabled\":false,\"success\":true}")); +} + +TEST_F(LoggingPreferencesInitializedEventTest, enableKeystrokeMask) +{ + Core::Event onKeystrokeMaskEnabledChange(false, true); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref) == 0) { + auto* param = static_cast(arg); + param->logStatus = 1; + } + return IARM_RESULT_SUCCESS; + }); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + // called by onKeystrokeMaskEnabledChange + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.LoggingPreferences.onKeystrokeMaskEnabledChange\"," + "\"params\":{\"keystrokeMaskEnabled\":true}" + "}"))); + + onKeystrokeMaskEnabledChange.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onKeystrokeMaskEnabledChange"), _T("org.rdk.LoggingPreferences"), message); + + //Simulating the case for setting the same value again + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{\"keystrokeMaskEnabled\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{\"keystrokeMaskEnabled\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, onKeystrokeMaskEnabledChange.Lock()); + + handler.Unsubscribe(0, _T("onKeystrokeMaskEnabledChange"), _T("org.rdk.LoggingPreferences"), message); +} + +TEST_F(LoggingPreferencesInitializedEventTest, disbleKeystrokeMask) +{ + Core::Event onKeystrokeMaskEnabledChange(false, true); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref) == 0) { + auto* param = static_cast(arg); + param->logStatus = 0; + } + return IARM_RESULT_SUCCESS; + }); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + // called by onKeystrokeMaskEnabledChange + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.LoggingPreferences.onKeystrokeMaskEnabledChange\"," + "\"params\":{\"keystrokeMaskEnabled\":false}" + "}"))); + + onKeystrokeMaskEnabledChange.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onKeystrokeMaskEnabledChange"), _T("org.rdk.LoggingPreferences"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{\"keystrokeMaskEnabled\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, onKeystrokeMaskEnabledChange.Lock()); + + handler.Unsubscribe(0, _T("onKeystrokeMaskEnabledChange"), _T("org.rdk.LoggingPreferences"), message); +} + +TEST_F(LoggingPreferencesInitializedTest, errorCases) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + if (strcmp(methodName, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref) == 0) { + return IARM_RESULT_IPCCORE_FAIL; + } else if (strcmp(methodName, IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref) == 0) { + auto* param = static_cast(arg); + param->logStatus = 0; + } + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isKeystrokeMaskEnabled"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{\"keystrokeMaskEnabled\":false}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setKeystrokeMaskEnabled"), _T("{\"keystrokeMaskEnabled\":false}"), response)); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_MaintenanceManager.cpp b/NetworkManager/Tests/L1Tests/tests/test_MaintenanceManager.cpp new file mode 100755 index 0000000000..80d19271d1 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_MaintenanceManager.cpp @@ -0,0 +1,397 @@ + +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" +#include +#include +#include "FactoriesImplementation.h" +#include "MaintenanceManager.h" +#include "RfcApiMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "WrapsMock.h" + +using namespace WPEFramework; +using ::testing::NiceMock; +using ::testing::_; +using ::testing::Invoke; +using ::testing::Test; +using ::testing::StrEq; +using ::testing::Gt; +using ::testing::AssertionResult; +using ::testing::AssertionSuccess; +using ::testing::AssertionFailure; + +extern "C" FILE* __real_popen(const char* command, const char* type); +extern "C" int __real_pclose(FILE* pipe); + +class MaintenanceManagerTest : public Test { +protected: + Core::ProxyType plugin_; + Core::JSONRPC::Handler& handler_; + Core::JSONRPC::Connection connection_; + string response_; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + RfcApiImplMock *p_rfcApiImplMock = nullptr ; + WrapsImplMock *p_wrapsImplMock = nullptr ; + + MaintenanceManagerTest() + : plugin_(Core::ProxyType::Create()) + , handler_(*plugin_) + , connection_(1, 0) + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_rfcApiImplMock = new testing::NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + + p_wrapsImplMock = new testing::NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + } + + virtual ~MaintenanceManagerTest() override + { + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + } +}; + + +static AssertionResult isValidCtrlmRcuIarmEvent(IARM_EventId_t ctrlmRcuIarmEventId) +{ + switch (ctrlmRcuIarmEventId) { + case IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE: + case IARM_BUS_DCM_NEW_START_TIME_EVENT: + return AssertionSuccess(); + default: + return AssertionFailure(); + } +} + +class MaintenanceManagerInitializedEventTest : public MaintenanceManagerTest { +protected: + IARM_EventHandler_t controlEventHandler_; + NiceMock service_; + NiceMock factoriesImplementation_; + Core::JSONRPC::Message message_; + PluginHost::IDispatcher* dispatcher_; + + MaintenanceManagerInitializedEventTest() : + MaintenanceManagerTest() + { + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(StrEq(IARM_BUS_MAINTENANCE_MGR_NAME),IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, _)) + .WillOnce(Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + controlEventHandler_ = handler; + return IARM_RESULT_SUCCESS; + })); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(StrEq(IARM_BUS_MAINTENANCE_MGR_NAME), IARM_BUS_DCM_NEW_START_TIME_EVENT, _)) + .WillRepeatedly(Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + EXPECT_TRUE(isValidCtrlmRcuIarmEvent(eventId)); + controlEventHandler_ = handler; + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin_->Initialize(&service_)); + PluginHost::IFactories::Assign(&factoriesImplementation_); + dispatcher_ = static_cast(plugin_->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher_->Activate(&service_); + } + + virtual ~MaintenanceManagerInitializedEventTest() override + { + plugin_->Deinitialize(&service_); + dispatcher_->Deactivate(); + dispatcher_->Release(); + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(MaintenanceManagerTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getMaintenanceActivityStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getMaintenanceStartTime"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("setMaintenanceMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("startMaintenance"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("stopMaintenance"))); + EXPECT_EQ(Core::ERROR_NONE, handler_.Exists(_T("getMaintenanceMode"))); +} + +TEST_F(MaintenanceManagerTest, setMaintenanceMode) +{ + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", MAX_PARAM_LEN); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"IGNORE_UPDATE\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"IGNORE_UPDATE\",\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"ENFORCE_OPTOUT\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"ENFORCE_OPTOUT\",\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"BYPASS_OPTOUT\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"FOREGROUND\",\"optOut\":\"BYPASS_OPTOUT\",\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"IGNORE_UPDATE\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"IGNORE_UPDATE\",\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"ENFORCE_OPTOUT\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"ENFORCE_OPTOUT\",\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.setMaintenanceMode"), _T("{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"BYPASS_OPTOUT\"}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("org.rdk.MaintenanceManager.1.getMaintenanceMode"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceMode\":\"BACKGROUND\",\"optOut\":\"BYPASS_OPTOUT\",\"success\":true}"); +} + +TEST_F(MaintenanceManagerTest, getMaintenanceActivityStatus) +{ + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("getMaintenanceActivityStatus"), _T("{}"), response_)); +} +#if 0 +TEST_F(MaintenanceManagerInitializedEventTest, startMaintenanceOnReboot) +{ + IARM_Bus_MaintMGR_EventData_t eventData; + struct tm result = {}; + time_t start_time = time(NULL); + + localtime_r(&start_time, &result); + snprintf(eventData.data.startTimeUpdate.start_time, MAX_TIME_LEN-1, "%04d-%02d-%02d %02d:%02d:%02d", + result.tm_year+1900, + result.tm_mon +1, + result.tm_mday, + result.tm_hour, + result.tm_min, + result.tm_sec); + eventData.data.startTimeUpdate.start_time[MAX_TIME_LEN-1] = '\0'; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_DCM_NEW_START_TIME_EVENT, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + EXPECT_CALL(wrapsImplMock, system(::testing::_)) + .Times(4) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/StartDCM_maintaince.sh &"))); + return 0; + })) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/RFCbase.sh &"))); + return 0; + })) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/swupdate_utility.sh >> /opt/logs/swupdate.log &"))); + return 0; + })) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/Start_uploadSTBLogs.sh &"))); + return 0; + })); + std::this_thread::sleep_for(std::chrono::seconds(3)); + + eventData.data.maintenance_module_status.status = MAINT_DCM_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_DCM_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_RFC_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_RFC_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(5)); + +} + +TEST_F(MaintenanceManagerInitializedEventTest, startMaintenance) +{ + IARM_Bus_MaintMGR_EventData_t eventData; + + EXPECT_CALL(wrapsImplMock, system(::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](const char* command) { + return 0; + })); + std::this_thread::sleep_for(std::chrono::seconds(3)); + + eventData.data.maintenance_module_status.status = MAINT_DCM_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_DCM_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_RFC_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_RFC_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("startMaintenance"), _T("{org.rdk.startMaintenance}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_RFC_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_RFC_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_FWDOWNLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(3)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_LOGUPLOAD_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + std::this_thread::sleep_for(std::chrono::seconds(5)); +} + +TEST_F(MaintenanceManagerInitializedEventTest, stopMaintenanceRFCEnable) +{ + IARM_Bus_MaintMGR_EventData_t eventData; + + EXPECT_CALL(wrapsImplMock, system(::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const char* command) { + return 0; + })); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + eventData.data.maintenance_module_status.status = MAINT_DCM_INPROGRESS; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + eventData.data.maintenance_module_status.status = MAINT_DCM_COMPLETE; + controlEventHandler_(IARM_BUS_MAINTENANCE_MGR_NAME, IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, &eventData, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + ON_CALL(rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", MAX_PARAM_LEN); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("stopMaintenance"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"success\":true}"); +} + +#endif + +TEST_F(MaintenanceManagerTest, getMaintenanceStartTime) +{ + + const char *deviceInfoScript = "/lib/rdk/getMaintenanceStartTime.sh"; + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("/lib/rdk/getMaintenanceStartTime.sh &"))); + return __real_popen(deviceInfoScript, type); + })); + ON_CALL(*p_wrapsImplMock, pclose(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](FILE* pipe){ + return __real_pclose(pipe); + })); + std::this_thread::sleep_for(std::chrono::seconds(2)); + +//Create fake device info script & Invoke getDeviceInfo + ofstream file(deviceInfoScript); + file << "echo \"123456789\"\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler_.Invoke(connection_, _T("getMaintenanceStartTime"), _T("{}"), response_)); + EXPECT_EQ(response_, "{\"maintenanceStartTime\":123456789,\"success\":true}"); + +} + diff --git a/NetworkManager/Tests/L1Tests/tests/test_Messenger.cpp b/NetworkManager/Tests/L1Tests/tests/test_Messenger.cpp new file mode 100755 index 0000000000..cd916ccd3b --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Messenger.cpp @@ -0,0 +1,376 @@ +#include + +#include "Messenger.h" + +#include "FactoriesImplementation.h" +#include "ServiceMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +// Make Subscribe/Unsubscribe public +class Messenger : public Plugin::Messenger { +public: + Messenger() = default; + ~Messenger() = default; + Messenger(const Messenger&) = delete; + Messenger& operator=(const Messenger&) = delete; + + void Subscribe(Core::JSONRPC::Handler& handler, const uint32_t channelId, const string& eventName, const string& callsign, Core::JSONRPC::Message& response) override + { + Plugin::Messenger::Subscribe(handler, channelId, eventName, callsign, response); + } + void Unsubscribe(Core::JSONRPC::Handler& handler, const uint32_t channelId, const string& eventName, const string& callsign, Core::JSONRPC::Message& response) override + { + Plugin::Messenger::Unsubscribe(handler, channelId, eventName, callsign, response); + } +}; +} + +class MessengerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + MessengerTest() + : plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + } + virtual ~MessengerTest() = default; +}; + +class MessengerInitializedTest : public MessengerTest { +protected: + NiceMock service; + + MessengerInitializedTest() + : MessengerTest() + { + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\"root\":{\"mode\":\"Off\"}}")); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~MessengerInitializedTest() override + { + plugin->Deinitialize(&service); + } +}; + +class MessengerInitializedEventTest : public MessengerInitializedTest { +protected: + NiceMock factoriesImplementation; + Core::JSONRPC::Message message; + PluginHost::IDispatcher* dispatcher; + + MessengerInitializedEventTest() + : MessengerInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~MessengerInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(MessengerTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("join"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("leave"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("send"))); +} + +TEST_F(MessengerInitializedEventTest, activate_join_roomupdate_leave_roomupdate_deactivate) +{ + Core::Event created(false, true); + Core::Event destroyed(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"Messenger.roomupdate\"," + "\"params\":" + "{" + "\"room\":\"room1\"," + "\"secure\":\"insecure\"," + "\"action\":\"created\"" + "}" + "}"))); + + created.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"Messenger.roomupdate\"," + "\"params\":" + "{" + "\"room\":\"room1\"," + "\"secure\":\"insecure\"," + "\"action\":\"destroyed\"" + "}" + "}"))); + + destroyed.SetEvent(); + + return Core::ERROR_NONE; + })); + + plugin->Subscribe(handler, 0, _T("roomupdate"), _T("Messenger"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user1\",\"room\":\"room1\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + EXPECT_EQ(Core::ERROR_NONE, created.Lock()); + + string paramsStr = response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("leave"), paramsStr, response)); + EXPECT_EQ(response, _T("")); + + EXPECT_EQ(Core::ERROR_NONE, destroyed.Lock()); + + plugin->Unsubscribe(handler, 0, _T("roomupdate"), _T("Messenger"), message); +} + +TEST_F(MessengerInitializedEventTest, activate_join_roomupdateOnSubscribe_deactivate) +{ + Core::Event created(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"Messenger.roomupdate\"," + "\"params\":" + "{" + "\"room\":\"room2\"," + "\"secure\":\"insecure\"," + "\"action\":\"created\"" + "}" + "}"))); + + created.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user2\",\"room\":\"room2\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + plugin->Subscribe(handler, 0, _T("roomupdate"), _T("Messenger"), message); + + EXPECT_EQ(Core::ERROR_NONE, created.Lock()); + + plugin->Unsubscribe(handler, 0, _T("roomupdate"), _T("Messenger"), message); +} + +TEST_F(MessengerInitializedEventTest, activate_join_userupdate_join_userupdate_leave_userupdate_deactivate) +{ + Core::Event joined3(false, true); + Core::Event joined4(false, true); + Core::Event left4(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(3) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.userupdate\"," + "\"params\":" + "\\{" + "\"user\":\"user3\"," + "\"action\":\"joined\"" + "\\}" + "\\}"))); + + joined3.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.userupdate\"," + "\"params\":" + "\\{" + "\"user\":\"user4\"," + "\"action\":\"joined\"" + "\\}" + "\\}"))); + + joined4.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.userupdate\"," + "\"params\":" + "\\{" + "\"user\":\"user4\"," + "\"action\":\"left\"" + "\\}" + "\\}"))); + + left4.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user3\",\"room\":\"room3\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + JsonObject params; + params.FromString(response); + string roomid1 = params["roomid"].String(); + plugin->Subscribe(handler, 0, _T("userupdate"), (roomid1 + _T(".Messenger")), message); + + EXPECT_EQ(Core::ERROR_NONE, joined3.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user4\",\"room\":\"room3\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + EXPECT_EQ(Core::ERROR_NONE, joined4.Lock()); + + string paramsStr = response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("leave"), paramsStr, response)); + EXPECT_EQ(response, _T("")); + + EXPECT_EQ(Core::ERROR_NONE, left4.Lock()); + + plugin->Unsubscribe(handler, 0, _T("userupdate"), (roomid1 + _T(".Messenger")), message); +} + +TEST_F(MessengerInitializedEventTest, activate_join_join_send_message_leave_sendToUserWhoLeft_deactivate) +{ + Core::Event message6_1(false, true); + Core::Event message6_2(false, true); + Core::Event message5(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(3) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.message\"," + "\"params\":" + "\\{" + "\"user\":\"user6\"," + "\"message\":\"Hi, user5\"" + "\\}" + "\\}"))); + + message6_1.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.message\"," + "\"params\":" + "\\{" + "\"user\":\"user6\"," + "\"message\":\"Hi, user5\"" + "\\}" + "\\}"))); + + message6_2.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"[a-z0-9]+\\.Messenger\\.message\"," + "\"params\":" + "\\{" + "\"user\":\"user5\"," + "\"message\":\"Hi, user6\"" + "\\}" + "\\}"))); + + message5.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user5\",\"room\":\"room4\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + JsonObject params5; + params5.FromString(response); + string roomid5 = params5["roomid"].String(); + plugin->Subscribe(handler, 0, _T("message"), (roomid5 + _T(".Messenger")), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("join"), _T("{\"user\":\"user6\",\"room\":\"room4\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"roomid\":\"[a-z0-9]+\"\\}")); + + JsonObject params6; + params6.FromString(response); + string roomid6 = params6["roomid"].String(); + plugin->Subscribe(handler, 0, _T("message"), (roomid6 + _T(".Messenger")), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("send"), ("{\"message\":\"Hi, user5\",\"roomid\":\"" + roomid6 + "\"}"), response)); + EXPECT_EQ(response, _T("")); + + EXPECT_EQ(Core::ERROR_NONE, message6_1.Lock()); + EXPECT_EQ(Core::ERROR_NONE, message6_2.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("leave"), ("{\"roomid\":\"" + roomid6 + "\"}"), response)); + EXPECT_EQ(response, _T("")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("send"), ("{\"message\":\"Hi, user6\",\"roomid\":\"" + roomid5 + "\"}"), response)); + EXPECT_EQ(response, _T("")); + + EXPECT_EQ(Core::ERROR_NONE, message5.Lock()); + + plugin->Unsubscribe(handler, 0, _T("message"), (roomid5 + _T(".Messenger")), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_MiracastPlayer.cpp b/NetworkManager/Tests/L1Tests/tests/test_MiracastPlayer.cpp new file mode 100644 index 0000000000..5c104df118 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_MiracastPlayer.cpp @@ -0,0 +1,1208 @@ +#include +#include +#include +#include "ServiceMock.h" +#include "MiracastPlayer.h" +#include "WrapsMock.h" +#include + +#include "FactoriesImplementation.h" + +using ::testing::NiceMock; +using namespace WPEFramework; + +namespace { + +#define RTSP_SEND (1) +#define RTSP_RECV (2) + +#define BUFFER_SIZE (2048) +#define PORT (7236) +#define TEST_LOG(FMT, ...) log(__func__, __FILE__, __LINE__, syscall(__NR_gettid),FMT,##__VA_ARGS__) + + typedef enum rtsp_srcmsg_reqresp + { + RTSP_SEND_M1_REQUEST = 0x00, + RTSP_RECV_M1_RESPONSE, + RTSP_RECV_M2_REQUEST, + RTSP_SEND_M2_RESPONSE, + RTSP_SEND_M3_REQUEST, + RTSP_RECV_M3_RESPONSE, + RTSP_SEND_M4_REQUEST, + RTSP_RECV_M4_RESPONSE, + RTSP_SEND_M5_REQUEST, + RTSP_RECV_M5_RESPONSE, + RTSP_RECV_M6_REQUEST, + RTSP_SEND_M6_RESPONSE, + RTSP_RECV_M7_REQUEST, + RTSP_SEND_M7_RESPONSE, + RTSP_SEND_M16_REQUEST, + RTSP_RECV_M16_RESPONSE, + RTSP_SEND_TEARDOWN_REQUEST, + RTSP_RECV_TEADOWN_RESPONSE, + RTSP_RECV_TEARDOWN_REQUEST, + RTSP_SEND_TEARDOWN_RESPONSE + } + RTSP_SRCMSG_REQ_RESP; + + typedef struct rtsp_src_msg_handler_format + { + int rtsp_sendorreceive; + RTSP_SRCMSG_REQ_RESP rtsp_msg_type; + const char* template_name; + } + RTSP_MSG_HANDLER_FORMAT; + + RTSP_MSG_HANDLER_FORMAT default_rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, + { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" }, + { RTSP_SEND , RTSP_SEND_M4_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 3\r\nContent-Type: text/parameters\r\nContent-Length: 246\r\n\r\nwfd_video_formats: 00 00 02 04 00000080 00000000 00000000 00 0000 0000 00 none none\r\nwfd_audio_codecs: AAC 00000001 00\r\nwfd_presentation_URL: rtsp://192.168.49.1/wfd1.0/streamid=0 none\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1990 0 mode=play\r\n" }, + { RTSP_RECV , RTSP_RECV_M4_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 3\r\n" }, + { RTSP_SEND , RTSP_SEND_M5_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 4\r\nContent-Type: text/parameters\r\nContent-Length: 27\r\n\r\nwfd_trigger_method: SETUP\r\n" }, + { RTSP_RECV , RTSP_RECV_M5_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 4\r\n\r\n" }, + { RTSP_RECV , RTSP_RECV_M6_REQUEST , "SETUP rtsp://192.168.49.1/wfd1.0/streamid=0 RTSP/1.0\r\nTransport: RTP/AVP/UDP;unicast;client_port=1990\r\nCSeq: %s\r\n"}, + { RTSP_SEND , RTSP_SEND_M6_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nTransport: RTP/AVP/UDP;unicast;client_port=1991-1992;server_port=19000-19001\r\n" }, + { RTSP_RECV , RTSP_RECV_M7_REQUEST , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, + { RTSP_SEND , RTSP_SEND_M7_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, + { RTSP_SEND , RTSP_SEND_M16_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 5\r\nSession: 1804289383\r\n"}, + { RTSP_RECV , RTSP_RECV_M16_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 5\r\n" } + //{ RTSP_SEND , RTSP_SEND_TEARDOWN_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n" }, + //{ RTSP_RECV , RTSP_RECV_TEADOWN_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 6\r\n" } + }; + + int default_rtsp_srcMsgSize = static_cast(sizeof(default_rtsp_srcMsgbuffer) / sizeof(default_rtsp_srcMsgbuffer[0])); + int server_fd = -1, client_fd = -1; + struct sockaddr_in server_addr, client_addr; + int opt = 1; + + void current_time(char *time_str) + { + struct timeval tv; + gettimeofday(&tv, NULL); + + long microseconds = tv.tv_usec; + + // Convert time to human-readable format + struct tm *tm_info; + tm_info = localtime(&tv.tv_sec); + + sprintf(time_str, ": %02d:%02d:%02d:%06ld", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, microseconds); + } + + void log( const char *func, const char *file, int line, int threadID,const char *format, ...) + { + const short kFormatMessageSize = 4096; + char formatted[kFormatMessageSize]; + char time[24] = {0}; + va_list argptr; + + current_time(time); + + va_start(argptr, format); + vsnprintf(formatted, kFormatMessageSize, format, argptr); + va_end(argptr); + + fprintf(stderr, "[GUNIT][%d] INFO [%s:%d %s] %s: %s \n", + (int)syscall(SYS_gettid), + basename(file), + line, + time, + func, + formatted); + + fflush(stderr); + } + + static void removeFile(const char* fileName) + { + if (std::remove(fileName) != 0) + { + TEST_LOG("ERROR: deleting File [%s] ...",strerror(errno)); + } + else + { + TEST_LOG("File %s successfully deleted", fileName); + } + } + + static void createFile(const char* fileName, const char* fileContent) + { + removeFile(fileName); + + std::ofstream fileContentStream(fileName); + fileContentStream << fileContent; + fileContentStream << "\n"; + fileContentStream.close(); + TEST_LOG("File %s successfully created", fileName); + } + + const char* get_RequestResponseFormat(RTSP_MSG_HANDLER_FORMAT *pstRTSPSrcHldrFmt , int index , size_t rtsp_msg_fmt_count ) + { + if (index >= 0 && index < static_cast(rtsp_msg_fmt_count)) + { + return pstRTSPSrcHldrFmt[index].template_name; + } + return ""; + } + + std::string parse_received_parser_field_value(std::string rtsp_msg_buffer , const char* given_tag ) + { + std::string seq_str = ""; + std::stringstream ss(rtsp_msg_buffer); + std::string prefix = ""; + std::string line; + + while (std::getline(ss, line)) + { + if (line.find(given_tag) != std::string::npos) + { + prefix = given_tag; + seq_str = line.substr(prefix.length()); + REMOVE_R(seq_str); + REMOVE_N(seq_str); + break; + } + } + return seq_str; + } + + void send_rtsp_msg( int sockfd , std::string msg_buffer ) + { + usleep(500000); + TEST_LOG("Send Msg[%lu][%s]...",msg_buffer.size(),msg_buffer.c_str()); + send(sockfd, msg_buffer.c_str(), msg_buffer.size(), 0); + } + + /* + * Wait for data returned by the socket for specified time + */ + bool wait_data_timeout(int m_Sockfd, unsigned int ms) + { + struct timeval timeout = {0}; + fd_set readFDSet; + bool returnValue = false; + + FD_ZERO(&readFDSet); + FD_SET(m_Sockfd, &readFDSet); + + timeout.tv_sec = (ms / 1000); + timeout.tv_usec = ((ms % 1000) * 1000); + + if (select(m_Sockfd + 1, &readFDSet, nullptr, nullptr, &timeout) > 0) + { + returnValue = FD_ISSET(m_Sockfd, &readFDSet); + } + return returnValue; + } + + bool recv_rtsp_msg(int socket_fd, void *buffer, size_t buffer_len ) + { + int recv_return = -1; + bool status = true; + + TEST_LOG("Entering "); + if (!wait_data_timeout(socket_fd, 15000 )) + { + TEST_LOG("ERROR: Exiting Timeout "); + return false; + } + else + { + recv_return = recv(socket_fd, buffer, buffer_len, 0); + } + + if (recv_return <= 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { + TEST_LOG("ERROR:recv timed out ..."); + status = false; + } + else + { + TEST_LOG("ERROR: recv failed [%s] ...",strerror(errno)); + status = false; + } + } + TEST_LOG("recv string [%s][%d] ...",buffer,recv_return); + return status; + } + + bool initialize_ServerSocket(void) + { + // Create socket file descriptor + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + return false; + } + + fcntl(server_fd, F_SETFL, O_NONBLOCK); + TEST_LOG("#### NON_BLOCKING Socket Enabled ####"); + + // Forcefully attaching socket to the port 7236 + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt"); + close(server_fd); + server_fd = -1; + return false; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(PORT); + + // Bind the socket to localhost port 7236 + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("bind failed"); + close(server_fd); + server_fd = -1; + return false; + } + return true; + } + + void release_SocketDescriptor(void) + { + if ( -1 != server_fd ) + { + close(server_fd); + server_fd = -1; + } + if ( -1 != client_fd ) + { + close(client_fd); + client_fd = -1; + } + } + + void runRTSPSourceHandler(RTSP_MSG_HANDLER_FORMAT* custom_src_msg_buffer, size_t rtsp_msg_count , std::string & response_buffer ) + { + int addrlen = sizeof(server_addr); + char buffer[BUFFER_SIZE] = {0}; + + response_buffer = "FAIL"; + + if( -1 == server_fd ) + { + return; + } + // Listen for incoming connections + if (listen(server_fd, 3) < 0) { + perror("listen"); + return; + } + + if (!wait_data_timeout(server_fd, 30000 )) + { + // connection timed out or failed + TEST_LOG("Socket Connection Timedout %s received(%d)...", strerror(errno), errno); + response_buffer = "FAIL"; + return; + } + else + { + // Accept an incoming connection + if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addrlen)) < 0) { + perror("accept"); + return; + } + TEST_LOG("socket accept done"); + } + + response_buffer = "SUCCESS"; + + std::string receivedCSeqNum = ""; + size_t current_msg = 0; + + while ( current_msg < rtsp_msg_count ) + { + RTSP_SRCMSG_REQ_RESP rtsp_msg_type = custom_src_msg_buffer[current_msg].rtsp_msg_type; + int rtsp_sendorreceive = custom_src_msg_buffer[current_msg].rtsp_sendorreceive; + const char* rtsp_req_resp_format = get_RequestResponseFormat(custom_src_msg_buffer,current_msg,rtsp_msg_count); + std::string msg_buffer = ""; + + memset( buffer , 0x00 , sizeof(buffer)); + TEST_LOG("Index[%d] RTSP Msg[%x]",current_msg,rtsp_msg_type); + + if ( RTSP_SEND == rtsp_sendorreceive ) + { + TEST_LOG("RTSP_SEND"); + switch (rtsp_msg_type) + { + case RTSP_SEND_M1_REQUEST: + case RTSP_SEND_M3_REQUEST: + case RTSP_SEND_M4_REQUEST: + case RTSP_SEND_M5_REQUEST: + case RTSP_SEND_M16_REQUEST: + case RTSP_SEND_TEARDOWN_REQUEST: + { + TEST_LOG("RTSP_SEND REQUEST Messages"); + msg_buffer = rtsp_req_resp_format; + } + break; + case RTSP_SEND_M2_RESPONSE: + case RTSP_SEND_M6_RESPONSE: + case RTSP_SEND_M7_RESPONSE: + case RTSP_SEND_TEARDOWN_RESPONSE: + { + std::string temp_buffer = rtsp_req_resp_format; + + TEST_LOG("RTSP_SEND RESPONSE Messages"); + if (temp_buffer.find("%s") != std::string::npos) + { + sprintf( buffer , rtsp_req_resp_format , receivedCSeqNum.c_str()); + msg_buffer = buffer; + TEST_LOG("Response sequence number replaced as [%s]",receivedCSeqNum.c_str()); + receivedCSeqNum.clear(); + } + else + { + msg_buffer = rtsp_req_resp_format; + } + } + break; + default: + { + + } + break; + } + if ( !msg_buffer.empty()) + { + send_rtsp_msg( client_fd , msg_buffer ); + } + } + else + { + TEST_LOG("RTSP_RECV"); + bool status = recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); + msg_buffer = buffer; + if ((msg_buffer.find("TEARDOWN") == 0) || (false == status )) + { + TEST_LOG("TEARDOWN initiated from Sink Device[%x]",status); + response_buffer = "SUCCESS"; + break; + } + switch (rtsp_msg_type) + { + case RTSP_RECV_M1_RESPONSE: + case RTSP_RECV_M4_RESPONSE: + case RTSP_RECV_M5_RESPONSE: + case RTSP_RECV_M16_RESPONSE: + case RTSP_RECV_TEADOWN_RESPONSE: + { + msg_buffer = rtsp_req_resp_format; + + if ( 0 != strncmp( buffer , rtsp_req_resp_format , strlen(rtsp_req_resp_format))) + { + response_buffer = "FAIL"; + TEST_LOG("ERROR: expected[%s] actual[%s]",rtsp_req_resp_format,buffer); + } + else if ( strlen(buffer) > strlen(rtsp_req_resp_format) ) + { + if (( RTSP_RECV_M1_RESPONSE == rtsp_msg_type ) || + ( RTSP_RECV_M5_RESPONSE == rtsp_msg_type )) + { + int processedBytes = strlen(rtsp_req_resp_format), + totalLen = strlen(buffer); + std::string temp_buffer = buffer; + std::string response = temp_buffer.substr(0,processedBytes); + EXPECT_EQ(response,string(rtsp_req_resp_format)); + std::string request = temp_buffer.substr(processedBytes, totalLen - processedBytes); + receivedCSeqNum = parse_received_parser_field_value( request , "CSeq: " ); + TEST_LOG("Parsed Response + Request[%s][%s]",response.c_str(),request.c_str()); + TEST_LOG("processedBytes[%d]totalLen[%d]",processedBytes,totalLen); + EXPECT_TRUE(!receivedCSeqNum.empty()); + TEST_LOG("Skipping to RTSP_RECV REQUEST Messages"); + ++current_msg; + } + } + } + break; + case RTSP_RECV_M3_RESPONSE: + { + TEST_LOG("RTSP_RECV M3 RESPONSE Messages"); + std::string expected_sequence_number = parse_received_parser_field_value( msg_buffer , "CSeq: " ), + actual_sequence_number = parse_received_parser_field_value( rtsp_req_resp_format , "CSeq: " ); + + if ( 0 != expected_sequence_number.compare(actual_sequence_number)) + { + response_buffer = "FAIL"; + TEST_LOG("Error: expected[%s]actual[%s]",msg_buffer.c_str(),rtsp_req_resp_format); + } + } + break; + case RTSP_RECV_M2_REQUEST: + case RTSP_RECV_M6_REQUEST: + case RTSP_RECV_M7_REQUEST: + { + TEST_LOG("RTSP_RECV REQUEST Messages"); + receivedCSeqNum = parse_received_parser_field_value( msg_buffer , "CSeq: " ); + } + break; + default: + { + break; + } + } + } + ++current_msg; + + if ( 0 == response_buffer.compare("FAIL")) + { + TEST_LOG("ERROR: RESPONSE FAILED"); + break; + } + } + + if ( 0 == response_buffer.compare("FAIL")) + { + TEST_LOG("ERROR: RTSP Msg Exchange Failed"); + } + else + { + TEST_LOG("RTSP Msg Exchange Success"); + } + } +} + +class MiracastPlayerTest : public ::testing::Test { + protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + ServiceMock service; + WrapsImplMock *p_wrapsImplMock = nullptr; + + MiracastPlayerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return nullptr; + })); + ON_CALL(*p_wrapsImplMock, system(::testing::_)) + .WillByDefault(::testing::Invoke([&](const char* command) {return 0;})); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~MiracastPlayerTest() override + { + plugin->Deinitialize(nullptr); + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + } +}; + +class MiracastPlayerEventTest : public MiracastPlayerTest { + protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + MiracastPlayerEventTest() + : MiracastPlayerTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~MiracastPlayerEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(MiracastPlayerTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("playRequest"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopRequest"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setPlayerState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLogging"))); +} + +TEST_F(MiracastPlayerTest, Logging) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"ENABLE\",\"logfilename\": \"GTest\"}}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"VERBOSE\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"WARNING\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"ERROR\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"FATAL\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"TRACE\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"INFO\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"UNKNOWN\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"DISABLE\",\"logfilename\": \"GTest\"}}"), response)); +} + +TEST_F(MiracastPlayerTest, setRTSPWaitTimeOutAndAVFormats) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setRTSPWaitTimeOut"), _T("{\"Request\": 10000,\"Response\": 10000}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoFormats"), _T("{\"native\": 0x02,\"display_mode_supported\": false,\"h264_codecs\": [{\"profile\": 0x01,\"level\": 0x08,\"cea_mask\": 0x00010000,\"vesa_mask\": 0x00000000,\"hh_mask\": 0x00000000,\"latency\": 0,\"min_slice\": 0,\"slice_encode\": 0,\"video_frame_skip_support\": true,\"max_skip_intervals\": 0,\"video_frame_rate_change_support\": false}]}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setAudioFormats"), _T("{\"audio_codecs\": [{\"audio_format\": 0x01,\"modes\": 0x00000002,\"latency\": 0}]}"), response)); +} + +TEST_F(MiracastPlayerEventTest, APP_REQUESTED_TO_STOP) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"201\"," + "\"reason\":\"APP REQUESTED TO STOP.\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + sleep(2); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 300}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerEventTest, APP_REQ_TO_STOP_FOR_NEW_CONNECTION) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"208\"," + "\"reason\":\"APP REQ TO STOP FOR NEW CONNECTION.\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + sleep(2); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 301}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerEventTest, SRC_DEV_REQUESTED_TO_STOP) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"202\"," + "\"reason\":\"SRC DEVICE REQUESTED TO STOP.\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); + + char buffer[BUFFER_SIZE] = {0}; + std::string teardown_request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n"; + std::string teardown_response = "RTSP/1.0 200 OK\r\nCSeq: 6\r\n\r\n", + temp_buffer = ""; + + send_rtsp_msg(client_fd,teardown_request); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); + temp_buffer = buffer; + + EXPECT_EQ(teardown_response, temp_buffer); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerEventTest, RTSP_TimeOut) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Stopped(false, true); + RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\nGET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, + { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" } + }; + + int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"204\"," + "\"reason\":\"RTSP Timeout.\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(25000)); + + release_SocketDescriptor(); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerEventTest, RTSP_Failure) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Stopped(false, true); + RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "wfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" } + }; + + int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"203\"," + "\"reason\":\"RTSP Failure.\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + sleep(2); + release_SocketDescriptor(); + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerEventTest, setPlayerState) +{ + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"name\":\"Sample-Android-Test-1\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + char buffer[BUFFER_SIZE] = {0}; + //std::string trigger_request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n"; + std::string trigger_response = "", + temp_buffer = ""; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"PAUSE\"}"), response)); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); + temp_buffer = buffer; + std::string receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("PAUSE") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + + sleep(2); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"PLAY\"}"), response)); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); + temp_buffer = buffer; + receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("PLAY") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + + sleep(2); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"UNKNOWN\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"STOP\"}"), response)); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); + temp_buffer = buffer; + receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("TEARDOWN") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + handler.Unsubscribe(0, _T("onStateChange"), _T("client.events"), message); +} + +TEST_F(MiracastPlayerTest, AutoConnectOptFlag) +{ + std::string rtsp_response = ""; + createFile("/opt/miracast_autoconnect","GTest"); + + sleep(2); + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + serverThread.join(); + sleep(2); + release_SocketDescriptor(); + removeFile("/opt/miracast_autoconnect"); + sleep(2); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_MiracastService.cpp b/NetworkManager/Tests/L1Tests/tests/test_MiracastService.cpp new file mode 100644 index 0000000000..a960fb9342 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_MiracastService.cpp @@ -0,0 +1,2049 @@ +#include +#include "FactoriesImplementation.h" +#include "ServiceMock.h" +#include "MiracastService.h" +#include "WrapsMock.h" +#include "WpaCtrlMock.h" +#include "IarmBusMock.h" + +using ::testing::NiceMock; +using namespace WPEFramework; +namespace +{ + static void removeFile(const char* fileName) + { + if (std::remove(fileName) != 0) + { + printf("File %s failed to remove\n", fileName); + perror("Error deleting file"); + } + else + { + printf("File %s successfully deleted\n", fileName); + } + } + static void removeEntryFromFile(const char* fileName, const char* entryToRemove) + { + std::ifstream inputFile(fileName); + if (!inputFile.is_open()) + { + printf("Error: Unable to open file: %s\n",fileName); + return; + } + + std::vector lines; + std::string line; + while (std::getline(inputFile, line)) { + if (line != entryToRemove) { + lines.push_back(line); + } + } + inputFile.close(); + + std::ofstream outputFile(fileName); + if (!outputFile.is_open()) + { + printf("Error: Unable to open file: %s for writing\n",fileName); + return; + } + + for (const auto& line : lines) { + outputFile << line << "\n"; + } + outputFile.close(); + + printf("Entry removed from file: %s\n",fileName); + } + static void createFile(const char* fileName, const char* fileContent) + { + removeFile(fileName); + + std::ofstream fileContentStream(fileName); + fileContentStream << fileContent; + fileContentStream << "\n"; + fileContentStream.close(); + } +} + +static struct wpa_ctrl global_wpa_ctrl_handle; + +class MiracastServiceTest : public ::testing::Test { + protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + ServiceMock service; + WrapsImplMock *p_wrapsImplMock = nullptr; + WpaCtrlApiImplMock *p_wpaCtrlImplMock = nullptr; + IarmBusImplMock *p_iarmBusImplMock = nullptr; + IARM_EventHandler_t pwrMgrEventHandler; + + MiracastServiceTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + p_wpaCtrlImplMock = new NiceMock ; + WpaCtrlApi::setImpl(p_wpaCtrlImplMock); + + p_iarmBusImplMock = new testing::NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke([&](const uint32_t, const string& name) -> void* { return nullptr; })); + ON_CALL(*p_wpaCtrlImplMock, wpa_ctrl_open(::testing::_)) + .WillByDefault(::testing::Invoke([&](const char *ctrl_path) { return &global_wpa_ctrl_handle; })); + ON_CALL(*p_wpaCtrlImplMock, wpa_ctrl_close(::testing::_)) + .WillByDefault(::testing::Invoke([&](struct wpa_ctrl *) { return; })); + ON_CALL(*p_wpaCtrlImplMock, wpa_ctrl_pending(::testing::_)) + .WillByDefault(::testing::Invoke([&](struct wpa_ctrl *ctrl) { return true; })); + ON_CALL(*p_wpaCtrlImplMock, wpa_ctrl_attach(::testing::_)) + .WillByDefault(::testing::Invoke([&](struct wpa_ctrl *ctrl) { return false; })); + ON_CALL(*p_wrapsImplMock, system(::testing::_)) + .WillByDefault(::testing::Invoke([&](const char* command) {return 0;})); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke([&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler){ + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + pwrMgrEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault([](const char* ownerName, const char* methodName, void* arg, size_t argLen){ + if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0){ + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + } + return IARM_RESULT_SUCCESS; + }); + } + virtual ~MiracastServiceTest() override + { + WpaCtrlApi::setImpl(nullptr); + if (p_wpaCtrlImplMock != nullptr) + { + delete p_wpaCtrlImplMock; + p_wpaCtrlImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class MiracastServiceEventTest : public MiracastServiceTest { + protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + MiracastServiceEventTest() + : MiracastServiceTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~MiracastServiceEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(MiracastServiceTest, P2PCtrlInterfaceNameNotFound) +{ + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + + //EXPECT_EQ(string("WIFI_P2P_CTRL_INTERFACE not configured in device properties file"), plugin->Initialize(&service)); + EXPECT_EQ("WIFI_P2P_CTRL_INTERFACE not configured in device properties file", plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); +} + +TEST_F(MiracastServiceTest, P2PCtrlInterfacePathNotFound) +{ + removeFile("/var/run/wpa_supplicant/p2p0"); + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + + //EXPECT_EQ(string("Invalid P2P Ctrl iface configured"), plugin->Initialize(&service)); + EXPECT_EQ("Invalid P2P Ctrl iface configured", plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); +} + +TEST_F(MiracastServiceTest, RegisteredMethods) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnable"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEnable"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("acceptClientConnection"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopClientConnection"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("updatePlayerState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLogging"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setP2PBackendDiscovery"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setWiFiState"))); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceTest, P2P_DiscoveryStatus) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Successfully enabled the WFD Discovery\",\"success\":true}")); + + /* @return : {"message":"WFD Discovery already enabled.","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnable"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Successfully disabled the WFD Discovery\",\"success\":true}")); + + /* @return : {"message":"WFD Discovery already disabled.","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnable"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"success\":true}")); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceTest, BackendDiscoveryStatus) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setP2PBackendDiscovery"), _T("{\"enabled\": true}"), response)); + + /* @return : {"message":"Invalid parameter passed","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setP2PBackendDiscovery"), _T("{\"enable\": true}"), response)); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceTest, Logging) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"ENABLE\",\"logfilename\": \"GTest\"}}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"VERBOSE\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"WARNING\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"ERROR\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"FATAL\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"TRACE\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"INFO\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"UNKNOWN\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"DISABLE\",\"logfilename\": \"GTest\"}}"), response)); + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); + removeFile("/opt/logs/GTest.log"); +} + +TEST_F(MiracastServiceEventTest, stopClientConnection) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + + /* @return : {"message":"Supported 'requestStatus' parameter values are Accept or Reject","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Timeout}"), response)); + /* @return : {"message":"Invalid parameter passed","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"request\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + sleep(2); + + /* @return : {"message":"Invalid MAC and Name","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_GOMode_onClientConnectionAndLaunchRequest) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"awk '$4 == ",strlen("awk '$4 == "))) + { + strncpy(buffer, "192.168.59.165",sizeof(buffer)); + } + else if ( 0 == strncmp(command,"awk '$1 == ",strlen("awk '$1 == "))) + { + // Need to return as empty + } + else if ( 0 == strncmp(command,"arping",strlen("arping"))) + { + strncpy(buffer, "Unicast reply from 192.168.59.165 [96:52:44:b6:7d:14] 2.189ms\nReceived 1 response",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-LOST 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-FIND-STOPPED", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo GO ssid=\"DIRECT-UU-Element-Xumo-TV\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 ip_addr=192.168.49.200 ip_mask=255.255.255.0 go_ip_addr=192.168.49.1", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.59.165\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Sample-Test-Android-2\"," + "\"sink_dev_ip\":\"192.168.59.1\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"INITIATED\"}"), response)); + sleep(1); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"INPROGRESS\"}"), response)); + sleep(1); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"PLAYING\"}"), response)); + sleep(1); + + /* @return : {"message":"Failed as MiracastPlayer already Launched.","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + + /* @return : {"message":"stopClientConnection received after Launch","success":false}*/ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"STOPPED\"}"), response)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, onClientConnectionRequestRejected) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Reject}"), response)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_CONNECT_FAIL_onClientConnectionError) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"FAIL",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PConnectFail(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}" + "}"))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionError\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"," + "\"error_code\":\"101\"," + "\"reason\":\"P2P CONNECT FAILURE.\"" + "}" + "}"))); + P2PConnectFail.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PConnectFail.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_GO_NEGOTIATION_FAIL_onClientConnectionError) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-FAILURE 96:52:44:b6:7d:14", *reply_len); + return false; + })) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGoFail(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}" + "}"))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionError\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"," + "\"error_code\":\"102\"," + "\"reason\":\"P2P GROUP NEGOTIATION FAILURE.\"" + "}" + "}"))); + P2PGoFail.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGoFail.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_GO_FORMATION_FAIL_onClientConnectionError) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-FAILURE", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGoFail(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}" + "}"))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionError\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"," + "\"error_code\":\"103\"," + "\"reason\":\"P2P GROUP FORMATION FAILURE.\"" + "}" + "}"))); + P2PGoFail.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGoFail.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_onClientConnectionAndLaunchRequest) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "udhcpc: sending select for 192.168.49.165\tudhcpc: lease of 192.168.49.165 obtained, lease time 3599\tdeleting routers\troute add default gw 192.168.49.1 dev lo\tadding dns 192.168.49.1",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-LOST 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-FIND-STOPPED", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU-Galaxy A23 5G\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.49.1\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Sample-Test-Android-2\"," + "\"sink_dev_ip\":\"192.168.49.165\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_DirectonClientConnectionAndLaunchRequest) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "udhcpc: sending select for 192.168.49.165\tudhcpc: lease of 192.168.49.165 obtained, lease time 3599\tdeleting routers\troute add default gw 192.168.49.1 dev lo\tadding dns 192.168.49.1",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU-Galaxy A23 5G\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.49.1\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Sample-Test-Android-2\"," + "\"sink_dev_ip\":\"192.168.49.165\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_DirectGroupStartWithName) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "udhcpc: sending select for 192.168.49.165\tudhcpc: lease of 192.168.49.165 obtained, lease time 3599\tdeleting routers\troute add default gw 192.168.49.1 dev lo\tadding dns 192.168.49.1",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU-Galaxy A23 5G\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Galaxy A23 5G\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.49.1\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Galaxy A23 5G\"," + "\"sink_dev_ip\":\"192.168.49.165\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_DirectGroupStartWithoutName) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "udhcpc: sending select for 192.168.49.165\tudhcpc: lease of 192.168.49.165 obtained, lease time 3599\tdeleting routers\troute add default gw 192.168.49.1 dev lo\tadding dns 192.168.49.1",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Miracast-Source\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.49.1\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Miracast-Source\"," + "\"sink_dev_ip\":\"192.168.49.165\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_DirectP2PGoNegotiationGroupStartWithoutName) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "udhcpc: sending select for 192.168.49.165\tudhcpc: lease of 192.168.49.165 obtained, lease time 3599\tdeleting routers\troute add default gw 192.168.49.1 dev lo\tadding dns 192.168.49.1",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU-Unknown\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGrpStart(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Miracast-Source\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onLaunchRequest\"," + "\"params\":{\"device_parameters\":{\"source_dev_ip\":\"192.168.49.1\"," + "\"source_dev_mac\":\"96:52:44:b6:7d:14\"," + "\"source_dev_name\":\"Miracast-Source\"," + "\"sink_dev_ip\":\"192.168.49.165\"" + "}}}" + ))); + P2PGrpStart.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onLaunchRequest"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_ClientMode_GENERIC_FAILURE) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"/sbin/udhcpc -v -i",strlen("/sbin/udhcpc -v -i"))) + { + strncpy(buffer, "P2P GENERIC FAILURE",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-LOST 2c:33:58:9c:73:2d p2p_dev_addr=2c:33:58:9c:73:2d pri_dev_type=1-0050F200-0 name='Sample-Test-Android-1' config_methods=0x11e8 dev_capab=0x25 group_capab=0x82 wfd_dev_info=0x01101c440006 new=0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-FIND-STOPPED", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo client ssid=\"DIRECT-UU-Galaxy A23 5G\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 [PERSISTENT]", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGenericFail(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionError\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"," + "\"error_code\":\"104\"," + "\"reason\":\"P2P GENERIC FAILURE.\"" + "}" + "}" + ))); + P2PGenericFail.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGenericFail.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_GOMode_GENERIC_FAILURE) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"awk '$4 == ",strlen("awk '$4 == "))) + { + strncpy(buffer, "192.168.59.165",sizeof(buffer)); + } + else if ( 0 == strncmp(command,"awk '$1 == ",strlen("awk '$1 == "))) + { + // Need to return as empty + } + else if ( 0 == strncmp(command,"arping",strlen("arping"))) + { + strncpy(buffer, "Received 0 response",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo GO ssid=\"DIRECT-UU-Element-Xumo-TV\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 ip_addr=192.168.49.200 ip_mask=255.255.255.0 go_ip_addr=192.168.49.1", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + Core::Event connectRequest(false, true); + Core::Event P2PGenericFail(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionRequest\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"" + "}}" + ))); + connectRequest.SetEvent(); + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"client.events.onClientConnectionError\"," + "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," + "\"name\":\"Sample-Test-Android-2\"," + "\"error_code\":\"104\"," + "\"reason\":\"P2P GENERIC FAILURE.\"" + "}" + "}" + ))); + P2PGenericFail.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Subscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, P2PGenericFail.Lock(10000)); + + handler.Unsubscribe(0, _T("onClientConnectionRequest"), _T("client.events"), message); + handler.Unsubscribe(0, _T("onClientConnectionError"), _T("client.events"), message); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, P2P_GOMode_AutoConnect) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + createFile("/opt/miracast_autoconnect","GTest"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) + { + char buffer[1024] = {0}; + if ( 0 == strncmp(command,"awk '$4 == ",strlen("awk '$4 == "))) + { + strncpy(buffer, "192.168.59.165",sizeof(buffer)); + } + else if ( 0 == strncmp(command,"awk '$1 == ",strlen("awk '$1 == "))) + { + // Need to return as empty + } + else if ( 0 == strncmp(command,"arping",strlen("arping"))) + { + strncpy(buffer, "Unicast reply from 192.168.59.165 [96:52:44:b6:7d:14] 2.189ms\nReceived 1 response",sizeof(buffer)); + } + return (fmemopen(buffer, strlen(buffer), "r")); + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_request(::testing::_, ::testing::_, ::testing::_,::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void(*msg_cb)(char *msg, size_t len)) + { + if ( 0 == strncmp(cmd,"P2P_CONNECT",strlen("P2P_CONNECT"))) + { + strncpy(reply,"OK",*reply_len); + } + return false; + })); + + EXPECT_CALL(*p_wpaCtrlImplMock, wpa_ctrl_recv(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-DEVICE-FOUND 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0 wfd_dev_info=0x01101c440032 vendor_elems=1 new=1", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-PROV-DISC-PBC-REQ 96:52:44:b6:7d:14 p2p_dev_addr=96:52:44:b6:7d:14 pri_dev_type=10-0050F204-5 name='Sample-Test-Android-2' config_methods=0x188 dev_capab=0x25 group_capab=0x0", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-REQUEST 96:52:44:b6:7d:14 dev_passwd_id=4 go_intent=13", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GO-NEG-SUCCESS role=client freq=2437 ht40=0 x=96:52:44:b6:7d:14 peer_iface=96:52:44:b6:fd:14 wps_method=PBC", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-GROUP-FORMATION-SUCCESS", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + strncpy(reply, "P2P-FIND-STOPPED", *reply_len); + return false; + })) + + .WillOnce(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + // Here using lo to avoid the operation not permitted error for unknown interfaces + strncpy(reply, "P2P-GROUP-STARTED lo GO ssid=\"DIRECT-UU-Element-Xumo-TV\" freq=2437 psk=12c3ce3d8976152df796e5f42fc646723471bf1aab8d72a546fa3dce60dc14a3 go_dev_addr=96:52:44:b6:7d:14 ip_addr=192.168.49.200 ip_mask=255.255.255.0 go_ip_addr=192.168.49.1", *reply_len); + return false; + })) + + .WillRepeatedly(::testing::Invoke( + [&](struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { + return true; + })); + + sleep(10); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); + removeFile("/opt/miracast_autoconnect"); +} + +TEST_F(MiracastServiceEventTest, powerStateChange) +{ + IARM_Bus_PWRMgr_EventData_t param; + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); + + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; + pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + sleep(5); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); + + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); + + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; + pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":false,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + sleep(5); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} + +TEST_F(MiracastServiceEventTest, wifiStateChange) +{ + createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + createFile("/var/run/wpa_supplicant/p2p0","p2p0"); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + + // Setting WiFi Connecting State + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 4 }"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":true,\"success\":true}")); + + // Setting WiFi Connected State + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 5 }"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); + + // Setting WiFi Connecting State + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 4 }"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":true,\"success\":true}")); + + // Setting WiFi Connect Failed State + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 6 }"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); + + plugin->Deinitialize(nullptr); + + removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); + removeFile("/var/run/wpa_supplicant/p2p0"); +} \ No newline at end of file diff --git a/NetworkManager/Tests/L1Tests/tests/test_MotionDetection.cpp b/NetworkManager/Tests/L1Tests/tests/test_MotionDetection.cpp new file mode 100755 index 0000000000..e57a6ad8f9 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_MotionDetection.cpp @@ -0,0 +1,320 @@ +#include +#include + +#include "MotionDetection.h" +#include "FactoriesImplementation.h" +#include "MotionDetectionMock.h" + +#include "IarmBusMock.h" +#include "ServiceMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; +using ::testing::Eq; + +class MotionDetectionTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + MotionDetectionTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~MotionDetectionTest() = default; +}; + +class MotionDetectionEventTest : public MotionDetectionTest { +protected: + + MotionDetectionImplMock *p_motionDetectionImplMock = nullptr ; + + MotionDetectionEventTest() + : MotionDetectionTest() + { + + p_motionDetectionImplMock = new NiceMock ; + MotionDetection::setImpl(p_motionDetectionImplMock); + + ON_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_Platform_Init()) + .WillByDefault(::testing::Return(MOTION_DETECTION_RESULT_SUCCESS)); + + ON_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_RegisterEventCallback(::testing::_)) + .WillByDefault(::testing::Return(MOTION_DETECTION_RESULT_SUCCESS)); + + ON_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_DisarmMotionDetector(::testing::_)) + .WillByDefault(::testing::Return(MOTION_DETECTION_RESULT_SUCCESS)); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + + } + virtual ~MotionDetectionEventTest() override + { + + plugin->Deinitialize(nullptr); + MotionDetection::setImpl(nullptr); + if (p_motionDetectionImplMock != nullptr) + { + delete p_motionDetectionImplMock; + p_motionDetectionImplMock = nullptr; + } + } +}; + +TEST_F(MotionDetectionTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getMotionDetectors"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("arm"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disarm"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isarmed"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setNoMotionPeriod"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getNoMotionPeriod"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setSensitivity"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSensitivity"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLastMotionEventElapsedTime"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMotionEventsActivePeriod"))); +} + +TEST_F(MotionDetectionEventTest, getMotionDetectors) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_GetMotionDetectors(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](MOTION_DETECTION_CurrentSensorSettings_t *pSensorStatus) { + + memset(pSensorStatus, 0, sizeof(MOTION_DETECTION_CurrentSensorSettings_t)); + + strcpy(pSensorStatus->m_sensorIndex, MOTION_DETECTOR); + strcpy(pSensorStatus->m_sensorDescription, MOTION_DETECTION_DESCRIPTION); + strcpy(pSensorStatus->m_sensorType, MOTION_DETECTOR_TYPE); + pSensorStatus->m_sensorDistance = MOTION_DETECTION_DISTANCE; + pSensorStatus->m_sensorAngle = MOTION_DETECTION_ANGLE; + pSensorStatus->m_sensitivityMode = 2; + + strcpy(pSensorStatus->m_sensitivity[SENSITIVITY_IDENTIFIER_1], STR_SENSITIVITY_LOW); + strcpy(pSensorStatus->m_sensitivity[SENSITIVITY_IDENTIFIER_2], STR_SENSITIVITY_MEDIUM); + strcpy(pSensorStatus->m_sensitivity[SENSITIVITY_IDENTIFIER_3], STR_SENSITIVITY_HIGH); + + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMotionDetectors"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"supportedMotionDetectors\":[\"FP_MD\"],\"supportedMotionDetectorsInfo\":{\"FP_MD\":{\"description\":\"The only motion detector\",\"type\":\"PID\",\"distance\":\"6000\",\"angle\":\"74\",\"sensitivityMode\":\"2\",\"sensitivities\":[\"low\",\"medium\",\"high\"]}},\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, armmotiondetected) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_ArmMotionDetector(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](MOTION_DETECTION_Mode_t mode,std::string index) { + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("arm"), _T("{\"index\":\"FP_MD\",\"mode\":\"1\" }"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, armmotiondetectedInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_ArmMotionDetector(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](MOTION_DETECTION_Mode_t mode, std::string index) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("arm"), _T("{ \"index\":\"FP_MD\",\"mode\":\"1\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, disarm) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_DisarmMotionDetector(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index) { + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("disarm"), _T("{\"index\":\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, disarmInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_DisarmMotionDetector(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("disarm"), _T("{\"index\":\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, isarmed) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_IsMotionDetectorArmed(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, bool *isArmed) { + *isArmed = false; + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isarmed"), _T("{\"index\"=\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("{\"state\":false,\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, isarmedInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_IsMotionDetectorArmed(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, bool *isArmed) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isarmed"), _T("{\"index\"=\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, setNoMotionPeriod) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_SetNoMotionPeriod(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, unsigned int period) { + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setNoMotionPeriod"), _T("{\"index\":\"FP_MD\",\"period\":\"10\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, setNoMotionPeriodInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_SetNoMotionPeriod(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, unsigned int period) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setNoMotionPeriod"), _T("{\"index\":\"FP_MD\",\"period\":\"10\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, getNoMotionPeriod) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_GetNoMotionPeriod(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, unsigned int *noMotionPeriod) { + *noMotionPeriod =(unsigned int)10; + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getNoMotionPeriod"), _T("{\"index\"=\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("{\"period\":\"10\",\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, getNoMotionPeriodInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock, MOTION_DETECTION_GetNoMotionPeriod(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, unsigned int *noMotionPeriod) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getNoMotionPeriod"), _T("{\"index\"=\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, setSensitivity) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_SetSensitivity(::testing::_,::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, std::string sensitivity, int inferredMode) { + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setSensitivity"), _T("{\"index\":\"FP_MD\",\"name\":\"high\",\"value\":\"40\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, setSensitivityInvalid) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setSensitivity"), _T("{\"index\":\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, getSensitivity) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_GetSensitivity(::testing::_,::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, char** sensitivity, int* currentMode) { + *currentMode = 1; + *sensitivity = (char *)malloc(sizeof(STR_SENSITIVITY_HIGH)); + memset(*sensitivity, 0, sizeof(STR_SENSITIVITY_HIGH)); + strcpy(*sensitivity, STR_SENSITIVITY_HIGH); + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSensitivity"), _T("{\"index\":\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("{\"value\":\"high\",\"success\":true}")); +} + +TEST_F(MotionDetectionEventTest, getSensitivityInvalid) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_GetSensitivity(::testing::_,::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, char** sensitivity, int* currentMode) { + return MOTION_DETECTION_RESULT_INDEX_ERROR; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSensitivity"), _T("{\"index\":\"FP_MD\"}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(MotionDetectionEventTest, getLastMotionEventElapsedTime) +{ + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLastMotionEventElapsedTime"), _T("{}"), response)); + + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"time\":\"[0-9]+.[0-9]+\"," + "\"success\":true" + "\\}"))); +} + +TEST_F(MotionDetectionEventTest, setMotionEventsActivePeriod) +{ + EXPECT_CALL(*p_motionDetectionImplMock,MOTION_DETECTION_SetActivePeriod(::testing::_,::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](std::string index, MOTION_DETECTION_TimeRange_t timeSet) { + return MOTION_DETECTION_RESULT_SUCCESS; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setMotionEventsActivePeriod"), _T("{\"nowTime\":1023,\"index\":\"FP_MD\",\"ranges\":[{\"startTime\":\"100\", \"endTime\":\"150\"}]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_Network.cpp b/NetworkManager/Tests/L1Tests/tests/test_Network.cpp new file mode 100755 index 0000000000..9db8a1fc8e --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Network.cpp @@ -0,0 +1,1411 @@ +#include +#include +#include +#include "Network.h" +#include "NetworkConnectivity.h" + +#include "FactoriesImplementation.h" +#include "ServiceMock.h" +#include "IarmBusMock.h" +#include "WrapsMock.h" + +using namespace std; +using namespace WPEFramework; + +using ::testing::NiceMock; + +extern "C" FILE* __real_popen(const char* command, const char* type); + +class NetworkTestBase : public ::testing::Test { +public: + + WrapsImplMock *p_wrapsImplMock = nullptr ; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + + NetworkTestBase() + { + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + ofstream file("/etc/device.properties"); + file << "DEVICE_TYPE=mediaclient\n"; + file << "WIFI_SUPPORT=true\n"; + file << "MOCA_INTERFACE=true\n"; + file <<"WIFI_INTERFACE==wlan0\n"; + file <<"MOCA_INTERFACE=eth0\n"; + file <<"ETHERNET_INTERFACE=eth0\n"; + file.close(); + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + return __real_popen(command, type); + })); + } +}; + +class NetworkTest : public NetworkTestBase { +protected: + + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + Core::JSONRPC::Message message; + ServiceMock service; + + NetworkTest() : plugin(Core::ProxyType::Create()), + handler(*plugin), + connection(1, 0) + { + IARM_EventHandler_t interfaceEnabled; + IARM_EventHandler_t interfaceConnection; + IARM_EventHandler_t interfaceIpaddress; + IARM_EventHandler_t defaultInterface; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call_with_IPCTimeout) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen, int timeout) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_isAvailable))); + return IARM_RESULT_SUCCESS; + }); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS)) { + interfaceEnabled = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS)) { + interfaceConnection = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS)) { + interfaceIpaddress = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE)) { + defaultInterface = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + + virtual ~NetworkTest() override + { + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class NetworkInitializedEventTest : public NetworkTest { +protected: + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + + NetworkInitializedEventTest() + : NetworkTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~NetworkInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + } +}; + +TEST_F(NetworkTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStbIp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isConnectedToInternet"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInternetConnectionState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPublicIP"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSTBIPFamily"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCaptivePortalURI"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("trace"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("traceNamedEndpoint"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getNamedEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("pingNamedEndpoint"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("ping"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getQuirks"))); +} + +TEST_F(NetworkTest, getStbIp) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getSTBip))); + + auto param = static_cast(arg); + memcpy(¶m->activeIfaceIpaddr, "192.168.1.101", sizeof("192.168.1.101")); + EXPECT_EQ(string(param->activeIfaceIpaddr), string(_T("192.168.1.101"))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStbIp"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ip\":\"192.168.1.101\",\"success\":true}")); +} + +TEST_F(NetworkTest, getStbIp_cache) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getSTBip))); + + auto param = static_cast(arg); + memcpy(¶m->activeIfaceIpaddr, "192.168.1.101", sizeof("192.168.1.101")); + EXPECT_EQ(string(param->activeIfaceIpaddr), string(_T("192.168.1.101"))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStbIp"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStbIp"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ip\":\"192.168.1.101\",\"success\":true}")); + +} + +TEST_F(NetworkTest, getNullStbIp) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getSTBip))); + + auto param = static_cast(arg); + EXPECT_EQ(string(param->activeIfaceIpaddr), string(_T(""))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStbIp"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ip\":\"\",\"success\":true}")); +} + +TEST_F(NetworkTest, getFailedStbIp) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getSTBip))); + + auto param = static_cast(arg); + EXPECT_EQ(string(param->activeIfaceIpaddr), string(_T(""))); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getStbIp"), _T("{}"), response)); + +} + +TEST_F(NetworkTest, getInterfaces) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getInterfaceList))); + auto param = static_cast(arg); + + param->size = 1; + memcpy(¶m->interfaces[0].name, "eth0", sizeof("eth0")); + memcpy(¶m->interfaces[0].mac, "AA:AA:AA:AA:AA:AA", sizeof("AA:AA:AA:AA:AA:AA")); + param->interfaces[0].flags = 69699; + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInterfaces"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"macAddress\":\"AA:AA:AA:AA:AA:AA\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"enabled\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"connected\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, getInterfacesFailed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getInterfaceList))); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getInterfaces"), _T("{}"), response)); +} + +TEST_F(NetworkTest, isInterfaceEnabled) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled))); + auto param = static_cast(arg); + + memcpy(¶m->setInterface, "ETHERNET", sizeof("ETHERNET")); + param->isInterfaceEnabled = true; + + EXPECT_EQ(string(param->setInterface), string(_T("ETHERNET"))); + EXPECT_EQ(param->isInterfaceEnabled, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isInterfaceEnabled"), _T("{\"interface\": \"ETHERNET\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"enabled\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, isInterfaceEnabled_failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled))); + auto param = static_cast(arg); + + memcpy(¶m->setInterface, "ETHERNET", sizeof("ETHERNET")); + param->isInterfaceEnabled = true; + + EXPECT_EQ(string(param->setInterface), string(_T("ETHERNET"))); + EXPECT_EQ(param->isInterfaceEnabled, true); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isInterfaceEnabled"), _T("{\"interface\": \"ETHERNET\"}"), response)); +} + +TEST_F(NetworkTest, getDefaultInterface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, getDefaultInterface_cache) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, isInterfaceEnabled_WrongIface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled))); + auto param = static_cast(arg); + + memcpy(¶m->setInterface, "ETHERNET", sizeof("ETHERNET")); + param->isInterfaceEnabled = true; + + EXPECT_EQ(string(param->setInterface), string(_T("ETHERNET"))); + EXPECT_EQ(param->isInterfaceEnabled, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isInterfaceEnabled"), _T("{\"interface\": \"TEST\"}"), response)); +} + +TEST_F(NetworkTest, isInterfaceEnabled_Fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled))); + auto param = static_cast(arg); + + memcpy(¶m->setInterface, "ETHERNET", sizeof("ETHERNET")); + param->isInterfaceEnabled = true; + + EXPECT_EQ(string(param->setInterface), string(_T("ETHERNET"))); + EXPECT_EQ(param->isInterfaceEnabled, true); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isInterfaceEnabled"), _T("{\"interface\": \"TEST\"}"), response)); +} + +TEST_F(NetworkTest, getIPSettings) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV4\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipversion\":\"IPV4\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"autoconfig\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipaddr\":\"192.168.1.101\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"netmask\":\"255.255.255.0\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"gateway\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"primarydns\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"secondarydns\":\"192.168.1.2\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, getIP6Settings) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV6", sizeof("IPV6")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV6"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV6\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipversion\":\"IPV6\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"autoconfig\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipaddr\":\"192.168.1.101\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"netmask\":\"255.255.255.0\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"gateway\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"primarydns\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"secondarydns\":\"192.168.1.2\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, getIPSettings_wifi) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "WIFI", sizeof("WIFI")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("WIFI"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"WIFI\",\"ipversion\": \"IPV4\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"WIFI\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipversion\":\"IPV4\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"autoconfig\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipaddr\":\"192.168.1.101\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"netmask\":\"255.255.255.0\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"gateway\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"primarydns\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"secondarydns\":\"192.168.1.2\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + +} + +TEST_F(NetworkTest, getIP6Settings_wifi) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "WIFI", sizeof("WIFI")); + memcpy(¶m->ipversion, "IPV6", sizeof("IPV6")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("WIFI"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV6"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"WIFI\",\"ipversion\": \"IPV6\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"WIFI\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipversion\":\"IPV6\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"autoconfig\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ipaddr\":\"192.168.1.101\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"netmask\":\"255.255.255.0\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"gateway\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"primarydns\":\"192.168.1.1\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"secondarydns\":\"192.168.1.2\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + +} + +TEST_F(NetworkTest, getIPSettings_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV4\"}"), response)); +} + +TEST_F(NetworkTest, getIPSettings_WrongIface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"TEST\",\"ipversion\": \"IPV4\"}"), response)); +} + +TEST_F(NetworkTest, getPublicIP) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getPublicIP))); + auto param = static_cast(arg); + memcpy(¶m->public_ip, "69.136.49.95", sizeof("69.136.49.95")); + + EXPECT_EQ(string(param->public_ip), string(_T("69.136.49.95"))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPublicIP"), _T("{\"iface\": \"WIFI\", \"ipv6\": false}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"public_ip\":\"69.136.49.95\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, setInterfaceEnabled) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setInterfaceEnabled"), _T("{\"interface\": \"WIFI\", \"enabled\": true, \"persist\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(NetworkTest, setInterfaceEnabled_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled))); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setInterfaceEnabled"), _T("{\"interface\": \"WIFI\", \"enabled\": true, \"persist\": true}"), response)); +} + +TEST_F(NetworkTest, setInterfaceEnabled_WrongIface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled))); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setInterfaceEnabled"), _T("{\"interface\": \"TEST\", \"enabled\": true, \"persist\": true}"), response)); +} + +TEST_F(NetworkTest, getSTBIPFamily) +{ + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSTBIPFamily"), _T("{\"family\": \"AF_INET\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ip\":\"192.168.1.101\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(NetworkTest, getSTBIPFamily_Error) +{ + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSTBIPFamily"), _T("{\"test\": \"AF_INET\"}"), response)); +} + +TEST_F(NetworkTest, getSTBIPFamily_Failed) +{ + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getIPSettings))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "ETHERNET", sizeof("ETHERNET")); + memcpy(¶m->ipversion, "IPV4", sizeof("IPV4")); + param->autoconfig = true; + memcpy(¶m->ipaddress, "192.168.1.101", sizeof("192.168.1.101")); + memcpy(¶m->netmask, "255.255.255.0", sizeof("255.255.255.0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->primarydns, "192.168.1.1", sizeof("192.168.1.1")); + memcpy(¶m->secondarydns, "192.168.1.2", sizeof("192.168.1.2")); + + EXPECT_EQ(string(param->interface), string(_T("ETHERNET"))); + EXPECT_EQ(string(param->ipversion), string(_T("IPV4"))); + EXPECT_EQ(string(param->ipaddress), string(_T("192.168.1.101"))); + EXPECT_EQ(string(param->netmask), string(_T("255.255.255.0"))); + EXPECT_EQ(string(param->gateway), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->primarydns), string(_T("192.168.1.1"))); + EXPECT_EQ(string(param->secondarydns), string(_T("192.168.1.2"))); + EXPECT_EQ(param->autoconfig, true); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getIPSettings"), _T("{\"interface\": \"ETHERNET\",\"ipversion\": \"IPV4\"}"), response)); +} + +TEST_F(NetworkTest, setDefaultInterface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setDefaultInterface))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setDefaultInterface"), _T("{\"interface\": \"WIFI\", \"persist\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(NetworkTest, setDefaultInterface_WrongIface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setDefaultInterface))); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setDefaultInterface"), _T("{\"interface\": \"TEST\", \"persist\": true}"), response)); +} + +TEST_F(NetworkTest, setDefaultInterface_failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setDefaultInterface))); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setDefaultInterface"), _T("{\"interface\": \"TEST\", \"persist\": true}"), response)); +} + +TEST_F(NetworkTest, setIPSettings) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setIPSettings))); + + auto param = static_cast(arg); + param->isSupported = true; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setIPSettings"), _T("{\"interface\": \"WIFI\", \"ipversion\": \"IPV4\",\"autoconfig\": true,\"ipaddr\": \"192.168.1.101\",\"netmask\": \"255.255.255.0\",\"gateway\": \"192.168.1.1\",\"primarydns\": \"192.168.1.1\",\"secondarydns\": \"192.168.1.2\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"supported\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + + + +//TEST_F(NetworkTest, trace) +//{ +// EXPECT_CALL(iarmBusImplMock, IARM_Bus_Call) +// .Times(::testing::AnyNumber()) +// .WillRepeatedly( +// [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { +// EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); +// EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); +// +// auto param = static_cast(arg); +// memcpy(¶m->interface, "eth0", sizeof("eth0")); +// memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); +// +// return IARM_RESULT_SUCCESS; +// }); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("trace"), _T("{\"endpoint\":\"45.57.221.20\", \"packets\":5}"), response)); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +//} +// +TEST_F(NetworkTest, trace_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("trace"), _T("{\"endpoint\":\"45.57.221.20\", \"packets\":5}"), response)); +} + +TEST_F(NetworkTest, trace_noiface) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("trace"), _T("{\"test\":\"45.57.221.20\", \"packets\":5}"), response)); +} + +//TEST_F(NetworkTest, traceNamedEndpoint) +//{ +// EXPECT_CALL(iarmBusImplMock, IARM_Bus_Call) +// .Times(::testing::AnyNumber()) +// .WillRepeatedly( +// [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { +// EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); +// EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); +// +// auto param = static_cast(arg); +// memcpy(¶m->interface, "eth0", sizeof("eth0")); +// memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); +// +// return IARM_RESULT_SUCCESS; +// }); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("traceNamedEndpoint"), _T("{\"endpointName\": \"CMTS\", \"packets\": 5}"), response)); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +//} + +TEST_F(NetworkTest, traceNamedEndpoint_noendoint) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("traceNamedEndpoint"), _T("{\"test\": \"CMTS\", \"packets\": 5}"), response)); +} + +TEST_F(NetworkTest, traceNamedEndpoint_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "45.57.221.20", sizeof("45.57.221.20")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("traceNamedEndpoint"), _T("{\"endpointName\": \"CMTS\", \"packets\": 5}"), response)); +} + +TEST_F(NetworkTest, getNamedEndpoints) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getNamedEndpoints"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"endpoints\":[\"CMTS\"],\"success\":true}")); +} + +//TEST_F(NetworkTest, pingNamedEndpoint) +//{ +// EXPECT_CALL(iarmBusImplMock, IARM_Bus_Call) +// .Times(::testing::AnyNumber()) +// .WillRepeatedly( +// [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { +// EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); +// EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); +// +// auto param = static_cast(arg); +// memcpy(¶m->interface, "eth0", sizeof("eth0")); +// memcpy(¶m->gateway, "127.0.0.1", sizeof("127.0.0.1")); +// +// return IARM_RESULT_SUCCESS; +// }); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("pingNamedEndpoint"), _T("{\"endpointName\": \"CMTS\", \"packets\": 5, \"guid\": \"...\"}"), response)); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"target\":\"127.0.0.1\""))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetsTransmitted\":5"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetsReceived\":5"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetLoss\":\" 0\""))); +//} + +TEST_F(NetworkTest, pingNamedEndpoint_noarg) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "127.0.0.1", sizeof("127.0.0.1")); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("pingNamedEndpoint"), _T("{\"test\": \"CMTS\", \"packets\": 5, \"guid\": \"...\"}"), response)); +} + +TEST_F(NetworkTest, pingNamedEndpoint_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "127.0.0.1", sizeof("127.0.0.1")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("pingNamedEndpoint"), _T("{\"endpointName\": \"CMTS\", \"packets\": 5, \"guid\": \"...\"}"), response)); +} + +//TEST_F(NetworkTest, ping) +//{ +// EXPECT_CALL(iarmBusImplMock, IARM_Bus_Call) +// .Times(::testing::AnyNumber()) +// .WillRepeatedly( +// [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { +// EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); +// EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); +// +// auto param = static_cast(arg); +// memcpy(¶m->interface, "eth0", sizeof("eth0")); +// memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); +// +// return IARM_RESULT_SUCCESS; +// }); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); +// EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ping"), _T("{\"endpoint\": \"127.0.0.1\", \"packets\": 5, \"guid\": \"...\"}"), response)); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"target\":\"127.0.0.1\""))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetsTransmitted\":5"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetsReceived\":5"))); +// EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"packetLoss\":\" 0\""))); +//} + +TEST_F(NetworkTest, ping_noendpoint) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("ping"), _T("{\"test\": \"127.0.0.1\", \"packets\": 5, \"guid\": \"...\"}"), response)); +} + +TEST_F(NetworkTest, ping_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("ping"), _T("{\"endpoint\": \"127.0.0.1\", \"packets\": 5, \"guid\": \"...\"}"), response)); +} + +TEST_F(NetworkTest, ping_fail1) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getDefaultInterface))); + + auto param = static_cast(arg); + memcpy(¶m->interface, "eth0", sizeof("eth0")); + memcpy(¶m->gateway, "192.168.1.1", sizeof("192.168.1.1")); + + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("ping"), _T("{\"test\": \"127.0.0.1\", \"packets\": 5, \"guid\": \"...\"}"), response)); +} + +TEST_F(NetworkTest, getQuirks) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getQuirks"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"quirks\":[\"RDK-20093\"],\"success\":true}")); +} + +TEST_F(NetworkTest, getInternetConnectionState) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T("{\"ipversion\": \"IPV6\"}"), response)); + EXPECT_EQ(response, string("{\"state\":0,\"ipversion\":\"IPV6\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"state\":0,\"ipversion\":\"IPV4\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"state\":0,\"success\":true}")); +} + +TEST_F(NetworkTest, getInternetConnectionState_cache) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"state\":0,\"ipversion\":\"IPV4\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"state\":0,\"ipversion\":\"IPV4\",\"success\":true}")); +} + + +TEST_F(NetworkTest, isConnectedToInternet) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV6\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV6\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV4\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"success\":true}")); +} + +TEST_F(NetworkTest, isConnectedToInternet_cache) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV6\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV6\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV6\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV6\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV4\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{\"ipversion\": \"IPV4\"}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"ipversion\":\"IPV4\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"connectedToInternet\":false,\"success\":true}")); +} + +TEST_F(NetworkTest, getCaptivePortalURI) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCaptivePortalURI"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"URI\":\"\",\"success\":true}")); +} + +TEST_F(NetworkInitializedEventTest, ConnectivityMonitoring) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + Core::Event onInternetStatusChange(false, true); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onInternetStatusChange\",\"params\":{\"state\":0,\"status\":\"NO_INTERNET\"}}"))); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startConnectivityMonitoring"), _T("{\"interval\":6}"), response)); + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + handler.Unsubscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); + EXPECT_NE(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopConnectivityMonitoring"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(NetworkTest, setConnectivityTestEndpoints) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://clients3.google.com/generate_204\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(NetworkTest, setStunEndPoint) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setStunEndPoint"), _T("{}"), response)); + //EXPECT_EQ(response, string("{\"quirks\":[\"RDK-20093\"],\"success\":true}")); +} + +TEST_F(NetworkTest, configurePNI) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_configurePNI))); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("configurePNI"), _T("{}"), response)); +} + +TEST_F(NetworkTest, configurePNI_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_configurePNI))); + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("configurePNI"), _T("{}"), response)); +} + +TEST_F(NetworkInitializedEventTest, onInterfaceStatusChanged) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_getInterfaceList))); + auto param = static_cast(arg); + + param->size = 1; + memcpy(¶m->interfaces[0].name, "eth0", sizeof("eth0")); + memcpy(¶m->interfaces[0].mac, "AA:AA:AA:AA:AA:AA", sizeof("AA:AA:AA:AA:AA:AA")); + param->interfaces[0].flags = 69699; + + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInterfaces"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"macAddress\":\"AA:AA:AA:AA:AA:AA\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"enabled\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"connected\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onInterfaceStatusChanged\",\"params\":{\"interface\":\"ETHERNET\",\"enabled\":true}}"))); + return Core::ERROR_NONE; + })); + IARM_BUS_NetSrvMgr_Iface_EventInterfaceEnabledStatus_t intData; + intData.status = 1; + strcpy(intData.interface,"eth0"); + handler.Subscribe(0, _T("onInterfaceStatusChanged"), _T("org.rdk.Network"), message); + plugin->eventHandler("NET_SRV_MGR", IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, static_cast(&intData), sizeof(intData)); + handler.Unsubscribe(0, _T("onInterfaceStatusChanged"), _T("org.rdk.Network"), message); +} + +TEST_F(NetworkInitializedEventTest, onConnectionStatusChanged) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T("{\"endpoints\": [\"http://localhost:8000\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + Core::Event onInternetStatusChange(false, true); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onConnectionStatusChanged\",\"params\":{\"interface\":\"ETHERNET\",\"status\":\"CONNECTED\"}}"))); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onInternetStatusChange\",\"params\":{\"state\":0,\"status\":\"NO_INTERNET\"}}"))); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t intData; + intData.status = 1; + strcpy(intData.interface,"eth0"); + handler.Subscribe(0, _T("onConnectionStatusChanged"), _T("org.rdk.Network"), message); + handler.Subscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); + plugin->eventHandler("NET_SRV_MGR", IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, static_cast(&intData), sizeof(intData)); + handler.Unsubscribe(0, _T("onConnectionStatusChanged"), _T("org.rdk.Network"), message); + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + handler.Unsubscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); + EXPECT_NE(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopConnectivityMonitoring"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(NetworkInitializedEventTest, onIPAddressStatusChanged) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onIPAddressStatusChanged\",\"params\":{\"interface\":\"ETHERNET\",\"ip4Address\":\"192.168.1.10\",\"status\":\"ACQUIRED\"}}"))); + return Core::ERROR_NONE; + })); + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t intData; + intData.is_ipv6 = 0; + strcpy(intData.interface,"eth0"); + intData.acquired = 1; + strcpy(intData.ip_address,"192.168.1.10"); + handler.Subscribe(0, _T("onIPAddressStatusChanged"), _T("org.rdk.Network"), message); + plugin->eventHandler("NET_SRV_MGR", IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, static_cast(&intData), sizeof(intData)); + handler.Unsubscribe(0, _T("onIPAddressStatusChanged"), _T("org.rdk.Network"), message); +} + +TEST_F(NetworkInitializedEventTest, onDefaultInterfaceChanged) +{ +/* + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInterfaces"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"interface\":\"ETHERNET\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"macAddress\":\"AA:AA:AA:AA:AA:AA\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"enabled\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"connected\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +*/ + Core::Event onDefaultInterfaceChanged(false, true); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onDefaultInterfaceChanged\",\"params\":{\"oldInterfaceName\":\"\",\"newInterfaceName\":\"ETHERNET\"}}"))); + onDefaultInterfaceChanged.SetEvent(); + return Core::ERROR_NONE; + })); + IARM_BUS_NetSrvMgr_Iface_EventDefaultInterface_t intData; + strcpy(intData.newInterface,"eth0"); + handler.Subscribe(0, _T("onDefaultInterfaceChanged"), _T("org.rdk.Network"), message); + plugin->eventHandler("NET_SRV_MGR", IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, static_cast(&intData), sizeof(intData)); + EXPECT_EQ(Core::ERROR_NONE, onDefaultInterfaceChanged.Lock()); + handler.Unsubscribe(0, _T("onDefaultInterfaceChanged"), _T("org.rdk.Network"), message); +} + +TEST_F(NetworkInitializedEventTest, onInternetStatusChange) +{ + Core::Event onInternetStatusChange(false, true); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Network.onInternetStatusChange\",\"params\":{\"state\":0,\"status\":\"NO_INTERNET\"}}"))); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + nsm_internetState intData = NO_INTERNET; + handler.Subscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); + plugin->notifyInternetStatusChange(intData); + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + handler.Unsubscribe(0, _T("onInternetStatusChange"), _T("org.rdk.Network"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_OCIContainer.cpp b/NetworkManager/Tests/L1Tests/tests/test_OCIContainer.cpp new file mode 100755 index 0000000000..b7257a565c --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_OCIContainer.cpp @@ -0,0 +1,225 @@ +#include + +#include "OCIContainer.h" +#include "ServiceMock.h" +#include "DobbyMock.h" +#include "FactoriesImplementation.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +class OCIContainerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + OCIContainerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~OCIContainerTest() = default; +}; + +class OCIContainerInitializedTest : public OCIContainerTest { +protected: + NiceMock service; + DobbyProxyMock *p_dobbymock = nullptr ; + IpcServiceMock *p_ipcservicemock = nullptr ; + + OCIContainerInitializedTest() + : OCIContainerTest() + { + p_dobbymock = new NiceMock ; + DobbyProxy::setImpl(p_dobbymock); + + p_ipcservicemock = new NiceMock ; + IpcService::setImpl(p_ipcservicemock); + + EXPECT_CALL(*p_ipcservicemock, start()) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_dobbymock, registerListener(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(5)); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + + virtual ~OCIContainerInitializedTest() override + { + EXPECT_CALL(*p_dobbymock, unregisterListener(5)) + .WillOnce(::testing::Return()); + + plugin->Deinitialize(&service); + DobbyProxy::setImpl(nullptr); + if (p_dobbymock != nullptr) + { + delete p_dobbymock; + p_dobbymock = nullptr; + } + IpcService::setImpl(nullptr); + if (p_ipcservicemock != nullptr) + { + delete p_ipcservicemock; + p_ipcservicemock = nullptr; + } + } +}; + + + +TEST_F(OCIContainerTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("listContainers"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getContainerState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getContainerInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startContainer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startContainerFromDobbySpec"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopContainer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("pauseContainer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resumeContainer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("executeCommand"))); +} + +TEST_F(OCIContainerInitializedTest, listContainersTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("listContainers"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"containers\":[{\"Descriptor\":91,\"Id\":\"com.bskyb.epgui\"},{\"Descriptor\":94,\"Id\":\"Netflix\"}],\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, getContainerStateTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, getContainerState(91)) + .WillOnce(::testing::Return(IDobbyProxyEvents::ContainerState::Running)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getContainerState"), _T("{" + "\"containerId\": \"com.bskyb.epgui\"}"), response)); + EXPECT_EQ(response, string("{\"containerId\":\"com.bskyb.epgui\",\"state\":\"Running\",\"success\":true}")); +} + + +TEST_F(OCIContainerInitializedTest, getContainerInfoTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, getContainerInfo(91)) + .WillOnce(::testing::Return("{\"cpu\":{\"usage\" :{\"percpu\" :[3661526845,3773518079,4484546066,4700379608]," + "\"total\" : 16619970598}},\"gpu\":{\"memory\" :{\"failcnt\" : 0,\"limit\" : 209715200,\"max\" : 3911680,\"usage\" : 0}}," + "\"id\":\"Cobalt-0\",\"ion\":{\"heaps\" :{\"ion.\" :{\"failcnt\" : null,\"limit\" : null,\"max\" : null,\"usage\" : null}}}," + "\"memory\":{\"user\" :{\"failcnt\" : 0,\"limit\" : 419430400,\"max\" : 73375744,\"usage\" : 53297152}},\"pids\":[13132,13418]," + "\"processes\":[{\"cmdline\" : \"/usr/libexec/DobbyInit /usr/bin/WPEProcess -l libWPEFrameworkCobaltImpl.so -c" + " CobaltImplementation -C Cobalt-0 -r /tmp/communicator -i 64 -x 48 -p \"/opt/persistent/rdkservices/Cobalt-0/\" -s" + " \"/usr/lib/wpeframework/plugins/\" -d \"/usr/share/WPEFramework/Cobalt/\" -a \"/usr/bin/\" -v \"/tmp/Cobalt-0/\" -m" + " \"/usr/lib/wpeframework/proxystubs/\" -P \"/opt/minidumps/\" \",\"executable\" : \"/usr/libexec/DobbyInit\",\"nsPid\" : 1," + "\"pid\" : 13132},{\"cmdline\" : \"WPEProcess -l libWPEFrameworkCobaltImpl.so -c CobaltImplementation -C Cobalt-0 -r /tmp/communicator" + " -i 64 -x 48 -p \"/opt/persistent/rdkservices/Cobalt-0/\" -s \"/usr/lib/wpeframework/plugins/\" -d \"/usr/share/WPEFramework/Cobalt/\"" + " -a \"/usr/bin/\" -v \"/tmp/Cobalt-0/\" -m \"/usr/lib/wpeframework/proxystubs/\" -P \"/opt/minidumps/\" \",\"executable\" : " + "\"/usr/bin/WPEProcess\",\"nsPid\" : 6,\"pid\" : 13418}],\"state\":\"running\",\"timestamp\":1298657054196}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getContainerInfo"), _T("{" + "\"containerId\": \"com.bskyb.epgui\"}"), response)); + EXPECT_EQ(response, string("{\"info\":{\"cpu\":{\"usage\" :{\"percpu\" :[3661526845,3773518079,4484546066,4700379608]," + "\"total\" : 16619970598}},\"gpu\":{\"memory\" :{\"failcnt\" : 0,\"limit\" : 209715200,\"max\" : 3911680,\"usage\" : 0}}," + "\"id\":\"Cobalt-0\",\"ion\":{\"heaps\" :{\"ion.\" :{\"failcnt\" : null,\"limit\" : null,\"max\" : null,\"usage\" : null}}}," + "\"memory\":{\"user\" :{\"failcnt\" : 0,\"limit\" : 419430400,\"max\" : 73375744,\"usage\" : 53297152}},\"pids\":[13132,13418]," + "\"processes\":[{\"cmdline\" : \"/usr/libexec/DobbyInit /usr/bin/WPEProcess -l libWPEFrameworkCobaltImpl.so -c" + " CobaltImplementation -C Cobalt-0 -r /tmp/communicator -i 64 -x 48 -p \"/opt/persistent/rdkservices/Cobalt-0/\" -s" + " \"/usr/lib/wpeframework/plugins/\" -d \"/usr/share/WPEFramework/Cobalt/\" -a \"/usr/bin/\" -v \"/tmp/Cobalt-0/\" -m" + " \"/usr/lib/wpeframework/proxystubs/\" -P \"/opt/minidumps/\" \",\"executable\" : \"/usr/libexec/DobbyInit\",\"nsPid\" : 1," + "\"pid\" : 13132},{\"cmdline\" : \"WPEProcess -l libWPEFrameworkCobaltImpl.so -c CobaltImplementation -C Cobalt-0 -r /tmp/communicator" + " -i 64 -x 48 -p \"/opt/persistent/rdkservices/Cobalt-0/\" -s \"/usr/lib/wpeframework/plugins/\" -d \"/usr/share/WPEFramework/Cobalt/\"" + " -a \"/usr/bin/\" -v \"/tmp/Cobalt-0/\" -m \"/usr/lib/wpeframework/proxystubs/\" -P \"/opt/minidumps/\" \",\"executable\" : " + "\"/usr/bin/WPEProcess\",\"nsPid\" : 6,\"pid\" : 13418}],\"state\":\"running\",\"timestamp\":1298657054196},\"success\":true}")); +} + + +TEST_F(OCIContainerInitializedTest, startContainerTest) +{ + EXPECT_CALL(*p_dobbymock, startContainerFromBundle(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(91)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startContainer"), _T("{" + "\"containerId\": \"com.bskyb.epgui\", \"bundlePath\":\"/containers/myBundle\"," + "\"command\":\"command\", \"westerosSocket\":\"/usr/mySocket\", \"envvar\":[\"FOO=BAR\"]}"), response)); + EXPECT_EQ(response, string("{\"descriptor\":91,\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, startContainerFromDobbySpecTest) +{ + EXPECT_CALL(*p_dobbymock, startContainerFromSpec(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(91)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startContainerFromDobbySpec"), _T("{" + "\"containerId\": \"com.bskyb.epgui\", \"dobbySpec\":\"/containers/dobbySpec\"," + "\"command\":\"command\", \"westerosSocket\":\"/usr/mySocket\"}"), response)); + EXPECT_EQ(response, string("{\"descriptor\":91,\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, stopContainerTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, stopContainer(91, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopContainer"), _T("{" + "\"containerId\": \"com.bskyb.epgui\", \"force\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, pauseContainerTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, pauseContainer(91)) + .WillOnce(::testing::Return(true)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("pauseContainer"), _T("{" + "\"containerId\": \"com.bskyb.epgui\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, resumeContainerTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, resumeContainer(91)) + .WillOnce(::testing::Return(true)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resumeContainer"), _T("{" + "\"containerId\": \"com.bskyb.epgui\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(OCIContainerInitializedTest, executeCommandTest) +{ + std::list> containerslist = {{91, "com.bskyb.epgui"},{94, "Netflix"}}; + EXPECT_CALL(*p_dobbymock, listContainers()) + .WillOnce(::testing::Return(containerslist)); + + EXPECT_CALL(*p_dobbymock, execInContainer(91, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("executeCommand"), _T("{" + "\"containerId\": \"com.bskyb.epgui\", \"options\":\"--cwd=PATH\", \"command\":\"/bin/sleep 5\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} \ No newline at end of file diff --git a/NetworkManager/Tests/L1Tests/tests/test_Packager.cpp b/NetworkManager/Tests/L1Tests/tests/test_Packager.cpp new file mode 100755 index 0000000000..6cf2720d54 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Packager.cpp @@ -0,0 +1,120 @@ + +#include "gtest/gtest.h" +#include "FactoriesImplementation.h" +#include "Packager.h" +#include "PackagerImplementation.h" +#include "ServiceMock.h" +#include "COMLinkMock.h" +#include "IarmBusMock.h" +#include +#include + + +using namespace WPEFramework; +using ::testing::NiceMock; + +namespace { +const string config = _T("Packager"); +const string callSign = _T("Packager"); +const string webPrefix = _T("/Service/Packager"); +const string volatilePath = _T("/tmp/"); +const string dataPath = _T("/tmp/"); +} + +class PackagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + PluginHost::IWeb* interface; + + PackagerTest() + : plugin(Core::ProxyType::Create()) + { + interface = static_cast(plugin->QueryInterface(PluginHost::IWeb::ID)); + } + virtual ~PackagerTest() + { + interface->Release(); + plugin.Release(); + } + + virtual void SetUp() + { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() + { + ASSERT_TRUE(interface != nullptr); + } +}; + +class PackagerInitializedTest : public PackagerTest { +protected: + NiceMock factoriesImplementation; + NiceMock service; + NiceMock comLinkMock; + Core::ProxyType PackagerImplementation; + + PackagerInitializedTest() + : PackagerTest() + { + PackagerImplementation = Core::ProxyType::Create(); + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(volatilePath)); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + ON_CALL(service, DataPath()) + .WillByDefault(::testing::Return(dataPath)); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(PackagerImplementation)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + opkg_config->lists_dir = strdup("/tmp/test"); + } + virtual ~PackagerInitializedTest() override + { + //plugin->Deinitialize(&service); + free(opkg_config->lists_dir); + PluginHost::IFactories::Assign(nullptr); + } +}; + + +TEST_F(PackagerInitializedTest, httpGetPutInstall) +{ + //HTTP_GET - Get status for all modules + Web::Request request; + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + _T("/Install"); + auto httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); +} + +TEST_F(PackagerInitializedTest, httpGetPutSynchornize) +{ + //HTTP_GET - Get status for all modules + Web::Request request; + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + _T("/SynchronizeRepository"); + auto httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); +} + +TEST_F(PackagerInitializedTest, InstallTest) +{ + EXPECT_EQ(Core::ERROR_NONE, PackagerImplementation->Install("Test", "1.0", "arm")); + +} + +TEST_F(PackagerInitializedTest, SynchronizeRepositoryTest) +{ + + EXPECT_EQ(Core::ERROR_NONE, PackagerImplementation->SynchronizeRepository()); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_RDKShell.cpp b/NetworkManager/Tests/L1Tests/tests/test_RDKShell.cpp new file mode 100755 index 0000000000..239be0ce95 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_RDKShell.cpp @@ -0,0 +1,855 @@ +#include +#include +#include "RDKShell.h" +#include "rdkshell.h" +#include "rdkshellmock.h" +#include "ServiceMock.h" + +using namespace WPEFramework; + +class RDKShellTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + Core::JSONRPC::Message message; + RDKShellImplMock *p_rdkShellImplMock = nullptr ; + CompositorImplMock *p_compositorImplMock = nullptr ; + RdkShellApiImplMock *p_rdkShellApiImplMock = nullptr ; + string response; + + RDKShellTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + p_rdkShellApiImplMock = new testing::NiceMock ; + RdkShell::RdkShellApi::setImpl(p_rdkShellApiImplMock); + + p_compositorImplMock = new testing::NiceMock ; + RdkShell::CompositorController::setImpl(p_compositorImplMock); + + p_rdkShellImplMock = new testing::NiceMock ; + RDKShell::setImpl(p_rdkShellImplMock); + } + virtual ~RDKShellTest() + { + RdkShell::RdkShellApi::setImpl(nullptr); + if (p_rdkShellApiImplMock != nullptr) + { + delete p_rdkShellApiImplMock; + p_rdkShellApiImplMock = nullptr; + } + + RDKShell::setImpl(nullptr); + if (p_rdkShellImplMock != nullptr) + { + delete p_rdkShellImplMock; + p_rdkShellImplMock = nullptr; + } + RdkShell::CompositorController::setImpl(nullptr); + if (p_compositorImplMock != nullptr) + { + delete p_compositorImplMock; + p_compositorImplMock = nullptr; + } + } +}; + + +TEST_F(RDKShellTest, RegisteredMethods){ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addAnimation"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addKeyIntercept"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addKeyIntercepts"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setKeyIntercepts"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addKeyListener"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addKeyMetadataListener"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("exitAgingMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("createDisplay"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("destroy"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableInactivityReporting"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableKeyRepeats"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableLogsFlushing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableVirtualDisplay"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("generateKey"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getAvailableTypes"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getBounds"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getClients"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCursorSize"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHolePunch"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getKeyRepeatsEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLastWakeupKey"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLogsFlushingEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOpacity"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getScale"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getScreenResolution"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getScreenshot"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSystemMemory"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSystemResourceInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVirtualDisplayEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVirtualResolution"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getVisibility"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getZOrder"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getGraphicsFrameRate"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("hideAllClients"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("hideCursor"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("hideFullScreenImage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("hideSplashLogo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("ignoreKeyInputs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("injectKey"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("kill"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("launch"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("launchApplication"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("launchResidentApp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("moveBehind"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("moveToBack"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("moveToFront"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("removeAnimation"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("removeKeyIntercept"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("removeKeyListener"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("removeKeyMetadataListener"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resetInactivityTime"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resumeApplication"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("scaleToFit"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setBounds"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setCursorSize"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFocus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setHolePunch"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setInactivityInterval"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMemoryMonitor"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOpacity"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setScale"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setScreenResolution"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setTopmost"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVirtualResolution"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVisibility"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setGraphicsFrameRate"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("showCursor"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("showFullScreenImage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("showSplashLogo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("showWatermark"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("suspend"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("suspendApplication"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("keyRepeatConfig"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setAVBlocked"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getBlockedAVApplications"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("addEasterEggs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("removeEasterEggs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableEasterEggs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEasterEggs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("launchFactoryApp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("launchFactoryAppShortcut"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableInputEvents"))); + } +TEST_F(RDKShellTest, enableInputEvents) +{ + ON_CALL(*p_compositorImplMock, enableInputEvents(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, bool enable){ + EXPECT_EQ(client, string("searchanddiscovery")); + EXPECT_EQ(enable, true); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableInputEvents"), _T("{" + "\"clients\": [" + " \"searchanddiscovery\"" + "]," + "\"enable\": true" + "}"), response)); +} + +TEST_F(RDKShellTest, getClients) +{ + ON_CALL(*p_compositorImplMock, getClients(::testing::_)) + .WillByDefault(::testing::Invoke( + [](std::vector& clients){ + clients.push_back("org.rdk.Netflix"); + clients.push_back("org.rdk.RDKBrowser2"); + clients.push_back("Test1"); + clients.push_back("Test2"); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getClients"), _T("{}"), response)); + EXPECT_EQ(response, string("{" + "\"clients\":[" + "\"org.rdk.Netflix\"," + "\"org.rdk.RDKBrowser2\"," + "\"Test1\"," + "\"Test2\"" + "]," + "\"success\":true" + "}")); +} + +TEST_F(RDKShellTest, keyRepeatConfig) +{ + ON_CALL(*p_compositorImplMock, setKeyRepeatConfig(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](bool enabled, int32_t initialDelay, int32_t repeatInterval){ + EXPECT_EQ(enabled, true); + EXPECT_EQ(initialDelay, 500); + EXPECT_EQ(repeatInterval, 250); + return true; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("keyRepeatConfig"), _T("{" + "\"enabled\":true," + "\"initialDelay\":500," + "\"repeatInterval\":250}"), response)); +} + +TEST_F(RDKShellTest, resetinactivity) +{ + ON_CALL(*p_compositorImplMock, resetInactivityTime()) + .WillByDefault(::testing::Invoke( + [&](){ + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetInactivityTime"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, launchApplication) +{ + ON_CALL(*p_compositorImplMock, launchApplication(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const std::string& uri, const std::string& mimeType, bool topmost, bool focus){ + EXPECT_EQ(client, string("testApp")); + EXPECT_EQ(uri, string("/usr/bin/westeros_test")); + EXPECT_EQ(mimeType, string("application/native")); + EXPECT_EQ(topmost, false); + EXPECT_EQ(focus, false); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("launchApplication"), _T("{\"client\": \"testApp\"," + "\"uri\": \"/usr/bin/westeros_test\"," + "\"mimeType\": \"application/native\"}"), response)); +} + +TEST_F(RDKShellTest, suspendApplication) +{ + ON_CALL(*p_compositorImplMock, suspendApplication(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client){ + EXPECT_EQ(client, string("HtmlApp")); + return true; + })); + ON_CALL(*p_compositorImplMock, setVisibility(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool visible){ + EXPECT_EQ(client, string("HtmlApp")); + EXPECT_EQ(visible, false); + return true; + })); + ON_CALL(*p_compositorImplMock, getMimeType(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const string& client, string& mimeType){ + mimeType = RDKSHELL_APPLICATION_MIME_TYPE_NATIVE; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("suspendApplication"), _T("{\"client\": \"HtmlApp\"}"), response)); +} + +TEST_F(RDKShellTest, resumeApplication) +{ + ON_CALL(*p_compositorImplMock, resumeApplication(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client){ + EXPECT_EQ(client, string("HtmlApp")); + return true; + })); + ON_CALL(*p_compositorImplMock, setVisibility(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool visible){ + EXPECT_EQ(client, string("HtmlApp")); + EXPECT_EQ(visible, true); + return true; + })); + ON_CALL(*p_compositorImplMock, getMimeType(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const string& client, string& mimeType){ + mimeType = RDKSHELL_APPLICATION_MIME_TYPE_NATIVE; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resumeApplication"), _T("{\"client\": \"HtmlApp\"}"), response)); +} + + +TEST_F(RDKShellTest, getGraphicsFrameRate) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getGraphicsFrameRate"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"framerate\":40,\"success\":true}")); +} + +TEST_F(RDKShellTest, setGraphicsFrameRate) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setGraphicsFrameRate"), _T("{\"framerate\":60}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, showFullScreenImage) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("showFullScreenImage"), _T("{\"path\":\"tmp\netflix.png\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, hideFullScreenImage) +{ + ON_CALL(*p_compositorImplMock, hideFullScreenImage()) + .WillByDefault(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("hideFullScreenImage"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, setvisibility) +{ + ON_CALL(*p_compositorImplMock, setVisibility(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool visible){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(visible, true); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVisibility"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"," + "\"visible\": true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, getVisibility) +{ + ON_CALL(*p_compositorImplMock, getVisibility(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, bool& visible){ + bool x = true; + visible = x; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVisibility"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"visible\":true,\"success\":true}")); +} + +TEST_F(RDKShellTest, getSystemMemory) +{ + EXPECT_CALL(*p_rdkShellApiImplMock, systemRam(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](uint32_t& freeKb, uint32_t& totalKb, uint32_t& availableKb, uint32_t& usedSwapKb) { + freeKb = 994056; + totalKb = 2830092; + usedSwapKb = 0; + availableKb = 764628; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSystemMemory"), _T("{}"), response)); + EXPECT_EQ(response, string("{" + "\"freeRam\":994056," + "\"swapRam\":0," + "\"totalRam\":2830092," + "\"availablememory\":764628," + "\"success\":true" + "}")); +} + + +TEST_F(RDKShellTest, setBounds) +{ + ON_CALL(*p_compositorImplMock, setBounds(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(x, 0); + EXPECT_EQ(y, 0); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBounds"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\",\"x\":0,\"y\":0,\"w\":1920,\"h\":1080}"),response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} +TEST_F(RDKShellTest, getBounds) +{ + ON_CALL(*p_compositorImplMock, getBounds(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, uint32_t &x, uint32_t &y, uint32_t &width, uint32_t &height){ + x = 0; + y = 0; + width = 1920; + height = 1080; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getBounds"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{" + "\"bounds\":{" + "\"x\":0," + "\"y\":0," + "\"w\":1920," + "\"h\":1080" + "}," + "\"success\":true" + "}")); +} + +TEST_F(RDKShellTest, setCursorSize) +{ + ON_CALL(*p_compositorImplMock, setCursorSize(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](uint32_t width, uint32_t height){ + EXPECT_EQ(width, 255); + EXPECT_EQ(height, 255); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setCursorSize"), _T("{\"width\":255,\"height\":255}"),response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} +TEST_F(RDKShellTest, getCursorSize) +{ + ON_CALL(*p_compositorImplMock, getCursorSize(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](uint32_t& width, uint32_t& height){ + width = 255; + height = 255; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCursorSize"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"width\":255,\"height\":255,\"success\":true}")); +} + +TEST_F(RDKShellTest, showCursor) +{ + ON_CALL(*p_compositorImplMock, showCursor()) + .WillByDefault(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("showCursor"), _T("{}"),response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} +TEST_F(RDKShellTest, hideCursor) +{ + ON_CALL(*p_compositorImplMock, hideCursor()) + .WillByDefault(::testing::Return(true)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("hideCursor"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, setLogLevel) +{ + ON_CALL(*p_compositorImplMock, setLogLevel(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string level){ + EXPECT_EQ(level, string("DEBUG")); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogLevel"), _T("{\"logLevel\": \"DEBUG\"}"), response)); +} + +TEST_F(RDKShellTest, getLogLevel) +{ + ON_CALL(*p_compositorImplMock, getLogLevel(::testing::_)) + .WillByDefault(::testing::Invoke( + [](std::string& level){ + std::string a = "DEBUG"; + level = a; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLogLevel"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"logLevel\":\"DEBUG\",\"success\":true}")); +} + + + +TEST_F(RDKShellTest, enablekeyRepeat) +{ + ON_CALL(*p_compositorImplMock, enableKeyRepeats(::testing::_)) + .WillByDefault(::testing::Invoke( + [](bool enable){ + EXPECT_EQ(enable, true); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableKeyRepeats"), _T("{\"enable\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, getKeyRepeatsEnabled) +{ + ON_CALL(*p_compositorImplMock, getKeyRepeatsEnabled(::testing::_)) + .WillByDefault(::testing::Invoke( + [](bool& enable){ + enable = true; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getKeyRepeatsEnabled"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"keyRepeat\":true,\"success\":true}")); +} + +TEST_F(RDKShellTest, setScreenResolution) +{ + ON_CALL(*p_compositorImplMock, setScreenResolution(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const uint32_t width, const uint32_t height){ + EXPECT_EQ(width, 1920); + EXPECT_EQ(height, 1080); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setScreenResolution"), _T("{\"w\":1920,\"h\":1080}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} +TEST_F(RDKShellTest, getScreenResolution) +{ + ON_CALL(*p_compositorImplMock, getScreenResolution(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](uint32_t &width, uint32_t &height){ + width = 1920; + height = 1080; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getScreenResolution"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"w\":1920,\"h\":1080,\"success\":true}")); +} + +TEST_F(RDKShellTest, setVirtualResolution) +{ + ON_CALL(*p_compositorImplMock, setVirtualResolution(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const uint32_t virtualWidth, const uint32_t virtualHeight){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(virtualWidth, 1920); + EXPECT_EQ(virtualHeight, 1080); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVirtualResolution"), _T("{\"client\":\"org.rdk.Netflix\",\"width\":1920,\"height\":1080}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, getVirtualResolution) +{ + ON_CALL(*p_compositorImplMock, getVirtualResolution(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, uint32_t &virtualWidth, uint32_t &virtualHeight){ + virtualWidth = 1920; + virtualHeight = 1080; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getVirtualResolution"), _T("{\"client\":\"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, _T("{\"width\":1920,\"height\":1080,\"success\":true}")); +} + + +TEST_F(RDKShellTest, ScaleToFit) +{ + ON_CALL(*p_compositorImplMock, scaleToFit(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const int32_t x, const int32_t y, const uint32_t width, const uint32_t height){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(x, 0); + EXPECT_EQ(y, 0); + EXPECT_EQ(width, 1920); + EXPECT_EQ(height, 1080); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("scaleToFit"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"," + "\"x\":0,\"y\":0,\"w\":1920,\"h\":1080}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + + +TEST_F(RDKShellTest, hideAllClients) +{ + ON_CALL(*p_compositorImplMock, getClients(::testing::_)) + .WillByDefault(::testing::Invoke( + [](std::vector& clients){ + clients.push_back("org.rdk.Netflix"); + clients.push_back("org.rdk.RDKBrowser2"); + clients.push_back("Test1"); + clients.push_back("Test2"); + return true; + })); + ON_CALL(*p_compositorImplMock, setVisibility(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool visible){ + EXPECT_EQ(visible, false); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("hideAllClients"), _T("{\"hide\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, ignoreKeyInputs) +{ + ON_CALL(*p_compositorImplMock, ignoreKeyInputs(::testing::_)) + .WillByDefault(::testing::Invoke( + [](bool ignore){ + EXPECT_EQ(ignore, false); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ignoreKeyInputs"), _T("{\"ignore\":false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + + +TEST_F(RDKShellTest, moveToFront) +{ + ON_CALL(*p_compositorImplMock, moveToFront(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client) { + EXPECT_EQ(client, string("org.rdk.Netflix")); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("moveToFront"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(RDKShellTest, moveToBack) +{ + ON_CALL(*p_compositorImplMock, moveToBack(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client) { + EXPECT_EQ(client, string("org.rdk.Netflix")); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("moveToBack"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, moveBehind) +{ + ON_CALL(*p_compositorImplMock, moveBehind(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const std::string& target) { + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(target, string("org.rdk.RDKBrowser2")); + return true; + })); + ON_CALL(*p_compositorImplMock, getClients(::testing::_)) + .WillByDefault(::testing::Invoke( + [](std::vector& clients){ + clients.push_back("org.rdk.Netflix"); + clients.push_back("org.rdk.RDKBrowser2"); + clients.push_back("Test2"); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("moveBehind"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"target\": \"org.rdk.RDKBrowser2\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(RDKShellTest, getOpacity) +{ + ON_CALL(*p_compositorImplMock, getOpacity(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, unsigned int& opacity) { + opacity = 100; + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOpacity"), _T("{\"client\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"opacity\":100,\"success\":true}")); +} + + +TEST_F(RDKShellTest, setFocus) +{ + ON_CALL(*p_compositorImplMock, setFocus(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFocus"), _T("{\"client\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, removeKeyIntercepts) +{ + ON_CALL(*p_compositorImplMock, removeKeyIntercept(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const uint32_t& keyCode, const uint32_t& flags){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(keyCode, 10); + EXPECT_EQ(flags, RDKSHELL_FLAGS_SHIFT); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("removeKeyIntercept"), _T("{" + "\"keyCode\": 10," + "\"modifiers\": [" + " \"shift\"" + "]," + "\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"" + "}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, removeKeyListeners) +{ + ON_CALL(*p_compositorImplMock, removeKeyListener(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const uint32_t& keyCode, const uint32_t& flags){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(keyCode, 10); + EXPECT_EQ(flags, RDKSHELL_FLAGS_SHIFT); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("removeKeyListener"), _T("{" + "\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"," + "\"keys\": [" + "{" + "\"keyCode\": 10," + "\"nativekeyCode\": 10," + "\"modifiers\": [" + "\"shift\"" + "]," + "\"activate\": false," + "\"propagate\": true" + "}" + "]" + "}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, removeKeyMetadataListener) +{ + ON_CALL(*p_compositorImplMock, removeKeyMetadataListener(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("removeKeyMetadataListener"), _T("{\"client\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(RDKShellTest, injectKey) +{ + ON_CALL(*p_compositorImplMock, injectKey(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const uint32_t& keyCode, const uint32_t& flags) { + EXPECT_EQ(keyCode, 10); + EXPECT_EQ(flags, RDKSHELL_FLAGS_SHIFT); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("injectKey"), _T("{\"keyCode\": 10, \"modifiers\": [\"shift\"]}"), response)); +} + +TEST_F(RDKShellTest, getZOrder) +{ + ON_CALL(*p_compositorImplMock, getZOrder(::testing::_)) + .WillByDefault(::testing::Invoke( + [](std::vector& clients){ + clients.push_back("org.rdk.Netflix"); + clients.push_back("org.rdk.RDKBrowser2"); + clients.push_back("Test1"); + clients.push_back("Test2"); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getZOrder"), _T("{}"), response)); + EXPECT_EQ(response, string("{" + "\"clients\":[" + "\"org.rdk.Netflix\"," + "\"org.rdk.RDKBrowser2\"," + "\"Test1\"," + "\"Test2\"" + "]," + "\"success\":true" + "}")); +} + +TEST_F(RDKShellTest, setHolePunch) +{ + ON_CALL(*p_compositorImplMock, setHolePunch(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool holePunch){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(holePunch, true); + return true; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setHolePunch"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"," + "\"holePunch\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(RDKShellTest, getHolePunch) +{ + ON_CALL(*p_compositorImplMock, getHolePunch(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, bool& holePunch){ + holePunch = true; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHolePunch"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); + EXPECT_EQ(response, string("{\"holePunch\":true,\"success\":true}")); + + +} + +TEST_F(RDKShellTest, getScale) +{ + ON_CALL(*p_compositorImplMock, getScale(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, double &scaleX, double &scaleY){ + scaleX = 1.0; + scaleY = 1.0; + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getScale"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"}"), response)); +} + + +TEST_F(RDKShellTest, enableVirtualDisplay) +{ + ON_CALL(*p_compositorImplMock, enableVirtualDisplay(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const std::string& client, const bool enable){ + EXPECT_EQ(client, string("org.rdk.Netflix")); + EXPECT_EQ(enable, true); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableVirtualDisplay"), _T("{\"client\": \"org.rdk.Netflix\"," + "\"callsign\": \"org.rdk.Netflix\"," + "\"enable\": true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(RDKShellTest, enableInactivityReporting) +{ + ON_CALL(*p_compositorImplMock, enableInactivityReporting(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const bool enable){ + EXPECT_EQ(enable, true); + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableInactivityReporting"), _T("{\"enable\": true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + + diff --git a/NetworkManager/Tests/L1Tests/tests/test_ScreenCapture.cpp b/NetworkManager/Tests/L1Tests/tests/test_ScreenCapture.cpp new file mode 100755 index 0000000000..07f086c28d --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_ScreenCapture.cpp @@ -0,0 +1,162 @@ +#include + +#include "ScreenCapture.h" + +#include "FactoriesImplementation.h" +#include "ServiceMock.h" +#include "DRMScreenCaptureMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class ScreenCaptureTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + ScreenCaptureTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~ScreenCaptureTest() = default; +}; + +class ScreenCaptureEventTest : public ScreenCaptureTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + ScreenCaptureEventTest() + : ScreenCaptureTest() + { + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~ScreenCaptureEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + + plugin->Deinitialize(nullptr); + } +}; + +class ScreenCaptureDRMTest : public ScreenCaptureEventTest { +protected: + NiceMock drmScreenCaptureApiImplMock; + + ScreenCaptureDRMTest() + : ScreenCaptureEventTest() + { + DRMScreenCaptureApi::getInstance().impl = &drmScreenCaptureApiImplMock; + } + virtual ~ScreenCaptureDRMTest() override + { + DRMScreenCaptureApi::getInstance().impl = nullptr; + } +}; + + +TEST_F(ScreenCaptureTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("uploadScreenCapture"))); +} + +TEST_F(ScreenCaptureDRMTest, Upload) +{ + DRMScreenCapture drmHandle = {0, 1280, 720, 5120, 32}; + uint8_t* buffer = (uint8_t*) malloc(5120 * 720); + memset(buffer, 0xff, 5120 * 720); + + Core::Event uploadComplete(false, true); + + EXPECT_CALL(drmScreenCaptureApiImplMock, Init()) + .Times(1) + .WillOnce( + ::testing::Return(&drmHandle)); + + ON_CALL(drmScreenCaptureApiImplMock, GetScreenInfo(::testing::_)) + .WillByDefault( + ::testing::Return(true)); + + ON_CALL(drmScreenCaptureApiImplMock, ScreenCapture(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Invoke( + [&](DRMScreenCapture* handle, uint8_t* output, uint32_t size) { + memcpy(output, buffer, size); + return true; + })); + + EXPECT_CALL(drmScreenCaptureApiImplMock, Destroy(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(true)); + + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_EQ(text, string(_T( + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.ScreenCapture.uploadComplete\",\"params\":{\"status\":true,\"message\":\"Success\",\"call_guid\":\"\"}}" + ))); + + uploadComplete.SetEvent(); + + return Core::ERROR_NONE; + })); + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + ASSERT_TRUE(sockfd != -1); + sockaddr_in sockaddr; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = INADDR_ANY; + sockaddr.sin_port = htons(11111); + ASSERT_FALSE(bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0); + ASSERT_FALSE(listen(sockfd, 10) < 0); + + std::thread thread = std::thread([&]() { + auto addrlen = sizeof(sockaddr); + const int connection = accept(sockfd, (struct sockaddr*)&sockaddr, (socklen_t*)&addrlen); + ASSERT_FALSE(connection < 0); + char buffer[2048] = { 0 }; + ASSERT_TRUE(read(connection, buffer, 2048) > 0); + + std::string reqHeader(buffer); + EXPECT_TRUE(std::string::npos != reqHeader.find("Content-Type: image/png")); + + std::string response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"; + send(connection, response.c_str(), response.size(), 0); + + close(connection); + }); + + handler.Subscribe(0, _T("uploadComplete"), _T("org.rdk.ScreenCapture"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadScreenCapture"), _T("{\"url\":\"http://127.0.0.1:11111\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, uploadComplete.Lock()); + + handler.Unsubscribe(0, _T("uploadComplete"), _T("org.rdk.ScreenCapture"), message); + + free(buffer); + thread.join(); + close(sockfd); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_SecurityAgent.cpp b/NetworkManager/Tests/L1Tests/tests/test_SecurityAgent.cpp new file mode 100755 index 0000000000..ac7943e4ef --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_SecurityAgent.cpp @@ -0,0 +1,271 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include + +#include "SecurityAgent.h" + +#include "ServiceMock.h" +#include "SystemInfo.h" +#include "WorkerPoolImplementation.h" + +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string callSign = _T("SecurityAgent"); +} + +class SecurityAgentTest : public ::testing::Test { +protected: + Core::ProxyType workerPool; + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + Core::Sink> subSystem; + NiceMock service; + + SecurityAgentTest() + : workerPool(Core::ProxyType::Create( + 2, Core::Thread::DefaultStackSize(), 16)) + , plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(_T("/Service/SecurityAgent"))); + ON_CALL(service, SubSystems()) + .WillByDefault(::testing::Invoke( + [&]() { + PluginHost::ISubSystem* result = (&subSystem); + result->AddRef(); + return result; + })); + ON_CALL(service, PersistentPath()) + .WillByDefault(::testing::Return(_T("/tmp/"))); + ON_CALL(service, DataPath()) + .WillByDefault(::testing::Return(_T("/tmp/"))); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(_T("/tmp/"))); + ON_CALL(service, ProxyStubPath()) + .WillByDefault(::testing::Return(_T("install/usr/lib/wpeframework/proxystubs"))); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + + Core::IWorkerPool::Assign(&(*workerPool)); + + workerPool->Run(); + } + virtual ~SecurityAgentTest() + { + plugin.Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + } +}; + +TEST_F(SecurityAgentTest, validate) +{ + const string payload = _T("{\"url\":\"http://localhost\"}"); + + string token; + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("validate"))); + EXPECT_EQ(Core::ERROR_NONE, plugin->CreateToken(static_cast(payload.length()), reinterpret_cast(payload.c_str()), token)); + + EXPECT_THAT(token, ::testing::MatchesRegex("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\\.eyJ1cmwiOiJodHRwOi8vbG9jYWxob3N0In0\\..*")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("validate"), "{\"token\":\"" + token + "\"}", response)); + EXPECT_EQ(response, _T("{\"valid\":true}")); + + plugin->Deinitialize(&service); +} + +TEST_F(SecurityAgentTest, rpcCom) +{ + const string payload = _T("{\"url\":\"http://localhost\"}"); + + string token; + string endPoint; + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_TRUE(Core::SystemInfo::GetEnvironment(_T("SECURITYAGENT_PATH"), endPoint)); + EXPECT_EQ(endPoint, _T("/tmp/token")); + + auto engine = Core::ProxyType>::Create(); + auto client = Core::ProxyType::Create( + Core::NodeId(endPoint.c_str()), Core::ProxyType(engine)); + + EXPECT_TRUE(client.IsValid() == true); + EXPECT_TRUE(client->IsOpen() == false); + + auto interface = client->Open(callSign.c_str()); + ASSERT_TRUE(interface != nullptr); + + EXPECT_EQ(Core::ERROR_NONE, interface->CreateToken(static_cast(payload.length()), reinterpret_cast(payload.c_str()), token)); + + EXPECT_THAT(token, ::testing::MatchesRegex("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\\.eyJ1cmwiOiJodHRwOi8vbG9jYWxob3N0In0\\..*")); + + interface->Release(); + + // /** + // * IUnknown Release() times out and + // returns without server response. The next action of the + // unit test is to destroy the server. When the server + // is being destroyed it also submits that response hence + // an ASSERT is hit. The problem with Release() + // happens due to the following commit in Thunder R2-v1.9 + // e70fe4856c7cef952238decf9730e8b5283658e5 which + // introduces a lock for IUnknown Release() which + // blocks both RPC-COM client and server if they are + // in the same process. + // */ + // sleep(1); + // ^^^ should no longer be needed ?? + + client.Release(); + engine.Release(); + + plugin->Deinitialize(&service); +} + +TEST_F(SecurityAgentTest, acl) +{ + const string payload = _T("{\"url\":\"http://example.com\"}"); + + std::ofstream file("/tmp/acl.json"); + file + << "{\n" + " \"assign\": [\n" + " {\n" + " \"url\": \"*://example.com\",\n" + " \"role\": \"example\"\n" + " }\n" + " ],\n" + " \"roles\": {\n" + " \"example\": {\n" + " \"default\": \"blocked\",\n" + " \"DeviceInfo\": {\n" + " \"default\": \"allowed\",\n" + " \"methods\": [ \"register\", \"unregister\" ]\n" + " }\n" + " }\n" + " }\n" + "}"; + file.close(); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return(_T("{\"acl\":\"acl.json\"}"))); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + PluginHost::IAuthenticate* interface = static_cast( + plugin->QueryInterface(PluginHost::IAuthenticate::ID)); + ASSERT_TRUE(interface != nullptr); + + string token; + EXPECT_EQ(Core::ERROR_NONE, interface->CreateToken(static_cast(payload.length()), reinterpret_cast(payload.c_str()), token)); + PluginHost::ISecurity* security = interface->Officer(token); + ASSERT_TRUE(security != nullptr); + + EXPECT_EQ(payload, security->Token()); + + Core::JSONRPC::Message message; + message.Designator = _T("Uknkown.method"); + EXPECT_FALSE(security->Allowed(message)); + message.Designator = _T("DeviceInfo.systeminfo"); + EXPECT_TRUE(security->Allowed(message)); + message.Designator = _T("DeviceInfo.register"); + EXPECT_FALSE(security->Allowed(message)); + + security->Release(); + + interface->Release(); + + plugin->Deinitialize(&service); +} + +TEST_F(SecurityAgentTest, aclForDACApps) +{ + const string payload = _T("{\"url\":\"example\",\"type\":\"dac\"}"); + + Core::Directory dir(_T("/tmp/dac")); + + EXPECT_TRUE(dir.Destroy(false)); + ASSERT_TRUE(dir.CreatePath()); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return(_T("{\"dac\":\"/tmp/dac\"}"))); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + PluginHost::IAuthenticate* interface = static_cast( + plugin->QueryInterface(PluginHost::IAuthenticate::ID)); + ASSERT_TRUE(interface != nullptr); + + string token; + EXPECT_EQ(Core::ERROR_NONE, interface->CreateToken(static_cast(payload.length()), reinterpret_cast(payload.c_str()), token)); + PluginHost::ISecurity* security = interface->Officer(token); + ASSERT_TRUE(security != nullptr); + + EXPECT_EQ(payload, security->Token()); + + Core::JSONRPC::Message message; + message.Designator = _T("DeviceInfo.systeminfo"); + EXPECT_FALSE(security->Allowed(message)); + + std::ofstream file("/tmp/dac/example"); + file + << "{\n" + " \"assign\": [\n" + " {\n" + " \"url\": \"example\",\n" + " \"role\": \"example\"\n" + " }\n" + " ],\n" + " \"roles\": {\n" + " \"example\": {\n" + " \"default\": \"blocked\",\n" + " \"DeviceInfo\": {\n" + " \"default\": \"allowed\"\n" + " }\n" + " }\n" + " }\n" + "}"; + file.close(); + // Wait up to 1s + for (int i = 0, retry = 20; ((i < retry) && (!security->Allowed(message))); i++) { + SleepMs(50); + } + EXPECT_TRUE(security->Allowed(message)); + + security->Release(); + + interface->Release(); + + plugin->Deinitialize(&service); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_SystemAudioPlayer.cpp b/NetworkManager/Tests/L1Tests/tests/test_SystemAudioPlayer.cpp new file mode 100755 index 0000000000..5ebfa3a196 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_SystemAudioPlayer.cpp @@ -0,0 +1,1850 @@ +#include +#include "SystemAudioPlayer.h" +#include "SystemAudioPlayerImplementation.h" +#include "ServiceMock.h" +#include "COMLinkMock.h" +#include "FactoriesImplementation.h" +#include "WorkerPoolImplementation.h" + +using namespace WPEFramework; +using ::testing::Test; +using ::testing::NiceMock; + +namespace { +const string config = _T("SystemAudioPlayer"); +const string callSign = _T("org.rdk.SystemAudioPlayer"); +const string webPrefix = _T("/Service/SystemAudioPlayer"); +const string volatilePath = _T("/tmp/"); +const string dataPath = _T("/tmp/"); +} + +class SAPTest : public Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + Core::ProxyType workerPool; + + SAPTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + , workerPool(Core::ProxyType::Create( + 2, Core::Thread::DefaultStackSize(), 16)) { + } + + virtual ~SAPTest() = default; +}; + +class SAPInitializedTest : public SAPTest { +protected: + NiceMock factoriesImplementation; + NiceMock service; + NiceMock comLinkMock; + PluginHost::IDispatcher* dispatcher; + Core::ProxyType SystemAudioPlayerImplementation; + string response; + + SAPInitializedTest() : SAPTest() { + SystemAudioPlayerImplementation = Core::ProxyType::Create(); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(volatilePath)); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + ON_CALL(service, DataPath()) + .WillByDefault(::testing::Return(dataPath)); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(SystemAudioPlayerImplementation)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~SAPInitializedTest() override { + plugin.Release(); + SystemAudioPlayerImplementation.Release(); + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + PluginHost::IFactories::Assign(nullptr); + dispatcher->Deactivate(); + dispatcher->Release(); + } +}; + +TEST_F(SAPInitializedTest,RegisteredMethods) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("close"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("config"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPlayerSessionId"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isspeaking"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("open"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("pause"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("play"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("playbuffer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resume"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMixerLevels"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setSmartVolControl"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stop"))); +} + +/******************************************************************************************************************* + * Test function for open + * Open : + * Opens a player instance and assigns it a unique ID + * + * @return Response object contains id and success status + * Use case coverage: + * @Success : 24 + * @Failure : 3 + ********************************************************************************************************************/ + +/** + * @name : SAPOpenPCMWebsocketSystem + * @brief : Open a player instance with pcm, websocket, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:1, success: true} + */ + +TEST_F(SAPInitializedTest, SAPOpenPCMWebsocketSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":1,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMDataSystem + * @brief : Open a player instance with pcm, websocket, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:3, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMDataSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"data\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":2,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMWebsocketApp + * @brief : Open a player instance with pcm, websocket, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:3, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMWebsocketApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":3,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMDataApp + * @brief : Open a player instance with pcm, data, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:4, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMDataApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"data\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":4,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMFilesrcSystem + * @brief : Open a player instance with pcm, filesrc, systen + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:5, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMFilesrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"filesrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":5,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMFilesrcApp + * @brief : Open a player instance with pcm, filesrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:6, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMFilesrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"filesrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":6,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMHttpsrcSystem + * @brief : Open a player instance with pcm, httpsrc, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:7, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMHttpsrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"httpsrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":7,\"success\":true}")); +} + +/** + * @name : SAPOpenPCMHttpsrcApp + * @brief : Open a player instance with pcm, httpsrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:8, success: true} + */ + +TEST_F(SAPInitializedTest,SAPOpenPCMHttpsrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"httpsrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":8,\"success\":true}")); +} + +/** + * @name : SAPMp3WebsocketSystem + * @brief : Open a player instance with mp3, websocket, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:9, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3WebsocketSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":9,\"success\":true}")); +} + +/** + * @name : SAPMp3WebsocketApp + * @brief : Open a player instance with mp3, websocket, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:10, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3WebsocketApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"websocket\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":10,\"success\":true}")); +} + +/** + * @name : SAPMp3DataSystem + * @brief : Open a player instance with mp3, data, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:11, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3DataSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"data\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":11,\"success\":true}")); +} + +/** + * @name : SAPMp3DataApp + * @brief : Open a player instance with mp3, data, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:12, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3DataApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"data\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":12,\"success\":true}")); +} + +/** + * @name : SAPMp3FilesrcSystem + * @brief : Open a player instance with mp3, filesrc, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:13, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3FilesrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"filesrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":13,\"success\":true}")); +} + +/** + * @name : SAPMp3FilesrcApp + * @brief : Open a player instance with mp3, filesrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:14, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3FilesrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"filesrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":14,\"success\":true}")); +} + +/** + * @name : SAPMp3HttpsrcSystem + * @brief : Open a player instance with mp3, httpsrc, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:15, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3HttpsrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"httpsrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":15,\"success\":true}")); +} + +/** + * @name : SAPMp3HttpsrcApp + * @brief : Open a player instance with mp3, httpsrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:16, success: true} + */ + +TEST_F(SAPInitializedTest,SAPMp3HttpsrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"httpsrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":16,\"success\":true}")); +} + +/** + * @name : SAPWavWebsocketSystem + * @brief : Open a player instance with wav, websocket, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:17, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavWebsocketSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":17,\"success\":true}")); +} + +/** + * @name : SAPWavWebsocketApp + * @brief : Open a player instance with wav, websocket, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:18, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavWebsocketApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"websocket\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":18,\"success\":true}")); +} + +/** + * @name : SAPWavDataSystem + * @brief : Open a player instance with wav, data, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:19, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavDataSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"data\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":19,\"success\":true}")); +} + +/** + * @name : SAPWavDataApp + * @brief : Open a player instance with wav, data, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:20, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavDataApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"data\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":20,\"success\":true}")); +} + +/** + * @name : SAPWavFileSrcSystem + * @brief : Open a player instance with wav, filesrc, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:21, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavFileSrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"filesrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":21,\"success\":true}")); +} + +/** + * @name : SAPWavFileSrcApp + * @brief : Open a player instance with wav, filesrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:22, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavFileSrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"filesrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":22,\"success\":true}")); +} + +/** + * @name : SAPWavHttpSrcSystem + * @brief : Open a player instance with wav, httpsrc, system + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:23, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavHttpSrcSystem) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"httpsrc\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":23,\"success\":true}")); +} + +/** + * @name : SAPWavHttpSrcApp + * @brief : Open a player instance with wav, httpsrc, app + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {id:24, success: true} + */ + +TEST_F(SAPInitializedTest,SAPWavHttpSrcApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"httpsrc\",\"playmode\": \"app\" }"), + response + )); + EXPECT_EQ(response, _T("{\"id\":24,\"success\":true}")); +} + +/** + * @name : SAPOpenInvalidAudioType + * @brief : Given InvalidAudioType It should return false + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPOpenInvalidAudioType) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"invalid\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/** + * @name : SAPOpenInvalidSourceType + * @brief : Given InvalidSourceType It should return false + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPOpenInvalidSourceType) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"invalid\",\"playmode\": \"system\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/** + * @name : SAPOpenInvalidPlayMode + * @brief : Given InvalidPlayMode It should return false + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPOpenInvalidPlayMode) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"invalid\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} +/******************************************************************************************************************* + * Test function for config + * Open : + * Configures playback for a PCM audio source (audio/x-raw) on the specified player + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : SAPConfig + * @brief : Sets a config for PCM audio playback + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPConfig) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"filesrc\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("config"), + _T("{\"id\": ") + + std::to_string(speechId) + + _T(", \"pcmconfig\": {\"format\": \"S16LE\",\"rate\": \"22050\",\"channels\": \"1\",\"layout\": \"interleaved\"},") + _T("\"websocketsecparam\": {\"cafilenames\": [{\"cafilename\": \"/etc/ssl/certs/Xfinity_Subscriber_ECC_Root.pem\"}],") + _T("\"certfilename\": \"...\",\"keyfilename\": \"...\"}}"), + response + )); + + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPConfigForOtherAudioType + * @brief : Sets a config for MP3 audio playback + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPConfigForOtherAudioType) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"mp3\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("config"), + _T("{\"id\": ") + + std::to_string(speechId) + + _T(", \"pcmconfig\": {\"format\": \"S16LE\",\"rate\": \"22050\",\"channels\": \"1\",\"layout\": \"interleaved\"},") + _T("\"websocketsecparam\": {\"cafilenames\": [{\"cafilename\": \"/etc/ssl/certs/Xfinity_Subscriber_ECC_Root.pem\"}],") + _T("\"certfilename\": \"...\",\"keyfilename\": \"...\"}}"), + response + )); + + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPConfigWithoutOpen + * @brief : Sets a config without player instance + * + * @param[in] : audiotype ,sourcetype, playmode + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPConfigWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("config"), + _T("{\"id\": 1, " + "\"pcmconfig\": {\"format\": \"S16LE\", \"rate\": \"22050\", \"channels\": \"1\", \"layout\": \"interleaved\"}, " + "\"websocketsecparam\": {\"cafilenames\": [{\"cafilename\": \"/etc/ssl/certs/Xfinity_Subscriber_ECC_Root.pem\"}], " + "\"certfilename\": \"...\", \"keyfilename\": \"...\"}}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for play + * Open : + * Plays audio on the specified player. + * + * @return Response object success status + * Use case coverage: + * @Success : 4 + * @Failure : 3 + ********************************************************************************************************************/ + +/** + * @name : SAPPlayWebsocket + * @brief : plays a player instance + * + * @param[in] : id ,url + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPPlayWebsocket) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"ws://example.com/socket\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayDataSrc + * @brief : plays a player instance + * + * @param[in] : id ,url + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPPlayDataSrc) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"data\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"data://example/data\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayFilesrc + * @brief : Opens a player instance with source:filesrc but given http url + * + * @param[in] : id ,url + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPPlayFilesrc) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"wav\",\"sourcetype\": \"filesrc\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"file:///example/data\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + sleep(1); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayHttpsrc + * @brief : Opens a player instance with source:httpsrc but given http url + * + * @param[in] : id ,url + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPPlayHttpsrc) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"httpsrc\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"http://example/data\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayDifferentSrcUrl + * @brief : Opens a player instance with source:httpsrc but given http url + * + * @param[in] : id ,url + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPPlayDifferentSrcUrl) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"httpsrc\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"file:///example/data\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayWithoutOpen + * @brief : Sets a play without player instance + * + * @param[in] : id ,url + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPPlayWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, \ + _T("play"), + _T("{\"id\": 1, \"url\": \"https://example/data\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/** + * @name : SAPPlayInvalidUrl + * @brief : Play with invalid url + * + * @param[in] : id , url + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPPlayInvalidUrl) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": 1,\"url\": \"invalid\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for close + * Close : + * Closes the specified Player + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @name : SAPClose + * @brief : Closes the player instance + * + * @param[in] : id + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPClose) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("close"), + _T("{\"id\": ") + std::to_string(speechId) + _T("}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPCloseWithoutOpen + * @brief : Close the player Which is not opened + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPCloseWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("close"), + _T("{\"id\": 1}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for resume + * Resume : + * Resumes the specified Player + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @name : SAPResume + * @brief : Resume the player instance + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPResume) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("resume"), + _T("{\"id\": ") + std::to_string(speechId) + _T("}"), + response\ + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPResumeWithOutOpen + * @brief : Resume the invalid player + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPResumeWithOutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("resume"), + _T("{\"id\": 1}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for pause + * Pause : + * Closes the specified Player + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @name : SAPPause + * @brief : Pause the player instance + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPPause) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("pause"), + _T("{\"id\": ") + std::to_string(speechId) + _T("}"), + response\ + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPauseWithOutOpen + * @brief : Pause the invalid player + * + * @param[in] : id + * @return : {success: false} + */ +TEST_F(SAPInitializedTest,SAPPauseWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("pause"), + _T("{\"id\": 1}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for stop + * Stop : + * stop the specified Players connection with source + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @name : SAPStop + * @brief : Stop the connection between websocket + * + * @param[in] : id + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPStop) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("stop"), + _T("{\"id\": ") + std::to_string(speechId) + _T("}"), + response\ + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPStopWithOutOpen + * @brief : Stop the invalid player + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPStopWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("stop"), + _T("{\"id\": 1}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for isSpeaking + * isSpeaking : + * Checks the player instance is speaking or not + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @name : SAPIsSpeaking + * @brief : checks the player instance is speaking or not + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPIsSpeaking) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("isspeaking"), + _T("{\"id\": ") + std::to_string(speechId) + _T("}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPisSpeakingWithoutOpen + * @brief : Check isSpeaking the invalid player + * + * @param[in] : id + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPisSpeakingWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("isspeaking"), + _T("{\"id\": 1}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for playbuffer + * PlayBuffer : + * Buffers the audio playback on the specified player + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 1 + ********************************************************************************************************************/ +/** + * @name : SAPPlayBuffer + * @brief : Buffers the audio playback on the specified player. + * + * @param[in] : id , data + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPPlayBuffer) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("playbuffer"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"data\": \"180\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPPlayBufferWithoutOpen + * @brief : Buffer on invalid player + * + * @param[in] : id , data + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPPlayBufferWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("playbuffer"), + _T("{\"id\": 1 , \"data\": \"180\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for setMixerLevel + * setMixerLevel : + * Sets the audio level on the specified player. The SystemAudioPlayer plugin can control the volume of the content being played back as well as the primary program audio; + * thus, an application can duck down the volume on the primary program + * audio when system audio is played and then restore it back when the system audio playback is complete. + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 5 + ********************************************************************************************************************/ + +/** + * @name : SAPSetMixerLevel + * @brief : SettingMixerlevels for Player + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPSetMixerLevel) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"primaryVolume\": \"80\" ,\"playerVolume\": \"70\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetMixerLevelPriVolLessThanZero + * @brief : Set Primary Volume less than zero and expects failure + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetMixerLevelPriVolLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"primaryVolume\": \"-1\" ,\"playerVolume\": \"70\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetMixerLevelPlayerVolLessThanZero + * @brief : Set Player Volume less than zero and expects failure + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetMixerLevelPlayerVolLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"primaryVolume\": \"80\" ,\"playerVolume\": \"-1\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetMixerLevelPriVolGreaterThan100 + * @brief : Set Primary Volume Greater than 100 and expects failure + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetMixerLevelPriVolGreaterThan100) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"primaryVolume\": \"101\" ,\"playerVolume\": \"70\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetMixerLevelPlayerVolGreaterThan100 + * @brief : Set Player Volume Greater than 100 and expects failure + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetMixerLevelPlayerVolGreaterThan100) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"primaryVolume\": \"80\" ,\"playerVolume\": \"101\"}"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetMixerLevelsWithoutOpen + * @brief : SettingMixerlevels for invalidPlayer + * + * @param[in] : id , primaryVolume , player volume + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest,SAPSetMixerLevelsWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setMixerLevels"), + _T("{\"id\": 1 , \"primaryVolume\": \"180\" ,\"playerVolume\": \"7\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for SetSmartVolControl + * SetSmartVolControl : + * Sets the smart volume audio control on the specified player. + * The plugin can control the smart volume of the content being played back as well as the primary program audio; + * thus, an application can duck down the volume on the primary program audio when system audio is played + * and then restore it back when the system audio playback is complete. + * + * @return Response object success status + * Use case coverage: + * @Success : 1 + * @Failure : 5 + ********************************************************************************************************************/ +/** + * @name : SAPSetSmartVolControl + * @brief : SettingSAPSetSmartVolControl for Player + * + * @param[in] : id, enable, playerAudioLevelThreshold, playerDetectTimeMs, playerHoldTimeMs, primaryDuckingPercent + * @return : {success: true} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControl) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": 1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlThresholdLessThanZero + * @brief : Set Thresholdvaluse < 0 which result in failure + * + * @param[in] : threshold = -1 + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControlThresholdLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": -1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": 1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlDetectTimeMsLessThanZero + * @brief : Set detectTimeMs < 0 which result in failure + * + * @param[in] : detectTimeMs = -1 + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControlDetectTimeMsLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": -1, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": 1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlHoldTimeMsLessThanZero + * @brief : Set holdTimeMs < 0 which result in failure + * + * @param[in] : holdTimeMs = -1 + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControlHoldTimeMsLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": -1, \"primaryDuckingPercent\": 1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlDuckPercentLessThanZero + * @brief : Set primaryDuckingPercent < 0 which result in failure + * + * @param[in] : primaryDuckingPercent = -1 + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControlDuckPercentLessThanZero) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": -1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlDuckPercentLessThanZero + * @brief : Set primaryDuckingPercent < 0 which result in failure + * + * @param[in] : primaryDuckingPercent = -1 + * @return : {success: false} + */ + +TEST_F(SAPInitializedTest, SAPSetSmartVolControlDuckPercentGreaterThan100) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": ") + std::to_string(speechId) + _T(",\"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": 101 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} + +/** + * @name : SAPSetSmartVolControlWithoutOpen + * @brief : SettingSmartVolControl for invalidPlayer + * + * @param[in] : id, enable, playerAudioLevelThreshold, playerDetectTimeMs, playerHoldTimeMs, primaryDuckingPercent + * @return : {success: false} + */ +TEST_F(SAPInitializedTest,SAPSetSmartVolControlWithoutOpen) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setSmartVolControl"), + _T("{\"id\": 1 , \"enable\": true, \"playerAudioLevelThreshold\": 0.1, \"playerDetectTimeMs\": 200, \"playerHoldTimeMs\": 1000, \"primaryDuckingPercent\": 1 }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +/******************************************************************************************************************* + * Test function for getPlayerSessionId + * getPlayerSessionId : + * Gets the session ID from the provided the URL. The session is the ID returned in open cal. + * + * @return Response object contains session id and success status + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : SAPGetPlayerSessionId + * @brief : Open the player and play the url and get sessionid for it + * + * @param[in] : id , url + * @return : {success: true} + */ +TEST_F(SAPInitializedTest, SAPGetPlayerSessionId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("open"), + _T("{\"audiotype\": \"pcm\",\"sourcetype\": \"websocket\",\"playmode\": \"system\" }"), + response + )); + + size_t idPos = response.find("\"id\""); + if (idPos != string::npos) { + size_t idStart = response.find(':', idPos) + 1; + size_t idEnd = response.find(',', idPos); + std::string idSubstring = response.substr(idStart, idEnd - idStart); + int speechId = std::stoi(idSubstring); + std::cout << "Speech ID: " << speechId << std::endl; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("play"), + _T("{\"id\": ") + std::to_string(speechId) + _T(", \"url\": \"ws://example.com/socket\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("getPlayerSessionId"), + _T("{\"url\": \"ws://example.com/socket\" }"), + response + )); + size_t sesPos = response.find("\"sessionId\""); + if (sesPos != string::npos) { + size_t sesStart = response.find(':', sesPos) + 1; + size_t sesEnd = response.find(',', sesPos); + std::string sesSubstring = response.substr(sesStart, sesEnd - sesStart); + int sessionId = std::stoi(sesSubstring); + std::cout << "Session ID: " << sessionId << std::endl; + EXPECT_EQ(speechId,sessionId); + } else { + EXPECT_TRUE(false) << "Error: 'sessionid' not found in the response."; + } + } else { + EXPECT_TRUE(false) << "Error: 'id' not found in the response."; + } +} +/** + * @name : SAPGetPlayerSessionIdInvalid + * @brief : GetSessionId for non-existing url + * + * @param[in] : id , url + * @return : {success: true} + */ +TEST_F(SAPInitializedTest, SAPGetPlayerSessionIdInvalid) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("getPlayerSessionId"), + _T("{\"url\": \"https://www.yahoo.com\" }"), + response + )); + EXPECT_EQ(response, _T("{\"sessionId\":-1,\"success\":true}")); +} +/** + * @name : SAPGetPlayerSessionIdInvalidUrl + * @brief : GetSessionId for invalid url + * + * @param[in] : id , url + * @return : {success: false} + */ +TEST_F(SAPInitializedTest, SAPGetPlayerSessionIdInvalidUrl) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("getPlayerSessionId"), + _T("{\"url\": \"invalid\" }"), + response + )); + EXPECT_EQ(response, _T("{\"success\":false}")); +} \ No newline at end of file diff --git a/NetworkManager/Tests/L1Tests/tests/test_SystemServices.cpp b/NetworkManager/Tests/L1Tests/tests/test_SystemServices.cpp new file mode 100755 index 0000000000..bec14391b0 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_SystemServices.cpp @@ -0,0 +1,6231 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "SystemServices.h" + +#include "FactoriesImplementation.h" +#include "HostMock.h" +#include "IarmBusMock.h" +#include "RfcApiMock.h" +#include "ServiceMock.h" +#include "DispatcherMock.h" +#include "SleepModeMock.h" +#include "WrapsMock.h" + +#include "deepSleepMgr.h" +#include "exception.hpp" + +#include + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class SystemServicesTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + RfcApiImplMock *p_rfcApiImplMock = nullptr; + IarmBusImplMock *p_iarmBusImplMock = nullptr; + WrapsImplMock *p_wrapsImplMock = nullptr; + SleepModeMock *p_sleepModeMock = nullptr; + HostImplMock *p_hostImplMock = nullptr; + + SystemServicesTest() + : plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + p_rfcApiImplMock = new NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_hostImplMock = new NiceMock ; + device::Host::setImpl(p_hostImplMock); + + p_sleepModeMock = new NiceMock ; + device::SleepMode::setImpl(p_sleepModeMock); + + } + + virtual ~SystemServicesTest() override + { + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + device::SleepMode::setImpl(nullptr); + if (p_sleepModeMock != nullptr) + { + delete p_sleepModeMock; + p_sleepModeMock = nullptr; + } + + device::Host::setImpl(nullptr); + if (p_hostImplMock != nullptr) + { + delete p_hostImplMock; + p_hostImplMock = nullptr; + } + } +}; + +class SystemServicesEventTest : public SystemServicesTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + SystemServicesEventTest() + : SystemServicesTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~SystemServicesEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class SystemServicesEventIarmTest : public SystemServicesEventTest { +protected: + IARM_BusCall_t SysModeChange; + IARM_EventHandler_t systemStateChanged; + IARM_EventHandler_t thermMgrEventsHandler; + IARM_EventHandler_t powerEventHandler; + + SystemServicesEventIarmTest() + : SystemServicesEventTest() + { + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_SYSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE)) { + systemStateChanged = handler; + } + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED)) { + thermMgrEventsHandler = handler; + } + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + powerEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterCall(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* methodName, IARM_BusCall_t handler) { + if (string(IARM_BUS_COMMON_API_SysModeChange) == string(methodName)) { + SysModeChange = handler; + } + return IARM_RESULT_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + + virtual ~SystemServicesEventIarmTest() override + { + plugin->Deinitialize(&service); + } + + virtual void SetUp() + { + ASSERT_TRUE(SysModeChange != nullptr); + ASSERT_TRUE(systemStateChanged != nullptr); + ASSERT_TRUE(thermMgrEventsHandler != nullptr); + ASSERT_TRUE(powerEventHandler != nullptr); + } +}; + +TEST_F(SystemServicesTest, TestedAPIsShouldExist) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("requestSystemUptime"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("fireFirmwarePendingReboot"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFirmwareAutoReboot"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFirmwareRebootDelay"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLastFirmwareFailureReason"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDownloadedFirmwareInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFirmwareDownloadPercent"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFirmwareUpdateState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setTimeZoneDST"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTimeZoneDST"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setTerritory"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTerritory"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPreviousRebootInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPreviousRebootInfo2"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPreviousRebootReason"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isOptOutTelemetry"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOptOutTelemetry"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSystemVersions"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("queryMocaStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableMoca"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("updateFirmware"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDeepSleepTimer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setNetworkStandbyMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getNetworkStandbyMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFriendlyName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFriendlyName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setPreferredStandbyMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPreferredStandbyMode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getAvailableStandbyModes"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getWakeupReason"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLastWakeupKeyCode"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTimeZones"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLastDeepSleepReason"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCoreTemperature"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTemperatureThresholds"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setTemperatureThresholds"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getOvertempGraceInterval"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setOvertempGraceInterval"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getRFCConfig"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enableXREConnectionRetention"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPowerState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setPowerState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPowerStateIsManagedByDevice"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPowerStateBeforeReboot"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setWakeupSrcConfiguration"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("reboot"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStateInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setBootLoaderPattern"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setBootLoaderSplashScreen"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getMacAddresses"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFirmwareUpdateInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearLastDeepSleepReason"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getMfgSerialNumber"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getXconfParams"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSerialNumber"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPlatformConfiguration"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("uploadLogs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("uploadLogsAsync"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("abortLogUpload"))); +} + +TEST_F(SystemServicesTest, SystemUptime) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("requestSystemUptime"), _T("{}"), response)); + + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"systemUptime\":\"[0-9]+.[0-9]+\"," + "\"success\":true" + "\\}"))); +} + +TEST_F(SystemServicesEventTest, PendingReboot) +{ + Core::Event onFirmwarePendingReboot(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onFirmwarePendingReboot\"," + "\"params\":" + "{" + "\"fireFirmwarePendingReboot\":600" + "}" + "}"))); + + onFirmwarePendingReboot.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onFirmwarePendingReboot"), _T("org.rdk.System"), message); + + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(strcmp(pcCallerID, "thunderapi"), 0); + EXPECT_EQ(strcmp(pcParameterName, "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.AutoReboot.fwDelayReboot"), 0); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("fireFirmwarePendingReboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, onFirmwarePendingReboot.Lock()); + + handler.Unsubscribe(0, _T("onFirmwarePendingReboot"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesTest, AutoReboot) +{ + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(strcmp(pcCallerID, "thunderapi"), 0); + EXPECT_EQ(strcmp(pcParameterName, "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.AutoReboot.Enable"), 0); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setFirmwareAutoReboot"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFirmwareAutoReboot"), _T("{\"enable\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, RebootDelay) +{ + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(strcmp(pcCallerID, "thunderapi"), 0); + EXPECT_EQ(strcmp(pcParameterName, "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.AutoReboot.fwDelayReboot"), 0); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setFirmwareRebootDelay"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setFirmwareRebootDelay"), _T("{\"delaySeconds\":86401}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFirmwareRebootDelay"), _T("{\"delaySeconds\":10}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, Firmware) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\nSDK_VERSION=17.3\nMEDIARITE=8.3.53\nYOCTO_VERSION=dunfell\nVERSION=000.36.0.0\nBUILD_TIME=\"2022-08-05 16:14:54\"\n"; + file.close(); + + file.open("/opt/fwdnldstatus.txt"); + file << "Method|xconf \nProto|\nStatus|Failure\nReboot|\nFailureReason|Invalid Request\nDnldVersn|AX013AN_5.6p4s1_VBN_sey\nDnldFile|\nDnlURL|https://dac15cdlserver.ae.ccp.xcal.tv:443/Images/AX013AN_5.6p4s1_VBN_sey-signed.bin\n FwupdateState|Failed\n"; + + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLastFirmwareFailureReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"failReason\":\"None\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDownloadedFirmwareInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"currentFWVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\",\"downloadedFWVersion\":\"\",\"downloadedFWLocation\":\"\",\"isRebootDeferred\":false,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareDownloadPercent"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"downloadPercent\":-1,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateState"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"firmwareUpdateState\":0,\"success\":true}")); +} + +TEST_F(SystemServicesEventTest, Timezone) +{ + Core::Event changed1(false, true); + Core::Event changed2(false, true); + Core::Event changed3(false, true); + Core::Event changed4(false, true); + Core::Event changed5(false, true); + Core::Event changed6(false, true); + Core::Event changed7(false, true); + Core::Event changed8(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(8) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "\\{" + "\"oldTimeZone\":\".*\"," + "\"newTimeZone\":\"America\\\\/New_York\"," + "\"oldAccuracy\":\".*\"," + "\"newAccuracy\":\".*\"" + "\\}" + "\\}"))); + + changed1.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"America\\/New_York\"," + "\"newTimeZone\":\"America\\/New_York\"," + "\"oldAccuracy\":\"INITIAL\"," + "\"newAccuracy\":\"INTERIM\"" + "}" + "}"))); + + changed2.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"America\\/New_York\"," + "\"newTimeZone\":\"America\\/Costa_Rica\"," + "\"oldAccuracy\":\"INTERIM\"," + "\"newAccuracy\":\"FINAL\"" + "}" + "}"))); + + changed3.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"America\\/Costa_Rica\"," + "\"newTimeZone\":\"America\\/New_York\"," + "\"oldAccuracy\":\"FINAL\"," + "\"newAccuracy\":\"FINAL\"" + "}" + "}"))); + + changed4.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "\\{" + "\"oldTimeZone\":\".*\"," + "\"newTimeZone\":\"Universal\"," + "\"oldAccuracy\":\".*\"," + "\"newAccuracy\":\".*\"" + "\\}" + "\\}"))); + + changed5.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"Universal\"," + "\"newTimeZone\":\"Universal\"," + "\"oldAccuracy\":\"INITIAL\"," + "\"newAccuracy\":\"INTERIM\"" + "}" + "}"))); + + changed6.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"Universal\"," + "\"newTimeZone\":\"Universal\"," + "\"oldAccuracy\":\"INTERIM\"," + "\"newAccuracy\":\"FINAL\"" + "}" + "}"))); + + changed7.SetEvent(); + + return Core::ERROR_NONE; + })) + + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTimeZoneDSTChanged\"," + "\"params\":" + "{" + "\"oldTimeZone\":\"Universal\"," + "\"newTimeZone\":\"America\\/New_York\"," + "\"oldAccuracy\":\"FINAL\"," + "\"newAccuracy\":\"FINAL\"" + "}" + "}"))); + + changed8.SetEvent(); + + return Core::ERROR_NONE; + })) ; + + handler.Subscribe(0, _T("onTimeZoneDSTChanged"), _T("org.rdk.System"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"America/New_York\",\"accuracy\":\"INITIAL\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed1.Lock()); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"America\\/New_York\",\"accuracy\":\"INITIAL\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"America/New_York\",\"accuracy\":\"INTERIM\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed2.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"America\\/New_York\",\"accuracy\":\"INTERIM\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"America/Costa_Rica\",\"accuracy\":\"FINAL\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed3.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"America\\/Costa_Rica\",\"accuracy\":\"FINAL\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"America/New_York\",\"accuracy\":\"\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed4.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"America\\/New_York\",\"accuracy\":\"FINAL\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"Universal\",\"accuracy\":\"INITIAL\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed5.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"Universal\",\"accuracy\":\"INITIAL\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"Universal\",\"accuracy\":\"INTERIM\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed6.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"Universal\",\"accuracy\":\"INTERIM\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"Universal\",\"accuracy\":\"FINAL\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed7.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"Universal\",\"accuracy\":\"FINAL\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTimeZoneDST"), _T("{\"timeZone\":\"America/New_York\",\"accuracy\":\"\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed8.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZoneDST"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeZone\":\"America\\/New_York\",\"accuracy\":\"FINAL\",\"success\":true}")); + + handler.Unsubscribe(0, _T("onTimeZoneDSTChanged"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesTest, InvalidTerritory) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"USA\",\"region\":\"U-NYC\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"US@\",\"region\":\"US-NYC\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"USA\",\"region\":\"US-N$C\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"US12\",\"region\":\"US-NYC\"}"), response)); +} + +TEST_F(SystemServicesEventTest, ValidTerritory) +{ + Core::Event changed1(false, true); + Core::Event changed2(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTerritoryChanged\"," + "\"params\":" + "\\{" + "\"oldTerritory\":\".*\"," + "\"newTerritory\":\"USA\"," + "\"oldRegion\":\".*\"," + "\"newRegion\":\"US-NYC\"" + "\\}" + "\\}"))); + + changed1.SetEvent(); + + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTerritoryChanged\"," + "\"params\":" + "{" + "\"oldTerritory\":\"USA\"," + "\"newTerritory\":\"GBR\"," + "\"oldRegion\":\"US-NYC\"," + "\"newRegion\":\"GB-EGL\"" + "}" + "}"))); + + changed2.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onTerritoryChanged"), _T("org.rdk.System"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"USA\",\"region\":\"US-NYC\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed1.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTerritory"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"territory\":\"USA\",\"region\":\"US-NYC\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTerritory"), _T("{\"territory\":\"GBR\",\"region\":\"GB-EGL\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, changed2.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTerritory"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"territory\":\"GBR\",\"region\":\"GB-EGL\",\"success\":true}")); + + handler.Unsubscribe(0, _T("onTerritoryChanged"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesTest, rebootReason) +{ + ofstream file("/opt/logs/rebootInfo.log"); + file << "PreviousRebootReason: RebootReason: Triggered from SystemServices! MAINTENANCE_REBOOT \n PreviousRebootTime: 18.08.2022_09:51.38\nPreviousRebootInitiatedBy: HAL_CDL_notify_mgr_event\nPreviousCustomReason: MAINTENANCE_REBOOT \n PreviousOtherReason: MAINTENANCE_REBOOT \n"; + file.close(); + + file.open("/opt/persistent/previousreboot.info"); + file << "{\n\"timestamp\":\"Thu Aug 18 13:51:39 UTC 2022\",\n \"source\":\"HAL_CDL_notify_mgr_event\",\n \"reason\":\"OPS_TRIGGERED\",\n \"customReason\":\"Unknown\",\n \"otherReason\":\"Rebooting the box due to VL_CDL_MANAGER_EVENT_REBOOT...!\"\n}\n"; + file.close(); + + file.open("/opt/persistent/hardpower.info"); + file << "{\n\"lastHardPowerReset\":\"Thu Aug 18 13:51:39 UTC 2022\"\n}\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPreviousRebootInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"timeStamp\":\"18.08.2022_09:51.38\",\"reason\":\"Triggered from SystemServices! MAINTENANCE_REBOOT\",\"source\":\"HAL_CDL_notify_mgr_event\",\"customReason\":\"MAINTENANCE_REBOOT\",\"otherReason\":\"MAINTENANCE_REBOOT\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPreviousRebootInfo2"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"rebootInfo\":{\"timestamp\":\"Thu Aug 18 13:51:39 UTC 2022\",\"source\":\"HAL_CDL_notify_mgr_event\",\"reason\":\"OPS_TRIGGERED\",\"customReason\":\"Unknown\",\"lastHardPowerReset\":\"Thu Aug 18 13:51:39 UTC 2022\"},\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPreviousRebootReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"reason\":\"OPS_TRIGGERED\",\"success\":true}")); +} + +TEST_F(SystemServicesTest, Telemetry) +{ + ofstream file("/opt/tmtryoptout"); + file << "false"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isOptOutTelemetry"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"Opt-Out\":false,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOptOutTelemetry"), _T("{\"Opt-Out\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isOptOutTelemetry"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"Opt-Out\":true,\"success\":true}")); +} + +TEST_F(SystemServicesTest, SystemVersions) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\nSDK_VERSION=17.3\nMEDIARITE=8.3.53\nYOCTO_VERSION=dunfell\nVERSION=000.36.0.0\nBUILD_TIME=\"2022-08-05 16:14:54\"\n"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSystemVersions"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"stbVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\",\"receiverVersion\":\"000.36.0.0\",\"stbTimestamp\":\"Fri 05 Aug 2022 16:14:54 UTC\",\"success\":true}")); +} +/******************************************************************************************************************* + * Test function for :setBootLoaderSplashScreen + * @brief : To update bootloader splash screen. + * @param1[in] : {"path":""} + * @param2[out] : {"result":{"success":}} + * @return : Core:: + * Use case coverage: + * @Success :1 + * @Failure :3 + ********************************************************************************************************************/ + + +TEST_F(SystemServicesTest, setBootLoaderSplashScreen_IARM_fail) +{ + ofstream file("/tmp/osd1"); + file << "testing setBootLoaderSplashScreen"; + file.close(); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_SetBlSplashScreen))); + auto param = static_cast(arg); + std::string path = param->path; + EXPECT_EQ(path, "/tmp/osd1"); + return IARM_RESULT_OOM; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setBootLoaderSplashScreen"), _T("{\"path\": \"/tmp/osd1\"}"), response)); + if(response != "") + { + EXPECT_EQ(response, string("{\"error\":{\"message\":\"Update failed\",\"code\":\"-32002\"},\"success\":false}")); + } +} + +TEST_F(SystemServicesTest, setBootLoaderSplashScreen_IARM_success) +{ + ofstream file("/tmp/osd1"); + file << "testing setBootLoaderSplashScreen"; + file.close(); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_SetBlSplashScreen))); + auto param = static_cast(arg); + std::string path = param->path; + EXPECT_EQ(path, "/tmp/osd1"); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBootLoaderSplashScreen"), _T("{\"path\": \"/tmp/osd1\"}"), response)); + if(response != "") + { + EXPECT_EQ(response, string("{\"success\":true}")); + } +} + +TEST_F(SystemServicesTest, setBootLoaderSplashScreen_empty_path) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setBootLoaderSplashScreen"), _T("{\"path\": \"\"}"), response)); + if(response != "") + { + EXPECT_EQ(response, string("{\"error\":{\"message\":\"Invalid path\",\"code\":\"-32001\"},\"success\":false}")); + } +} + +TEST_F(SystemServicesTest, setBootLoaderSplashScreen_invalid_path) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setBootLoaderSplashScreen"), _T("{\"path\": \"/tmp/osd2\"}"), response)); + if(response != "") + { + EXPECT_EQ(response, string("{\"error\":{\"message\":\"Invalid path\",\"code\":\"-32001\"},\"success\":false}")); + } +} + +TEST_F(SystemServicesTest, MocaStatus) +{ + ON_CALL(*p_wrapsImplMock, system(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/etc/init.d/moca_init start"))); + return 0; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("enableMoca"), _T("{}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableMoca"), _T("{\"value\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_TRUE(Core::File(string(_T("/opt/enablemoca"))).Exists()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("queryMocaStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mocaEnabled\":true,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableMoca"), _T("{\"value\":false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_FALSE(Core::File(string(_T("/opt/enablemoca"))).Exists()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("queryMocaStatus"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mocaEnabled\":false,\"success\":true}")); +} + +TEST_F(SystemServicesTest, updateFirmware) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/swupdate_utility.sh 0 4 >> /opt/logs/swupdate.log &"))); + return nullptr; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updateFirmware"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, Mode) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"modeInfo\":{\"mode\":\"\",\"duration\":0},\"success\":true}")); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setMode"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setMode"), _T("{\"modeInfo\":{}}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setMode"), _T("{\"modeInfo\":{\"mode\":\"unknown\",\"duration\":0}}"), response)); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DAEMON_NAME))); + EXPECT_EQ(string(methodName), string(_T("DaemonSysModeChange"))); + return IARM_RESULT_SUCCESS; + }); + + ON_CALL(*p_wrapsImplMock, system(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("rm -f /opt/warehouse_mode_active"))); + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setMode"), _T("{\"modeInfo\":{\"mode\":\"NORMAL\",\"duration\":-1}}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"modeInfo\":{\"mode\":\"NORMAL\",\"duration\":0},\"success\":true}")); +} + +TEST_F(SystemServicesTest, setDeepSleepTimer) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setDeepSleepTimer"), _T("{}"), response)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetDeepSleepTimeOut))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setDeepSleepTimer"), _T("{\"seconds\":5}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, setNetworkStandbyMode) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setNetworkStandbyMode"), _T("{}"), response)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetNetworkStandbyMode))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setNetworkStandbyMode"), _T("{\"nwStandby\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, getsetFriendlyName) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFriendlyName"), _T("{\"friendlyName\": \"friendlyTest\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFriendlyName"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"friendlyName\":\"friendlyTest\",\"success\":true}")); +} + + +TEST_F(SystemServicesTest, getNetworkStandbyMode) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_GetNetworkStandbyMode))); + auto param = static_cast(arg); + param->bStandbyMode = true; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getNetworkStandbyMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"nwStandby\":true,\"success\":true}")); +} + +TEST_F(SystemServicesTest, setPreferredStandbyMode) +{ + device::SleepMode mode; + + ON_CALL(*p_sleepModeMock, getInstanceByName) + .WillByDefault(::testing::Invoke( + [&](const std::string& name) -> device::SleepMode& { + EXPECT_EQ(name, "LIGHT_SLEEP"); + return mode; + })); + EXPECT_CALL(*p_hostImplMock, setPreferredSleepMode) + .Times(2) + .WillOnce(::testing::Return(0)) + .WillOnce(::testing::Invoke( + [](const device::SleepMode) -> int { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPreferredStandbyMode"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPreferredStandbyMode"), _T("{\"standbyMode\":\"LIGHT_SLEEP\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPreferredStandbyMode"), _T("{\"standbyMode\":\"LIGHT_SLEEP\"}"), response)); +} + +TEST_F(SystemServicesTest, getPreferredStandbyMode) +{ + device::SleepMode mode; + + string sleepModeString(_T("DEEP_SLEEP")); + + ON_CALL(*p_hostImplMock, getPreferredSleepMode) + .WillByDefault(::testing::Return(mode)); + ON_CALL(*p_sleepModeMock, toString) + .WillByDefault(::testing::ReturnRef(sleepModeString)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPreferredStandbyMode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"preferredStandbyMode\":\"DEEP_SLEEP\",\"success\":true}")); + + ON_CALL(*p_hostImplMock, getPreferredSleepMode) + .WillByDefault(::testing::Invoke( + []() -> device::SleepMode { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getPreferredStandbyMode"), _T("{}"), response)); +} + +TEST_F(SystemServicesTest, getAvailableStandbyModes) +{ + device::SleepMode mode; + string sleepModeString(_T("DEEP_SLEEP")); + + ON_CALL(*p_hostImplMock, getAvailableSleepModes) + .WillByDefault(::testing::Return(std::vector({ mode }))); + ON_CALL(*p_sleepModeMock, toString) + .WillByDefault(::testing::ReturnRef(sleepModeString)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableStandbyModes"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"supportedStandbyModes\":[\"DEEP_SLEEP\"],\"success\":true}")); + + ON_CALL(*p_hostImplMock, getAvailableSleepModes) + .WillByDefault(::testing::Invoke( + []() -> device::List { + throw device::Exception("test"); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getAvailableStandbyModes"), _T("{}"), response)); +} + +/******************************************************************************************************************* + * Test function for :getWakeupReason + * getWakeupReason : + * The API which Collects reason for the device coming out of deep sleep. + * + * @return Returns the reason for the device coming out of deep sleep. + * Use case coverage: + * @Success : 17 + * @Failure : 1 + ********************************************************************************************************************/ + +/** + * @brief : getWakeupReason without passing any reason. + * Check if BUS call to retrieve the reason for the device is failed, + * then getWakeupReason shall be failed. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_UNKNOWN","success":false} + */ +TEST_F(SystemServicesTest, getWakeupReasonFailure) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + return IARM_RESULT_INVALID_PARAM; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_IR. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_IR as a reason, + * then the response returned is "WAKEUP_REASON_IR" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_IR","success":true} + */ + +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_IR) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_IR; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_IR\",\"success\":true}")); +} +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_RCU_BT. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_RCU_BT as a reason, + * then the response returned is "WAKEUP_REASON_RCU_BT" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_RCU_BT","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_RCU_BT) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_RCU_BT; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_RCU_BT\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_RCU_RF4CE. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_RCU_RF4CE as a reason, + * then the response returned is "WAKEUP_REASON_RCU_RF4CE" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_RCU_RF4CE","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_RCU_RF4CE) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_RCU_RF4CE; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_RCU_RF4CE\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_GPIO. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_GPIO as a reason, + * then the response returned is "WAKEUP_REASON_GPIO" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_GPIO","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_GPIO) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_GPIO; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_GPIO\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_LAN. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_LAN as a reason, + * then the response returned is "WAKEUP_REASON_LAN" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_LAN","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_LAN) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_LAN; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_LAN\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_WLAN. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_WLAN as a reason, + * then the response returned is "WAKEUP_REASON_WLAN" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_WLAN","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_WLAN) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_WLAN; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_WLAN\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_TIMER. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_TIMER as a reason, + * then the response returned is "WAKEUP_REASON_TIMER" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_TIMER","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_TIMER) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_TIMER; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_TIMER\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_FRONT_PANEL. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_FRONT_PANEL as a reason, + * then the response returned is "WAKEUP_REASON_FRONT_PANEL" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_FRONT_PANEL","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_FRONT_PANEL) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_FRONT_PANEL; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_FRONT_PANEL\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_WATCHDOG. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_WATCHDOG as a reason, + * then the response returned is "WAKEUP_REASON_WATCHDOG" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_WATCHDOG","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_WATCHDOG) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_WATCHDOG; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_WATCHDOG\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_SOFTWARE_RESET. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_SOFTWARE_RESET as a reason, + * then the response returned is "WAKEUP_REASON_SOFTWARE_RESET" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_SOFTWARE_RESET","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_SOFTWARE_RESET) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_SOFTWARE_RESET; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_SOFTWARE_RESET\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_THERMAL_RESET. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_THERMAL_RESET as a reason, + * then the response returned is "WAKEUP_REASON_THERMAL_RESET" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_THERMAL_RESET","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_THERMAL_RESET) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_THERMAL_RESET; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_THERMAL_RESET\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_WARM_RESET. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_WARM_RESET as a reason, + * then the response returned is "WAKEUP_REASON_WARM_RESET" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_WARM_RESET","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_WARM_RESET) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_WARM_RESET; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_WARM_RESET\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_COLDBOOT. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_COLDBOOT as a reason, + * then the response returned is "WAKEUP_REASON_COLDBOOT" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_COLDBOOT","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_COLDBOOT) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_COLDBOOT; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_COLDBOOT\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_STR_AUTH_FAILURE. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_STR_AUTH_FAILURE as a reason, + * then the response returned is "WAKEUP_REASON_STR_AUTH_FAILURE" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_STR_AUTH_FAILURE","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_STR_AUTH_FAILURE) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_STR_AUTH_FAILURE; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_STR_AUTH_FAILURE\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_CEC. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_CEC as a reason, + * then the response returned is "WAKEUP_REASON_CEC" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_CEC","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_CEC) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_CEC; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_CEC\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_PRESENCE. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_PRESENCE as a reason, + * then the response returned is "WAKEUP_REASON_PRESENCE" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_PRESENCE","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_PRESENCE) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_PRESENCE; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_PRESENCE\",\"success\":true}")); +} + +/** + * @brief : getWakeupReason when the reason is DEEPSLEEP_WAKEUPREASON_VOICE. + * When BUS call retrieves DEEPSLEEP_WAKEUPREASON_VOICE as a reason, + * then the response returned is "WAKEUP_REASON_VOICE" with Success status as true. + * + * @param[in] : This method takes no parameters. + * @return : {"wakeupReason":"WAKEUP_REASON_VOICE","success":true} + */ +TEST_F(SystemServicesTest, getWakeupReasonSuccess_When_WAKEUPREASON_VOICE) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason))); + auto param = static_cast(arg); + *param = DEEPSLEEP_WAKEUPREASON_VOICE; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getWakeupReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupReason\":\"WAKEUP_REASON_VOICE\",\"success\":true}")); +} +/*Test cases for getWakeupReason ends here*/ + + +TEST_F(SystemServicesTest, getLastWakeupKeyCode) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_DEEPSLEEPMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupKeyCode))); + auto param = static_cast(arg); + param->keyCode = 5; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLastWakeupKeyCode"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"wakeupKeyCode\":5,\"success\":true}")); +} + +TEST_F(SystemServicesEventIarmTest, onFirmwareUpdateStateChange) +{ + Core::Event onFirmwareUpdateStateChange(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + // TODO: BUG. enum should be used + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onFirmwareUpdateStateChange\"," + "\"params\":" + "\\{" + "\"firmwareUpdateStateChange\":4" + "\\}" + "\\}"))); + + onFirmwareUpdateStateChange.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onFirmwareUpdateStateChange"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_FIRMWARE_UPDATE_STATE; + sysEventData.data.systemStates.state = IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_DOWNLOAD_COMPLETE; + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateStateChange.Lock()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateState"), _T("{}"), response)); + // TODO: BUG. enum should be used + EXPECT_EQ(response, string("{\"firmwareUpdateState\":4,\"success\":true}")); + + handler.Unsubscribe(0, _T("onFirmwareUpdateStateChange"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesEventIarmTest, onRecoveryStateChange) +{ + Core::Event onRecoveryStateChange(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onRecoveryStateChange\"," + "\"params\":" + "\\{" + "\"recoveryStateChange\":3" + "\\}" + "\\}"))); + + onRecoveryStateChange.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onRecoveryStateChange"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_RED_RECOV_UPDATE_STATE; + sysEventData.data.systemStates.state = IARM_BUS_SYSMGR_RECOVERY_STATE_PROGRAMMED; + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onRecoveryStateChange.Lock()); + + handler.Unsubscribe(0, _T("onRecoveryStateChange"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesEventIarmTest, onSystemClockSet) +{ + Core::Event onSystemClockSet(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemClockSet\"," + "\"params\":" + "\\{" + "\\}" + "\\}"))); + + onSystemClockSet.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemClockSet"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_TIME_SOURCE; + sysEventData.data.systemStates.state = 666; // I have no idea what it should be but SystemServices needs non-zero + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSystemClockSet.Lock()); + + handler.Unsubscribe(0, _T("onSystemClockSet"), _T("org.rdk.System"), message); +} + +/************************************************************************************************************* + * Test function for :onTemperatureThresholdChanged + * onTemperatureThresholdChanged : + * Triggered when the device temperature changes beyond the WARN or MAX limits. + * + * @return Whether the mode change is succeeded. + * Use case coverage: + * @Success :4 + * @Failure :5 + ************************************************************************************************************/ + +/** + * @brief : onTemperatureThresholdChanged when instance is invalid. + * Check if SystemServices instance is null, + * then onTemperatureThresholdChanged shall be failed and mode change will not be successful. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedFailed_withoutValidInstance) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + WPEFramework::Plugin::SystemServices::_instance = nullptr; + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + param.data.therm.curLevel = IARM_BUS_PWRMGR_TEMPERATURE_CRITICAL; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onTemperatureThresholdChanged.Lock(100)); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when newLevel is empty. + * Check if newLevel is empty, + * then onTemperatureThresholdChanged shall be failed and mode change will not be successful. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedFailed_whenNewLevelEmpty) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onTemperatureThresholdChanged.Lock(100)); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is NORMAL and current level is empty. + * Check if new level is NORMAL and current level is empty, + * then onTemperatureThresholdChanged shall be failed and mode change will not be successful. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedFailed_currLevelEmpty_newLevelNORMAL) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_NORMAL; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onTemperatureThresholdChanged.Lock(100)); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is HIGH and current level is empty. + * Check if new level is HIGH and current level is empty, + * then onTemperatureThresholdChanged shall be failed and mode change will not be successful. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedFailed_currLevelEmpty_newLevelHIGH) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onTemperatureThresholdChanged.Lock(100)); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is CRITICAL and current level is empty. + * Check if new level is CRITICAL and current level is empty, + * then onTemperatureThresholdChanged shall be failed and mode change will not be successful. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedFailed_currLevelEmpty_newLevelCRITICAL) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_CRITICAL; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onTemperatureThresholdChanged.Lock(100)); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is HIGH and current level is NORMAL. + * Check if new level is HIGH and current level is NORMAL, + * then onTemperatureThresholdChanged shall be succeeded, + * And set the value :thresholdType = "WARN" , exceeded ="true" and temperature= curTemperature obtained from IarmEvent. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedSuccess_whenNormalToHigh) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + // TODO: BUG. number should not be string + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTemperatureThresholdChanged\"," + "\"params\":" + "\\{" + "\"thresholdType\":\"WARN\"," + "\"exceeded\":true," + "\"temperature\":\"100.000000\"" + "\\}" + "\\}"))); + + onTemperatureThresholdChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + param.data.therm.curLevel = IARM_BUS_PWRMGR_TEMPERATURE_NORMAL; + param.data.therm.curTemperature = 100; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onTemperatureThresholdChanged.Lock()); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is HIGH and current level is CRITICAL. + * Check if new level is HIGH and current level is CRITICAL, + * then onTemperatureThresholdChanged shall be succeeded; + * And set the value :thresholdType = "MAX" , exceeded ="false" and temperature= curTemperature obtained from IarmEvent. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedSuccess_whenCriticalToHigh) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTemperatureThresholdChanged\"," + "\"params\":" + "\\{" + "\"thresholdType\":\"MAX\"," + "\"exceeded\":false," + "\"temperature\":\"48.000000\"" + "\\}" + "\\}"))); + + onTemperatureThresholdChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + param.data.therm.curLevel = IARM_BUS_PWRMGR_TEMPERATURE_CRITICAL; + param.data.therm.curTemperature = 48; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onTemperatureThresholdChanged.Lock()); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is CRITICAL and current level is HIGH. + * Check if new level is CRITICAL and current level is HIGH, + * then onTemperatureThresholdChanged shall be succeeded; + * And set the value :thresholdType = "MAX" , exceeded ="true" and temperature= curTemperature obtained from IarmEvent. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedSuccess_whenHighToCritical) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTemperatureThresholdChanged\"," + "\"params\":" + "\\{" + "\"thresholdType\":\"MAX\"," + "\"exceeded\":true," + "\"temperature\":\"100.000000\"" + "\\}" + "\\}"))); + + onTemperatureThresholdChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_CRITICAL; + param.data.therm.curLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + param.data.therm.curTemperature = 100; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onTemperatureThresholdChanged.Lock()); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief : onTemperatureThresholdChanged when new level is NORMAL and current level is HIGH. + * Check if new level is NORMAL and current level is HIGH, + * then onTemperatureThresholdChanged shall be succeeded; + * And set the value :thresholdType = "WARN" , exceeded ="false" and temperature= curTemperature obtained from IarmEvent. + * + * @param[in] : None. + * @return : None. + */ +TEST_F(SystemServicesEventIarmTest, onTemperatureThresholdChangedSuccess_whenHighToNormal) +{ + Core::Event onTemperatureThresholdChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onTemperatureThresholdChanged\"," + "\"params\":" + "\\{" + "\"thresholdType\":\"WARN\"," + "\"exceeded\":false," + "\"temperature\":\"100.000000\"" + "\\}" + "\\}"))); + + onTemperatureThresholdChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.therm.newLevel = IARM_BUS_PWRMGR_TEMPERATURE_NORMAL; + param.data.therm.curLevel = IARM_BUS_PWRMGR_TEMPERATURE_HIGH; + param.data.therm.curTemperature = 100; + thermMgrEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onTemperatureThresholdChanged.Lock()); + + handler.Unsubscribe(0, _T("onTemperatureThresholdChanged"), _T("org.rdk.System"), message); +} +/*Test cases for onTemperatureThresholdChanged ends here*/ + +extern "C" FILE* __real_popen(const char* command, const char* type); + +TEST_F(SystemServicesTest, getTimeZones) +{ + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("zdump \\/usr\\/share\\/zoneinfo/.+")); + return __real_popen(command, type); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimeZones"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{\"zoneinfo\":\\{.*\"GMT\":\".+ GMT\".*\\},\"success\":true\\}")); +} + +TEST_F(SystemServicesTest, getLastDeepSleepReason) +{ + ofstream file("/opt/standbyReason.txt"); + file << "thermal_deepsleep_critical_threshold"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLastDeepSleepReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"reason\":\"thermal_deepsleep_critical_threshold\",\"success\":true}")); +} + +TEST_F(SystemServicesTest, getCoreTemperature) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_GetThermalState))); + auto param = static_cast(arg); + param->curTemperature = 100; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCoreTemperature"), _T("{}"), response)); + // TODO: BUG. number should not be string + EXPECT_EQ(response, string("{\"temperature\":\"100.000000\",\"success\":true}")); +} + +TEST_F(SystemServicesTest, getTemperatureThresholds) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + if (string(methodName) == string(_T(IARM_BUS_PWRMGR_API_GetTemperatureThresholds))) { + auto param = static_cast(arg); + param->tempHigh = 100; + param->tempCritical = 200; + } else if (string(methodName) == string(_T(IARM_BUS_PWRMGR_API_GetThermalState))) { + auto param = static_cast(arg); + param->curTemperature = 62; + } + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTemperatureThresholds"), _T("{}"), response)); + // TODO: BUG. number should not be string + EXPECT_EQ(response, string("{\"temperatureThresholds\":{\"WARN\":\"100.000000\",\"MAX\":\"200.000000\",\"temperature\":\"62.000000\"},\"success\":true}")); +} + +TEST_F(SystemServicesTest, setTemperatureThresholds) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetTemperatureThresholds))); + auto param = static_cast(arg); + EXPECT_EQ(param->tempHigh, 99); + EXPECT_EQ(param->tempCritical, 199); + return IARM_RESULT_SUCCESS; + }); + + // TODO: BUG. number should not be string + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setTemperatureThresholds"), _T("{\"thresholds\":{\"WARN\":\"99.000000\",\"MAX\":\"199.000000\"}}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, getOvertempGraceInterval) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_GetOvertempGraceInterval))); + auto param = static_cast(arg); + param->graceInterval = 600; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getOvertempGraceInterval"), _T("{}"), response)); + // TODO: BUG. number should not be string + EXPECT_EQ(response, string("{\"graceInterval\":\"600\",\"success\":true}")); +} + +TEST_F(SystemServicesTest, setOvertempGraceInterval) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetOvertempGraceInterval))); + auto param = static_cast(arg); + EXPECT_EQ(param->graceInterval, 600); + return IARM_RESULT_SUCCESS; + }); + + // TODO: BUG. number should not be string + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setOvertempGraceInterval"), _T("{\"graceInterval\":\"600\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(SystemServicesTest, getRFCConfig) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getRFCConfig"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getRFCConfig"), _T("{\"rfclist\":[]}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getRFCConfig"), _T("{\"rfclist\":[\"#@!\"]}"), response)); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + EXPECT_EQ(string(pcCallerID), string("SystemServices")); + EXPECT_EQ(string(pcParameterName), string("Device.DeviceInfo.SerialNumber")); + strncpy(pstParamData->value, "test", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getRFCConfig"), _T("{\"rfcList\":[\"Device.DeviceInfo.SerialNumber\"]}"), response)); + EXPECT_EQ(response, string("{\"RFCConfig\":{\"Device.DeviceInfo.SerialNumber\":\"test\"},\"success\":true}")); +} + +TEST_F(SystemServicesTest, enableXREConnectionRetention) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableXREConnectionRetention"), _T("{\"enable\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_TRUE(Core::File(string(_T("/tmp/retainConnection"))).Exists()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enableXREConnectionRetention"), _T("{\"enable\":false}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_FALSE(Core::File(string(_T("/tmp/retainConnection"))).Exists()); +} + +TEST_F(SystemServicesTest, getPowerState) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_GetPowerState))); + auto param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPowerState"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"powerState\":\"STANDBY\",\"success\":true}")); +} + +/******************************************************************************************************************* + * Test function for :setPowerState + * setPowerState : + * Sets the power state of the device. + * valid powerState: {"STANDBY", "DEEP_SLEEP", "LIGHT_SLEEP", "ON"} + * + * @return Whether the request succeeded. + * Event : onSystemPowerStateChanged + * Triggers when the system power state changes. + * Use case coverage: + * @Success :5 + * @Failure :3 + ********************************************************************************************************************/ + +/** + * @brief : setPowerState when param is empty. + * If param is empty, + * then setPowerState shall be failed. + * + * @param[in] : "params": {} + * @return : {"success":false} + */ +TEST_F(SystemServicesTest, setPowerStateFailed_without_powerstate) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPowerState"), _T(""), response)); +} + +/** + * @brief : setPowerState when param contains invalid powerstate. + * Check if input param contains invalid powerstate, + * then setPowerState shall be failed. + * + * @param[in] : "params": {"powerState": "abc"} + * @return : {"success":false} + */ +TEST_F(SystemServicesTest, setPowerStateFailed_with_invalidpowerstate) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"abc\"}"), response)); +} + +/** + * @brief : setPowerState when Bus call returns other than IARM_RESULT_SUCCESS, + * then setPowerState shall be failed. + * + * @return : {"success":false} + */ + TEST_F(SystemServicesTest, setPowerStateFailed_when_Bus_call_fails) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + return IARM_RESULT_INVALID_PARAM; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"ON\"}"), response)); +} + +/** + * * @brief : setPowerState when powerstate is ON. + * Check if input param : powerstate is ON, + * then setPowerState will sets with provided state and setPowerState shall be succeeded. + * + * @param[in] : "params": {"powerState": "ON"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setPowerStateSuccess_when_powerstate_ON) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + auto param = static_cast(arg); + EXPECT_EQ(param->newState, IARM_BUS_PWRMGR_POWERSTATE_ON); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"ON\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * * @brief : setPowerState when powerstate is LIGHT_SLEEP. + * Check if input param : powerstate is LIGHTSLEEP, + * then setPowerState will sets with provided state and setPowerState shall be succeeded. + * + * @param[in] : "params": {"powerState": "LIGHT_SLEEP"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setPowerStateSuccess_when_powerstate_Light_sleep) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + auto param = static_cast(arg); + EXPECT_EQ(param->newState, IARM_BUS_PWRMGR_POWERSTATE_STANDBY); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"LIGHT_SLEEP\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * * @brief : setPowerState when powerstate is STANDBY and has valid SystemServices instance + * Check if SystemServices instance is not null,and if sleepmode is not DEEP_SLEEP + * then it calls setPowerState with state as the parameter and setPowerState shall be succeeded. + * + * @param[in] : "params": {"powerState": "STANDBY"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setPowerStateSuccess_when_powerstate_STANDBY_withValidInstance) +{ + device::SleepMode mode; + string sleepModeString(_T("STANDBY")); + + ON_CALL(*p_hostImplMock, getPreferredSleepMode) + .WillByDefault(::testing::Return(mode)); + ON_CALL(*p_sleepModeMock, toString) + .WillByDefault(::testing::ReturnRef(sleepModeString)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + auto param = static_cast(arg); + EXPECT_EQ(param->newState, IARM_BUS_PWRMGR_POWERSTATE_STANDBY); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"STANDBY\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * * @brief : setPowerState when powerstate is STANDBY and SystemServices instance is null + * Check if SystemServices instance is null,then it sets the PowerState with the current value of state and + * setPowerState shall be succeeded. + * + * @param[in] : "params": {"powerState": "STANDBY"} + * @return : {"success":true} + */ + +TEST_F(SystemServicesTest, setPowerStateSuccess_when_powerstate_STANDBY_withoutValidInstance) +{ + WPEFramework::Plugin::SystemServices::_instance = nullptr; + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + auto param = static_cast(arg); + EXPECT_EQ(param->newState, IARM_BUS_PWRMGR_POWERSTATE_STANDBY); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"STANDBY\"}"), response)); +} + +/** + * * @brief : setPowerState when valid preferredStandbyMode + * Check if getPreferredStandbyMode returns valid preferred standby mode, + * then it set the powerstate with prefered standbymode and setPowerState shall be succeeded. + * + * @param[in] : "params": {"powerState": "STANDBY"} + * @return : {"success":true} + */ + +TEST_F(SystemServicesTest, setPowerStateSuccess_with_PreferedStandbyMode) +{ + device::SleepMode mode; + string sleepModeString(_T("DEEP_SLEEP")); + + ON_CALL(*p_hostImplMock, getPreferredSleepMode) + .WillByDefault(::testing::Return(mode)); + ON_CALL(*p_sleepModeMock, toString) + .WillByDefault(::testing::ReturnRef(sleepModeString)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetPowerState))); + auto param = static_cast(arg); + EXPECT_EQ(param->newState, IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPowerState"), _T("{\"powerState\":\"STANDBY\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +/*Test cases for setPowerState ends here*/ + +TEST_F(SystemServicesTest, getPowerStateIsManagedByDevice) +{ + unsetenv("RDK_ACTION_ON_POWER_KEY"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPowerStateIsManagedByDevice"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"powerStateManagedByDevice\":false,\"success\":true}")); + setenv("RDK_ACTION_ON_POWER_KEY", "1", 1); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPowerStateIsManagedByDevice"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"powerStateManagedByDevice\":true,\"success\":true}")); +} + +TEST_F(SystemServicesTest, getPowerStateBeforeReboot) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_GetPowerStateBeforeReboot))); + auto param = static_cast(arg); + strncpy(param->powerStateBeforeReboot, "DEEP_SLEEP", sizeof(param->powerStateBeforeReboot)); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPowerStateBeforeReboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"state\":\"DEEP_SLEEP\",\"success\":true}")); +} + +TEST_F(SystemServicesTest, setWakeupSrcConfiguration) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_SetWakeupSrcConfig))); + auto param = static_cast(arg); + EXPECT_EQ(param->pwrMode, (1<srcType, (1<config, (1< service; + NiceMock amazonService; + string amazonPersistentPath(_T("/tmp/amazonPersistentPath")); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("deletePersistentPath"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("deletePersistentPath"), _T("{\"callsign\":\"\"}"), response)); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("Amazon"))); + return &amazonService; + })); + ON_CALL(amazonService, PersistentPath()) + .WillByDefault(::testing::Return(amazonPersistentPath)); + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/container_setup.sh Amazon"))); + return 0; + })); + + Core::Directory dir(amazonPersistentPath.c_str()); + EXPECT_TRUE(dir.Destroy(false)); + ASSERT_TRUE(dir.CreatePath()); + EXPECT_TRUE(Core::File(amazonPersistentPath).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("deletePersistentPath"), _T("{\"callsign\":\"Amazon\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_FALSE(Core::File(amazonPersistentPath).Exists()); + + plugin->Deinitialize(&service); +} + +/********************************************************************************************************* + * Test function for :onSystemPowerStateChanged + * onSystemPowerStateChanged : + * Triggered when the power manager detects a device power state change. + * The power state (must be one of the following: STANDBY, DEEP_SLEEP, LIGHT_SLEEP, ON) + * + * Use case coverage: + * @Success :4 + * @Failure :0 + ********************************************************************************************************/ + +/** + * @brief :Triggered when the power state changes from DEEPSLEEP to ON. + * Check when powerEventHandler function called with power state change event from DEEPSLEEP to ON; + * then onSystemPowerStateChanged event shall be triggered successfully and + * the expected JSON message is sent + */ +TEST_F(SystemServicesEventIarmTest, onSystemPowerStateChanged_From_DEEPSLEEP_to_ON) +{ + Core::Event onSystemPowerStateChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemPowerStateChanged\"," + "\"params\":" + "\\{" + "\"powerState\":\"ON\"," + "\"currentPowerState\":\"DEEP_SLEEP\"" + "\\}" + "\\}"))); + + onSystemPowerStateChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSystemPowerStateChanged.Lock()); + + handler.Unsubscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief :Triggered when the power state changes from ON to LIGHTSLEEP + * Check when powerEventHandler function called with power state change event from ON to LIGHTSLEEP; + * then onSystemPowerStateChanged event shall be triggered successfully and + * the expected JSON message is sent + */ +TEST_F(SystemServicesEventIarmTest, onSystemPowerStateChanged_PowerState_ON_To_LIGHTSLEEP) +{ + Core::Event onSystemPowerStateChanged(false, true); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemPowerStateChanged\"," + + "\"params\":" + "\\{" + "\"powerState\":\"LIGHT_SLEEP\"," + "\"currentPowerState\":\"ON\"" + "\\}" + "\\}"))); + + onSystemPowerStateChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSystemPowerStateChanged.Lock()); + + handler.Unsubscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); +} + +/** + * @brief :Triggered when the power state changes from STANDBY to LIGHTSLEEP + * Check when powerEventHandler function called with power state change event from STANDBY to LIGHTSLEEP; + * then onSystemPowerStateChanged event shall be triggered successfully and + * the expected JSON message is sent + */ +TEST_F(SystemServicesEventIarmTest, onSystemPowerStateChanged_PowerState_STANDBY_To_LIGHTSLEEP) +{ + Core::Event onSystemPowerStateChanged(false, true); + EXPECT_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .Times(0); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemPowerStateChanged\"," + + "\"params\":" + "\\{" + "\"powerState\":\"LIGHT_SLEEP\"," + "\"currentPowerState\":\"LIGHT_SLEEP\"" + "\\}" + "\\}"))); + + onSystemPowerStateChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSystemPowerStateChanged.Lock()); + + handler.Unsubscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); +} +/** + * @brief :Triggered when the power state changes from ON to DEEPSLEEP + * Check when powerEventHandler function called with power state change event from ON to DEEPSLEEP; + * then onSystemPowerStateChanged event shall be triggered successfully and + * the expected JSON message is sent + */ +TEST_F(SystemServicesEventIarmTest, onSystemPowerStateChanged_PowerState_ON_To_DEEPSLEEP) +{ + Core::Event onSystemPowerStateChanged(false, true); + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + + EXPECT_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .Times(0); + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + + ofstream dcmPropertiesFile("/etc/dcm.properties"); + dcmPropertiesFile << "LOG_SERVER=logs.xcal.tv\n"; + dcmPropertiesFile.close(); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemPowerStateChanged\"," + "\"params\":" + "\\{" + "\"powerState\":\"DEEP_SLEEP\"," + "\"currentPowerState\":\"ON\"" + "\\}" + "\\}"))); + + onSystemPowerStateChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onSystemPowerStateChanged.Lock()); + + handler.Unsubscribe(0, _T("onSystemPowerStateChanged"), _T("org.rdk.System"), message); +} +/*Test cases for onSystemPowerStateChanged ends here*/ + +TEST_F(SystemServicesEventIarmTest, onNetworkStandbyModeChanged) +{ + Core::Event onNetworkStandbyModeChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onNetworkStandbyModeChanged\"," + "\"params\":" + "\\{" + "\"nwStandby\":true" + "\\}" + "\\}"))); + + onNetworkStandbyModeChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onNetworkStandbyModeChanged"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_EventData_t param; + param.data.bNetworkStandbyMode = true; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_NETWORK_STANDBYMODECHANGED, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onNetworkStandbyModeChanged.Lock()); + + handler.Unsubscribe(0, _T("onNetworkStandbyModeChanged"), _T("org.rdk.System"), message); +} + +TEST_F(SystemServicesEventIarmTest, onRebootRequest) +{ + Core::Event onRebootRequest(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onRebootRequest\"," + "\"params\":" + "\\{" + "\"requestedApp\":\"test\"," + "\"rebootReason\":\"test\"" + "\\}" + "\\}"))); + + onRebootRequest.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onRebootRequest"), _T("org.rdk.System"), message); + + IARM_Bus_PWRMgr_RebootParam_t param; + strncpy(param.requestor, "test", sizeof(param.requestor)); + strncpy(param.reboot_reason_other, "test", sizeof(param.reboot_reason_other)); + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_REBOOTING, ¶m, 0); + + EXPECT_EQ(Core::ERROR_NONE, onRebootRequest.Lock()); + + handler.Unsubscribe(0, _T("onRebootRequest"), _T("org.rdk.System"), message); +} + + + /******************************************************************************************************************* + * Test function for :getDeviceInfo + * getDeviceInfo : + * The API which Collects device details such as bluetooth_mac, boxIP, build_type, estb_mac, + * imageVersion, rf4ce_mac, and wifi_mac. + * + * @return An object containing the device details. + * Use case coverage: + * @Success :9 + * @Failure :5 + ********************************************************************************************************************/ + +/** + * @brief : getDeviceInfo when QueryParam Contains Unallowable Character. + * Check if input query Param passed with unallowable characters, + * then getDeviceInfo shall be failed and returns an error message + * in the response + * + * @param[in] : "params":{"params": {"abc#$"}} + * @return : {"message":"Input has unallowable characters","success":false} + */ +TEST_F(SystemServicesTest, getDeviceInfoFailed_OnQueryParamContainsUnallowableCharacter) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":abc#$}"), response)); +} + +/** + * @brief : getDeviceInfo with Invalid query Param + * Check if Invalid query parameters passed , + * then getDeviceInfo shall be failed without giving any response + * + * @param[in] : "params":{"params": {friendId"}} + * @return : {"success":false}") + */ +TEST_F(SystemServicesTest, getDeviceInfoFailed_OnInvalidQueryParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":friendId}"), response)); +} + +/** + * @brief : getDeviceInfo When Query Parameter is make ,but Missing Key in property File + * Check if 'make' parameter contains missing key: MFG_NAME + * then ,getDeviceInfo shall be failed and returns an error message in the response + * + * @param[in] : "params":{"params": "make"} + * @return : {"message":"Missing required key/value(s)","success":false} + */ +TEST_F(SystemServicesTest, getDeviceInfoFailed_OnMissingKeyInDevicePropertyFile) +{ + ofstream file("/etc/device.properties"); + file << "MFGNAME=\"SKY\""; + file.close(); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":make}"), response)); +} + +/** + * @brief : getDeviceInfo When Query Parameter is make ,but Missing KeyValue in property File + * check if 'make' parameter contains missing key value + * then ,getDeviceInfo shall be failed and returns an error message in the response + * + * @param[in] : "params":{"params": "make"} + * @return : {"message":"Missing required key/value(s)","success":false} + */ +TEST_F(SystemServicesTest, getDeviceInfoFailed_OnMissingKeyValueInDevicePropertyFile) +{ + ofstream file("/etc/device.properties"); + file << "MFG_NAME="; + file.close(); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":make}"), response)); +} + +/** + * @brief : getDeviceInfo When ManufactureDataReadAPI Failed For GetModelName/HardwareID + * Check if (i) input parametr as Model name/Hardware ID and + * (ii) Manufacture Data Read API[IARM_BUS_MFRLIB_API_GetSerializedData] failed + * then, getDeviceInfo shall be failed and returns an error message in the response + * @param[in] : "params":{"params": "modelName"} + * @return : {"message":"Manufacturer Data Read Failed","success":false} + */ +TEST_F(SystemServicesTest, getDeviceInfoFailed_OnManufactureDataReadAPIFailed) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + //setting up a mock that always returns an error code. + return IARM_RESULT_IPCCORE_FAIL; + }); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":hardwareID}"), response)); +} + +/** + * @brief : getDeviceInfo When QueryParam is Make + * Check if query parameter = make + * then, getDeviceInfo shall succesfully retrieve the information from device property file + * @param[in] : "params":{"params": "make"} + * @return : {"make":"SKY","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onMakeParameter) +{ + ofstream file("/etc/device.properties"); + file << "MFG_NAME=SKY"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":make}"), response)); + EXPECT_EQ(response, string("{\"make\":\"SKY\",\"success\":true}")); +} + +/** + * @brief : getDeviceInfo With Valid QueryParam other than make + * Check if valid query parameter is passed, + * then getDeviceInfo shall successfully retrieve the corresponding value from getDeviceDetails script file + * and returns it in the response. + * Check if valid query parameter string contains any of the following characters [\"] , + * then getDeviceInfo shall remove those characters from input param + * and then successfully retrieve the corresponding value and returns it in the response + * Tested with following valid input params: {"bluetooth_mac","boxIP","build_type","estb_mac","eth_mac","friendly_id","imageVersion","version","software_version","model_number","wifi_mac"} + * @param[in] : "params":{"params": "estb_mac"} / + * : "params":{"params": "[estb_mac]"} + * @return : {"estb_mac":"20:F1:9E:EE:62:08","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onValidInput) +{ + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string("sh /lib/rdk/getDeviceDetails.sh read estb_mac")); + // Simulated the behavior of "getDeviceDetails.sh" script inorder to obtain the value of estb_mac key + const char key_estb_mac[] = "12:34:56:78:90:AB"; + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, key_estb_mac); + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":estb_mac}"), response)); + EXPECT_EQ(response, string("{\"estb_mac\":\"12:34:56:78:90:AB\",\"success\":true}")); +} + +/** + * @brief : getDeviceInfo When QueryParam is HardwareId + * Check if device's HardwareId as input query param, + * then getDeviceInfo shall succeed and retrieves the information from the external Bus device API + * and returns it in the response. + * @param[in] : "params":{"params": "hardwareID"} + * @return : {"hardwareId":"5678","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onQueryParamHardwareId) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "5678"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, sizeof(param->buffer)); + param->type = mfrSERIALIZED_TYPE_HWID; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":hardwareID}"), response)); + EXPECT_EQ(response, string("{\"hardwareID\":\"5678\",\"success\":true}")); +} + +/** + * @brief : getDeviceInfo When QueryParam is FriendlyId/ModelName + * Check if device's FriendlyId/ModelName as input query param, + * then getDeviceInfo shall succeed and retrieves the information from the external Bus device API + * and returns it in the response. + * @param[in] : "params": {"params": "friendly_id"} + * : "params": {"params": "model_name"} + * @return : {"friendly_id":"IP061-ec","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onQueryParamFriendlyIdOrModelName) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "IP061-ec"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, sizeof(param->buffer)); + param->type = mfrSERIALIZED_TYPE_PROVISIONED_MODELNAME; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":friendly_id}"), response)); + EXPECT_EQ(response, string("{\"friendly_id\":\"IP061-ec\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":modelName}"), response)); + EXPECT_EQ(response, string("{\"modelName\":\"IP061-ec\",\"success\":true}")); + +} + +/** + * @brief : getDeviceInfo returns Cached data When QueryParam is HardwareId + * Check (i) If input query param is device's Hardware ID + * and (ii) if cached data of hardware Id is available + * then , getDeviceInfo shall successfully retrieves the cached information and returns it in the response + * @param[in] : "params": {"params": "hardwareID"} + * @return : {"hardwareId":"5678","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_getCachedHardwareId) +{ + //Below IARM_Bus_Call function is called for saving the retrieved data + //in member variables [cached value] & setting the corresponding flags to true + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "5678"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, sizeof(param->buffer)); + param->type = mfrSERIALIZED_TYPE_HWID; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":hardwareID}"), response)); + EXPECT_EQ(response, string("{\"hardwareID\":\"5678\",\"success\":true}")); + + //To confirm that the retrieved data is cached Data; + //sets an expectation that the IARM_Bus_Call function should not be called during this sequence + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":hardwareID}"), response)); + EXPECT_EQ(response, string("{\"hardwareID\":\"5678\",\"success\":true}")); + +} + +/** + * @brief : getDeviceInfo returns Cached data When QueryParam is ModelName + * Check (i) If input query param is device's ModelName + * and (ii) if cached data of Model Name is available + * then , getDeviceInfo shall successfully retrieves the cached information and returns it in the response + * @param[in] : "params": {"params": "modelName"} + * @return : {"modelName":"IP061-ec","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_getCachedModelName) +{ + //Below IARM_Bus_Call function is called for saving the retrieved data + //in member variables [cached value] & setting the corresponding flags to true + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "IP061-ec"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, sizeof(param->buffer)); + param->type = mfrSERIALIZED_TYPE_PROVISIONED_MODELNAME; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":modelName}"), response)); + EXPECT_EQ(response, string("{\"modelName\":\"IP061-ec\",\"success\":true}")); + + //To confirm that the retrieved data is cached Data; + //sets an expectation that the IARM_Bus_Call function should not be called during this sequence + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":modelName}"), response)); + EXPECT_EQ(response, string("{\"modelName\":\"IP061-ec\",\"success\":true}")); +} + +/** + * @brief : getDeviceInfo When QueryParam passed without label "param" + * Check if QueryParams contains no label as "params" + * then getDeviceInfo shall successfully retrieve the device info and returns it in the response + * @param[in] : "params" :{} + * @return : {"make":"SKY","bluetooth_mac":"D4:52:EE:32:A3:B2", + * "boxIP":"192.168.1.100","build_type":"VBN", + * "estb_mac":"D4:52:EE:32:A3:B0","eth_mac":"D4:52:EE:32:A3:B0", + * "friendly_id":"IP061-ec","imageVersion":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "software_version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "model_number":"SKXI11ANS","wifi_mac":"D4:52:EE:32:A3:B1","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onQueryParameterHasNoLabelParam) +{ + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + const uint8_t deviceInfoContent[] = "echo \"bluetooth_mac=D4:52:EE:32:A3:B2\n" + "boxIP=192.168.1.0\n" + "build_type=VBN\n" + "estb_mac=D4:52:EE:32:A3:B0\n" + "eth_mac=D4:52:EE:32:A3:B0\n" + "friendly_id=IP061-ec\n" + "imageVersion=SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\n" + "model_number=SKXI11ANS\n" + "wifi_mac=D4:52:EE:32:A3:B1\"\n"; + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("sh /lib/rdk/getDeviceDetails.sh read"))); + return __real_popen(command, type); + })); + + //Create fake device property file + ofstream propFile("/etc/device.properties"); + propFile << "MFG_NAME=SKY"; + propFile.close(); + + //Create fake device info script + Core::File file(deviceInfoScript); + file.Create(); + file.Write(deviceInfoContent, sizeof(deviceInfoContent)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"make\":\"SKY\",\"bluetooth_mac\":\"D4:52:EE:32:A3:B2\",\"boxIP\":\"192.168.1.0\",\"build_type\":\"VBN\",\"estb_mac\":\"D4:52:EE:32:A3:B0\",\"eth_mac\":\"D4:52:EE:32:A3:B0\",\"friendly_id\":\"\",\"imageVersion\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"software_version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"model_number\":\"SKXI11ANS\",\"wifi_mac\":\"D4:52:EE:32:A3:B1\",\"success\":true}")); + file.Destroy(); +} + +/** + * @brief : getDeviceInfo When QueryParam passed without any value for "params" + * Check if no value is passed with input query param, + * then getDeviceInfo shall succesfully retrieve the information from both device property file and + * getDeviceDetails script file ,then returns it in the response + * @param[in] : "params": {"params": } + * @return : {"make":"SKY","bluetooth_mac":"D4:52:EE:32:A3:B2", + * "boxIP":"192.168.1.100","build_type":"VBN", + * "estb_mac":"D4:52:EE:32:A3:B0","eth_mac":"D4:52:EE:32:A3:B0", + * "friendly_id":"IP061-ec","imageVersion":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "software_version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "model_number":"SKXI11ANS","wifi_mac":"D4:52:EE:32:A3:B1","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_onNoValueForQueryParameter) +{ + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + const uint8_t deviceInfoContent[] = "echo \"bluetooth_mac=D4:52:EE:32:A3:B2\n" + "boxIP=192.168.1.0\n" + "build_type=VBN\n" + "estb_mac=D4:52:EE:32:A3:B0\n" + "eth_mac=D4:52:EE:32:A3:B0\n" + "friendly_id=IP061-ec\n" + "imageVersion=SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\n" + "model_number=SKXI11ANS\n" + "wifi_mac=D4:52:EE:32:A3:B1\"\n"; + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("sh /lib/rdk/getDeviceDetails.sh read"))); + return __real_popen(command, type); + })); + + //Create fake device property file + ofstream propFile("/etc/device.properties"); + propFile << "MFG_NAME=SKY"; + propFile.close(); + + //Create fake device info script + Core::File file(deviceInfoScript); + file.Create(); + file.Write(deviceInfoContent, sizeof(deviceInfoContent)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":}"), response)); + EXPECT_EQ(response, _T("{\"make\":\"SKY\",\"bluetooth_mac\":\"D4:52:EE:32:A3:B2\",\"boxIP\":\"192.168.1.0\",\"build_type\":\"VBN\",\"estb_mac\":\"D4:52:EE:32:A3:B0\",\"eth_mac\":\"D4:52:EE:32:A3:B0\",\"friendly_id\":\"\",\"imageVersion\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"software_version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"model_number\":\"SKXI11ANS\",\"wifi_mac\":\"D4:52:EE:32:A3:B1\",\"success\":true}")); + file.Destroy(); +} + +/** + * @brief : getDeviceInfo When QueryParams Value is Empty and getDeviceDetails Script contains some specific key-value pairs [ImageVersion,CableCardVersion/ModelNumber] + * Check if No value in input parameter and getDeviceDetails Script Contain key value = ImageVersion/ key value = CableCardVersion/ key value = ModelNumber + * then getDeviceInfo shall successfully retrieve the device info and returns it in the response where + * ImageVersion stored in keys, "version" and "software_version" ,"cable_card_firmware_version","model_number" respectively + * @param[in] : "params": {"params" : {}} + * @return : {"make":"SKY","bluetooth_mac":"D4:52:EE:32:A3:B2", + * "boxIP":"192.168.1.100","build_type":"VBN", + * "estb_mac":"D4:52:EE:32:A3:B0","eth_mac":"D4:52:EE:32:A3:B0", + * "friendly_id":"IP061-ec","imageVersion":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "software_version":"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI", + * "model_number":"SKXI11ANS","wifi_mac":"D4:52:EE:32:A3:B1","success":true} + */ +TEST_F(SystemServicesTest, getDeviceInfoSuccess_OnSpecificKeyValueParsing) +{ + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + const uint8_t deviceInfoContent[] = "echo \"bluetooth_mac=D4:52:EE:32:A3:B2\n" + "boxIP=192.168.1.0\n" + "build_type=VBN\n" + "estb_mac=D4:52:EE:32:A3:B0\n" + "eth_mac=D4:52:EE:32:A3:B0\n" + "friendly_id=IP061-ec\n" + "imageVersion=SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\n" + "model_number=SKXI11ANS\n" + "wifi_mac=D4:52:EE:32:A3:B1\"\n"; + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("sh /lib/rdk/getDeviceDetails.sh read"))); + return __real_popen(command, type); + })); + + //Create fake device property file + ofstream propFile("/etc/device.properties"); + propFile << "MFG_NAME=SKY"; + propFile.close(); + + //Create fake device info script + Core::File file(deviceInfoScript); + file.Create(); + file.Write(deviceInfoContent, sizeof(deviceInfoContent)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{\"params\":}"), response)); + EXPECT_EQ(response, _T("{\"make\":\"SKY\",\"bluetooth_mac\":\"D4:52:EE:32:A3:B2\",\"boxIP\":\"192.168.1.0\",\"build_type\":\"VBN\",\"estb_mac\":\"D4:52:EE:32:A3:B0\",\"eth_mac\":\"D4:52:EE:32:A3:B0\",\"friendly_id\":\"\",\"imageVersion\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"software_version\":\"SKXI11ANS_VBN_23Q1_sprint_20230129224229sdy_SYNA_CI\",\"model_number\":\"SKXI11ANS\",\"wifi_mac\":\"D4:52:EE:32:A3:B1\",\"success\":true}")); + file.Destroy(); +} + +/*Test cases for getDeviceInfo ends here*/ + +/******************************************************************************************************************* + * Test function for :requestSystemReboot + * requestSystemReboot : + * Requests that the system performs a reboot of the set-top box. + * Triggering onRebootRequest event. + * + * @return IARM BUS status and Whether the request succeeded. + * Use case coverage: + * @Success :6 + * @Failure :0 + ********************************************************************************************************************/ + +/** + * @brief :requestSystemReboot when "nrdPluginApp" process is NOT running. + * Check if "nrdPluginApp" process is not running ensure that the system reboot is initiated + * without any issues and returns the BUS call status in the response. + * + * @param[in] : "params": {} + * @return : {"IARM_Bus_Call_STATUS":0,"success":true} + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_NrdPluginAppNotRunning) +{ + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(-1)); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":0,\"success\":true}")); +} + +/** + * @brief :requestSystemReboot when "nrdPluginApp" process is running & It can't be terminated successfully + * Check if NrdPlugin App is Running & if unable to shutdown the app, + * then ensure that the system reboot is initiated + * without any issues and returns the BUS call status in the response. + * + * @param[in] : "params": {} + * @return : {"IARM_Bus_Call_STATUS":0,"success":true} + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_NrdPluginAppShutdownFailed) +{ + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(0)); + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pkill nrdPluginApp"))) + .WillByDefault(::testing::Return(-1)); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":0,\"success\":true}")); +} +/** + * @brief :requestSystemReboot when "nrdPluginApp" process is running & It can be terminated successfully + * Check if NrdPlugin App is Running ,then ensure that it is terminated + * properly before initiating the system reboot. + * and returns the BUS call status in the response. + * @param[in] : "params": {} + * @return : {"IARM_Bus_Call_STATUS":0,"success":true} + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_NrdPluginAppShutdownSuccess) +{ + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(0)); + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pkill nrdPluginApp"))) + .WillByDefault(::testing::Return(0)); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":0,\"success\":true}")); +} + +/** + * @brief :requestSystemReboot when reason is not passed + * Check if (i) input parameter is empty then requestSystemReboot + * shall be succeeded and returns the BUS call status in the response. + * + * @param[in] : "params": {} + * @return : {"IARM_Bus_Call_STATUS":0,"success":true} + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_withoutReason) +{ + // Ignore the application shutdown process here because it would add extra time + // to the test execution and is not relevant to this particular test case. + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(-1)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":0,\"success\":true}")); +} +/** + * @brief :requestSystemReboot when reason is passed + * Check if (i)reboot reason is passed as input parameter and + * (ii) if Bus call status returns as SUCCESS + * then requestSystemReboot shall be succeeded and returns the BUS call status in the response. + * + * @param[in] : "params": {"rebootReason": "FIRMWARE_FAILURE"} + * @return : {"IARM_Bus_Call_STATUS":0,"success":true} + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_withReason) +{ + // Ignore the application shutdown process here because it would add extra time + // to the test execution and is not relevant to this particular test case. + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(-1)); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + auto rebootParam = static_cast(arg); + EXPECT_THAT(string(rebootParam->requestor), "SystemServices"); + EXPECT_THAT(string(rebootParam->reboot_reason_custom), "FIRMWARE_FAILURE"); + EXPECT_THAT(string(rebootParam->reboot_reason_other), "FIRMWARE_FAILURE"); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{\"rebootReason\":\"FIRMWARE_FAILURE\"}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":0,\"success\":true}")); +} + +/** + * @brief :requestSystemReboot when reason is passed and Bus API failed + * Check if (i)reboot reason is passed as input parameter and + * (ii) if Bus call status returns some error_codes + * then requestSystemReboot shall be succeeded and returns the respective Bus call status + * [IARM_RESULT_INVALID_PARAM/IARM_RESULT_INVALID_STATE/IARM_RESULT_IPCCORE_FAIL/IARM_RESULT_OOM] + * + * @param[in] : "params": {"rebootReason": "FIRMWARE_FAILURE"} + * @return : {"IARM_Bus_Call_STATUS":4,"success":true} + * + */ +TEST_F(SystemServicesTest, requestSystemRebootSuccess_onRebootBusAPIFailed) +{ + // Ignore the application shutdown process here because it would add extra time + // to the test execution and is not relevant to this particular test case. + ON_CALL(*p_wrapsImplMock, system(::testing::StrEq("pgrep nrdPluginApp"))) + .WillByDefault(::testing::Return(-1)); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_PWRMGR_API_Reboot))); + return IARM_RESULT_INVALID_STATE; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("reboot"), _T("{\"rebootReason\":\"FIRMWARE_FAILURE\"}"), response)); + EXPECT_EQ(response, string("{\"IARM_Bus_Call_STATUS\":2,\"success\":true}")); +} + +/*Test cases for requestSystemReboot ends here*/ + +/******************************************************************************************************************* + * Test function for :getStateInfo + * getStateInfo : + * Queries device state information of various properties. + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :27 + * @Failure :2 + ********************************************************************************************************************/ + +/** + * @brief : getStateInfo When QueryParam is Empty + * Check if QueryParam is not passed + * then,getStateInfo shall be failed and returns the error code:SysSrv_MissingKeyValues + * in the response + * + * @param[in] : "params": {} + * @return : {"SysSrv_Status":2,"errorMessage":"Missing required key\/value(s)","success":false}} + */ +TEST_F(SystemServicesTest, getStateInfoFailed_onEmptyParamList) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getStateInfo"), _T("{}"), response)); +} + +/** + * @brief : getStateInfo when Invalid query Param is passed + * Check if Invalid query parameters passed, + * then getStateInfo shall be failed and returns the error code: SysSrv_Unexpected in the response + * + * @param[in] : "params": {"card.disconnected"} + * @return : {"SysSrv_Status":7,"errorMessage":"Unexpected error","success":false} + */ +TEST_F(SystemServicesTest, getStateInfoFailed_OnInvalidQueryParam) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getStateInfo"), _T("{}"), response)); +} + +/** + * @brief : getStateInfo When QueryParam is channel_map + * Check if valid query parameter com.comcast.channel_map is passed, + * then the function makes a bus call to retrieve the channel map state, + * getStateInfo shall be succeed and returns the channel map state in response. + * + * @param[in] : "params": {"com.comcast.channel_map"} + * @return : {"com.comcast.channel_map":2,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamChannelMap) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_SYSMGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_SYSMGR_API_GetSystemStates))); + auto* paramGetSysState = static_cast(arg); + paramGetSysState->channel_map.state = 2; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.channel_map}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.channel_map\":2,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is card.disconnected + * Check if valid query parameter card.disconnected passed, + * then getStateInfo shall be succeed and returns card.disconnected state in response. + * + * @param[in] : "params": {"com.comcast.card.disconnected"} + * @return : {"com.comcast.card.disconnected":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCardDisconnected) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.card.disconnected}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.card.disconnected\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is tune_ready + * Check if valid query parameter tune_ready is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.tune_ready"} + * @return : {"com.comcast.tune_ready":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamTuneReady) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.tune_ready}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.tune_ready\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is cmac + * Check if valid query parameter cmac is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.cmac"} + * @return : {"com.comcast.cmac":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCmac) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.cmac}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.cmac\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is card.moto.entitlements + * Check if valid query parameter card.moto.entitlements is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.card.moto.entitlements"} + * @return : {"com.comcast.card.moto.entitlements":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCardMotoEntitlements) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.card.moto.entitlements}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.card.moto.entitlements\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is card.moto.hrv_rx + * Check if valid query parameter card.moto.hrv_rx is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.card.moto.hrv_rx"} + * @return : {"com.comcast.card.moto.hrv_rx":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCardMotoHrvRx) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.card.moto.hrv_rx}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.card.moto.hrv_rx\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is card.cisco.status + * Check if valid query parameter card.cisco.status is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.card.cisco.status"} + * @return : {"com.comcast.card.cisco.status":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCardCiscoStatus) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.card.cisco.status}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.card.cisco.status\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is video_presenting + * Check if valid query parameter video_presenting is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.video_presenting"} + * @return : {"com.comcast.video_presenting":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamVideoPresenting) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.video_presenting}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.video_presenting\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is hdmi_out + * Check if valid query parameters hdmi_out is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.hdmi_out"} + * @return : {"com.comcast.hdmi_out":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamHdmiOut) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.hdmi_out}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.hdmi_out\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is hdcp_enabled + * Check if valid query parameters hdcp_enabled is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.hdcp_enabled"} + * @return : {"com.comcast.hdcp_enabled":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamHdcpEnabled) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.hdcp_enabled}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.hdcp_enabled\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is hdmi_edid_read + * Check if valid query parameter hdmi_edid_read is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.hdmi_edid_read"} + * @return : {"com.comcast.hdmi_edid_read":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamHdmiEdidRead) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.hdmi_edid_read}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.hdmi_edid_read\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is firmware_download + * Check if valid query parameters firmware_download is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.firmware_download"} + * @return : {"com.comcast.firmware_download":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamFirmwareDownload) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.firmware_download}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.firmware_download\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is time_source + * Check if valid query parameter time_source is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.time_source"} + * @return : {"com.comcast.time_source":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamTimeSource) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.time_source}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.time_source\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is time_zone_available + * Check if valid query parameter time_zone_available is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.time_zone_available"} + * @return : {"com.comcast.time_zone_available":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamTimeZoneAvailable) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.time_zone_available}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.time_zone_available\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is ca_system + * Check if valid query parameter ca_system is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.ca_system"} + * @return : {"com.comcast.ca_system":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCaSystem) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.ca_system}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.ca_system\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is estb_ip + * Check if valid query parameters estb_ip is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.estb_ip"} + * @return : {"com.comcast.estb_ip":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamEstbIp) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.estb_ip}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.estb_ip\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is ecm_ip + * Check if valid query parameter ecm_ip is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.ecm_ip"} + * @return : {"com.comcast.ecm_ip":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamEcmIp) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.ecm_ip}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.ecm_ip\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is lan_ip + * Check if valid query parameters lan_ip is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.lan_ip"} + * @return : {"com.comcast.lan_ip":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamLanIp) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.lan_ip}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.lan_ip\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is moca + * Check if valid query parameter moca is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.moca"} + * @return : {"com.comcast.moca":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamMoca) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.moca}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.moca\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is docsis + * Check if valid query parameter docsis is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.docsis"} + * @return : {"com.comcast.docsis":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamDocsis) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.docsis}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.docsis\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is dsg_broadcast_tunnel + * Check if valid query parameter dsg_broadcast_tunnel is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.dsg_broadcast_tunnel"} + * @return : {"com.comcast.dsg_broadcast_tunnel":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamDsgBroadcastTunnel) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.dsg_broadcast_tunnel}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.dsg_broadcast_tunnel\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is dsg_ca_tunnel + * Check if valid query parameter dsg_ca_tunnel is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.dsg_ca_tunnel"} + * @return : {"com.comcast.dsg_ca_tunnel":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamDsgCaTunnel) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.dsg_ca_tunnel}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.dsg_ca_tunnel\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is cable_card + * Check if valid query parameter cable_card is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.cable_card"} + * @return : {"com.comcast.cable_card":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCableCard) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.cable_card}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.cable_card\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is cable_card_download + * Check if valid query parameter cable_card_download is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.cable_card_download"} + * @return : {"com.comcast.cable_card_download":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCableCardDownload) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.cable_card_download}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.cable_card_download\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is cvr_subsystem + * Check if valid query parameters cvr_subsystem is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.cvr_subsystem"} + * @return : {"com.comcast.cvr_subsystem":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamCvrSubsystem) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.cvr_subsystem}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.cvr_subsystem\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is download + * Check if valid query parameter download is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.download"} + * @return : {"com.comcast.download":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamDownload) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.download}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.download\":0,\"success\":true}")); +} + +/** + * @brief : getStateInfo When QueryParam is vod_ad + * Check if valid query parameter vod_ad is passed, + * then getStateInfo shall be succeed and returns an success message in the response. + * + * @param[in] : "params": {"com.comcast.vod_ad"} + * @return : {"com.comcast.vod_ad":0,"success":true} + */ +TEST_F(SystemServicesTest, getStateInfoSuccess_onQueryParamVodAd) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStateInfo"), _T("{\"param\":com.comcast.vod_ad}"), response)); + EXPECT_EQ(response, string("{\"com.comcast.vod_ad\":0,\"success\":true}")); +} + +/*Test cases for getStateInfo ends here*/ + +/******************************************************************************************************************* + * Test function for :setBootLoaderPattern + * setBootLoaderPattern : + * Sets the boot loader pattern mode in MFR. + * valid patterns: {"NORMAL","SILENT","SILENT_LED_ON"} + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :3 + * @Failure :2 + ********************************************************************************************************************/ + +/** + * @brief : setBootLoaderPattern when pattern is not passed + * Check if pattern is not passed, + * then setBootLoaderPattern will Fail. + * + * @param[in] : "params": {} + * @return : {"success":false} + */ +TEST_F(SystemServicesTest, setBootLoaderPatternFailed_OnEmptyParamList) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setBootLoaderPattern"), _T("{}"), response)); +} + +/** + * @brief : setBootLoaderPattern when pattern is passed + * Check if invalid pattern is passed, + * then setBootLoaderPattern will Fail. + * + * @param[in] : "params": {"pattern": "SILENT_LED_OFF"} + * @return : {"success":false} + */ +TEST_F(SystemServicesTest, setBootLoaderPatternFailed_Oninvalidpattern) +{ + /*sets the expectation that IARM_Bus_Call should not be called*/ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setBootLoaderPattern"), _T("{\"pattern\":SILENT_LED_OFF}"), response)); +} + +/** + * @brief : setBootLoaderPattern when pattern is NORMAL + * Check if (i)pattern is NORMAL and + * (ii) if Bus call status returns as SUCCESS + * then setBootLoaderPattern will Succeed. + * + * + * @param[in] : "params": {"pattern": "NORMAL"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setBootLoaderPatternSuccess_onPatterntypeNORMAL) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_SetBootLoaderPattern))); + auto param = static_cast(arg); + EXPECT_EQ(param->pattern, mfrBL_PATTERN_NORMAL); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBootLoaderPattern"), _T("{\"pattern\":NORMAL}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * @brief : setBootLoaderPattern when pattern is SILENT + * Check if (i)pattern is SILENT and + * (ii) if Bus call status returns as SUCCESS + * then setBootLoaderPattern will Succeed. + * + * + * @param[in] : "params": {"pattern": "SILENT"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setBootLoaderPatternSuccess_onPatterntypeSILENT) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_SetBootLoaderPattern))); + auto param = static_cast(arg); + EXPECT_EQ(param->pattern, mfrBL_PATTERN_SILENT); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBootLoaderPattern"), _T("{\"pattern\":SILENT}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * @brief : setBootLoaderPattern when pattern is SILENT_LED_ON + * Check if (i)pattern is SILENT_LED_ON and + * (ii) if Bus call status returns as SUCCESS + * then setBootLoaderPattern will Succeed. + * + * + * @param[in] : "params": {"pattern": "SILENT_LED_ON"} + * @return : {"success":true} + */ +TEST_F(SystemServicesTest, setBootLoaderPatternSuccess_onPatterntypeSILENTLEDON) +{ + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_SetBootLoaderPattern))); + auto param = static_cast(arg); + EXPECT_EQ(param->pattern, mfrBL_PATTERN_SILENT_LED_ON); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setBootLoaderPattern"), _T("{\"pattern\":SILENT_LED_ON}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +/*Test cases for setBootLoaderPattern ends here*/ + +/************************************************************************************************************* +* Test function for :getMacAddresses +* getMacAddresses : +* Gets the MAC address of the device. +* @input GUID[Optional] /Can run without input params +* @return Whether the request succeeded. +* Event : onMacAddressesRetreived +* Triggers when the MAC addresses are requested +* Use case coverage: +* @Failure :1 +* @Success :1 +************************************************************************************************************/ + +/** + * @brief :getMacAddresses when getDeviceDetails.sh not exist. + * Check if the file getDeviceDetails.sh not present, + * then getMacAddresses shall be failed. + * + * @param[in]   : "params": "{}"  + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesTest,getMacAddressesFailed_WhenFileNotExist) +{ + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + Core::File file(deviceInfoScript); + remove("/lib/rdk/getDeviceDetails.sh"); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getMacAddresses"), _T("{}"), response)); + file.Destroy(); +} + +/** + * @brief : onMacAddressesRetrieved event triggered when getMacAddresses is successful + * Check if the onMacAddressesRetrieved event is correctly triggered with expected Json params + * when MAC addresses are requested successfully. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onMacAddressesRetrieved) +{ + Core::Event onMacAddressesRetreived(false, true); + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + Core::File file(deviceInfoScript); + file.Create(); + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + const char* valueToReturn = NULL; + if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read ecm_mac") == 0) { + valueToReturn = "A8:11:XX:FD:0C:XX"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read estb_mac") == 0) { + valueToReturn = "A8:11:XX:FD:0C:XX"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read moca_mac") == 0) { + valueToReturn = "00:15:5F:XX:20:5E:57:XX"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read eth_mac") == 0) { + valueToReturn = "A8:11:XX:FD:0C:XX"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read wifi_mac") == 0) { + valueToReturn = "A8:11:XX:FD:0C:XX"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read bluetooth_mac") == 0) { + valueToReturn = "AA:AA:AA:AA:AA:AA"; + } else if (strcmp(command, "/lib/rdk/getDeviceDetails.sh read rf4ce_mac") == 0) { + valueToReturn = "00:00:00:00:00:00"; + } + if (valueToReturn != NULL) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, valueToReturn); + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + } else { + return __real_popen(command, type); + } + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onMacAddressesRetreived\",\"params\":\\{\"ecm_mac\":\"A8:11:XX:FD:0C:XX\",\"estb_mac\":\"A8:11:XX:FD:0C:XX\",\"moca_mac\":\"00:15:5F:XX:20:5E:57:XX\",\"eth_mac\":\"A8:11:XX:FD:0C:XX\",\"wifi_mac\":\"A8:11:XX:FD:0C:XX\",\"bluetooth_mac\":\"AA:AA:AA:AA:AA:AA\",\"rf4ce_mac\":\"00:00:00:00:00:00\",\"success\":true\\}}"))); + onMacAddressesRetreived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onMacAddressesRetreived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMacAddresses"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onMacAddressesRetreived.Lock()); + handler.Unsubscribe(0, _T("onMacAddressesRetreived"), _T("org.rdk.System"), message); + file.Destroy(); +} +/*Test cases for getMacAddresses ends here*/ + +/******************************************************************************************************** +* Test function for :getFirmwareUpdateInfo +* getFirmwareUpdateInfo : +* Checks the firmware update information +* @input GUID[Optional] /Can run without input params +* @return Whether the request succeeded. +* Event : onFirmwareUpdateInfoReceived +* Triggers when the firmware update information is requested +* Use case coverage: +* @Failure :0 +* @Success :14 +************************************************************************************************************/ + +/** + * @brief : Test that onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful with HTTP status code 460. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WithHttpStatusCode460) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : Test that onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful with HTTP status code 403. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WithHttpStatusCode403) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "403"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":403,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"firmwareUpdateVersion\":\"1234\",\"updateAvailable\":true,\"updateAvailableEnum\":0,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful with an HTTP status code other than 460 or 403. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WithHttpStatusCodeOther) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "400"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":400,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"firmwareUpdateVersion\":\"1234\",\"updateAvailable\":true,\"updateAvailableEnum\":0,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful and the environment is PROD. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenEnvPROD) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_PROD_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful and the environment is DEV. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenEnvDev) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful and the environment is VBN. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenEnvVBN) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful and the environment is CQA. + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenEnvCqa) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful with the environment is other than PROD[eg:VBN] and /opt/swupdate.conf is NOT present + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenEnvNotProdWithoutConfFile) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful with the environment is other than PROD[eg:VBN] and /opt/swupdate.conf is present and contains empty URL + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, OnFirmwareUpdateInfoReceived_WhenEnvNotProdWithConfFileEmptyUrl) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + const string swUpdateFile = _T("/opt/swupdate.conf"); + Core::File file2(swUpdateFile); + file2.Destroy(); + file2.Create(); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"\",\"rebootImmediately\":false,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event is triggered correctly when getFirmwareUpdateInfo is successful and the environment is other than PROD[eg:VBN] with /opt/swupdate.conf is present and contains URL to override + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, OnFirmwareUpdateInfoReceived_WhenEnvNotProdWithConfFileOverrideUrl) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + const string swUpdateFile = _T("/opt/swupdate.conf"); + const uint8_t swUpdateUrl[] = "test_url"; + Core::File file2(swUpdateFile); + file2.Destroy(); + file2.Create(); + file2.Write(swUpdateUrl, sizeof(swUpdateUrl)); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{\"firmwareVersion\":\"1234\"}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"{\\\"firmwareVersion\\\":\\\"1234\\\"}\",\"rebootImmediately\":null,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event triggered when getFirmwareUpdateInfo is successful with missing HTTP status code + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WithoutHttpStatusCode) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":\\{\"status\":0,\"responseString\":\"\",\"rebootImmediately\":false,\"firmwareUpdateVersion\":\"\",\"updateAvailable\":false,\"updateAvailableEnum\":2,\"success\":false\\}}"))); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief : onFirmwareUpdateInfoReceived event triggered when getFirmwareUpdateInfo is successful with Repsonse string is empty + * @param[in]   :  This method takes no parameters. + * @return      :  {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenResponseEmpty) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_PROD_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = ""; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"\",\"rebootImmediately\":false,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/* + * @brief: onFirmwareUpdateInfoReceived event triggered when there is an error parsing the response from getFirmwareUpdateInfo. + * @param[in] : This method takes no parameters. + * @return : {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenErrorInParsingResponse) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_PROD_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "firmwareVersion:1234"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"firmwareVersion:1234\",\"rebootImmediately\":false,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/** + * @brief: onFirmwareUpdateInfoReceived event triggered when the ixconf response is not valid json and/or doesn't contain firmwareVersion + * @param[in] : This method takes no parameters. + * @return : {\"asyncResponse\":true,\"success\":true} + */ +TEST_F(SystemServicesEventTest, onFirmwareUpdateInfoReceived_WhenInvalidResponse) +{ + Core::Event onFirmwareUpdateInfoReceived(false, true); + std::ofstream fileVer("/version.txt"); + fileVer << "imagename:PX051AEI_PROD_2203_sprint_20220331225312sdy_NG"; + fileVer.close(); + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string("cat /tmp/xconf_httpcode_thunder.txt")) { + const char http_code_str[] = "460"; + strcpy(buffer, http_code_str); + } else if (string(command) == string("cat /tmp/xconf_response_thunder.txt")) { + const char response_str[] = "{}"; + strcpy(buffer, response_str); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.System.onFirmwareUpdateInfoReceived\",\"params\":{\"status\":0,\"responseString\":\"\",\"rebootImmediately\":false,\"updateAvailable\":false,\"updateAvailableEnum\":3,\"success\":true}}"); + onFirmwareUpdateInfoReceived.SetEvent(); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFirmwareUpdateInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"asyncResponse\":true,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onFirmwareUpdateInfoReceived.Lock()); + handler.Unsubscribe(0, _T("onFirmwareUpdateInfoReceived"), _T("org.rdk.System"), message); + + // Clear file contents + fileVer.open("/version.txt", std::ofstream::out | std::ofstream::trunc); + fileVer.close(); +} + +/**************************************************************************************************** + * Test functions for :clearLastDeepSleepReason + * clearLastDeepSleepReason : + * clear the last deep sleep reason by removing the file that stores it. + * This method takes no parameters. + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :1 + * @Failure :2 + ***************************************************************************************************/ + +/** + * @brief : clearLastDeepSleepReason when file doesn't exists/failed to remove. + * Check if If the file for the last deep sleep reason cannot be found or failed to remove, + * then clearLastDeepSleepReason shall be failed and an error message is returned in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"SysSrv_Status":7,"errorMessage":"Unexpected error","success":false} + */ +TEST_F(SystemServicesTest, clearLastDeepSleepReasonFailed_WhenFileFailedToRemove) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("rm -f /opt/standbyReason.txt"))); + return nullptr; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("clearLastDeepSleepReason"), _T("{}"), response)); +} + +/** + * @brief : clearLastDeepSleepReason when pclose fails to close the opened pipe. + * Check if the pclose failed to close the opened pipe, + * then clearLastDeepSleepReason shall be failed and + * an error message is returned in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"SysSrv_Status":7,"errorMessage":"Unexpected error","success":false} + */ +TEST_F(SystemServicesTest, clearLastDeepSleepReasonFailed_WhenPcloseFailed) +{ + //popen mock returns a fake file pointer value. + FILE* fakePipe = reinterpret_cast(0x1234); + EXPECT_CALL(*p_wrapsImplMock, popen(testing::_, testing::_)) + .WillOnce(testing::Return(fakePipe)); + //pclose mock returns -1 to simulate a failure to close the file + EXPECT_CALL(*p_wrapsImplMock, pclose(fakePipe)) + .WillOnce(testing::Return(-1)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("clearLastDeepSleepReason"), _T("{}"), response)); +} + +/** + * @brief : clearLastDeepSleepReason when file successfully removed. + * Check if the file for the last deep sleep reason is successfully removed using popen, + * then clearLastDeepSleepReason shall be succeeded. + * + * @param[in] : This method takes no parameters. + * @return : {"success": true} + */ +TEST_F(SystemServicesTest, clearLastDeepSleepReasonSuccess_whenFileSuccessfullyRemoved) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("rm -f /opt/standbyReason.txt"))); + return __real_popen(command, type); + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearLastDeepSleepReason"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/*Test cases for clearLastDeepSleepReason ends here*/ + +/********************************************************************************************************* + * Test function for :getXconfParams + * getXconfParams : + * Returns XCONF configuration parameters for the device. + * + * @return XconfParams, whether the request succeeded. + * Use case coverage: + * @Success :7 + ******************************************************************************************************/ +/** + * @brief : getXconfParams when stb version not found. + * Check if stb version is not found in VERSION_FILE + * then getXconfParams shall be succeeded and returns XconfParams with value env = "dev" + * and value of firmwareVersion= "unknown" if STB_VERSION_STRING not defined, + * and value of firmwareVersion = value defined in STB_VERSION_STRING if STB_VERSION_STRING is defined. + * + * @param[in] : This method takes no parameters. + * @return[if STB_VERSION_STRING defined] : {\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"\",\"model\":\"\",\"firmwareVersion\":\"string[STB_VERSION_STRING]\"},\"success\":true} + * @return[if STB_VERSION_STRING not defined] : {\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"\",\"model\":\"\",\"firmwareVersion\":\"unknown\"},\"success\":true} + */ +#ifdef STB_VERSION_STRING +TEST_F(SystemServicesTest, getXconfParamsSuccess_whenStbVersionNotFound_withVersionDefined) +{ + //stb version information + //Simulated as version not provided in the vesion.txt file + ofstream file("/version.txt"); + file << ""; + file.close(); + + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + string firmwareVersion = STB_VERSION_STRING; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\""+firmwareVersion+"\"},\"success\":true}")); +} + +#else +TEST_F(SystemServicesTest, getXconfParamsSuccess_whenStbVersionNotFoundwith_VersionNotDefined) +{ + //stb version information + //Simulated as version not provided in the vesion.txt file + ofstream file("/version.txt"); + file << ""; + file.close(); + + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"unknown\"},\"success\":true}")); +} +#endif + +/** + * @brief : getXconfParams when STB version string does not contain environment information like VBN/PROD/QA. + * Check if stb version string does not contain env information, + * then getXconfParams shall be succeeded and returns xconfParams with env="dev" and firmwareVersion=stb version string . + * + * @param[in] : This method takes no parameters. + * @return : {\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_2203_sprint_20220331225312sdy_NG\"},\"success\":true} + */ +TEST_F(SystemServicesTest, getXconfParamsSuccess_whenVersionStringWithoutEnvInfo) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_2203_sprint_20220331225312sdy_NG"; + file.close(); + + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"dev\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_2203_sprint_20220331225312sdy_NG\"},\"success\":true}")); +} + +/** + * @brief : getXconfParams getting all XCONF configuration parameters + * check if all the configiration parameters are provided in respective files, + * then getXconfParams shall be Succeeded and all the values for xconfParams shall be populated. + * + * @param[in] : This method takes no parameters. + * @return : "{\"xconfParams\":{\"env\":\"vbn\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"AX061AEI\",\"firmwareVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\"},\"success\":true}" + */ +TEST_F(SystemServicesTest, getXconfParamsSuccess_withAllXConfparams) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + file.close(); + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + //model information + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("PATH=${PATH}:/sbin:/usr/sbin /lib/rdk/getDeviceDetails.sh read"))); + std::string filename = "getDeviceDetail.sh"; + std::ofstream file_stream(filename); + file_stream << "model=AX061AEI\n"; + file_stream.close(); + FILE *fp = __real_popen(("cat " + filename).c_str(), "r"); + return fp; + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"vbn\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"AX061AEI\",\"firmwareVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\"},\"success\":true}")); +} +/** + * @brief : getXconfParams when firm value is "VBN". + * Check if the firm value is "VBN" + * then getXconfParams shall be succeeded and returns xconfParam with env="vbn". + * + * @param[in] : This method takes no parameters. + * @return : {\"xconfParams\":{\"env\":\"vbn\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\"},\"success\":true} + */ +TEST_F(SystemServicesTest, getXconfParamsSuccess_onFirmvalueVBN) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_VBN_2203_sprint_20220331225312sdy_NG"; + file.close(); + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"vbn\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_VBN_2203_sprint_20220331225312sdy_NG\"},\"success\":true}")); +} + +/** + * @brief : getXconfParams when firm value is "PROD". + * Check if the firm value is "PROD" + * then getXconfParams shall be succeeded and returns xconfParam with env="prod". + * + * @param[in] : This method takes no parameters. + * @return : {\"xconfParams\":{\"env\":\"prod\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_PROD_2203_sprint_20220331225312sdy_NG\"},\"success\":true} + */ +TEST_F(SystemServicesTest, getXconfParamsSuccess_onFirmvaluePROD) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_PROD_2203_sprint_20220331225312sdy_NG"; + file.close(); + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"prod\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_PROD_2203_sprint_20220331225312sdy_NG\"},\"success\":true}")); +} + +/** + * @brief : getXconfParams when firm value is "QA". + * Check if the firm value is "QA" + * then getXconfParams shall be succeeded and returns xconfParam with env="qa". + * + * @param[in] : This method takes no parameters. + * @return : {\"xconfParams\":{\"env\":\"qa\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_QA_2203_sprint_20220331225312sdy_NG\"},\"success\":true} + */ +TEST_F(SystemServicesTest, getXconfParamsSuccess_onFirmvalueQA) +{ + ofstream file("/version.txt"); + file << "imagename:PX051AEI_QA_2203_sprint_20220331225312sdy_NG"; + file.close(); + //estb_mac information + file.open("/tmp/.estb_mac"); + file << "D4:52:EE:32:A3:B0"; + file.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getXconfParams"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"xconfParams\":{\"env\":\"qa\",\"eStbMac\":\"D4:52:EE:32:A3:B0\",\"model\":\"ERROR\",\"firmwareVersion\":\"PX051AEI_QA_2203_sprint_20220331225312sdy_NG\"},\"success\":true}")); +} + +/*Test cases for getXconfParams ends here*/ + +/***************************************************************************************************** + * Test function for :getMfgSerialNumber + * getMfgSerialNumber : + * Gets the Manufacturing Serial Number. + * + * @return Manufacturing Serial Number, whether the request succeeded. + * Use case coverage: + * @Success :2 + * @Failure :1 + ******************************************************************************************************/ +/** + * @brief : getMfgSerialNumber when Bus call for retrieving the serial number failed. + * Check if BUS call to retrieve the manufacturing serial number is failed, + * then getMfgSerialNumber shall be failed and returns an error message in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"success":false}") + */ +TEST_F(SystemServicesTest, getMfgSerialNumberFailed_whenBusCallFailed) +{ + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + //setting up a mock that always returns an error code. + return IARM_RESULT_IPCCORE_FAIL; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getMfgSerialNumber"), _T("{}"), response)); +} + +/** + * @brief : getMfgSerialNumber when Bus call for retrieving the serial number succeeded. + * Check if BUS call to retrieve the manufacturing serial number succeeded, + * then getMfgSerialNumber shall be succeeded and + * returns retrieved manufacture serial number in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"mfgSerialNumber": "F00020CE000003","success": true} + */ +TEST_F(SystemServicesTest, getMfgSerialNumberSuccess_whenBusCallSuccess) +{ + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "F00020CE000003"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, param->bufLen); + param->type = mfrSERIALIZED_TYPE_MANUFACTURING_SERIALNUMBER; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMfgSerialNumber"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mfgSerialNumber\":\"F00020CE000003\",\"success\":true}")); +} + +/** + * @brief : getMfgSerialNumber when cached value available. + * Check if cached data of mfg serial number is available + * then , getMfgSerialNumber shall successfully retrieves the cached information and returns it. + * + * @param[in] : This method takes no parameters. + * @return : "result": {"mfgSerialNumber": "F00020CE000003","success": true} + */ +TEST_F(SystemServicesTest, getMfgSerialNumberSuccess_getCachedMfgSerialNumber) +{ + //Below IARM_Bus_Call function is called for saving the retrieved data + //in member variables [cached value] + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_MFRLIB_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_MFRLIB_API_GetSerializedData))); + auto* param = static_cast(arg); + const char* str = "F00020CE000003"; + param->bufLen = strlen(str); + strncpy(param->buffer, str, param->bufLen); + param->type = mfrSERIALIZED_TYPE_MANUFACTURING_SERIALNUMBER; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMfgSerialNumber"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mfgSerialNumber\":\"F00020CE000003\",\"success\":true}")); + //To confirm that the retrieved data is cached Data; + //sets an expectation that the IARM_Bus_Call function should not be called during this sequence + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMfgSerialNumber"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mfgSerialNumber\":\"F00020CE000003\",\"success\":true}")); +} +/*Test cases for getMfgSerialNumber ends here*/ + +/************************************************************************************************************* + * Test function for :getSerialNumber + * getSerialNumber : + * Returns the device serial number. + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :2 + * @Failure :3 + ************************************************************************************************************/ + +#ifdef USE_TR_69 +/** + * @brief : getSerialNumber when GetRFCParameter return failure + * Check if GetRFCParameter returns other than Success, + * then getSerialNumber shall be failed and return error message in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"SysSrv_Status":7,"errorMessage":"Unexpected error","success":false} + */ +TEST_F(SystemServicesTest, getSerialNumberTR069Failed_OnGetRFCParameterFailed) +{ + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + return WDMP_FAILURE; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSerialNumber"), _T("{}"), response)); +} + +/** + * @brief : getSerialNumber when GetRFCParameter return Success + * Check if GetRFCParameter returns Success, + * then getSerialNumber shall be Succeeded and + * returns the retrieved serial number in the response. + * + * @param[in] : This method takes no parameters. + * @return : {"serialNumber":"32E10400103240447","success":true} + */ +TEST_F(SystemServicesTest, getSerialNumberTR069Success_OnGetRFCParameterSuccess) +{ + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + // Define the expected serial number + const char* expectedSerialNumber = "32E10400103240447"; + strncpy(pstParamData->value, expectedSerialNumber, sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSerialNumber"), _T("{}"), response)); + EXPECT_THAT(response, string("{\"serialNumber\":\"32E10400103240447\",\"success\":true}")); +} + +#else +/** + * @brief : getSerialNumber when getStateDetails.sh does not exist + * Check if /lib/rdk/getStateDetails.sh file doesn't exist, + * then getSerialNumber shall be failed and return the error message in response. + * + * @param[in] : This method takes no parameters. + * @return : {"SysSrv_Status":4,"errorMessage":"Unexpected Error","success":false} + */ +TEST_F(SystemServicesTest, getSerialNumberSnmpFailed_WhenScriptFileNotExist) +{ + const string deviceStateInfoScript = _T("/lib/rdk/getStateDetails.sh"); + Core::File file(deviceStateInfoScript); + file.Create(); + // Remove the file to simulate it is not-existing + file.Destroy(); + EXPECT_FALSE(Core::File(string(_T("/lib/rdk/getStateDetails.sh"))).Exists()); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSerialNumber"), _T("{}"), response)); +} + +/** + * @brief : getSerialNumber when TMP_SERIAL_NUMBER_FILE does not exist. + * Check if TMP_SERIAL_NUMBER_FILE doesn't exist,then getSerialNumber shall be failed and + * return the error message in response + * + * @param[in] : This method takes no parameters. + * @return : {"SysSrv_Status":4,"errorMessage":"Expected file not found","success":false} + */ +TEST_F(SystemServicesTest, getSerialNumberSnmpFailed_WhenTmpSerialNumberFileNotExist) +{ + const string deviceStateInfoScript = _T("/lib/rdk/getStateDetails.sh"); + Core::File file(deviceStateInfoScript); + file.Create(); + + ofstream file2("/tmp/.STB_SER_NO"); + file2 << "32E10400103240447"; + file2.close(); + // Remove the file to simulate it is not-existing + std::remove("/tmp/.STB_SER_NO"); + + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/getStateDetails.sh"))).Exists()); + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/getStateDetails.sh STB_SER_NO"))); + return 0; + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getSerialNumber"), _T("{}"), response)); +} + + +/** + * @brief : getSerialNumber when serial number successfully read from /tmp/.STB_SER_NO . + * Check if file /lib/rdk/getStateDetails.sh and TMP_SERIAL_NUMBER_FILE file[/tmp/.STB_SER_NO] exist, + * then getSerialNumber shall be succeeded and returns serial number in response. + * + * @param[in] : This method takes no parameters. + * @return : {"serialNumber":"32E10400103240447","success":true} + */ +TEST_F(SystemServicesTest, getSerialNumberSnmpSuccess_whenSerialNumberIsInTmpFile) +{ + const string deviceStateInfoScript = _T("/lib/rdk/getStateDetails.sh"); + Core::File file(deviceStateInfoScript); + file.Create(); + ofstream file2("/tmp/.STB_SER_NO"); + file2 << "32E10400103240447"; + file2.close(); + + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/getStateDetails.sh"))).Exists()); + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/getStateDetails.sh STB_SER_NO"))); + return 0; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSerialNumber"), _T("{}"), response)); + EXPECT_THAT(response, string("{\"serialNumber\":\"32E10400103240447\",\"success\":true}")); +} +#endif + +/*Test cases for getSerialNumber ends here*/ + +/************************************************************************************************************* + * Test function for :onSystemModeChanged + * onSystemModeChanged : + * Triggered when the device operating mode changes. + * + * @return Whether the mode change is succeeded. + * Use case coverage: + * @Success :1 + * @Failure :0 + ************************************************************************************************************/ + +/** + * @brief : Check when the system mode is changed from IARM, + * the onSystemModeChanged event is triggered with the expected JSON string containing the new mode. + * + * @param[in] : This method takes mode as parameter. + */ +TEST_F(SystemServicesEventIarmTest, onSystemModeChanged) +{ + Core::Event onSystemModeChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onSystemModeChanged\"," + "\"params\":" + "\\{" + "\"mode\":\"NORMAL\"" + "\\}" + "\\}"))); + + onSystemModeChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onSystemModeChanged"), _T("org.rdk.System"), message); + + IARM_Bus_CommonAPI_SysModeChange_Param_t param; + param.newMode = IARM_BUS_SYS_MODE_NORMAL; + SysModeChange(¶m); + + EXPECT_EQ(Core::ERROR_NONE, onSystemModeChanged.Lock()); + + handler.Unsubscribe(0, _T("onSystemModeChanged"), _T("org.rdk.System"), message); +} +/*Test cases for onSystemModeChanged ends here*/ + +/******************************************************************************************************** + * Test function for :getPlatformConfiguration + * getPlatformConfiguration : + * Returns the supported features and device/account info. + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :8 + * @Failure :1 +*********************************************************************************************************/ + +/** + * @brief : getPlatformConfiguration when called with Invalid Query Parameter + * Check if getPlatformConfiguration api called with Invalid query then getPlatformConfiguration + * shall be failed and the PlatformCaps object shall NOT be populated with information + * + * @param[in] : This method takes query parameters other than "accountInfo"/"deviceInfo" which considered as Invalid + * @return : Returns the response string as success:false. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationFailed_withBadQuery) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"InvalidQueryParam\"}"), response)); + EXPECT_EQ(response, string("{\"success\":false}")); +} +/** + * @brief : getPlatformConfiguration when called with empty Query Parameter + * Check if getPlatformConfiguration api called with empty query then getPlatformConfiguration + * shall be succeeded and the PlatformCaps object shall be populated with information + * about both the account and device. + * + * @param[in] : This method takes no parameters. + * @return : Returns a PlatformCaps object containing the retrieved configuration information. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_withEmptyQuery) +{ + NiceMock service; + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + DispatcherMock* dispatcher = new DispatcherMock(); + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + bool firmwareUpdateDisabled = false; + if (Core::File(string("/opt/swupdate.conf")).Exists()) { + firmwareUpdateDisabled = true; + } + + Core::ProxyType mockResponse = Core::ProxyType::Create(); + Core::JSONRPC::Message resp; + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + if (message.Designator == "org.rdk.AuthService.1.getAlternateIds") { + resp.Result = Core::JSON::String("{\"alternateIds\":{\"_xbo_account_id\":\"1234567890\"}}"); + } + if (message.Designator == "org.rdk.AuthService.1.getXDeviceId") { + resp.Result = Core::JSON::String("{\"xDeviceId\":\"1000000000000000000\"}"); + } + if (message.Designator == "org.rdk.AuthService.1.getExperience") { + resp.Result = Core::JSON::String("{\"experience\":\"test_experience_string\"}"); + } + if (message.Designator == "org.rdk.Network.1.getPublicIP") { + resp.Result = Core::JSON::String("{\"public_ip\":\"test_publicIp_string\"}"); + } + mockResponse->Result = resp.Result; + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\"}"), response)); + EXPECT_EQ(response, string( "{\"AccountInfo\":{\"accountId\":\"1234567890\",\"x1DeviceId\":\"1000000000000000000\",\"XCALSessionTokenAvailable\":true,\"experience\":\"test_experience_string\",\"deviceMACAddress\":\"null\",\"firmwareUpdateDisabled\":" + std::string(firmwareUpdateDisabled ? "true" : "false") + "},\"DeviceInfo\":{\"quirks\":[\"XRE-4621\",\"XRE-4826\",\"XRE-4896\",\"XRE-5553\",\"XRE-5743\",\"XRE-6350\",\"XRE-6827\",\"XRE-7267\",\"XRE-7366\",\"XRE-7415\",\"XRE-7389\",\"DELIA-6142\",\"RDK-2222\",\"XRE-7924\",\"DELIA-8978\",\"XRE-7711\",\"RDK-2849\",\"DELIA-9338\",\"ZYN-172\",\"XRE-8970\",\"XRE-9001\",\"DELIA-17939\",\"DELIA-17204\",\"CPC-1594\",\"DELIA-21775\",\"XRE-11602\",\"CPC-1767\",\"CPC-1824\",\"XRE-10057\",\"RDK-21197\",\"CPC-2004\",\"DELIA-27583\",\"XRE-12919\",\"DELIA-28101\",\"XRE-13590\",\"XRE-13692\",\"XRE-13722\",\"DELIA-30269\",\"RDK-22801\",\"CPC-2404\",\"XRE-14664\",\"XRE-14921\",\"XRE-14963\",\"RDK-26425\",\"RDK-28990\",\"RDK-32261\"],\"mimeTypeExclusions\":{\"CDVR\":[\"application\\/dash+xml\"],\"DVR\":[\"application\\/dash+xml\"],\"EAS\":[\"application\\/dash+xml\"],\"IPDVR\":[\"application\\/dash+xml\"],\"IVOD\":[\"application\\/dash+xml\"],\"LINEAR_TV\":[\"application\\/dash+xml\"],\"VOD\":[\"application\\/dash+xml\"]},\"features\":{\"allowSelfSignedWithIPAddress\":1,\"connection.supportsSecure\":1,\"htmlview.callJavaScriptWithResult\":1,\"htmlview.cookies\":1,\"htmlview.disableCSSAnimations\":1,\"htmlview.evaluateJavaScript\":1,\"htmlview.headers\":1,\"htmlview.httpCookies\":1,\"htmlview.postMessage\":1,\"htmlview.urlpatterns\":1,\"keySource\":1,\"uhd_4k_decode\":0},\"model\":\"null\",\"deviceType\":\"\",\"supportsTrueSD\":true,\"webBrowser\":{\"browserType\":\"WPE\",\"version\":\"1.0.0.0\",\"userAgent\":\"Mozilla\\/5.0 (Linux; x86_64 GNU\\/Linux) AppleWebKit\\/601.1 (KHTML, like Gecko) Version\\/8.0 Safari\\/601.1 WPE\"},\"HdrCapability\":\"\",\"canMixPCMWithSurround\":false,\"publicIP\":\"test_publicIp_string\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); +} + +/** + * @brief : getPlatformConfiguration when called with Query Parameter as AccountInfo + * Check if getPlatformConfiguration api called with query :AccountInfo then getPlatformConfiguration + * shall be succeeded and the PlatformCaps object shall be populated with Account information + * + * @param[in] : query:"AccountInfo" + * @return : Returns a PlatformCaps object containing the retrieved configuration information. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_withQueryAccountInfo) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + DispatcherMock* dispatcher = new DispatcherMock(); + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + bool firmwareUpdateDisabled = false; + if (Core::File(string("/opt/swupdate.conf")).Exists()) { + firmwareUpdateDisabled = true; + } + Core::ProxyType mockResponse = Core::ProxyType::Create(); + Core::JSONRPC::Message resp; + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + if (message.Designator == "org.rdk.AuthService.1.getAlternateIds") { + resp.Result = Core::JSON::String("{\"alternateIds\":{\"_xbo_account_id\":\"1234567890\"}}"); + } + if (message.Designator == "org.rdk.AuthService.1.getXDeviceId") { + resp.Result = Core::JSON::String("{\"xDeviceId\":\"1000000000000000000\"}"); + } + if (message.Designator == "org.rdk.AuthService.1.getExperience") { + resp.Result = Core::JSON::String("{\"experience\":\"test_experience_string\"}"); + } + if (message.Designator == "org.rdk.AuthService.1.getSessionToken") { + resp.Result = Core::JSON::String("{\"token\":\"12345\"}"); + } + if (message.Designator == "org.rdk.System.1.getDeviceInfo") { + resp.Result = Core::JSON::String("{\"estb_mac\":\"test_estb_mac_string\"}"); + } + mockResponse->Result = resp.Result; + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"AccountInfo\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"accountId\":\"1234567890\",\"x1DeviceId\":\"1000000000000000000\",\"XCALSessionTokenAvailable\":true,\"experience\":\"test_experience_string\",\"deviceMACAddress\":\"test_estb_mac_string\",\"firmwareUpdateDisabled\":" + std::string(firmwareUpdateDisabled ? "true" : "false") + "},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); +} + +/** + * @brief : getPlatformConfiguration when called with Query Parameter as DeviceInfo + * Check if getPlatformConfiguration api called with query :DeviceInfo then getPlatformConfiguration + * shall be succeeded and the PlatformCaps object shall be populated with Device information + * + * @param[in] : query:"DeviceInfo" + * @return : Returns a PlatformCaps object containing the retrieved configuration information. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_withQueryDeviceInfo) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + DispatcherMock* dispatcher = new DispatcherMock(); + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + + Core::ProxyType mockResponse = Core::ProxyType::Create(); + Core::JSONRPC::Message resp; + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + if (message.Designator == "org.rdk.System.1.getDeviceInfo") { + resp.Result = Core::JSON::String("{\"model_number\":\"PX051AEI\"}"); + } + if (message.Designator == "org.rdk.AuthService.1.getDeviceInfo") { + //Hex value for Json Resp -> "deviceInfo": "deviceType=IpStb", + resp.Result = Core::JSON::String("{\"deviceInfo\":\"646576696365547970653d49705374622c20646576696365547970653d4969505374622c20766f69636549643d312c206d616e7566616374757265723d496e74656c\"}"); + } + if (message.Designator == "org.rdk.Network.1.getPublicIP") { + resp.Result = Core::JSON::String("{\"public_ip\":\"test_publicIp_string\"}"); + } + mockResponse->Result = resp.Result; + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"DeviceInfo\"}"), response)); + EXPECT_EQ(response, string("{\"DeviceInfo\":{\"quirks\":[\"XRE-4621\",\"XRE-4826\",\"XRE-4896\",\"XRE-5553\",\"XRE-5743\",\"XRE-6350\",\"XRE-6827\",\"XRE-7267\",\"XRE-7366\",\"XRE-7415\",\"XRE-7389\",\"DELIA-6142\",\"RDK-2222\",\"XRE-7924\",\"DELIA-8978\",\"XRE-7711\",\"RDK-2849\",\"DELIA-9338\",\"ZYN-172\",\"XRE-8970\",\"XRE-9001\",\"DELIA-17939\",\"DELIA-17204\",\"CPC-1594\",\"DELIA-21775\",\"XRE-11602\",\"CPC-1767\",\"CPC-1824\",\"XRE-10057\",\"RDK-21197\",\"CPC-2004\",\"DELIA-27583\",\"XRE-12919\",\"DELIA-28101\",\"XRE-13590\",\"XRE-13692\",\"XRE-13722\",\"DELIA-30269\",\"RDK-22801\",\"CPC-2404\",\"XRE-14664\",\"XRE-14921\",\"XRE-14963\",\"RDK-26425\",\"RDK-28990\",\"RDK-32261\"],\"mimeTypeExclusions\":{\"CDVR\":[\"application\\/dash+xml\"],\"DVR\":[\"application\\/dash+xml\"],\"EAS\":[\"application\\/dash+xml\"],\"IPDVR\":[\"application\\/dash+xml\"],\"IVOD\":[\"application\\/dash+xml\"],\"LINEAR_TV\":[\"application\\/dash+xml\"],\"VOD\":[\"application\\/dash+xml\"]},\"features\":{\"allowSelfSignedWithIPAddress\":1,\"connection.supportsSecure\":1,\"htmlview.callJavaScriptWithResult\":1,\"htmlview.cookies\":1,\"htmlview.disableCSSAnimations\":1,\"htmlview.evaluateJavaScript\":1,\"htmlview.headers\":1,\"htmlview.httpCookies\":1,\"htmlview.postMessage\":1,\"htmlview.urlpatterns\":1,\"keySource\":1,\"uhd_4k_decode\":0},\"model\":\"PX051AEI\",\"deviceType\":\"IpStb\",\"supportsTrueSD\":true,\"webBrowser\":{\"browserType\":\"WPE\",\"version\":\"1.0.0.0\",\"userAgent\":\"Mozilla\\/5.0 (Linux; x86_64 GNU\\/Linux) AppleWebKit\\/601.1 (KHTML, like Gecko) Version\\/8.0 Safari\\/601.1 WPE\"},\"HdrCapability\":\"\",\"canMixPCMWithSurround\":false,\"publicIP\":\"test_publicIp_string\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); +} + +/** + * @brief : getPlatformConfiguration when called with a specific DeviceInfo /AccountInfo Query Parameter + * Check if getPlatformConfiguration api called with passing any specified configuration parameter + * of DeviceInfo /AccountInfo; then getPlatformConfiguration shall be succeeded + * and the PlatformCaps object shall be populated with the value for that + * specfic configuration parameter + * + * @param[in] : This method takes any specific configuration parameter of AccountInfo/DeviceInfo + * @return : Returns a PlatformCaps object containing the requested configuration information. + */ + +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_withQueryParameterValue) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + DispatcherMock* dispatcher = new DispatcherMock(); + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + + Core::ProxyType mockResponse = Core::ProxyType::Create(); + Core::JSONRPC::Message resp; + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + if (message.Designator == "org.rdk.AuthService.1.getXDeviceId") { + resp.Result = Core::JSON::String("{\"xDeviceId\":\"1000000000000000000\"}"); + } + mockResponse->Result = resp.Result; + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"AccountInfo.x1DeviceId\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"x1DeviceId\":\"1000000000000000000\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); + +} + + + /* @brief : getPlatformConfiguration when the dispatcher object is null. + * Check if getPlatformConfiguration api called and if dispatcher object is null; + * then getPlatformConfiguration shall be succeeded . + * But PlatformCaps object shall be populated with Null/empty + * + * @param[in] : This method takes parameter :AccountInfo/DeviceInfo/Empty param + * @return : Returns PlatformCaps object with empty/Null value. + */ + +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_whenDispatcherNull) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + DispatcherMock* dispatcher = new DispatcherMock(); + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"AccountInfo.x1DeviceId\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"x1DeviceId\":\"null\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); +} + + /* @brief : getPlatformConfiguration when pass invalid callsign. + * Check if getPlatformConfiguration api called with invalid callsign; + * then getPlatformConfiguration shall be succeeded . + * But PlatformCaps object shall be populated with Null/empty + * + * @param[in] : This method takes Invalid callsign + * @return : Returns PlatformCaps object with empty/Null value. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_whenInvalidCallsign) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + DispatcherMock* dispatcher = new DispatcherMock(); + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(0); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"auth\",\"query\":\"AccountInfo.x1DeviceId\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"x1DeviceId\":\"null\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + +} + /* @brief : getPlatformConfiguration when the response JSON RPC message is unable to parse. + * Check if getPlatformConfiguration api called and if the JSON RPC response message is failed to parse * then getPlatformConfiguration shall be succeeded . + * But PlatformCaps object shall be populated with Null/empty + * + * @param[in] : This method takes parameter :AccountInfo/DeviceInfo/Empty param + * @return : Returns PlatformCaps object with empty/Null value. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_whenParseError) +{ + NiceMock service; + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + DispatcherMock* dispatcher = new DispatcherMock(); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + + Core::ProxyType mockResponse = Core::ProxyType::Create(); + Core::JSONRPC::Message resp; + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + if (message.Designator == "org.rdk.AuthService.1.getXDeviceId") { + resp.Result = Core::JSON::String("1000000000000000000"); + } + mockResponse->Result = resp.Result; + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"AccountInfo.x1DeviceId\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"x1DeviceId\":\"null\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); +} + + /* @brief : getPlatformConfiguration when the dispatcher Invoke method returns an error in Response object. + * Check if getPlatformConfiguration api called and + * if dispatcher Invoke method returns an error in Response object; + * then getPlatformConfiguration shall be succeeded . + * But PlatformCaps object shall be populated with Null/empty + * + * @param[in] : This method takes parameter :AccountInfo/DeviceInfo/Empty param + * @return : Returns PlatformCaps object with empty/Null value. + */ +TEST_F(SystemServicesTest, getPlatformConfigurationSuccess_withDispatcherInvokeError) +{ + NiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + NiceMock factoriesImplementation; + PluginHost::IFactories::Assign(&factoriesImplementation); + + DispatcherMock* dispatcher = new DispatcherMock(); + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return (reinterpret_cast(dispatcher)); + })); + + + Core::ProxyType mockResponse = Core::ProxyType::Create(); + + EXPECT_CALL(*dispatcher, Invoke(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const std::string&, + uint32_t, + const Core::JSONRPC::Message& message) ->Core::ProxyType { + mockResponse->Error.SetError(3); + return mockResponse; + })); + EXPECT_CALL(*dispatcher, Release()) + .Times(::testing::AnyNumber()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPlatformConfiguration"), _T("{\"callsign\":\"authService\",\"query\":\"AccountInfo.x1DeviceId\"}"), response)); + EXPECT_EQ(response, string("{\"AccountInfo\":{\"x1DeviceId\":\"null\"},\"success\":true}")); + + delete dispatcher; + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); +} +/*Test cases for getPlatformConfiguration ends here*/ + +/******************************************************************************************************** + * Test function for :uploadLogs + * uploadLogs: + * Uploads logs to a URL returned by SSR. + * + * @return Whether the request succeeded. + * Use case coverage: + * @Success :3 + * @Failure :0 +*********************************************************************************************************/ + +/** + * @brief : uploadLogs with invalid input URL + * This API is deprecated so calls to uploadLogs use uploadLogsAsync instead. + * The url passed into uploadLogs is not used. + * + * @param[in] : URL NOT starting with "https" + * @return : Returns response string as success:true. + */ +TEST_F(SystemServicesTest, uploadLogSuccess_withBadUrl) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogs"), _T("{\"url\": \"http://ssr.ccp.xcal.tv/cgi-bin/rdkb_snmp.cgi\"}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogs with valid input URL + * Check if a valid URL is provided in the input parameters JsonObject; + * then uploadLogs shall be suceeded with the correct URL. + * + * @param[in] : Valid input URL + * @return : Returns response string as success:true. + */ +TEST_F(SystemServicesTest, uploadLogSuccess_withValidURL) +{ + const string logArchievedPath = _T("/tmp/test_mac_Logs_" + currentDateTimeUtc("%m-%d-%y-%I-%M%p") + ".tgz"); + Core::File file(logArchievedPath); + file.Create(); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string(". /lib/rdk/utils.sh && getMacAddressOnly")) { + const char mac_Addr[] = "test_mac"; + strcpy(buffer, mac_Addr); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + EXPECT_TRUE(Core::File(string(_T(logArchievedPath))).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogs"), _T("{\"url\": \"https://ssr.ccp.xcal.tv/cgi-bin/rdkb_snmp.cgi\"}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogs without Any input URL + * Check if a No URL is provided in the input parameters JsonObject; + * then uploadLogs shall be suceeded with the default URL. + * + * @param[in] : None + * @return : Returns response string as success:true. + */ +TEST_F(SystemServicesTest, uploadLogSuccess_WithDefaultURL) +{ + const string logArchievedPath = _T("/tmp/test_mac_Logs_" + currentDateTimeUtc("%m-%d-%y-%I-%M%p") + ".tgz"); + Core::File file(logArchievedPath); + file.Create(); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + if (string(command) == string(". /lib/rdk/utils.sh && getMacAddressOnly")) { + const char mac_Addr[] = "test_mac"; + strcpy(buffer, mac_Addr); + } + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + })); + EXPECT_TRUE(Core::File(string(_T(logArchievedPath))).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogs"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} +/*Test cases for uploadLogs ends here*/ + + /*********************************************************************************************************** + * Test function for :uploadLogsAsync + * uploadLogsAsync : + * Starts background process to upload logs. + * @returns Whether the request succeeded + * Event onLogUpload: Triggered when logs upload process is done + * Use case coverage: + * @Success :2 + * @Failure :3 + ********************************************************************************************************/ + +/** + * @brief : uploadLogsAsync when uploadSTBLogs.sh not present. + * Checks if uploadSTBLogs.sh is not present in /lib/rdk, then uploadLogsAsync + * should return a response status as true but fail to start the log upload process. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, uploadLogsAsyncFailed_WhenUploadLogFileNotExist) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogsAsync without BUILD_TYPE information. + * Check if device.properties does not contain BUILD_TYPE information then, + * then uploadLogsAsync should return a response status as true but fail to start the log upload process. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, uploadLogsAsyncFailed_withoutBuildType) +{ + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties.close(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogsAsync when dcm property file not exist. + * Checks if the DCM property file is not present in the /opt or /etc folder, + * then uploadLogsAsync should return a response status as true but fail + * to start the log upload process since it could not get the LOG information. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, uploadLogsAsyncFailed_WhenDcmFileNotExist) +{ + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/uploadSTBLogs.sh"))).Exists()); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + EXPECT_TRUE(Core::File(string(_T("/etc/device.properties"))).Exists()); + + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_TRUE(Core::File(string(_T("/tmp/DCMSettings.conf"))).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogsAsync when Build type is PROD. + * Checks if the device.properties file contains BUILD_TYPE="prod", + * then uploadLogsAsync should retrieve the LOG SERVER information from etc/dcm.properties + * and the log upload process should succeed. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, uploadLogsAsyncSuccess_WithBuildTypeProd) +{ + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/uploadSTBLogs.sh"))).Exists()); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=prod\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + EXPECT_TRUE(Core::File(string(_T("/etc/device.properties"))).Exists()); + + ofstream dcmPropertiesFile("/etc/dcm.properties"); + dcmPropertiesFile << "LOG_SERVER=logs.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER=stblogger.ccp.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER_URL=https://xconf.xcal.tv/loguploader/getSettings\n"; + dcmPropertiesFile << "DCM_SCP_SERVER=stbscp.ccp.xcal.tv\n"; + dcmPropertiesFile << "HTTP_UPLOAD_LINK=https://ssr.ccp.xcal.tv/cgi-bin/S3.cgi\n"; + dcmPropertiesFile << "DCA_UPLOAD_URL=https://stbrtl.r53.xcal.tv\n"; + dcmPropertiesFile.close(); + EXPECT_TRUE(Core::File(string(_T("/etc/dcm.properties"))).Exists()); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_TRUE(Core::File(string(_T("/tmp/DCMSettings.conf"))).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +/** + * @brief : uploadLogsAsync when dcm property exist. + * Checks if the dcm.properties file is present, + * then uploadLogsAsync should retrieve the LOG SERVER information from dcm.properties + * and the log upload process should succeed. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, uploadLogsAsyncSuccess_WhenDcmFileExist) +{ + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/uploadSTBLogs.sh"))).Exists()); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + EXPECT_TRUE(Core::File(string(_T("/etc/device.properties"))).Exists()); + + ofstream dcmPropertiesFile("/opt/dcm.properties"); + dcmPropertiesFile << "LOG_SERVER=logs.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER=stblogger.ccp.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER_URL=https://xconf.xcal.tv/loguploader/getSettings\n"; + dcmPropertiesFile << "DCM_SCP_SERVER=stbscp.ccp.xcal.tv\n"; + dcmPropertiesFile << "HTTP_UPLOAD_LINK=https://ssr.ccp.xcal.tv/cgi-bin/S3.cgi\n"; + dcmPropertiesFile << "DCA_UPLOAD_URL=https://stbrtl.r53.xcal.tv\n"; + dcmPropertiesFile.close(); + EXPECT_TRUE(Core::File(string(_T("/opt/dcm.properties"))).Exists()); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_TRUE(Core::File(string(_T("/tmp/DCMSettings.conf"))).Exists()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} +/*Test cases for uploadLogsAsync ends here*/ + + /*********************************************************************************************************** + * Test function for :abortLogUpload + * uploadLogsAsync : + * Stops background process to upload logs. + * @returns Whether the request succeeded + * Event onLogUpload :Triggered when logs upload process is stopped + * Use case coverage: + * @Success :1 + * @Failure :1 + ********************************************************************************************************************/ + +/** + * @brief : abortLogUploadFailure when UploadLogScript is Not Running. + * Checks if the abortLogUpload method is called when the uploadLogScript is not running, + * then response status should be false indicating failure. + * + * @param[in] : no parameter + * @return : "{\"success\":false}") + */ +TEST_F(SystemServicesTest, abortLogUploadFailure_whenUploadLogScriptNotRunning) +{ + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + return __real_popen(command, type); + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("abortLogUpload"), _T("{}"), response)); +} + +/** + * @brief : abortLogUploadSuccess + * Checks if the abortLogUpload method is called successfully and + * returns a response status as true. + * + * @param[in] : no parameter + * @return : "{\"success\":true}") + */ +TEST_F(SystemServicesTest, abortLogUploadSuccess) +{ + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + EXPECT_TRUE(Core::File(string(_T("/lib/rdk/uploadSTBLogs.sh"))).Exists()); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + + EXPECT_TRUE(Core::File(string(_T("/etc/device.properties"))).Exists()); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_TRUE(Core::File(string(_T("/tmp/DCMSettings.conf"))).Exists()); + + //uploadLogsAsync method is invoked first to ensure that m_uploadLogsPid is assigned a value other than -1. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + return __real_popen(command, type); + })); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("abortLogUpload"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} +/*Test cases for abortLogUpload ends here*/ + +/*********************************************************************************************************** + * Test function for Event API :onLogUpload + * onLogUplaod: + * Triggered when logs upload process is done or stopped. + * @returns Upload status (must be one of the following: UPLOAD_SUCCESS, UPLOAD_FAILURE, UPLOAD_ABORTED) + * Use case coverage: + * @Success :2 + * @Failure :1 + ********************************************************************************************************************/ +/** + * @brief Test case for onLogUpload with uploadStatusSuccess. + * + * Verifies if the onLogUpload event is triggered correctly with log upload status as success. + * + * @param None. + * @return None. + */ +TEST_F(SystemServicesEventIarmTest, onLogUploadSuccess_withUploadStatusSuccess) +{ + Core::Event onLogUpload(false, true); + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + + ofstream dcmPropertiesFile("/opt/dcm.properties"); + dcmPropertiesFile << "LOG_SERVER=logs.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER=stblogger.ccp.xcal.tv\n"; + dcmPropertiesFile << "DCM_LOG_SERVER_URL=https://xconf.xcal.tv/loguploader/getSettings\n"; + dcmPropertiesFile << "DCM_SCP_SERVER=stbscp.ccp.xcal.tv\n"; + dcmPropertiesFile << "HTTP_UPLOAD_LINK=https://ssr.ccp.xcal.tv/cgi-bin/S3.cgi\n"; + dcmPropertiesFile << "DCA_UPLOAD_URL=https://stbrtl.r53.xcal.tv\n"; + dcmPropertiesFile.close(); + EXPECT_TRUE(Core::File(string(_T("/opt/dcm.properties"))).Exists()); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onLogUpload\"," + "\"params\":" + "\\{" + "\"logUploadStatus\":\"UPLOAD_SUCCESS\"" + "\\}" + "\\}"))); + + onLogUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_LOG_UPLOAD; + sysEventData.data.systemStates.state = IARM_BUS_SYSMGR_LOG_UPLOAD_SUCCESS; + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onLogUpload.Lock()); + + handler.Unsubscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); +} + +/** + * @brief Test case for onLogUploadSuccess with abortStatusSuccess. + * + * Verifies if the onLogUpload event is triggered correctly with log abort status as success. + * + * @param None. + * @return None. + */ +TEST_F(SystemServicesEventIarmTest, onLogUploadSuccess_withAbortStatusSuccess) +{ + Core::Event onLogUpload(false, true); + const string uploadStbLogFile = _T("/lib/rdk/uploadSTBLogs.sh"); + Core::File file(uploadStbLogFile); + file.Create(); + + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + pstParamData->type = WDMP_BOOLEAN; + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + + std::ofstream deviceProperties("/etc/device.properties"); + deviceProperties << "BUILD_TYPE=dev\n"; + deviceProperties << "FORCE_MTLS=true\n"; + deviceProperties.close(); + + ofstream dcmPropertiesFile("/etc/dcm.properties"); + dcmPropertiesFile << "LOG_SERVER=logs.xcal.tv\n"; + dcmPropertiesFile.close(); + + std::ofstream tmpDcmSettings("/tmp/DCMSettings.conf"); + tmpDcmSettings << "LogUploadSettings:UploadRepository:uploadProtocol=https\n"; + tmpDcmSettings << "LogUploadSettings:UploadRepository:URL=https://example.com/upload\n"; + tmpDcmSettings << "LogUploadSettings:UploadOnReboot=true\n"; + tmpDcmSettings.close(); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadLogsAsync"), _T("{}"), response)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_THAT(text, ::testing::MatchesRegex(_T("\\{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.System.onLogUpload\"," + "\"params\":" + "\\{" + "\"logUploadStatus\":\"UPLOAD_SUCCESS\"" + "\\}" + "\\}"))); + + onLogUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_LOG_UPLOAD; + sysEventData.data.systemStates.state = IARM_BUS_SYSMGR_LOG_UPLOAD_SUCCESS; + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_NONE, onLogUpload.Lock()); + + handler.Unsubscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); +} + +/** + * @brief Test case for onLogUploadFailed when uploadLogScriptNotRunning. + * + * Verifies onLogUpload event will NOT be triggered correctly when the upload log script is not running. + * + * @param None. + * @return None. + */ +TEST_F(SystemServicesEventIarmTest, onLogUploadFailed_whenUploadLogScriptNotRunning) +{ + Core::Event onLogUpload(false, true); + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)).Times(0); + handler.Subscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); + + IARM_Bus_SYSMgr_EventData_t sysEventData; + sysEventData.data.systemStates.stateId = IARM_BUS_SYSMGR_SYSSTATE_LOG_UPLOAD; + sysEventData.data.systemStates.state = IARM_BUS_SYSMGR_LOG_UPLOAD_SUCCESS; + systemStateChanged(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, &sysEventData, 0); + + EXPECT_EQ(Core::ERROR_TIMEDOUT, onLogUpload.Lock(100)); + + handler.Unsubscribe(0, _T("onLogUpload"), _T("org.rdk.System"), message); +} +/*Test cases for onLogUpload ends here*/ + +class SystemServicesEmptyTest : public ::testing::Test { +}; + +/** + * @brief Test case for SystemServices constructor when /opt/system_service_settings.conf is the directory. + * + * Verifies if constructor doesn't hang if /opt/system_service_settings.conf is not a regular file. + * + * @param None. + * @return None. + */ + +TEST_F(SystemServicesEmptyTest, system_service_settings_conf_as_dir) +{ + Core::File(string("/opt/system_service_settings.conf")).Destroy(); + + EXPECT_TRUE(Core::Directory("/opt/system_service_settings.conf").CreatePath()); + + Core::ProxyType plugin; + plugin = Core::ProxyType::Create(); + + EXPECT_TRUE(Core::Directory("/opt/system_service_settings.conf").Destroy(true)); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_Telemetry.cpp b/NetworkManager/Tests/L1Tests/tests/test_Telemetry.cpp new file mode 100755 index 0000000000..49203d7ddc --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Telemetry.cpp @@ -0,0 +1,641 @@ +#include + +#include "Telemetry.h" + +#include "FactoriesImplementation.h" +#include "RfcApiMock.h" +#include "ServiceMock.h" +#include "TelemetryMock.h" +#include "RBusMock.h" +#include "IarmBusMock.h" + +namespace { +const string profileFN = _T("/tmp/DefaultProfile.json"); +const string t2PpersistentFolder = _T("/tmp/.t2reportprofiles/"); +const uint8_t profileContent[] = "{\"profile\":\"default\"}"; +} + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class T2Test : public ::testing::Test { +protected: + TelemetryApiImplMock *p_telemetryApiImplMock = nullptr ; + + T2Test() + { + p_telemetryApiImplMock = new NiceMock ; + TelemetryApi::setImpl(p_telemetryApiImplMock); + + EXPECT_CALL(*p_telemetryApiImplMock, t2_init(::testing::_)) + .Times(1); + } + virtual ~T2Test() + { + TelemetryApi::setImpl(nullptr); + if (p_telemetryApiImplMock != nullptr) + { + delete p_telemetryApiImplMock; + p_telemetryApiImplMock = nullptr; + } + } +}; + +class TelemetryTest : public T2Test { +protected: + NiceMock service; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + IARM_EventHandler_t powerEventHandler; + string response; + + TelemetryTest() + : T2Test() + , plugin(Core::ProxyType::Create()) + , handler(*plugin) + , connection(1, 0) + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + Core::Directory(t2PpersistentFolder.c_str()).Destroy(true); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { + EXPECT_TRUE(handler != nullptr); + powerEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + } + virtual ~TelemetryTest() override + { + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class TelemetryRfcTest : public TelemetryTest { +protected: + RfcApiImplMock *p_rfcApiImplMock = nullptr ; + + TelemetryRfcTest() + : TelemetryTest() + { + p_rfcApiImplMock = new NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + } + virtual ~TelemetryRfcTest() override + { + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + } +}; + +class TelemetryRBusTest : public TelemetryTest { +protected: + + ServiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + RBusApiImplMock *p_rBusApiImplMock = nullptr; + + TelemetryRBusTest() + : TelemetryTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + + p_rBusApiImplMock = new NiceMock ; + RBusApi::setImpl(p_rBusApiImplMock); + } + virtual ~TelemetryRBusTest() override + { + RBusApi::setImpl(nullptr); + if (p_rBusApiImplMock != nullptr) + { + delete p_rBusApiImplMock; + p_rBusApiImplMock = nullptr; + } + + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(TelemetryTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setReportProfileStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("logApplicationEvent"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("uploadReport"))); +} + +TEST_F(TelemetryRfcTest, InitializeDefaultProfile) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault( + ::testing::Return("{" + "\"t2PersistentFolder\":\"/tmp/.t2reportprofiles/\"," + "\"defaultProfilesFile\":\"/tmp/DefaultProfile.json\"" + "}")); + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Telemetry")); + EXPECT_EQ(string(pcParameterName), _T("Device.X_RDKCENTRAL-COM_T2.ReportProfiles")); + EXPECT_EQ(string(pcParameterValue), _T("{\\\"profile\\\":\\\"default\\\"}")); + EXPECT_EQ(eDataType, WDMP_STRING); + + return WDMP_SUCCESS; + })); + { + Core::Directory(t2PpersistentFolder.c_str()).CreatePath(); + Core::File file(profileFN); + file.Create(); + file.Write(profileContent, sizeof(profileContent)); + } + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRfcTest, InitializeDefaultProfileRFCFailure) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault( + ::testing::Return("{" + "\"t2PersistentFolder\":\"/tmp/.t2reportprofiles/\"," + "\"defaultProfilesFile\":\"/tmp/DefaultProfile.json\"" + "}")); + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + return WDMP_FAILURE; + })); + { + Core::Directory(t2PpersistentFolder.c_str()).CreatePath(); + Core::File file(profileFN); + file.Create(); + file.Write(profileContent, sizeof(profileContent)); + } + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryTest, InitializeZeroSizeDefaultProfile) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault( + ::testing::Return("{" + "\"t2PersistentFolder\":\"/tmp/.t2reportprofiles/\"," + "\"defaultProfilesFile\":\"/tmp/DefaultProfile.json\"" + "}")); + { + Core::Directory(t2PpersistentFolder.c_str()).CreatePath(); + Core::File file(profileFN); + file.Create(); + } + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryTest, InitializePersistentFolder) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault( + ::testing::Return("{" + "\"t2PersistentFolder\":\"/tmp/.t2reportprofiles/\"," + "\"defaultProfilesFile\":\"/tmp/DefaultProfile.json\"" + "}")); + { + Core::Directory(t2PpersistentFolder.c_str()).CreatePath(); + Core::File file(t2PpersistentFolder + "SomeReport"); + file.Create(); + } + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRfcTest, Plugin) +{ + ON_CALL(service, ConfigLine()) + .WillByDefault( + ::testing::Return("{}")); + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(3) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + return WDMP_FAILURE; + })) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Telemetry")); + EXPECT_EQ(string(pcParameterName), _T("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.Telemetry.FTUEReport.Enable")); + EXPECT_EQ(string(pcParameterValue), _T("false")); + EXPECT_EQ(eDataType, WDMP_BOOLEAN); + + return WDMP_SUCCESS; + })) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Telemetry")); + EXPECT_EQ(string(pcParameterName), _T("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.Telemetry.FTUEReport.Enable")); + EXPECT_EQ(string(pcParameterValue), _T("true")); + EXPECT_EQ(eDataType, WDMP_BOOLEAN); + + return WDMP_SUCCESS; + })); + EXPECT_CALL(*p_telemetryApiImplMock, t2_event_s(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* marker, char* value) { + EXPECT_EQ(string(marker), _T("NAME")); + EXPECT_EQ(string(value), _T("VALUE")); + return T2ERROR_SUCCESS; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setReportProfileStatus"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setReportProfileStatus"), _T("{\"status\":\"wrongvalue\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setReportProfileStatus"), _T("{\"status\":\"STARTED\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setReportProfileStatus"), _T("{\"status\":\"STARTED\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setReportProfileStatus"), _T("{\"status\":\"COMPLETE\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("logApplicationEvent"), _T("{\"eventName\":\"NAME\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("logApplicationEvent"), _T("{\"eventValue\":\"VALUE\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("logApplicationEvent"), _T("{\"eventName\":\"NAME\", \"eventValue\":\"VALUE\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsRbusOpenFailure) +{ + EXPECT_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](rbusHandle_t* handle, char const* componentName) { + EXPECT_TRUE(nullptr != handle); + EXPECT_EQ(string(componentName), _T("TelemetryThunderPlugin")); + return RBUS_ERROR_BUS_ERROR; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_OPENING_FAILED, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsRbusMethodFailure) +{ + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + return RBUS_ERROR_BUS_ERROR; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_RPC_CALL_FAILED, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsCallbackFailed) +{ + Core::Event onReportUpload(false, true); + + struct _rbusObject rbObject; + + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + callback(handle, methodName, RBUS_ERROR_BUS_ERROR, &rbObject); + + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_EQ(text, string(_T( + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Telemetry.onReportUpload\",\"params\":{\"telemetryUploadStatus\":\"UPLOAD_FAILURE\"}}" + ))); + + onReportUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + handler.Subscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, onReportUpload.Lock()); + + handler.Unsubscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsGetValueFailure) +{ + Core::Event onReportUpload(false, true); + + struct _rbusObject rbObject; + + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusObject_GetValue(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusObject_t object, char const* name) { + EXPECT_EQ(object, &rbObject); + EXPECT_EQ(string(name), _T("UPLOAD_STATUS")); + return nullptr; + })); + + ON_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + callback(handle, methodName, RBUS_ERROR_SUCCESS, &rbObject); + + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_EQ(text, string(_T( + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Telemetry.onReportUpload\",\"params\":{\"telemetryUploadStatus\":\"UPLOAD_FAILURE\"}}" + ))); + + onReportUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + handler.Subscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, onReportUpload.Lock()); + + handler.Unsubscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsFailure) +{ + Core::Event onReportUpload(false, true); + + struct _rbusObject rbObject; + struct _rbusValue rbValue; + + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusValue_GetString(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusValue_t value, int* len) { + EXPECT_EQ(value, &rbValue); + return "FAILURE"; + })); + + ON_CALL(*p_rBusApiImplMock, rbusObject_GetValue(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](rbusObject_t object, char const* name) { + EXPECT_EQ(object, &rbObject); + EXPECT_EQ(string(name), _T("UPLOAD_STATUS")); + return &rbValue; + })); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + callback(handle, methodName, RBUS_ERROR_SUCCESS, &rbObject); + + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_EQ(text, string(_T( + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Telemetry.onReportUpload\",\"params\":{\"telemetryUploadStatus\":\"UPLOAD_FAILURE\"}}" + ))); + + onReportUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + handler.Subscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, onReportUpload.Lock()); + + handler.Unsubscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogs) +{ + Core::Event onReportUpload(false, true); + + struct _rbusObject rbObject; + struct _rbusValue rbValue; + + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + ON_CALL(*p_rBusApiImplMock, rbusValue_GetString(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return( "SUCCESS")); + + ON_CALL(*p_rBusApiImplMock, rbusObject_GetValue(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](rbusObject_t object, char const* name) { + EXPECT_EQ(object, &rbObject); + EXPECT_EQ(string(name), _T("UPLOAD_STATUS")); + return &rbValue; + })); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + callback(handle, methodName, RBUS_ERROR_SUCCESS, &rbObject); + + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + + EXPECT_EQ(text, string(_T( + "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.Telemetry.onReportUpload\",\"params\":{\"telemetryUploadStatus\":\"UPLOAD_SUCCESS\"}}" + ))); + + onReportUpload.SetEvent(); + + return Core::ERROR_NONE; + })); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + handler.Subscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("uploadReport"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_NONE, onReportUpload.Lock()); + + handler.Unsubscribe(0, _T("onReportUpload"), _T("org.rdk.Telemetry"), message); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsOnStandby) +{ + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + EXPECT_EQ(string(methodName), _T("Device.X_RDKCENTRAL-COM_T2.UploadDCMReport")); + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + ASSERT_TRUE(powerEventHandler != nullptr); + + IARM_Bus_PWRMgr_EventData_t eventData; + eventData.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + eventData.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, &eventData , 0); + + plugin->Deinitialize(nullptr); +} + +TEST_F(TelemetryRBusTest, uploadLogsOnDeepSleep) +{ + ON_CALL(*p_rBusApiImplMock, rbus_open(::testing::_, ::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_CALL(*p_rBusApiImplMock, rbusMethod_InvokeAsync(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](rbusHandle_t handle, char const* methodName, rbusObject_t inParams, rbusMethodAsyncRespHandler_t callback, int timeout) { + EXPECT_EQ(string(methodName), _T("Device.X_RDKCENTRAL-COM_T2.AbortDCMReport")); + return RBUS_ERROR_SUCCESS; + })); + + ON_CALL(*p_rBusApiImplMock, rbus_close(::testing::_)) + .WillByDefault( + ::testing::Return(RBUS_ERROR_SUCCESS)); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + ASSERT_TRUE(powerEventHandler != nullptr); + + IARM_Bus_PWRMgr_EventData_t eventData; + eventData.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP; + eventData.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; + powerEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, &eventData , 0); + + plugin->Deinitialize(nullptr); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_TextToSpeech.cpp b/NetworkManager/Tests/L1Tests/tests/test_TextToSpeech.cpp new file mode 100755 index 0000000000..d36a081a21 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_TextToSpeech.cpp @@ -0,0 +1,1603 @@ +#include +#include "TextToSpeech.h" +#include "TextToSpeechImplementation.h" + +#include "ServiceMock.h" +#include "COMLinkMock.h" +#include "FactoriesImplementation.h" +#include "WorkerPoolImplementation.h" + +using namespace WPEFramework; +using ::testing::Test; +using ::testing::NiceMock; + +namespace { +const string config = _T("TextToSpeech"); +const string callSign = _T("org.rdk.TextToSpeech"); +const string webPrefix = _T("/Service/TextToSpeech"); +const string volatilePath = _T("/tmp/"); +const string dataPath = _T("/tmp/"); +} + +class TTSTest : public Test{ +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + Core::ProxyType workerPool; + + TTSTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + , workerPool(Core::ProxyType::Create( + 2, Core::Thread::DefaultStackSize(), 16)) { + } + + virtual ~TTSTest() = default; +}; + +class TTSInitializedTest : public TTSTest { +protected: + NiceMock factoriesImplementation; + NiceMock service; + NiceMock comLinkMock; + PluginHost::IDispatcher* dispatcher; + Core::ProxyType TextToSpeechImplementation; + string response; + + TTSInitializedTest() : TTSTest() { + TextToSpeechImplementation = Core::ProxyType::Create(); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(volatilePath)); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + ON_CALL(service, DataPath()) + .WillByDefault(::testing::Return(dataPath)); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(TextToSpeechImplementation)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~TTSInitializedTest() override { + plugin.Release(); + TextToSpeechImplementation.Release(); + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + PluginHost::IFactories::Assign(nullptr); + dispatcher->Deactivate(); + dispatcher->Release(); + } +}; + +TEST_F(TTSInitializedTest,RegisteredMethods) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("enabletts"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getapiversion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getspeechstate"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getttsconfiguration"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isspeaking"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isttsenabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("listvoices"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("pause"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resume"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setttsconfiguration"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("speak"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setACL"))); +} + +/******************************************************************************************************************* + * Test function for enableTTS + * enableTTS : + * Enables or disables the TTS conversion processing + * + * @return Response object contains TTS_Status and success + * Use case coverage: + * @Success : 3 + * @Failure : 0 + ********************************************************************************************************************/ +/** + * @name : EnableTTSDefault + * @brief : Enables or disables the TTS conversion processing + * + * @param[in] : enabletts + * @return : TTS_Status = 0 and success = true + */ + +TEST_F(TTSInitializedTest,EnableTTSDefault) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enabletts"), _T("{\"enabletts\": \"true\"}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"TTS_Status\":0"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +/** + * @name : EnableTTSTrue + * @brief : Enable with enabletts = true and checked if isttsenabled == true + * + * @param[in] : enabletts = true + * @return : isttsenabled = true; TTS_Status = 0 and success = true + */ + +TEST_F(TTSInitializedTest,EnableTTSTrue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enabletts"), _T("{\"enabletts\": true }"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isttsenabled"), _T(""), response)); + EXPECT_EQ(response, _T("{\"isenabled\":true,\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : EnableTTSFalse + * @brief : Enable with enabletts = false and checked if isttsenabled == false + * + * @param[in] : enabletts = false + * @return : isttsenabled = false; TTS_Status = 0 and success = true + */ + +TEST_F(TTSInitializedTest,EnableTTSFalse) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("enabletts"), _T("{\"enabletts\": false }"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isttsenabled"), _T(""), response)); + EXPECT_EQ(response, _T("{\"isenabled\":false,\"TTS_Status\":0,\"success\":true}")); +} + +/******************************************************************************************************************* + * Test function for getAPIVersion + * getAPIVersion : + * Gets the API Version. + * + * @return Response object contains version and success + * Use case coverage: + * @Success : 1 + * @Failure : 0 + ********************************************************************************************************************/ +/** + * @name : GetAPIVersion + * @brief : Gets the API Version. + * + * @param[in] : NONE + * @return : version = 1 and success = true + */ + +TEST_F(TTSInitializedTest,GetAPIVersion) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getapiversion"), _T(""), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"version\":1"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +/******************************************************************************************************************* + * Test function for isTTSEnabled + * isTTSEnabled : + * Returns whether the TTS engine is enabled or disabled. By default the TTS engine is disabled. + * + * @return Response object contains isenabled, TTS_Status and success + * Use case coverage: + * @Success : 1 + * @Failure : 0 + ********************************************************************************************************************/ +/** + * @name : IsTTSEnabledDefault + * @brief : Returns whether the TTS engine is enabled or disabled. By default the TTS engine is disabled. + * + * @param[in] : NONE + * @return : isenabled = false; TTS_Status = 0; success = true + */ + +TEST_F(TTSInitializedTest,IsTTSEnabledDefault) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isttsenabled"), _T(""), response)); + EXPECT_EQ(response, _T("{\"isenabled\":false,\"TTS_Status\":0,\"success\":true}")); +} + +/******************************************************************************************************************* + * Test function for listVoices + * SpeechState : + * Returns voice based on language + * + * @return Response object contains speaking and success + * Use case coverage: + * @Success : 1 + * @Failure : 4 + ********************************************************************************************************************/ +/** + * @name : IsListVoicesEmpty + * @brief : Returns speaking(true,false) of the given speechid + * + * @param[in] : language + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest,IsListVoicesEmpty) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("listvoices"), _T("{\"language\":\"en-US\"}"), response)); + EXPECT_EQ(response, _T("{\"voices\":[],\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : ListVoicesSetEmptyLanguage + * @brief : Set language as empty and check whether it return error + * + * @param[in] : Set "" in language + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, ListVoicesSetEmptyLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("listvoices"), _T("{\"language\": \"\"}"), response)); +} + +/** + * @name : ListVoicesSetWhiteSpaceLanguage + * @brief : Set language as " " and check whether it return error + * + * @param[in] : Set " " in language + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, ListVoicesSetWhiteSpaceAsLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("listvoices"), _T("{\"language\": \" \"}"), response)); +} + +/** + * @name : ListVoicesSetNumberAsLanguage + * @brief : Set language as Number and check whether it return error + * + * @param[in] : Set "" in language + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, ListVoicesSetNumberAsLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("listvoices"), _T("{\"language\": 01}"), response)); +} + +/** + * @name : ListVoicesSetNullLanguage + * @brief : Set language as NULL and check whether it return error + * + * @param[in] : Set NULL language + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, ListVoicesSetNullLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("listvoices"), _T("{\"language\": NULL}"), response)); +} + +/******************************************************************************************************************* + * Test function for speak + * speak : + * Converts the input text to speech when TTS is enabled. Any ongoing speech is interrupted and the newly requested speech is processed. + * + * @return Response speechid, TTS_Status and success + * Use case coverage: + * @Success : 1 + * @Failure : 0 + ********************************************************************************************************************/ +/** + * @name : Speak + * @brief : Converts the input text to speech when TTS is enabled. Any ongoing speech is interrupted and the newly requested speech is processed. + * + * @param[in] : text + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest,Speak) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpointsecured\":\"https://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"ttsendpoint\":\"http://example-tts-dummy.net/tts/v1/cdn/location?\"}" + ), + response + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("speak"), _T("{\"text\": \"speech_123\"}"), response)); + sleep(1); + + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"speechid\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"TTS_Status\":0"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +/******************************************************************************************************************* + * Test function for IsSpeaking + * SpeechState : + * Returns whether current speechid is speaking or not + * + * @return Response object contains speaking and success + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : IsSpeaking + * @brief : Returns speaking(true,false) of the given speechid + * + * @param[in] : speechid + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest,IsSpeaking) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isspeaking"), _T("{\"speechid\": 1}"), response)); + EXPECT_EQ(response, _T("{\"speaking\":false,\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : IsSpeakingEmptySpeechId + * @brief : Given a empty speechid it should return error + * + * @param[in] : "" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,IsSpeakingEmptySpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isspeaking"), _T("{\"speechid\": }"), response)); +} + +/** + * @name : IsSpeakingStringAsSpeechId + * @brief : Given a string speechid it should return error + * + * @param[in] : "hello" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,IsSpeakingStringAsSpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("isspeaking"), _T("{\"speechid\": \"hello\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for GetSpeechState + * SpeechState : + * Returns the SpeechState of the given speechid + * + * @return Response object contains speechstate and success + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : SpeechState + * @brief : Returns the SpeechState of the given speechid + * + * @param[in] : speechid + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest,SpeechState) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getspeechstate"), _T("{\"speechid\": 1}"), response)); + EXPECT_EQ(response, _T("{\"speechstate\":3,\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : GetSpeechStateEmptySpeechId + * @brief : Given a empty speechid it should return error + * + * @param[in] : "" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,GetSpeechStateEmptySpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getspeechstate"), _T("{\"speechid\": }"), response)); +} + +/** + * @name : GetSpeechStateStringAsSpeechId + * @brief : Given a string speechid it should return error + * + * @param[in] : "hello" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,GetSpeechStateStringAsSpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getspeechstate"), _T("{\"speechid\": \"hello\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for Cancel + * cancel : + * Cancel the speech currently happening + * + * @return Response object contains TTS_Status and success + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : Cancel + * @brief : Given a speechid it should cancel it + * + * @param[in] : Valid configuration + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest,Cancel) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("cancel"), _T("{\"speechid\": 1}"), response)); + EXPECT_EQ(response, _T("{\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : CancelEmptySpeechId + * @brief : Given a speechid it should return error + * + * @param[in] : "" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,CancelEmptySpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("cancel"), _T("{\"speechid\": }"), response)); +} + +/** + * @name : CancelStringAsSpeechId + * @brief : Given a string speechid it should return error + * + * @param[in] : "hello" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,CancelStringAsSpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("cancel"), _T("{\"speechid\": \"hello\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for Pause + * cancel : + * Cancel the speech currently happening + * + * @return Response object contains TTS_Status and success + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : Pause + * @brief : Given a speechid it should cancel it + * + * @param[in] : Valid configuration + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,Pause) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("pause"), _T("{\"speechid\": 1}"), response)); +} + +/** + * @name : PauseEmptySpeechId + * @brief : Given a speechid it should return error + * + * @param[in] : "" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,PauseEmptySpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("pause"), _T("{\"speechid\":\"\"}"), response)); +} + +/** + * @name : PauseStringAsSpeechId + * @brief : Given a string speechid it should return error + * + * @param[in] : "hello" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,PauseStringAsSpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("pause"), _T("{\"speechid\": \"hello\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for resume + * resume : + * resume the speech which is resumed + * + * @return Response object contains TTS_Status and success + * Use case coverage: + * @Success : 1 + * @Failure : 2 + ********************************************************************************************************************/ +/** + * @name : Resume + * @brief : Given a speechid it should resume it + * + * @param[in] : Valid configuration + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,Resume) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{\"speechid\": 1}"), response)); +} + +/** + * @name : ResumeEmptySpeechId + * @brief : Given a speechid it should return error + * + * @param[in] : "" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,ResumeEmptySpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{\"speechid\":\"\"}"), response)); +} + +/** + * @name : ResumeStringAsSpeechId + * @brief : Given a string speechid it should return error + * + * @param[in] : "hello" in speechId + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest,ResumeStringAsSpeechId) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{\"speechid\": \"hello\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for :setttsconfiguration + * setttsconfiguration : + * Set The TTS configurations based on params + * + * @return Response object contains TTS_Status and success + * Use case coverage: + * @Success : 2 + * @Failure : 34 + ********************************************************************************************************************/ +/** + * @name : SetTTSConfiguration + * @brief : Given a valid JSON request check whether response is success + * + * @param[in] : Valid configuration + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetTTSConfiguration) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpoint\":\"http://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"ttsendpointsecured\":\"https://example-tts-dummy.net/tts/v1/cdn/location?\"}" + ), + response + )); + + EXPECT_EQ(response, _T("{\"TTS_Status\":0,\"success\":true}")); +} + +/** + * @name : DefaultTTSConfiguration + * @brief : Update the value and check the value using gettsconfiguration + * + * @param[in] : Valid configuration + * @expected : getttsconfiguration should return the update value + */ + +TEST_F(TTSInitializedTest, DefaultTTSConfiguration) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpoint\":\"http://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"ttsendpointsecured\":\"https://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"volume\": \"95\",\"primvolduckpercent\": \"50\",\"rate\": \"40\",\"speechrate\":\"medium\"}" + ), + response + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + + EXPECT_EQ(response, + _T("{\"ttsendpoint\":\"http:\\/\\/example-tts-dummy.net\\/tts\\/v1\\/cdn\\/location?\"," + "\"ttsendpointsecured\":\"https:\\/\\/example-tts-dummy.net\\/tts\\/v1\\/cdn\\/location?\"," + "\"language\":\"en-US\",\"voice\":\"carol\",\"speechrate\":\"medium\",\"rate\":40,\"volume\":\"95\"," + "\"TTS_Status\":0,\"success\":true}" + )); +} + +/** + * @name : SetInvalidTTSEndpoint + * @brief : Set Invalid URL in ttsendpoint and check it return error + * + * @param[in] : Set invalid url in ttsendpoint + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetInvalidTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\",\"ttsendpoint\":\"invalid1@#\"," + "\"ttsendpointsecured\":\"https://localhost:50050/nuanceEve/tts?\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsEndPointPos = response.find("\"ttsendpoint\""); + + if (ttsEndPointPos != string::npos) { + size_t ttsEndpointStart = response.find(':', ttsEndPointPos ) + 1; + size_t ttsEndpointEnd = response.find(',', ttsEndPointPos ); + std::string ttsSubstring = response.substr(ttsEndpointStart ,ttsEndpointEnd - ttsEndpointStart ); + EXPECT_EQ(ttsSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsendpoint' not found in the response."; + } +} + +/** + * @name : SetInvalidSecuredTTSEndpoint + * @brief : Set Invalid URL in ttssecuredendpoint and check it return error + * + * @param[in] : Set invalid url in ttsendpoint + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetInvalidtSecuredTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpoint\":\"http://localhost:50050/nuanceEve/tts?\",\"ttsendpointsecured\":\"invalid1@#\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsendpointsecuredPos = response.find("\"ttsendpointsecured\""); + + if (ttsendpointsecuredPos != string::npos) { + size_t ttsendpointsecuredStart = response.find(':', ttsendpointsecuredPos ) + 1; + size_t ttsendpointsecuredEnd = response.find(',', ttsendpointsecuredPos ); + std::string ttsendpointsecuredSubstring = response.substr(ttsendpointsecuredStart ,ttsendpointsecuredEnd - ttsendpointsecuredStart ); + EXPECT_EQ(ttsendpointsecuredSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsEndpointSecured' not found in the response."; + } +} + +/** + * @name : SetEmptyTTSEndpoint + * @brief : Set Empty URL in ttsendpoint and check it returns error + * + * @param[in] : Set "" in ttsendpoint + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptyTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"ttsendpoint\":\"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsEndPointPos = response.find("\"ttsendpoint\""); + + if (ttsEndPointPos != string::npos) { + size_t ttsEndpointStart = response.find(':', ttsEndPointPos ) + 1; + size_t ttsEndpointEnd = response.find(',', ttsEndPointPos ); + std::string ttsSubstring = response.substr(ttsEndpointStart ,ttsEndpointEnd - ttsEndpointStart ); + EXPECT_EQ(ttsSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsendpoint' not found in the response."; + } +} + +/** + * @name : SetEmptySecuredTTSEndpoint + * @brief : Set Empty URL in ttssecuredendpoint and check it returns error + * + * @param[in] : Set "" in ttsendpoint + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptySecuredTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"ttssecuredendpoint\":\"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsEndPointPos = response.find("\"ttsendpointsecured\""); + + if (ttsEndPointPos != string::npos) { + size_t ttsEndpointStart = response.find(':', ttsEndPointPos ) + 1; + size_t ttsEndpointEnd = response.find(',', ttsEndPointPos ); + std::string ttsSubstring = response.substr(ttsEndpointStart ,ttsEndpointEnd - ttsEndpointStart ); + EXPECT_EQ(ttsSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttssecuredendpoint' not found in the response."; + } +} + +/** + * @name : SetNullTTSEndpoint + * @brief : Set NULL in ttsendpoint and check it returns error + * + * @param[in] : Set NULL in ttsendpoint + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetNULLTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"ttsendpoint\": null}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsEndPointPos = response.find("\"ttsendpoint\""); + + if (ttsEndPointPos != string::npos) { + size_t ttsEndpointStart = response.find(':', ttsEndPointPos ) + 1; + size_t ttsEndpointEnd = response.find(',', ttsEndPointPos ); + std::string ttsSubstring = response.substr(ttsEndpointStart ,ttsEndpointEnd - ttsEndpointStart ); + EXPECT_EQ(ttsSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsendpoint' not found in the response."; + } +} + +/** + * @name : SetNULLSecuredTTSEndpoint + * @brief : Set NULL in ttssecuredendpoint and check it returns error + * + * @param[in] : Set NULL in ttsendpoint + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetNULLSecuredTTSEndpoint) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"ttssecuredendpoint\": null}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ttsendpointsecuredPos = response.find("\"ttsendpointsecured\""); + + if (ttsendpointsecuredPos != string::npos) { + size_t ttsendpointsecuredStart = response.find(':', ttsendpointsecuredPos ) + 1; + size_t ttsendpointsecuredEnd = response.find(',', ttsendpointsecuredPos ); + std::string ttsendpointsecuredSubstring = response.substr(ttsendpointsecuredStart ,ttsendpointsecuredEnd - ttsendpointsecuredStart ); + EXPECT_EQ(ttsendpointsecuredSubstring ,"\"\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsendpointsecured' not found in the response."; + } +} + +/** + * @name : SetStringAsVolume + * @brief : Set string in Volume and check it returns error + * + * @param[in] : Set "invalid" in Volume + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetStringAsVolume) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"volume\": \"invalid\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t volumePos = response.find("\"volume\""); + + if (volumePos != string::npos) { + size_t volumeStart = response.find(':', volumePos ) + 1; + size_t volumeEnd = response.find(',', volumePos ); + std::string volumeSubstring = response.substr(volumeStart ,volumeEnd - volumeStart ); + EXPECT_EQ(volumeSubstring ,"\"95\""); + } else { + EXPECT_TRUE(false) << "Error: 'volume' not found in the response."; + } +} + +/** + * @name : SetVolumeLessThanMinValue + * @brief : Set volume as -1 and check whether it return error + * + * @param[in] : Set -1 in Volume + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetVolumeLessThanMinValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"volume\": -1}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t volumePos = response.find("\"volume\""); + + if (volumePos != string::npos) { + size_t volumeStart = response.find(':', volumePos ) + 1; + size_t volumeEnd = response.find(',', volumePos ); + std::string volumeSubstring = response.substr(volumeStart ,volumeEnd - volumeStart ); + EXPECT_EQ(volumeSubstring ,"\"95\""); + } else { + EXPECT_TRUE(false) << "Error: 'volume' not found in the response."; + } +} + +/** + * @name : SetVolumeLessThanMaxValue + * @brief : Set volume as 101 and check whether it return error + * + * @param[in] : Set 101 in Volume + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetVolumeGreaterThanMaxValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"volume\": 101}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t volumePos = response.find("\"volume\""); + + if (volumePos != string::npos) { + size_t volumeStart = response.find(':', volumePos ) + 1; + size_t volumeEnd = response.find(',', volumePos ); + std::string volumeSubstring = response.substr(volumeStart ,volumeEnd - volumeStart ); + EXPECT_EQ(volumeSubstring ,"\"95\""); + } else { + EXPECT_TRUE(false) << "Error: 'volume' not found in the response."; + } +} + +/** + * @name : SetEmptyVolume + * @brief : Set volume as empty and check whether it return error + * + * @param[in] : Set in Volume + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptyVolume) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"volume\":}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t volumePos = response.find("\"volume\""); + + if (volumePos != string::npos) { + size_t volumeStart = response.find(':', volumePos ) + 1; + size_t volumeEnd = response.find(',', volumePos ); + std::string volumeSubstring = response.substr(volumeStart ,volumeEnd - volumeStart ); + EXPECT_EQ(volumeSubstring ,"\"95\""); + } else { + EXPECT_TRUE(false) << "Error: 'ttsendpoint' not found in the response."; + } +} + +/** + * @name : SetStringAsRate + * @brief : Set string in rate and check it returns error + * + * @param[in] : Set "invalid" in rate + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetStringAsRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"rate\": \"invalid\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ratePos = response.find("\"rate\""); + + if (ratePos != string::npos) { + size_t rateStart = response.find(':', ratePos ) + 1; + size_t rateEnd = response.find(',', ratePos ); + std::string rateSubstring = response.substr(rateStart ,rateEnd - rateStart ); + EXPECT_EQ(rateSubstring ,"40"); + } else { + EXPECT_TRUE(false) << "Error: 'rate' not found in the response."; + } +} + +/** + * @name : SetRateLessThanMinValue + * @brief : Set rate as -1 and check whether it return error + * + * @param[in] : Set -1 in rate + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetRateLessThanMinValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"rate\": -1}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ratePos = response.find("\"rate\""); + + if (ratePos != string::npos) { + size_t rateStart = response.find(':', ratePos ) + 1; + size_t rateEnd = response.find(',', ratePos ); + std::string rateSubstring = response.substr(rateStart ,rateEnd - rateStart ); + EXPECT_EQ(rateSubstring ,"40"); + } else { + EXPECT_TRUE(false) << "Error: 'rate' not found in the response."; + } +} + +/** + * @name : SetRateGreaterThanMaxValue + * @brief : Set rate as 101 and check whether it return error + * + * @param[in] : Set 101 in rate + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetRateGreaterThanMaxValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"rate\": 101}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ratePos = response.find("\"rate\""); + + if (ratePos != string::npos) { + size_t rateStart = response.find(':', ratePos ) + 1; + size_t rateEnd = response.find(',', ratePos ); + std::string rateSubstring = response.substr(rateStart ,rateEnd - rateStart ); + EXPECT_EQ(rateSubstring ,"40"); + } else { + EXPECT_TRUE(false) << "Error: 'rate' not found in the response."; + } +} + +/** + * @name : SetEmptyRate + * @brief : Set rate as empty and check whether it return error + * + * @param[in] : Set in rate + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptyRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"rate\":\"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t ratePos = response.find("\"rate\""); + + if (ratePos != string::npos) { + size_t rateStart = response.find(':', ratePos ) + 1; + size_t rateEnd = response.find(',', ratePos ); + std::string rateSubstring = response.substr(rateStart ,rateEnd - rateStart ); + EXPECT_EQ(rateSubstring ,"40"); + } else { + EXPECT_TRUE(false) << "Error: 'rate' not found in the response."; + } +} + +/** + * @name : SetStringAsPrimvolduckpercent + * @brief : Set string in primvolduckpercent and check it returns error + * + * @param[in] : Set "invalid" in primvolduckpercent + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetStringAsprimvolduckpercent) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"primvolduckpercent\": \"invalid\"}"), response)); +} + +/** + * @name : SetPrimvolduckpercentLessThanMinValue + * @brief : Set primvolduckpercent as -1 and check whether it return error + * + * @param[in] : Set -1 in primvolduckpercent + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetPrimvolduckpercentLessThanMinValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"primvolduckpercent\": -1}"), response)); +} + +/** + * @name : SetPrimvolduckpercentGreaterThanMaxValue + * @brief : Set primvolduckpercent as 101 and check whether it return error + * + * @param[in] : Set 101 in primvolduckpercent + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetPrimvolduckpercentGreaterThanMaxValue) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"primvolduckpercent\": 101}"), response)); +} + +/** + * @name : SetEmptyPrimvolduckpercent + * @brief : Set primvolduckpercent as empty and check whether it return error + * + * @param[in] : Set in primvolduckpercent + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetEmptyPrimvolduckpercent) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"primvolduckpercent\": \"\"}"), response)); +} + +/** + * @name : SetEmptySpeechRate + * @brief : Set speechrate as empty and check whether it return error + * + * @param[in] : Set "" in speechrate + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptySpeechRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"speechrate\": \"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t speechRatePos = response.find("\"speechrate\""); + + if (speechRatePos != string::npos) { + size_t speechRatePosStart = response.find(':', speechRatePos ) + 1; + size_t speechRatePosEnd = response.find(',', speechRatePos ); + std::string speechRateSubstring = response.substr(speechRatePosStart ,speechRatePosEnd - speechRatePosStart); + EXPECT_EQ(speechRateSubstring ,"\"medium\""); + } else { + EXPECT_TRUE(false) << "Error: 'speechrate' not found in the response."; + } +} + +/** + * @name : SetWhiteSpaceSpeechRate + * @brief : Set speechrate as " " and check whether it return error + * + * @param[in] : Set " " in speechrate + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetWhiteSpaceAsSpeechRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"speechrate\": \" \"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t speechRatePos = response.find("\"speechrate\""); + + if (speechRatePos != string::npos) { + size_t speechRatePosStart = response.find(':', speechRatePos ) + 1; + size_t speechRatePosEnd = response.find(',', speechRatePos ); + std::string speechRateSubstring = response.substr(speechRatePosStart ,speechRatePosEnd - speechRatePosStart); + EXPECT_EQ(speechRateSubstring ,"\"medium\""); + } else { + EXPECT_TRUE(false) << "Error: 'speechrate' not found in the response."; + } +} + +/** + * @name : SetNumberAsSpeechRate + * @brief : Set speechrate as Number and check whether it return error + * + * @param[in] : Set "" in speechrate + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetNumberAsSpeechRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"speechrate\": 01}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t speechRatePos = response.find("\"speechrate\""); + + if (speechRatePos != string::npos) { + size_t speechRatePosStart = response.find(':', speechRatePos ) + 1; + size_t speechRatePosEnd = response.find(',', speechRatePos ); + std::string speechRateSubstring = response.substr(speechRatePosStart ,speechRatePosEnd - speechRatePosStart); + EXPECT_EQ(speechRateSubstring ,"\"medium\""); + } else { + EXPECT_TRUE(false) << "Error: 'speechrate' not found in the response."; + } +} + +/** + * @name : SetNullSpeechRate + * @brief : Set speechrate as NULL and check whether it return error + * + * @param[in] : Set NULL speechrate + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetNullSpeechRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"speechrate\": null}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t speechRatePos = response.find("\"speechrate\""); + + if (speechRatePos != string::npos) { + size_t speechRatePosStart = response.find(':', speechRatePos ) + 1; + size_t speechRatePosEnd = response.find(',', speechRatePos ); + std::string speechRateSubstring = response.substr(speechRatePosStart ,speechRatePosEnd - speechRatePosStart); + EXPECT_EQ(speechRateSubstring ,"\"medium\""); + } else { + EXPECT_TRUE(false) << "Error: 'speechrate' not found in the response."; + } +} + +/** + * @name : SetInvalidSpeechRate + * @brief : Set speechrate as Invalid It should be one of the following [slow,medium,fast,faster] + * + * @param[in] : Set invalid speechrate + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetInvalidSpeechRate) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"speechrate\": \"invalid\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t speechRatePos = response.find("\"speechrate\""); + + if (speechRatePos != string::npos) { + size_t speechRatePosStart = response.find(':', speechRatePos ) + 1; + size_t speechRatePosEnd = response.find(',', speechRatePos ); + std::string speechRateSubstring = response.substr(speechRatePosStart ,speechRatePosEnd - speechRatePosStart); + EXPECT_EQ(speechRateSubstring ,"\"medium\""); + } else { + EXPECT_TRUE(false) << "Error: 'speechrate' not found in the response."; + } +} + +/** + * @name : SetEmptyLanguage + * @brief : Set language as empty and check whether it return error + * + * @param[in] : Set "" in language + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptyLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"language\": \"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t languagePos = response.find("\"language\""); + + if (languagePos != string::npos) { + size_t languagePosStart = response.find(':', languagePos ) + 1; + size_t languagePosEnd = response.find(',', languagePos ); + std::string languageSubstring = response.substr(languagePosStart ,languagePosEnd - languagePosStart); + EXPECT_EQ(languageSubstring ,"\"en-US\""); + } else { + EXPECT_TRUE(false) << "Error: 'language' not found in the response."; + } +} + +/** + * @name : SetWhiteSpaceLanguage + * @brief : Set language as " " and check whether it return error + * + * @param[in] : Set " " in language + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetWhiteSpaceAsLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"language\": \" \"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t languagePos = response.find("\"language\""); + + if (languagePos != string::npos) { + size_t languagePosStart = response.find(':', languagePos ) + 1; + size_t languagePosEnd = response.find(',', languagePos ); + std::string languageSubstring = response.substr(languagePosStart ,languagePosEnd - languagePosStart); + EXPECT_EQ(languageSubstring ,"\"en-US\""); + } else { + EXPECT_TRUE(false) << "Error: 'language' not found in the response."; + } +} + +/** + * @name : SetNumberAsLanguage + * @brief : Set language as Number and check whether it return error + * + * @param[in] : Set "" in language + * @expected : ERRERROR_GENERALOR_NONE + */ + +TEST_F(TTSInitializedTest, SetNumberAsLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"language\": 01}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t languagePos = response.find("\"language\""); + + if (languagePos != string::npos) { + size_t languagePosStart = response.find(':', languagePos ) + 1; + size_t languagePosEnd = response.find(',', languagePos ); + std::string languageSubstring = response.substr(languagePosStart ,languagePosEnd - languagePosStart); + EXPECT_EQ(languageSubstring ,"\"en-US\""); + } else { + EXPECT_TRUE(false) << "Error: 'language' not found in the response."; + } +} + +/** + * @name : SetNullLanguage + * @brief : Set language as NULL and check whether it return error + * + * @param[in] : Set NULL language + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetNullLanguage) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"language\": NULL}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t languagePos = response.find("\"language\""); + + if (languagePos != string::npos) { + size_t languagePosStart = response.find(':', languagePos ) + 1; + size_t languagePosEnd = response.find(',', languagePos ); + std::string languageSubstring = response.substr(languagePosStart ,languagePosEnd - languagePosStart); + EXPECT_EQ(languageSubstring ,"\"en-US\""); + } else { + EXPECT_TRUE(false) << "Error: 'language' not found in the response."; + } +} + +/** + * @name : SetEmptyVoice + * @brief : Set voice as empty and check whether it return error + * + * @param[in] : Set "" in voice + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetEmptyVoice) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"voice\": \"\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t voicePos = response.find("\"voice\""); + + if (voicePos != string::npos) { + size_t voicePosStart = response.find(':', voicePos ) + 1; + size_t voicePosEnd = response.find(',', voicePos ); + std::string voiceSubstring = response.substr(voicePosStart ,voicePosEnd - voicePosStart ); + EXPECT_EQ(voiceSubstring ,"\"carol\""); + } else { + EXPECT_TRUE(false) << "Error: 'voice' not found in the response."; + } +} + +/** + * @name : SetWhiteSpaceVoice + * @brief : Set voice as " " and check whether it return error + * + * @param[in] : Set " " in voice + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetWhiteSpaceAsVoice) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"voice\": \" \"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t voicePos = response.find("\"voice\""); + + if (voicePos != string::npos) { + size_t voicePosStart = response.find(':', voicePos ) + 1; + size_t voicePosEnd = response.find(',', voicePos ); + std::string voiceSubstring = response.substr(voicePosStart ,voicePosEnd - voicePosStart ); + EXPECT_EQ(voiceSubstring ,"\"carol\""); + } else { + EXPECT_TRUE(false) << "Error: 'voice' not found in the response."; + } +} + +/** + * @name : SetNumberAsVoice + * @brief : Set voice as Number and check whether it return error + * + * @param[in] : Set "" in voice + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetNumberAsVoice) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"voice\": 01}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t voicePos = response.find("\"voice\""); + + if (voicePos != string::npos) { + size_t voicePosStart = response.find(':', voicePos ) + 1; + size_t voicePosEnd = response.find(',', voicePos ); + std::string voiceSubstring = response.substr(voicePosStart ,voicePosEnd - voicePosStart ); + EXPECT_EQ(voiceSubstring ,"\"carol\""); + } else { + EXPECT_TRUE(false) << "Error: 'voice' not found in the response."; + } +} + +/** + * @name : SetNullVoice + * @brief : Set voice as NULL and check whether it return error + * + * @param[in] : Set NULL voice + * @expected : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetNullVoice) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setttsconfiguration"), _T("{\"voice\": null}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getttsconfiguration"), _T(""), response)); + size_t voicePos = response.find("\"voice\""); + + if (voicePos != string::npos) { + size_t voicePosStart = response.find(':', voicePos ) + 1; + size_t voicePosEnd = response.find(',', voicePos ); + std::string voiceSubstring = response.substr(voicePosStart ,voicePosEnd - voicePosStart ); + EXPECT_EQ(voiceSubstring ,"\"carol\""); + } else { + EXPECT_TRUE(false) << "Error: 'voice' not found in the response."; + } +} +#if 0 +/** + * @name : SetAuthInfoTypeEmpty + * @brief : Set AuthInfo type Empty + * + * @param[in] : Set type as invalid + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetAuthInfoTypeEmpty) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), + _T("{\"authinfo\": {\"type\":\"\",\"value\":\"speak text\"}}"), response)); +} + +/** + * @name : SetAuthInfoTypeWhiteSpace + * @brief : Set AuthInfo type " " + * + * @param[in] : Set type as " " + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetAuthInfoTypeWhiteSpace) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), + _T("{\"authinfo\": {\"type\":\" \",\"value\":\"speak text\"}}"), response)); +} + +/** + * @name : SetAuthInfoTypeNull + * @brief : Set AuthInfo type NULL + * + * @param[in] : Set type as NULL + * @expected : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetAuthInfoTypeNull) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setttsconfiguration"), + _T("{\"authinfo\": {\"type\":null,\"value\":\"speak text\"}}"), response)); +} +#endif + +/******************************************************************************************************************* + * Test function for SetACL + * resume : + * Gives speak access for applications + * + * @return Response object contains bool success + * Use case coverage: + * @Success : 1 + * @Failure : 8 + ********************************************************************************************************************/ + /** + * @name : SetACL + * @brief : Gives speak access for applications + * + * @param[in] : method of tts and app name + * @return : ERROR_NONE + */ + + TEST_F(TTSInitializedTest,SetACL) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"speak\",\"apps\":[\"WebAPP1\"]}]}"), + response + )); + + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpoint\":\"http://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"ttsendpointsecured\":\"https://example-tts-dummy.net/tts/v1/cdn/location?\"}" + ), + response + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("speak"), + _T("{\"text\": \"speech_123\",\"callsign\":\"WebAPP1\"}"), response)); + sleep(1); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"speechid\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"TTS_Status\":0"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + + /** + * @name : SetACLInvalidAccess + * @brief : Gives speak access for applications + * + * @param[in] : method of tts and app name + * @return : ERROR_NONE + */ + +TEST_F(TTSInitializedTest, SetACLInvalidAccess) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"speak\",\"apps\":\"WebAPP1\"}]}"), + response + )); + + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke( + connection, + _T("setttsconfiguration"), + _T("{\"language\": \"en-US\",\"voice\": \"carol\"," + "\"ttsendpoint\":\"http://example-tts-dummy.net/tts/v1/cdn/location?\"," + "\"ttsendpointsecured\":\"https://example-tts-dummy.net/tts/v1/cdn/location?\"}" + ), + response + )); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("speak"), + _T("{\"text\": \"speech_123\",\"callsign\":\"WebAPP2\"}"), + response + )); + + EXPECT_EQ(response, _T("")); +} + +/** + * @name : SetACLInvalidMethod + * @brief : Calling speak method with invalid method other than speak + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLInvalidMethod) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"invalid\",\"apps\":\"WebAPP1\"}]}"), + response + )); +} + +/** + * @name : SetACLEmptyMethod + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLEmptyMethod) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"\",\"apps\":\"WebAPP1\"}]}"), + response + )); +} + +/** + * @name : SetACLWhiteSpaceMethod + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLWhitespaceMethod) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\" \",\"apps\":\"WebAPP1\"}]}"), + response + )); +} + +/** + * @name : SetACLNullMethod + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLNullMethod) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":NULL,\"apps\":\"WebAPP1\"}]}"), + response + )); +} + +/*** + * @name : SetACLEmptyApp + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLEmptyApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"speak\",\"apps\":\"\"}]}"), + response + )); +} + +/** + * @name : SetACLWhiteSpaceApp + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLWhitespaceApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"speak\",\"apps\":\" \"}]}"), + response + )); +} + +/** + * @name : SetACLNullApp + * @brief : Calling speak method with empty method + * + * @param[in] : method of tts and app name + * @return : ERROR_GENERAL + */ + +TEST_F(TTSInitializedTest, SetACLNullApp) { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke( + connection, + _T("setACL"), + _T("{\"accesslist\": [{\"method\":\"speak\",\"apps\":NULL}]}"), + response + )); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_Timer.cpp b/NetworkManager/Tests/L1Tests/tests/test_Timer.cpp new file mode 100755 index 0000000000..85d40322a3 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Timer.cpp @@ -0,0 +1,228 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" + +#include "Timer.h" + +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +class TimerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + TimerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~TimerTest() = default; +}; + +class TimerInitializedTest : public TimerTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + + TimerInitializedTest() + : TimerTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~TimerInitializedTest() override + { + plugin->Deinitialize(nullptr); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + } +}; + +class TimerInitializedEventTest : public TimerInitializedTest { +protected: + ServiceMock service; + Core::JSONRPC::Message message; + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + TimerInitializedEventTest() + : TimerInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~TimerInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(TimerTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startTimer"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("suspend"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resume"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTimerStatus"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getTimers"))); +} + +TEST_F(TimerTest, paramsMissing) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startTimer"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("cancel"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("suspend"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getTimerStatus"), _T("{}"), response)); +} + +TEST_F(TimerTest, jsonRpc) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startTimer"), _T("{\"interval\":10,\"repeatInterval\":15,\"remindBefore\":5}"), response)); + EXPECT_EQ(response, _T("{\"timerId\":0,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimerStatus"), _T("{\"timerId\":0}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"state\":\"RUNNING\"," + "\"mode\":\"GENERIC\"," + "\"timeRemaining\":\"[0-9]+.[0-9]+\"," + "\"repeatInterval\":\"15.000\"," + "\"remindBefore\":\"5.000\"," + "\"success\":true" + "\\}"))); + //Get timer status - Negative test case - get status of a wrong timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getTimerStatus"), _T("{\"timerId\":10}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getTimers"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex(_T("\\{" + "\"timers\":\\[" + "\\{" + "\"timerId\":0," + "\"state\":\"RUNNING\"," + "\"mode\":\"GENERIC\"," + "\"timeRemaining\":\"[0-9]+.[0-9]+\"," + "\"repeatInterval\":\"15.000\"," + "\"remindBefore\":\"5.000\"" + "\\}" + "\\]," + "\"success\":true" + "\\}"))); + //Suspend the timer + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("suspend"), _T("{\"timerId\":0}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + //Suspend the timer - Negative test case - Suspend an already suspended timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("suspend"), _T("{\"timerId\":0}"), response)); + //Suspend the timer - Negative test case - Suspend a wrong timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("suspend"), _T("{\"timerId\":10}"), response)); + + //Resume the timer + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resume"), _T("{\"timerId\":0}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + //Resume the timer - Negative test case - Resume an already resumed timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{\"timerId\":0}"), response)); + //Resume the timer - Negative test case - Resume a wrong timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("resume"), _T("{\"timerId\":10}"), response)); + + //Cancel the timer + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("cancel"), _T("{\"timerId\":0}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + //Cancel the timer - Negative test case - Cancel an already cancelled timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("cancel"), _T("{\"timerId\":0}"), response)); + //Cancel the timer - Negative test case - Cancel a wrong timer + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("cancel"), _T("{\"timerId\":10}"), response)); +} + +/** + * Segmentation fault without valgrind + */ +TEST_F(TimerInitializedEventTest, DISABLED_timerExpiry) +{ + Core::Event timerExpiryReminder(false, true); + Core::Event timerExpired(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + // called by Timer::sendTimerExpiryReminder + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.Timer.timerExpiryReminder\"," + "\"params\":{\"timerId\":0," + "\"mode\":\"WAKE\"," + "\"timeRemaining\":0}" + "}"))); + + timerExpiryReminder.SetEvent(); + + return Core::ERROR_NONE; + })) + // called by Timer::sendTimerExpired + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.Timer.timerExpired\"," + "\"params\":{\"timerId\":0," + "\"mode\":\"WAKE\"," + "\"status\":0}" + "}"))); + + timerExpired.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("timerExpiryReminder"), _T("org.rdk.Timer"), message); + handler.Subscribe(0, _T("timerExpired"), _T("org.rdk.Timer"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startTimer"), _T("{\"interval\":0.2,\"mode\":\"WAKE\",\"remindBefore\":0.1}"), response)); + EXPECT_EQ(response, _T("{\"timerId\":0,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, timerExpiryReminder.Lock()); + EXPECT_EQ(Core::ERROR_NONE, timerExpired.Lock()); + + handler.Unsubscribe(0, _T("timerExpiryReminder"), _T("org.rdk.Timer"), message); + handler.Unsubscribe(0, _T("timerExpired"), _T("org.rdk.Timer"), message); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_TraceControlJsonRpc.cpp b/NetworkManager/Tests/L1Tests/tests/test_TraceControlJsonRpc.cpp new file mode 100755 index 0000000000..53b07a71f2 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_TraceControlJsonRpc.cpp @@ -0,0 +1,158 @@ +#include + +#include "TraceControl.h" + +#include "COMLinkMock.h" +#include "ServiceMock.h" +#include "WrapsMock.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +namespace { +const string callSign = _T("TraceControl"); +const string webPrefix = _T("/Service/TraceControl"); +const string volatilePath = _T("/tmp/"); +} + +class TraceControlJsonRpcTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + WrapsImplMock *p_wrapsImplMock = nullptr ; + string response; + + TraceControlJsonRpcTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + Trace::TraceUnit::Instance().Open(volatilePath); + p_wrapsImplMock = new testing::NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + } + + virtual ~TraceControlJsonRpcTest() + { + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + plugin.Release(); + Trace::TraceUnit::Instance().Close(); + } +}; + +class TraceControlJsonRpcInitializedTest : public TraceControlJsonRpcTest { +protected: + ServiceMock service; + COMLinkMock comLinkMock; + + TraceControlJsonRpcInitializedTest() + : TraceControlJsonRpcTest() + { + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{\n" + "\"console\":false,\n" + "\"syslog\":true,\n" + "\"abbreviated\":false\n" + "}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(volatilePath)); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~TraceControlJsonRpcInitializedTest() override + { + plugin->Deinitialize(&service); + } +}; + +TEST_F(TraceControlJsonRpcTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("set"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("status"))); +} + +/** + * fails without valgrind + * 2022-12-22T12:54:08.4645286Z Actual function call count doesn't match EXPECT_CALL(wrapsImplMock, syslog(::testing::_, ::testing::_, ::testing::_))... +2022-12-22T12:54:08.4645396Z Expected: to be called once +2022-12-22T12:54:08.4645592Z Actual: never called - unsatisfied and active +2022-12-22T12:54:08.4645786Z [ FAILED ] TraceControlJsonRpcInitializedTest.jsonRpc (4 ms) + */ +TEST_F(TraceControlJsonRpcInitializedTest, DISABLED_jsonRpc) +{ + EXPECT_CALL(*p_wrapsImplMock, syslog(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("status"), _T("{}"), response)); + + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"console\":false," + "\"settings\":" + "\\[(\\{\"module\":\"[^\"]+\",\"category\":\"[^\"]+\",\"state\":\"(disabled|enabled|tristated)\"\\},{0,}){0,}\\]" + "\\}")); + + //Set Plugin_TraceControl:Information:enabled + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("set"), _T("{\"module\":\"Plugin_TraceControl\",\"category\":\"Information\",\"state\":\"enabled\"}"), response)); + + //Get status Plugin_TraceControl:Information:enabled + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("status"), _T("{\"module\":\"Plugin_TraceControl\",\"category\":\"Information\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"console\":false," + "\"settings\":" + "\\[\\{\"module\":\"Plugin_TraceControl\",\"category\":\"Information\",\"state\":\"enabled\"\\}\\]" + "\\}")); + + //Set Plugin_TraceControl:All:disabled + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("set"), _T("{\"module\":\"Plugin_TraceControl\",\"state\":\"disabled\"}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("status"), _T("{\"module\":\"Plugin_TraceControl\"}"), response)); + //Check all categories are set to disabled + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"console\":false," + "\"settings\":" + "\\[(\\{\"module\":\"Plugin_TraceControl\",\"category\":\"[^\"]+\",\"state\":\"disabled\"\\},{0,}){0,}\\]" + "\\}")); + + //Set Plugin_TraceControl:All:enabled + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("set"), _T("{\"module\":\"Plugin_TraceControl\",\"state\":\"enabled\"}"), response)); + + //Log some trace data and verify the output format + TRACE(Trace::Information, (_T("Test1"))); +} + +/** + * fails without valgrind + * 2022-12-22T12:54:08.4661163Z Actual function call count doesn't match EXPECT_CALL(wrapsImplMock, syslog(::testing::_, ::testing::_, ::testing::_))... +2022-12-22T12:54:08.4661270Z Expected: to be called once +2022-12-22T12:54:08.4661458Z Actual: never called - unsatisfied and active +2022-12-22T12:54:08.4661670Z [ FAILED ] TraceControlJsonRpcInitializedTest.syslogFormat (5 ms) + */ +TEST_F(TraceControlJsonRpcInitializedTest, DISABLED_syslogFormat) +{ + EXPECT_CALL(*p_wrapsImplMock, syslog(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [&](int pri, const char* fmt, va_list args) -> void { + EXPECT_EQ(LOG_NOTICE, pri); + va_list args2; + va_copy(args2, args); + char strFmt[256]; + vsnprintf(strFmt, sizeof(strFmt), fmt, args2); + EXPECT_THAT(std::string(strFmt), ::testing::MatchesRegex("\\[.+\\]:\\[test_TraceControlJsonRpc.cpp:[0-9]+\\] Information: Test2.+")); + va_end(args2); + })); + + //Log some trace data and verify the output format + TRACE(Trace::Information, (_T("Test2"))); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_TraceControlWeb.cpp b/NetworkManager/Tests/L1Tests/tests/test_TraceControlWeb.cpp new file mode 100755 index 0000000000..359d450ad3 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_TraceControlWeb.cpp @@ -0,0 +1,183 @@ +#include + +#include "TraceControl.h" + +#include "COMLinkMock.h" +#include "FactoriesImplementation.h" +#include "ServiceMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +namespace { +const string callSign = _T("TraceControl"); +const string webPrefix = _T("/Service/TraceControl"); +const string volatilePath = _T("/tmp/"); +} + +class TraceControlWebTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + PluginHost::IWeb* interface; + + TraceControlWebTest() + : plugin(Core::ProxyType::Create()) + { + interface = static_cast(plugin->QueryInterface(PluginHost::IWeb::ID)); + Trace::TraceUnit::Instance().Open(volatilePath); + } + + virtual ~TraceControlWebTest() + { + interface->Release(); + plugin.Release(); + Trace::TraceUnit::Instance().Close(); + } +}; + +class TraceControlWebInitializedTest : public TraceControlWebTest { +protected: + NiceMock factoriesImplementation; + NiceMock service; + NiceMock comLinkMock; + + TraceControlWebInitializedTest() + : TraceControlWebTest() + { + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return("{}")); + ON_CALL(service, WebPrefix()) + .WillByDefault(::testing::Return(webPrefix)); + ON_CALL(service, VolatilePath()) + .WillByDefault(::testing::Return(volatilePath)); + ON_CALL(service, Callsign()) + .WillByDefault(::testing::Return(callSign)); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Return(&comLinkMock)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~TraceControlWebInitializedTest() override + { + plugin->Deinitialize(&service); + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(TraceControlWebInitializedTest, httpGetPut) +{ + //HTTP_GET - Get status for all modules + Web::Request request; + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix; + auto httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + EXPECT_EQ(httpResponse->ContentType, Web::MIMETypes::MIME_JSON); + //Validate the status for all modules. The state should be one of disabled/enabled/tristated + auto body = httpResponse->Body>(); + ASSERT_TRUE(body.IsValid()); + string bodyStr; + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"settings\":" + "\\[(\\{\"module\":\"[^\"]+\",\"category\":\"[^\"]+\",\"state\":\"(disabled|enabled|tristated)\"\\},{0,}){0,}\\]" + "\\}")); + + //HTTP_PUT - Set all module state to "disabled" + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/off"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + EXPECT_EQ(httpResponse->ContentType, Web::MIMETypes::MIME_JSON); + //Validate the status for all modules. The state should be disabled + body = httpResponse->Body>(); + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::MatchesRegex("\\{" + "\"settings\":" + "\\[(\\{\"module\":\"[^\"]+\",\"category\":\"[^\"]+\",\"state\":\"disabled\"\\},{0,}){0,}\\]" + "\\}")); + + //HTTP_PUT - Set Plugin_TraceControl module state to "enabled" + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/Plugin_TraceControl/on"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + EXPECT_EQ(httpResponse->ContentType, Web::MIMETypes::MIME_JSON); + //Validate the status for Plugin_TraceControl module. The state should be enabled + //For the rest of the modules the state should be "disabled" + body = httpResponse->Body>(); + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::Not(::testing::ContainsRegex("\\{\"module\":\"Plugin_TraceControl\",\"category\":\"[^\"]+\",\"state\":\"disabled\"\\}"))); + + //HTTP_PUT - Set Plugin_TraceControl module, Information category state to "disabled" + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/Plugin_TraceControl/Information/off"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + request.Verb = Web::Request::HTTP_GET; + request.Path = webPrefix; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_OK); + EXPECT_EQ(httpResponse->Message, "OK"); + EXPECT_EQ(httpResponse->ContentType, Web::MIMETypes::MIME_JSON); + //Validate the status for Plugin_TraceControl module, Information category. The state should be disabled + //For the rest of the modules the state should be "disabled" + body = httpResponse->Body>(); + body->ToString(bodyStr); + EXPECT_THAT(bodyStr, ::testing::HasSubstr("{\"module\":\"Plugin_TraceControl\",\"category\":\"Information\",\"state\":\"disabled\"}")); +} + +TEST_F(TraceControlWebInitializedTest, httpGetPut_negative) +{ + //HTTP_PUT - No data + Web::Request request; + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix; + auto httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_BAD_REQUEST); + + //HTTP_PUT - Module - No data + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/Test"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_BAD_REQUEST); + + //HTTP_PUT - Module - Category - No data + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/Test_mod/Test_Cat"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_BAD_REQUEST); + + //HTTP_PUT - Module - Category - Wrong data + request.Verb = Web::Request::HTTP_PUT; + request.Path = webPrefix + "/Test_mod/Test_cat/Test_on"; + httpResponse = interface->Process(request); + ASSERT_TRUE(httpResponse.IsValid()); + EXPECT_EQ(httpResponse->ErrorCode, Web::STATUS_BAD_REQUEST); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_UsbAccess.cpp b/NetworkManager/Tests/L1Tests/tests/test_UsbAccess.cpp new file mode 100755 index 0000000000..8dbe73ab3e --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_UsbAccess.cpp @@ -0,0 +1,2306 @@ +#include +#include +#include +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "UsbAccess.h" + +#include // Added for file creation +#include +#include +#include +#include + +#include "UdevMock.h" +#include "WrapsMock.h" +#include "secure_wrappermock.h" + +using ::testing::NiceMock; +using namespace WPEFramework; + +class UsbAccessTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + Core::JSONRPC::Message message; + string response; + UdevImplMock *p_udevImplMock = nullptr ; + WrapsImplMock *p_wrapsImplMock = nullptr ; + IarmBusImplMock *p_iarmBusImplMock = nullptr; + + UsbAccessTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + /*In order to ensure consistent behavior across all test APIs, + the "/etc/device.properties" file is opened only once*/ + std::ofstream file("/etc/device.properties"); + file << "MODEL_NUM=HSTP11MWR"; + file.close(); + p_wrapsImplMock = new testing::NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + p_udevImplMock = new testing::NiceMock ; + Udev::setImpl(p_udevImplMock); + + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + } + virtual ~UsbAccessTest() override + { + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + Udev::setImpl(nullptr); + if (p_udevImplMock != nullptr) + { + delete p_udevImplMock; + p_udevImplMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class UsbAccessEventTest : public UsbAccessTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + UsbAccessEventTest() + : UsbAccessTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~UsbAccessEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +class UsbAccessEventIarmTest : public UsbAccessEventTest { +protected: + IARM_EventHandler_t eventHandler; + + UsbAccessEventIarmTest() + : UsbAccessEventTest() + { + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_SYSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_SYSMGR_EVENT_USB_MOUNT_CHANGED)) { + eventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + + virtual ~UsbAccessEventIarmTest() override + { + plugin->Deinitialize(&service); + } + + virtual void SetUp() + { + ASSERT_TRUE(eventHandler != nullptr); + } +}; + +TEST_F(UsbAccessTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFileList"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("createLink"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearLink"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getLinks"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getAvailableFirmwareFiles"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getMounted"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("updateFirmware"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("ArchiveLogs"))); +} +extern "C" FILE* __real_popen(const char* command, const char* type); + +/******************************************************************************************************************* +* Test function for UpdateFirmware +* UpdateFirmware : +* Updates the firmware using the specified file retrieved from the getAvailableFirmwareFiles method. +* +* @return Whether the request succeeded or failed. +********************************************************************************************************************/ + +/** +* @breif : UpdateFirmware when path is found +* Check if path is matching with the files retrived from the getAvailableFirmwareFiles method. + +* @param[in] : path to file retrieved from getAvailableFirmwareFiles method. +* @return : {\"success\":true} for a vaild path and filename or error code : ERROR_GENERAL for invaild path and file names +**/ + +TEST_F(UsbAccessTest, UpdateFirmware) +{ + EXPECT_CALL(*p_wrapsImplMock, v_secure_system(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command, va_list args) { + /*Since we have added the "etc/device.properties" file in the test fixture, it can be opened, + and the model number is now available. Therefore, we need to change the input parameter for this test API as well as the corresponding string in the system command to match the model number.*/ + va_list args2; + va_copy(args2,args); + char strFmt[256]; + vsnprintf(strFmt, sizeof(strFmt), command, args2); + EXPECT_EQ(string(strFmt), string(_T("/lib/rdk/userInitiatedFWDnld.sh usb '/tmp/reboot/' 'HSTP11MWR.bin' 0 >> /opt/logs/swupdate.log &"))); + return 0; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/tmp\';reboot;/my.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/tm!p/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/$tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/@tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/#tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/%tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/*tmp/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/tmp:/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/tmp;/reboot/HSTP11MWR.bin\"}"), response)); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("updateFirmware"), _T("{\"fileName\":\"/&tmp/reboot/HSTP11MWR.bin\"}"), response)); +} + +/******************************************************************************************************************* + * Test function for :getFileList + * getFileList : + * Gets a list of files and folders from the specified directory or path. + * + * @return Response object containing the file list + * Use case coverage: + * @Success :3 + * @Failure :5 + ********************************************************************************************************************/ + +/** + * @brief : getFileList when path parameter is missing in the request parameter + * Check if path parameter is missing from the parameters JSON object; + * then getFileList shall be failed and return Erorr code: ERROR_BAD_REQUEST + * + * @param[in] : Invalid parameters without the "path" label + * @return : error code: ERROR_BAD_REQUEST + */ +TEST_F(UsbAccessTest, getFileListFailure_BadRequest) +{ + EXPECT_EQ(Core::ERROR_BAD_REQUEST, handler.Invoke(connection, _T("getFileList"), _T("{\"MissingPathParam\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : getFileList when the device list is empty; + * Check if the device list is empty after retrieving mounted paths; + * then getFileList shall be failed + * + * @param[in] : Valid parameters with the "path" label + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getFileListFailure_whenDeviceListEmpty) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(nullptr)); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/media/sda1/logs/PreviousLogs"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : getFileList when setmntent returns nullptr + * Check if setmntent fails to open the mounts file + * then getFileList shall be failed + * + * @param[in] : Valid parameters with the "path" label + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getFileListFailure_when_setmntentNull) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, setmntent(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/proc/mounts"))); + return nullptr; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : getFileList when getmntent returns nullptr + * Check if getmntent fails to retrieve mount entries + * then getFileList shall be failed + * + * @param[in] : Valid parameters with the "path" label + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getFileListFailure_when_getmntentNull) +{ + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + return static_cast(NULL); + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : getFileList when device node is not found + * Check if the device node is not found in the devnodes list + * then getFileList shall be failed + * + * @param[in] : Valid parameters with the "path" label + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getFileListFailure_when_devNodNotFound) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + //To simulate the behavior where the device node is not found in the devnodes list; + //set a different name for entry1.mnt_fsname + entry1.mnt_fsname = const_cast("/dev/sda2"); + entry1.mnt_dir = const_cast("/run/media/sda1/logs/PreviousLogs"); + + entry2.mnt_fsname = const_cast("/dev/sdb1"); + entry2.mnt_dir = const_cast("/run/media/sdb1/logs/"); + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : getFileList when absolute path is found + * Check if an absolute path matching the path parameter is found in the mounted paths + * then getFileList shall be succeeded and retrieves the list of files from the absolute path. + * + * @param[in] : Valid parameters with the "path" label + * @return : response object containing the list of retrieved files and success status as true + */ +TEST_F(UsbAccessTest, getFileListSuccess_whenAbsPathFound) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1/logs/"); // Set the value for mnt_dir + + entry2.mnt_fsname = const_cast("/dev/sdb1"); // Set the value for mnt_fsname + entry2.mnt_dir = const_cast("/run/media/sdb1/logs"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); + bool res1 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\\/PreviousLogs\",\"contents\":[{\"name\":\"logFile.txt\",\"t\":\"f\"},{\"name\":\"..\",\"t\":\"d\"},{\"name\":\".\",\"t\":\"d\"}],\"success\":true}")) == 0); + bool res2 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\\/PreviousLogs\",\"contents\":[{\"name\":\".\",\"t\":\"d\"},{\"name\":\"..\",\"t\":\"d\"},{\"name\":\"logFile.txt\",\"t\":\"f\"}],\"success\":true}")) == 0); + EXPECT_EQ(res1 || res2, true); +} + +/** + * @brief : getFileList when no path given in path param + * Check if no path is given in path param + * then construct an absolute path [will be the first retrieved mount path] + * and getFileList shall be succeeded and retrieves the list of files from the constructed + * absolute path. + * + * @param[in] : Empty string with the "path" label + * @return : response object containing the list of retrieved files and success status as true + */ +TEST_F(UsbAccessTest, getFileListSuccess_withoutPath) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1/logs"); // Set the value for mnt_dir + + entry2.mnt_fsname = const_cast("/dev/sdb1"); // Set the value for mnt_fsname + entry2.mnt_dir = const_cast("/run/media/sdb1/logs/"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":}"), response)); + bool res1 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\",\"contents\":[{\"name\":\"..\",\"t\":\"d\"},{\"name\":\"PreviousLogs\",\"t\":\"d\"},{\"name\":\".\",\"t\":\"d\"}],\"success\":true}")) == 0); + bool res2 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\",\"contents\":[{\"name\":\".\",\"t\":\"d\"},{\"name\":\"..\",\"t\":\"d\"},{\"name\":\"PreviousLogs\",\"t\":\"d\"}],\"success\":true}")) == 0); + EXPECT_EQ(res1 || res2, true); +} + +/** + * @brief : getFileList when absolute path is created from a relative path param + * Check if an absolute path matching the path parameter is NOT found in the mounted paths + * then construct an absolute path [by combining the first mounted path with the pathParam] + * assumig that the pathParam is a relative path within the USB device. + * and getFileList shall be succeeded and retrieves the list of files from the constructed + * absolute path. + * + * @param[in] : Valid parameters with the "path" label + * @return : response object containing the list of retrieved files and success status as true + */ +TEST_F(UsbAccessTest, getFileListSuccess_withRelativePathParam) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + //To simulate the behaviour where the absPath is not match with the mount path, + //set a differnt mount path here + entry1.mnt_dir = const_cast("/run/media"); + + entry2.mnt_fsname = const_cast("/dev/sdb1"); + entry2.mnt_dir = const_cast("/run/media/sdb1/logs/"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"sda1/logs/PreviousLogs\"}"), response)); + bool res1 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\\/PreviousLogs\",\"contents\":[{\"name\":\"logFile.txt\",\"t\":\"f\"},{\"name\":\"..\",\"t\":\"d\"},{\"name\":\".\",\"t\":\"d\"}],\"success\":true}")) == 0); + bool res2 = (response.compare(string("{\"path\":\"\\/run\\/media\\/sda1\\/logs\\/PreviousLogs\",\"contents\":[{\"name\":\".\",\"t\":\"d\"},{\"name\":\"..\",\"t\":\"d\"},{\"name\":\"logFile.txt\",\"t\":\"f\"}],\"success\":true}")) == 0); + EXPECT_EQ(res1 || res2, true); +} +/** + * @brief : getFileList when absolute path is found + * Check if an absolute path matching the path parameter is found in the mounted paths + * then getFileList shall be succeeded and retrieves the list of files from the absolute path which dont have any special characters. + + * @param[in] : Valid parameters with the "path" label + * @return : response object containing the list of retrieved files which dont have any special characters and success status as true + */ +TEST_F(UsbAccessTest, getFileListSuccess_withSpecialCharacters) +{ + std::string directory = "/run/media/sda1/logs/PreviousLogs/"; + std::vector fileNames = {"file1.txt","!file.txt", "@file.txt", "$file.txt", "%file.txt", "*file.txt", "~file.txt", "&file.txt", "*file.txt", "+file.txt", "fi?le.txt", "file=.txt","fi^le.txt"}; + for (const auto& fileName : fileNames){ + std::string filePath = directory + fileName; + std::ofstream fileStream(filePath); + } + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1/logs/"); // Set the value for mnt_dir + + entry2.mnt_fsname = const_cast("/dev/sdb1"); // Set the value for mnt_fsname + entry2.mnt_dir = const_cast("/run/media/sdb1/logs"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFileList"), _T("{\"path\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); + EXPECT_THAT(response, ::testing::MatchesRegex("\\{" + "\"path\":\"\\\\/run\\\\/media\\\\/sda1\\\\/logs\\\\/PreviousLogs\"," + "\"contents\":" + "\\[(\\{\"name\":\"(.|..|file1.txt|logFile.txt)\",\"t\":\"(f|d)\"\\},{0,}){0,}\\]," + "\"success\":true" + "\\}")); + +for (const auto& fileName1 :fileNames) { + std::string filePaths = directory + fileName1; + std::remove(filePaths.c_str()); + } +} + /*Test cases for getFileList ends here*/ + +/******************************************************************************************************************* + * Test function for :getMounted + * getMounted : Returns a list of mounted USB devices. + * + * + * @return Response object containing the list of mounted USB devices + * Use case coverage: + * @Success :4 + * @Failure :1 + ********************************************************************************************************************/ + + +/** + * @brief : getMounted when setmntent returns nullptr + * Check if setmntent fails to open the currently mounted file system + * then getMounted shall be failed + * + * @param[in] : None + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getMountedFailure_when_setmntentNull) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, setmntent(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/proc/mounts"))); + return nullptr; + })); + + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getMounted"), _T("{}"), response)); +} + +/** + * @brief : getMounted when getmntent returns nullptr + * Check if getmntent fails to retrieve mount entries + * then getMounted shall be succeded and returns empty path list + * + * @param[in] : None + * @return : {\"mounted\":[],\"success\":true} + */ +TEST_F(UsbAccessTest, getMountedSuccess_when_getmntentNull) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + return static_cast(NULL); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMounted"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mounted\":[],\"success\":true}")); +} +/** + * @brief : getMounted when the device list is empty; + * Check if the device list is empty; + * then getMounted shall be succeded and returns empty path list + * + * @param[in] : None + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, getMountedSuccess_whenDeviceListEmpty) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(nullptr)); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/media/sda1/logs/PreviousLogs"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMounted"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mounted\":[],\"success\":true}")); +} +/** + * @brief : getMounted when device node is not found + * Check if the device node is not found in the devnodes list + * then getMounted shall be succeded and returns empty path list + * + * @param[in] : None + * @return : {\"mounted\":[],\"success\":true} + */ +TEST_F(UsbAccessTest, getMountedSuccess_when_devNodNotFound) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + //To simulate the behavior where the device node is not found in the devnodes list; + //set a different name for entry1.mnt_fsname + entry1.mnt_fsname = const_cast("/dev/sda2"); + entry1.mnt_dir = const_cast("/run/media/sda1/logs/PreviousLogs"); + + entry2.mnt_fsname = const_cast("/dev/sdb1"); + entry2.mnt_dir = const_cast("/run/media/sdb1/logs/"); + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMounted"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mounted\":[],\"success\":true}")); +} +/** + * @brief : getMounted when the device node of the mounted file system is found in the devnodes list + * Check if the device node of the mounted file system is found in the devnodes list + * then getMounted shall be succeeded and retrieves the the list of file paths + * where USB devices are mounted + * + * @param[in] : None + * @return : response object containing the USB mount point paths + */ +TEST_F(UsbAccessTest, getMountedSuccess_withUSBMountPath) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1/logs"); // Set the value for mnt_dir + + entry2.mnt_fsname = const_cast("/dev/sdb1"); // Set the value for mnt_fsname + entry2.mnt_dir = const_cast("/run/media/sdb1/logs/"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else if (callCount == 1) { + callCount++; + return &entry2; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getMounted"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"mounted\":[\"\\/run\\/media\\/sda1\\/logs\"],\"success\":true}")); +} +/*Test cases for getMounted ends here*/ + +/******************************************************************************************************************* +* Test function for :getAvailableFirmwareFiles +* getAvailableFirmwareFiles : +* Gets a list of firmware files on a device. +* +* @return list of firmware files and request succeeded. +* Use case coverage: +* @Failure :1 +* @Success :5 +********************************************************************************************************************/ + +/** +* @brief : getAvailableFirmwareFiles when setmntent returns nullptr, +* Check if setmntent fails to open the mounts file, +* then getAvailableFirmwareFiles shall be failed. +* +* @param[in] : NONE +* @return : {"availableFirmwareFiles": [],"success":false} +*/ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesFailed_whenSetmntentValueNull) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, setmntent(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/proc/mounts"))); + return nullptr; + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); +} + +/** +* @brief : getAvailableFirmwareFiles when getmntent returns nullptr, +* Check if getmntent fails to retrieve mount entries +* then getAvailableFirmwareFiles shall be succeded and returns empty path list. +* +* @param[in] : NONE +* @return : {"availableFirmwareFiles": [],"success":true} +*/ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesSuccess_when_getmntentNull) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + return static_cast(NULL); + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"availableFirmwareFiles\":[],\"success\":true}")); +} + +/** + * @brief : getAvailableFirmwareFiles when the device list is empty, + * Check if the device list is empty, + * then getAvailableFirmwareFiles shall be succeded and returns empty path list. + * + * @param[in] : NONE + * @return : {"availableFirmwareFiles": [],"success":true} + */ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesSuccess_whenDeviceListEmpty) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(nullptr)); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"availableFirmwareFiles\":[],\"success\":true}")); +} + + +/** + * @brief : getAvailableFirmwareFiles when device node is not found, + * Check if the device node is not found in the devnodes list, + * then getMounted shall be succeded and returns empty path list. + * + * @param[in] : NONE + * @return : {"availableFirmwareFiles": [],"success":true} + */ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesSuccess_when_devNodNotFound) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + static struct mntent entry2; + + entry1.mnt_fsname = const_cast("/dev/sdb1"); + entry1.mnt_dir = const_cast("/mnt/usb1"); + entry2.mnt_fsname = const_cast("/dev/sdb2"); + entry2.mnt_dir = const_cast("/mnt/usb2"); + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } + else if (callCount == 1) { + callCount++; + return &entry2; + } + else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"availableFirmwareFiles\":[],\"success\":true}")); +} + +/** +* @brief : getAvailableFirmwareFiles when bin files are not present, +* Check if .bin files are not present in mounted paths, +* then getAvailableFirmwareFiles shall succeed and returns an empty list. +* +* @param[in] : NONE +* @return : {"availableFirmwareFiles": [],"success":true} +*/ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesSuccess_withoutBinfiles) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda2")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda2")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda2"); + entry1.mnt_dir = const_cast("/run/sda2"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"availableFirmwareFiles\":[],\"success\":true}")); +} + +/** +* @brief : getAvailableFirmwareFiles when bin files are present, +* Check if .bin files are present in mounted paths, additional paths(UsbTestFWUpdate, UsbProdFWUpdate), +* then getAvailableFirmwareFiles shall succeed and returns all the file paths. +* +* @param[in] : NONE +* @return : returns The list of firmware files including the full path name +*/ +TEST_F(UsbAccessTest, getAvailableFirmwareFilesSuccess_withBinFiles) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getAvailableFirmwareFiles"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"availableFirmwareFiles\":[\"\\/run\\/sda1\\/UsbTestFWUpdate\\/HSTP11MWR_3.11p5s1_VBN_sdy.bin\",\"\\/run\\/sda1\\/UsbProdFWUpdate\\/HSTP11MWR_4.11p5s1_VBN_sdy.bin\",\"\\/run\\/sda1\\/HSTP11MWR_5.11p5s1_VBN_sdy.bin\"],\"success\":true}")); +} +/*Test cases for getAvailableFirmwareFiles ends here*/ + +/******************************************************************************************************************* +* Test function for :ArchiveLogs +* ArchiveLogs : +* Compresses and uploads device logs into attached USB drive. +* @return Whether the request succeeded. +* +*Event : onArchiveLogs +* Triggered to archive the device logs and returns the status of the archive. +* +* @return status of the archive. +* Use case coverage: +* @Failure :7 +* @Success :2 +********************************************************************************************************************/ + +/** + * @brief : ArchiveLogs when path label is missing in the request parameter + * Check if path label is missing from the parameters JSON object; + * then ArchiveLogs shall be failed and return Erorr code: ERROR_BAD_REQUEST + * + * @param[in] : Invalid parameters without the "path" label + * @return : error code: ERROR_BAD_REQUEST + */ +TEST_F(UsbAccessEventTest, archiveLogsFailure_BadRequest) +{ + EXPECT_EQ(Core::ERROR_BAD_REQUEST, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"params\":{}}"), response)); +} + +/** +* @brief : onArchiveLogs event when setmntent returns nullptr, +* Check if setmntent fails to open the mounts file, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : No USB. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_whenSetmntentValueNull) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, setmntent(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/proc/mounts"))); + return nullptr; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + std::string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"No USB\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs event when getmntent returns nullptr, +* Check if getmntent fails to retrieve mount entries, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : No USB. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_whengetmntentNull) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + return static_cast(NULL); + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + std::string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"No USB\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs event when device node is not found, +* Check if the device node is not found in the devnodes list, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : No USB. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_when_devNodNotFound) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda2"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + std::string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"No USB\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs event when path Param was not found in Mountedpath, +* Check if the path Param was not found in Mountedpath, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : No USB. +* +* @param[in] : "params": {"path":"run/sda2"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_when_pathParamNotFoundInMountedpath) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + std::string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"No USB\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda2\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs event when file open is not Successful, +* Check /lib/rdk/usbLogUpload.sh file open is not successful, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : script error. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_when_FileFailedtoOpen) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_CALL(*p_wrapsImplMock, v_secure_popen(::testing::_, ::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char *direction, const char *command, va_list args) { + va_list args2; + va_copy(args2, args); + char strFmt[256]; + vsnprintf(strFmt, sizeof(strFmt), command, args2); + va_end(args2); + EXPECT_EQ(string(strFmt), string(_T("/lib/rdk/usbLogUpload.sh /run/sda1"))); + return nullptr; + })); + + ON_CALL(*p_wrapsImplMock, v_secure_pclose(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](FILE* pipe){ + return -1; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"script error\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs when file termination is not successful, +* Check /lib/rdk/usbLogUpload.sh file termination is not successful, +* then ArchiveLogs shall succeed and onArchiveLogs return Erorr code : script error. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, onArchiveLogsFailure_when_FileFailedtoTerminate) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const char* command, const char* type) { + EXPECT_EQ(string(command), string(_T("/lib/rdk/usbLogUpload.sh /run/sda1"))); + return __real_popen(command, type); + })); + + ON_CALL(*p_wrapsImplMock, v_secure_pclose(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](FILE* pipe){ + return -1; + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"script error\",\"success\":false,\"path\":\"\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief :onArchiveLogs event successful when path param is empty, +* Check if any mounted paths are present, and archiving the logs into the first mounted path, +* then onArchiveLogs shall succeed and return Erorr code : none. +* +* @param[in] : "params": {"path":""} +* @return : "success":true +*/ + +TEST_F(UsbAccessEventTest, archiveLogsSuccess_When_pathParamisEmpty) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + ON_CALL(*p_wrapsImplMock, v_secure_popen(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char *direction, const char *command, va_list args) -> FILE* { + const char* valueToReturn = NULL; + va_list args2; + va_copy(args2, args); + char strFmt[256]; + vsnprintf(strFmt, sizeof(strFmt), command, args2); + va_end(args2); + if (strcmp(strFmt, "/lib/rdk/usbLogUpload.sh /run/sda1") == 0) { + valueToReturn = "/run/sda1/5C3400F15492_Logs_12-05-22-10-41PM.tgz"; + } + if (valueToReturn != NULL) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, valueToReturn); + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + } else { + return nullptr; + } + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + std::string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"none\",\"success\":true,\"path\":\"\\/run\\/sda1\\/5C3400F15492_Logs_12-05-22-10-41PM.tgz\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} + +/** +* @brief : onArchiveLogs event successful when valid path is passed, +* Check if valid path is passed, and /lib/rdk/usbLogUpload.sh file is terminating, +* then onArchiveLogs shall succeed and return Erorr code : none. +* +* @param[in] : "params": {"path":"run/sda1"} +* @return : "success":true +*/ +TEST_F(UsbAccessEventTest, archiveLogsSuccess_onValidPath) +{ + Core::Event onArchiveLogs(false, true); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); + entry1.mnt_dir = const_cast("/run/sda1"); + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + ON_CALL(*p_wrapsImplMock, v_secure_popen(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char *direction, const char *command, va_list args) -> FILE* { + const char* valueToReturn = NULL; + va_list args2; + va_copy(args2, args); + char strFmt[256]; + vsnprintf(strFmt, sizeof(strFmt), command, args2); + va_end(args2); + if (strcmp(strFmt, "/lib/rdk/usbLogUpload.sh /run/sda1") == 0) { + valueToReturn = "/run/sda1/5C3400F15492_Logs_12-05-22-10-41PM.tgz"; + } + if (valueToReturn != NULL) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, valueToReturn); + FILE* pipe = fmemopen(buffer, strlen(buffer), "r"); + return pipe; + } else { + return nullptr; + } + })); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onArchiveLogs\",\"params\":{\"error\":\"none\",\"success\":true,\"path\":\"\\/run\\/sda1\\/5C3400F15492_Logs_12-05-22-10-41PM.tgz\"}}"); + onArchiveLogs.SetEvent(); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ArchiveLogs"), _T("{\"path\":\"/run/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onArchiveLogs.Lock()); + handler.Unsubscribe(0, _T("onArchiveLogs"), _T("org.rdk.UsbAccess"), message); +} +/*Test cases for ArchiveLogs ends here*/ + +/********************************************************************************************************* + * Test function for :createLink + * createLink :Creates a symbolic link to the root folder of the USB drive. + * If called, and a link already exists, then it errors out. + * + * + * @return The URL of the web server that points to this location + * Use case coverage: + * @Success :3 + * @Failure :4 + *******************************************************************************************************/ + + +/** + * @brief : createLink when send Bad request + * Check if path parameter is missing from the parameters JSON object; + * then createLink shall be failed and return Erorr code: ERROR_BAD_REQUEST + * + * @param[in] : Invalid parameters without the "path" label + * @return : error code: ERROR_BAD_REQUEST + */ +TEST_F(UsbAccessTest, createLinkFailed_BadRequest) +{ + EXPECT_EQ(Core::ERROR_BAD_REQUEST, handler.Invoke(connection, _T("createLink"), _T("{\"MissingPathParam\":\"/run/media/sda1/logs/PreviousLogs\"}"), response)); +} + +/** + * @brief : createLink When a symlink already exists for the given pathParam: + * Check if a symlink already exists for the given pathParam:; + * then createLink shall be failed + * + * @param[in] : Any valid path parameter for eg: {\"path\":\"/run/media/sda1\"} + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, createLinkFailed_when_LinkExistInthePathParam) +{ + //To simulate a symbolicLink already exist in the pathParam + symlink("/run/media/sda1", "/tmp/usbdrive"); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("createLink"), _T("{\"path\":\"/run/media/sda1\"}"), response)); + //Remove the symbolicLink created + std::remove("/tmp/usbdrive"); +} + +/** + * @brief : createLink request with empty param and symlink already exists for the first USB mount path. + * Check if no pathParam is passed ,then the first path in the paths list is used as pathParam + * But if symlink already exists for the this pathParam;then createLink shall be failed + * + * @param[in] : No pathParam + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, createLinkFailed_withEmptyParam_LinkExistIntheFirstUsbMountedPath) +{ + //To simulate symbolicLink already exist in the pathParam + symlink("/run/media/sda1", "/tmp/usbdrive"); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("createLink"), _T("{}"), response)); + //Remove the symbolicLink created + std::remove("/tmp/usbdrive"); +} + +/** + * @brief : createLink request with pathParam is not the first usb path and symlink already Not exit. + * + * Check if symbolic Link not exist with the specific pathParam, then loop through the stored m_CreatedLinkIds map + * for exact match, If no match found,the createLink shall be failed and cound not create synlink + * the baseURL is added to the response object + * + * @param[in] : pathParam different from first usb mounted path + * @return : ERROR_GENERAL + */ +TEST_F(UsbAccessTest, createLinkFailed_with_m_CreatedLinkIds_bLink_NOT_Exists) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{}"), response)); + std::remove("/tmp/usbdrive"); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("createLink"), _T("{\"path\":\"/run/media/sdb1\"}"), response)); +} + +/** + * @brief : createLink request with pathParam and symlink already Not exit + * Check if pathParam is passed ,and if symlink is not already exist + * in the specific pathParam;then createLink shall be succeeded and + * the baseURL is added to the response object. + * + * @param[in] : Valid pathParam for eg:{\"path\":\"/run/media/sda1\"} + * @return : baseURL as response + */ +TEST_F(UsbAccessTest, createLinkSuccess_whenReadLinkFailed_withPathParam) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{\"path\":\"/run/media/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"baseURL\":\"http:\\/\\/localhost:50050\\/usbdrive\",\"success\":true}")); + //Remove the symbolicLink created + std::remove("/tmp/usbdrive"); +} + +/** + * @brief : createLink request without pathParam and symlink already Not exit + * Check if no pathParam is passed ,then the first path in the paths list is used as pathParam + * and if symlink is not already exist in this pathParam; + * then createLink shall be succeeded and the baseURL is added to the response object. + * + * @param[in] : No pathParam + * @return : baseURL as response + */ +TEST_F(UsbAccessTest, createLinkSuccess_whenReadLinkFailed_withoutPathParam) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"baseURL\":\"http:\\/\\/localhost:50050\\/usbdrive\",\"success\":true}")); + //Remove the symbolicLink created + std::remove("/tmp/usbdrive"); +} + +/** + * @brief : createLink request where link not exist with first USB drive and had to loop through stored m_CreatedLinkIds + * Check if symbolic Link not exist with the first USB drive, then loop through the stored m_CreatedLinkIds map + * to see if it already has the link;If the Link is not already exist then createLink shall be succeeded and + * the baseURL is added to the response object. + * + * @param[in] : Any valid input pathParam + * @return : baseURL as response + */ +TEST_F(UsbAccessTest, createLinkSuccess_with_m_CreatedLinkIds_bLink_NOT_Exists_CreatedLinkForFor1stUsb) +{ + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + /*As per this invoke call,created link for the first usb drive, + then the link ID and path are added to the m_CreatedLinkIds map. */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{}"), response)); + + /*Remove the above created symbolic link inorder to simulate the behavior as symlink NoT exists with first usbdrive + *and need to loop through the stored m_CreatedLinkIds map to see if it already has the link.*/ + std::remove("/tmp/usbdrive"); + + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{\"path\":\"/run/media/sda1\"}"), response)); + EXPECT_EQ(response, string("{\"baseURL\":\"http:\\/\\/localhost:50050\\/usbdrive\",\"success\":true}")); + std::remove("/tmp/usbdrive"); +} +/*Test cases for createLink ends here*/ + +/********************************************************************************************************* + * Test function for :getLinks + * getLinks :Returns a list of created links and the associated root folder of the USB drive. + * + * @return Whether the request succeeded + * Use case coverage: + * @Success :2 + *******************************************************************************************************/ + +/** + * @brief : getLinks when there are no Links, + * Check if there is no symbolic link exists, + * then getLinks shall be succeded and returns empty links list. + * + * @param[in] : None + * @return : {"links":[],"success":true} + */ +TEST_F(UsbAccessTest, getLinkSuccess_WhenNoSymLink) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLinks"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"links\":[],\"success\":true}")); +} + +/** + * @brief : getLinks when symbolic links exist, + * Check if symbolic links are created and stored, + * then getLinks shall be succeded and returns a list of created links and the associated root folder of the USB drive. + * + * @param[in] : None + * @return : {"links":["path":"run/media/sda1","baseURL":"http:/localhost:50050/usbdrive"],"success":true} +*/ +TEST_F(UsbAccessTest, getLinkSuccess_whenSymLinkExist) +{ + EXPECT_CALL(*p_udevImplMock, udev_enumerate_get_list_entry(testing::_)) + .WillOnce(testing::Return(reinterpret_cast(0x3))); + + EXPECT_CALL(*p_udevImplMock, udev_list_entry_get_name(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_parent_with_subsystem_devtype(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::Return(reinterpret_cast(0x5))); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devtype(testing::_)) + .WillRepeatedly(testing::Return("disk")); + + EXPECT_CALL(*p_udevImplMock, udev_device_get_devnode(testing::_)) + .WillRepeatedly(testing::Return("/dev/sda1")); + + EXPECT_CALL(*p_wrapsImplMock, getmntent(testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](FILE*) -> struct mntent* { + static struct mntent entry1; + + entry1.mnt_fsname = const_cast("/dev/sda1"); // Set the value for mnt_fsname + entry1.mnt_dir = const_cast("/run/media/sda1"); // Set the value for mnt_dir + + static int callCount = 0; + if (callCount == 0) { + callCount++; + return &entry1; + } else { + return static_cast(NULL); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("createLink"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"baseURL\":\"http:\\/\\/localhost:50050\\/usbdrive\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getLinks"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"links\":[{\"path\":\"\\/run\\/media\\/sda1\",\"baseURL\":\"http:\\/\\/localhost:50050\\/usbdrive\"}],\"success\":true}")); + //Remove the symbolicLink created + std::remove("/tmp/usbdrive"); + +} +/*Test cases for getLinks ends here*/ + +/********************************************************************************************************* + * Test function for :clearLink + * clearLink :Clears or removes the symbolic link created by the createLink + * + * @return Whether the request succeeded + * Use case coverage: + * @Success :3 + * @Failure :4 + *******************************************************************************************************/ + + +/** + * @brief : clearLink without baseURL + * Check if input parameter baseURL is missing from the request parameters JSON object; + * then clearLink shall be failed and return Erorr code: ERROR_BAD_REQUEST + * + * @param[in] : Invalid parameters without the "baseURL" label + * @return : error code: ERROR_BAD_REQUEST + */ +TEST_F(UsbAccessTest, clearLinkFailed_onBadRequest) +{ + EXPECT_EQ(Core::ERROR_BAD_REQUEST, handler.Invoke(connection, _T("clearLink"), _T("{\"MissingBaseUrl\":\"http://localhost:50050/usbdrive\"}"), response)); +} + +/** + * @brief : clearLink when input baseURL[LINK_URL_HTTP] not exists + * Check if input parameter baseURL is the default URL [http://localhost:50050/usbdrive];and if this link does not exist; + * then clearLink shall be failed + * + * @param[in] : valid baseURL + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkFailed_withDefaultInputBaseUrl_whenLinkNotExist) +{ + std::remove("/tmp/usbdrive"); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":\"http://localhost:50050/usbdrive\"}"), response)); +} + +/** + * @brief : clearLink when input baseURL is other than [LINK_URL_HTTP] ,but this link does not exists + * Check if input parameter baseURL is other than [http://localhost:50050/usbdrive];and if this link does not exist; + * then clearLink shall be failed + * + * @param[in] : any valid baseURL other than http://localhost:50050/usbdrive + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkFailed_withNonDefaultInputBaseUrl_whenLinkNotExist) +{ + std::remove("/tmp/usbdrive123"); + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":\"http://localhost:50050/usbdrive123\"}"), response)); +} + +/** + * @brief : clearLink with Invalid input baseURL. + * Check if input parameter baseURL is invalid[ contains characters other than 0-9 digits]; + * then clearLink shall be failed + * + *@param[in] : Invalid baseURL [contains characters other than 0-9 digits] + *@return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkFailed_withInvalidInputBaseUrl) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":\"http://localhost:50050/usbdrive#_123\"}"), response)); +} + +/** + * @brief : clearLink when input baseURL is empty + * Check if input parameter baseURL is empty; + * then the default LINK PATH "/tmp/usbdrive" will be cleared + * + * @param[in] : any valid baseURL other than http://localhost:50050/usbdrive + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkSuccess_whenInputParamIsEmpty) +{ + symlink("/run/media/sda1", "/tmp/usbdrive"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * @brief : clearLink when input baseURL is "http://localhost:50050/usbdrive" + * Check if input parameter baseURL = http://localhost:50050/usbdrive; + * and if the LINK_PATH is presnt,then clearLink shall be succeeded and input baseURL will be cleared + * + * @param[in] : default baseURL http://localhost:50050/usbdrive + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkSuccess_withDefaultInputBaseUrl) +{ + symlink("/run/media/sda1", "/tmp/usbdrive"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":\"http://localhost:50050/usbdrive\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +/** + * @brief : clearLink with valid input baseURL is other than "http://localhost:50050/usbdrive". + * Check if input parameter baseURL is Other than http://localhost:50050/usbdrive; + * and if the particular LINK_PATH is present,then clearLink shall be succeeded and input baseURL will be cleared + * + * @param[in] : default baseURL http://localhost:50050/usbdrive + * @return : error code: ERROR_GENERAL + */ +TEST_F(UsbAccessTest, clearLinkSuccess_withNonDefaultInputBaseUrl) +{ + symlink("/run/media/sda1", "/tmp/usbdrive123"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearLink"), _T("{\"baseURL\":\"http://localhost:50050/usbdrive123\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} +/*Test cases for clearLinks ends here*/ + +/******************************************************************************************************************* +*Test function for Event:onUSBMountChanged +*Event : onUSBMountChanged +* Triggered when a USB drive is mounted or unmounted. +* +* @return (i)mount status [true when the USB device is mounted or false when the USB device is unmounted] +* and (ii)the location where the device is mounted +* Use case coverage: +* @Success :2 +********************************************************************************************************************/ + +/** + * @brief : onUSBMountChanged when a USB drive is mounted/unmounted + * Check onUSBMountChanged triggered successfully when a USB drive is mounted + * with mount status = true and the location where the device is mounted + * @param[in]   :  This method takes no parameters. + * @return      :  \"params\":{\"mounted\":true,\"device\":\"\\/dev\\/sda1\"} + * + */ +TEST_F(UsbAccessEventIarmTest, onUSBMountChangedSuccess) +{ + Core::Event onUSBMountChanged(false, true); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, "{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.UsbAccess.onUSBMountChanged\",\"params\":{\"mounted\":true,\"device\":\"\\/dev\\/sda1\"}}"); + + onUSBMountChanged.SetEvent(); + + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onUSBMountChanged"), _T("org.rdk.UsbAccess"), message); + + IARM_Bus_SYSMgr_EventData_t usbEventData; + usbEventData.data.usbMountData.mounted= 1; + strcpy(usbEventData.data.usbMountData.dir, "/dev/sda1"); + eventHandler(IARM_BUS_SYSMGR_NAME, IARM_BUS_SYSMGR_EVENT_USB_MOUNT_CHANGED, &usbEventData, 1); + + EXPECT_EQ(Core::ERROR_NONE, onUSBMountChanged.Lock()); + + handler.Unsubscribe(0, _T("onUSBMountChanged"), _T("org.rdk.System"), message); +} +/*Test cases for onUSBMountChanged ends here*/ diff --git a/NetworkManager/Tests/L1Tests/tests/test_UserPreferences.cpp b/NetworkManager/Tests/L1Tests/tests/test_UserPreferences.cpp new file mode 100755 index 0000000000..1560cd81fa --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_UserPreferences.cpp @@ -0,0 +1,89 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" + +#include "UserPreferences.h" + +using namespace WPEFramework; + +namespace { +const string userPrefFile = _T("/opt/user_preferences.conf"); +const uint8_t userPrefLang[] = "[General]\nui_language=US_en\n"; +} + +class UserPreferencesTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + UserPreferencesTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + virtual ~UserPreferencesTest() = default; +}; + +TEST_F(UserPreferencesTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getUILanguage"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setUILanguage"))); +} + +TEST_F(UserPreferencesTest, paramsMissing) +{ + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setUILanguage"), _T("{}"), response)); +} + +TEST_F(UserPreferencesTest, getUILanguage) +{ + //Fail case: File doesn't exists + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getUILanguage"), _T("{}"), response)); + + Core::File file(userPrefFile); + file.Destroy(); + file.Create(); + + //Fail case: No key exists + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getUILanguage"), _T("{}"), response)); + + file.Write(userPrefLang, sizeof(userPrefLang)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getUILanguage"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ui_language\":\"US_en\",\"success\":true}")); + + file.Destroy(); +} + +TEST_F(UserPreferencesTest, setUILanguage) +{ + Core::File file(userPrefFile); + file.Create(); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setUILanguage"), _T("{\"ui_language\":\"US_en\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getUILanguage"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ui_language\":\"US_en\",\"success\":true}")); + + file.Destroy(); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_UtilsFile.cpp b/NetworkManager/Tests/L1Tests/tests/test_UtilsFile.cpp new file mode 100755 index 0000000000..04e3b9df73 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_UtilsFile.cpp @@ -0,0 +1,59 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "Module.h" + +#include "UtilsFile.h" + +namespace { +const uint8_t bytes[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xFE, 0x03, 0x20, 0x04, 0x00, 0x01 }; +} + +using namespace WPEFramework; + +TEST(UtilsFileTest, createFolder_createFile_moveFile_verifyFile) +{ + Core::Directory dir(_T("/tmp/UtilsFileTest")); + + EXPECT_TRUE(dir.Destroy(false)); + ASSERT_TRUE(dir.CreatePath()); + + Core::File file(string(_T("/tmp/UtilsFileTest/file"))); + + EXPECT_FALSE(file.Exists()); + EXPECT_TRUE(file.Create()); + EXPECT_EQ(sizeof(bytes), file.Write(bytes, sizeof(bytes))); + + Core::File file2(string(_T("/tmp/UtilsFileTest/destination/for/new/file"))); + + EXPECT_FALSE(file2.Exists()); + EXPECT_TRUE(Utils::MoveFile(file.Name(), file2.Name())); + file.LoadFileInfo(); + file2.LoadFileInfo(); + EXPECT_FALSE(file.Exists()); + EXPECT_TRUE(file2.Exists()); + EXPECT_TRUE(file2.Open(true)); + + uint8_t buffer[2 * sizeof(bytes)]; + + EXPECT_EQ(sizeof(bytes), file2.Read(buffer, 2 * sizeof(bytes))); + EXPECT_EQ(0, memcmp(buffer, bytes, sizeof(bytes))); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_Warehouse.cpp b/NetworkManager/Tests/L1Tests/tests/test_Warehouse.cpp new file mode 100755 index 0000000000..cb15005c99 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_Warehouse.cpp @@ -0,0 +1,780 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "gtest/gtest.h" +#include + +#include "Warehouse.h" + +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "RfcApiMock.h" +#include "WrapsMock.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class WarehouseTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + WarehouseTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + } + + virtual ~WarehouseTest() + { + plugin.Release(); + } +}; + +class WarehouseInitializedTest : public WarehouseTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + RfcApiImplMock *p_rfcApiImplMock = nullptr ; + NiceMock wrapsImplMock; + WrapsImplMock *p_wrapsImplMock = nullptr ; + + IARM_EventHandler_t whMgrStatusChangeEventsHandler; + + WarehouseInitializedTest() + : WarehouseTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_rfcApiImplMock = new NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_WAREHOUSEOPS_STATUSCHANGED)) { + whMgrStatusChangeEventsHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + EXPECT_EQ(string(""), plugin->Initialize(nullptr)); + } + virtual ~WarehouseInitializedTest() override + { + plugin->Deinitialize(nullptr); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + } +}; + +class WarehouseEventTest : public WarehouseInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + WarehouseEventTest() + : WarehouseInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + virtual ~WarehouseEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(WarehouseTest, registeredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("resetDevice"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDeviceInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFrontPanelState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("internalReset"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("lightReset"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isClean"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("executeHardwareTest"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHardwareTestResults"))); +} + +class WarehouseResetDeviceTest : public WarehouseEventTest { +protected: + Core::Event resetDone; + WarehouseResetDeviceTest() + : WarehouseEventTest(), resetDone(false, true) + { + handler.Subscribe(0, _T("resetDone"), _T("org.rdk.Warehouse"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + // called by WareHouseResetIARM + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + //Check for error response for the second call - Negative test case + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.Warehouse.resetDone\"," + "\"params\":{\"success\":true}" + "}"))); + resetDone.SetEvent(); + return Core::ERROR_NONE; + })); + } + + virtual ~WarehouseResetDeviceTest() override + { + handler.Unsubscribe(0, _T("resetDone"), _T("org.rdk.Warehouse"), message); + } +}; + +TEST_F(WarehouseResetDeviceTest, ColdFactoryResetDevice) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_ColdFactoryReset)); + //Return error for the Negative test case + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: true, type: COLD + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"COLD\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseResetDeviceTest, FactoryResetDevice) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_FactoryReset)); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: true, type: FACTORY + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"FACTORY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseResetDeviceTest, UserFactoryResetDevice) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_UserFactoryReset)); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: true, type: USERFACTORY + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"USERFACTORY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseResetDeviceTest, WarehouseClearResetDevice) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_WareHouseClear)); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: false, type: WAREHOUSE_CLEAR + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":false,\"resetType\":\"WAREHOUSE_CLEAR\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseInitializedTest, WarehouseClearResetDeviceNoResponse) +{ + Core::Event resetCallRxed(false, true); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [&](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_WareHouseClear)); + resetCallRxed.SetEvent(); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: true, type: WAREHOUSE_CLEAR, Expect no response + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"WAREHOUSE_CLEAR\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetCallRxed.Lock()); +} + +TEST_F(WarehouseResetDeviceTest, GenericResetDevice) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_WareHouseReset)); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: false + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseInitializedTest, GenericResetDeviceNoResponse) +{ + Core::Event resetCallRxed(false, true); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [&](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_WareHouseReset)); + resetCallRxed.SetEvent(); + return IARM_RESULT_SUCCESS; + }); + + //reset: suppress reboot: true - This doesn't generate any event (Expect no response) + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetCallRxed.Lock()); +} + +class WarehouseResetDeviceFailureTest : public WarehouseEventTest { +protected: + Core::Event resetDone; + WarehouseResetDeviceFailureTest() + : WarehouseEventTest(), resetDone(false, true) + { + handler.Subscribe(0, _T("resetDone"), _T("org.rdk.Warehouse"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + // called by WareHouseResetIARM + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + //Check for error response for the second call - Negative test case + EXPECT_EQ(text, string(_T("{" + "\"jsonrpc\":\"2.0\"," + "\"method\":\"org.rdk.Warehouse.resetDone\"," + "\"params\":{\"success\":false," + "\"error\":\"Reset failed\"}" + "}"))); + resetDone.SetEvent(); + return Core::ERROR_NONE; + })); +} + + virtual ~WarehouseResetDeviceFailureTest() override + { + handler.Unsubscribe(0, _T("resetDone"), _T("org.rdk.Warehouse"), message); + } +}; + +TEST_F(WarehouseResetDeviceFailureTest, UserFactoryResetDeviceFailure) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_PWRMGR_NAME))); + EXPECT_EQ(string(methodName), string(IARM_BUS_PWRMGR_API_UserFactoryReset)); + //Return error for the Negative test case + return IARM_RESULT_INVALID_PARAM; + }); + + //reset: suppress reboot: true, type: USERFACTORY + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"USERFACTORY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} + +TEST_F(WarehouseResetDeviceTest, ColdFactoryResetDevicePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(4) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh coldfactory")); + return Core::ERROR_NONE; + })) + .WillRepeatedly(::testing::Return(Core::ERROR_NONE)); + + //reset: suppress reboot: true, type: COLD + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"COLD\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseResetDeviceTest, FactoryResetDevicePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(3) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh factory")); + return Core::ERROR_NONE; + })) + .WillRepeatedly(::testing::Return(Core::ERROR_NONE)); + + //reset: suppress reboot: true, type: FACTORY + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"FACTORY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseResetDeviceTest, UserFactoryResetDevicePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(3) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh userfactory")); + return Core::ERROR_NONE; + })); + + //reset: suppress reboot: true, type: USERFACTORY + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"USERFACTORY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseResetDeviceTest, WarehouseClearResetDevicePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(4) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh WAREHOUSE_CLEAR")); + return Core::ERROR_NONE; + })); + + //reset: suppress reboot: false, type: WAREHOUSE_CLEAR + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":false,\"resetType\":\"WAREHOUSE_CLEAR\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseInitializedTest, WarehouseClearResetDeviceNoResponsePwrMgr2RFCEnabled) +{ + Core::Event resetCallRxed(false, true); + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(2) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh WAREHOUSE_CLEAR --suppressReboot")); + resetCallRxed.SetEvent(); + return Core::ERROR_NONE; + })); + + //reset: suppress reboot: true, type: WAREHOUSE_CLEAR, Expect no response + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true,\"resetType\":\"WAREHOUSE_CLEAR\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetCallRxed.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseResetDeviceTest, GenericResetDevicePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(4) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh warehouse")); + return Core::ERROR_NONE; + })); + + //reset: suppress reboot: false + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseInitializedTest, GenericResetDeviceNoResponsePwrMgr2RFCEnabled) +{ + Core::Event resetCallRxed(false, true); + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(2) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [&](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh warehouse --suppressReboot &")); + resetCallRxed.SetEvent(); + return Core::ERROR_NONE; + })); + + //reset: suppress reboot: true - This doesn't generate any event (Expect no response) + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetCallRxed.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseResetDeviceFailureTest, UserFactoryResetDeviceFailurePwrMgr2RFCEnabled) +{ + //Enable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = true; + + EXPECT_CALL(*p_wrapsImplMock, system(::testing::_)) + .Times(2) + .WillOnce(::testing::Return(Core::ERROR_NONE)) + .WillOnce(::testing::Invoke( + [](const char* command) { + EXPECT_EQ(string(command), string("sh /lib/rdk/deviceReset.sh warehouse --suppressReboot &")); + return Core::ERROR_GENERAL; + })); + + //reset: suppress reboot: true - This doesn't generate any event (Expect no response) + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("resetDevice"), _T("{\"suppressReboot\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); + //Disable Power manager 2 + plugin->m_isPwrMgr2RFCEnabled = false; +} + +TEST_F(WarehouseInitializedTest, internalResetFailPassPhrase) +{ + //Invoke internalReset - No pass phrase + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("internalReset"), _T("{}"), response)); + + //Invoke internalReset - Incorrect pass phrase + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("internalReset"), _T("{\"passPhrase\":\"Test Phrase\"}"), response)); +} + +TEST_F(WarehouseInitializedTest, internalResetScriptFail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_SYSMGR_NAME))); + if (string(methodName) == string(_T(IARM_BUS_SYSMGR_API_RunScript))) + { + auto* runScriptParam = static_cast(arg); + runScriptParam->return_value = -1; + } + return IARM_RESULT_SUCCESS; + }); + + //Invoke internalReset - Correct pass phrase - Return error + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("internalReset"), _T("{\"passPhrase\":\"FOR TEST PURPOSES ONLY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false,\"error\":\"script returned: -1\"}")); +} + +TEST_F(WarehouseInitializedTest, internalReset) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_SYSMGR_NAME))); + if (string(methodName) == string(_T(IARM_BUS_SYSMGR_API_RunScript))) + { + auto* runScriptParam = static_cast(arg); + runScriptParam->return_value = 0; + EXPECT_EQ(string(runScriptParam->script_path), string("rm -rf /opt/drm /opt/www/whitebox /opt/www/authService && /rebootNow.sh -s WarehouseService &")); + } + return IARM_RESULT_SUCCESS; + }); + + //Invoke internalReset - Correct pass phrase - Return success + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("internalReset"), _T("{\"passPhrase\":\"FOR TEST PURPOSES ONLY\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(WarehouseInitializedTest, lightResetScriptFail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_SYSMGR_NAME))); + if (string(methodName) == string(_T(IARM_BUS_SYSMGR_API_RunScript))) + { + auto* runScriptParam = static_cast(arg); + runScriptParam->return_value = -1; + } + return IARM_RESULT_SUCCESS; + }); + + //Invoke lightReset - returns error + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("lightReset"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false,\"error\":\"script returned: -1\"}")); +} + +TEST_F(WarehouseInitializedTest, lightReset) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(1) + .WillOnce( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_SYSMGR_NAME))); + if (string(methodName) == string(_T(IARM_BUS_SYSMGR_API_RunScript))) + { + auto* runScriptParam = static_cast(arg); + runScriptParam->return_value = 0; + EXPECT_EQ(string(runScriptParam->script_path), string("rm -rf /opt/netflix/* /opt/QT/home/data/* /opt/hn_service_settings.conf /opt/apps/common/proxies.conf /opt/lib/bluetooth /opt/persistent/rdkservicestore")); + } + return IARM_RESULT_SUCCESS; + }); + + //Invoke lightReset + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("lightReset"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(WarehouseInitializedTest, isClean) +{ + const string userPrefFile = _T("/opt/user_preferences.conf"); + const uint8_t userPrefLang[] = "[General]\nui_language=US_en\n"; + const string customDataFile = _T("/lib/rdk/wh_api_5.conf"); + const uint8_t customDataFileContent[] = "[files]\n/opt/user_preferences.conf\n"; + + //Invoke isClean - No conf file + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isClean"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false,\"error\":\"Can't open file \\/lib\\/rdk\\/wh_api_5.conf\",\"clean\":false,\"files\":[]}")); + + //Invoke isClean - Empty conf file + Core::File fileConf(customDataFile); + Core::Directory(fileConf.PathName().c_str()).CreatePath(); + fileConf.Create(); + EXPECT_TRUE(Core::File(customDataFile).Exists()); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isClean"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"error\":\"file \\/lib\\/rdk\\/wh_api_5.conf doesn't have any lines with paths\",\"success\":false,\"files\":[]}")); + + //Invoke isClean - Create empty conf file + fileConf.Write(customDataFileContent, sizeof(customDataFileContent)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isClean"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true,\"files\":[],\"clean\":true}")); + + //Invoke isClean - Add test data to conf file + Core::File filePref(userPrefFile); + filePref.Create(); + filePref.Write(userPrefLang, sizeof(userPrefLang)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isClean"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true,\"files\":[\"\\/opt\\/user_preferences.conf\"],\"clean\":false}")); + + fileConf.Destroy(); + filePref.Destroy(); +} + +TEST_F(WarehouseInitializedTest, executeHardwareTest) +{ + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Warehouse")); + EXPECT_EQ(string(pcParameterName), _T("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.hwHealthTest.Enable")); + EXPECT_EQ(string(pcParameterValue), _T("true")); + EXPECT_EQ(eDataType, WDMP_BOOLEAN); + return WDMP_SUCCESS; + })) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Warehouse")); + EXPECT_EQ(string(pcParameterName), _T("Device.DeviceInfo.X_RDKCENTRAL-COM_xOpsDeviceMgmt.hwHealthTest.ExecuteTest")); + EXPECT_EQ(string(pcParameterValue), _T("1")); + EXPECT_EQ(eDataType, WDMP_INT); + return WDMP_SUCCESS; + })); + + //Invoke executeHardwareTest + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("executeHardwareTest"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(WarehouseInitializedTest, getHardwareTestResults) +{ + EXPECT_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + EXPECT_EQ(string(pcCallerID), string("Warehouse")); + EXPECT_EQ(string(pcParameterName), string("Device.DeviceInfo.X_RDKCENTRAL-COM_xOpsDeviceMgmt.hwHealthTest.Results")); + strncpy(pstParamData->value, "test", sizeof(pstParamData->value)); + return WDMP_SUCCESS; + })); + EXPECT_CALL(*p_rfcApiImplMock, setRFCParameter(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, const char* pcParameterValue, DATA_TYPE eDataType) { + EXPECT_EQ(string(pcCallerID), _T("Warehouse")); + EXPECT_EQ(string(pcParameterName), _T("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.hwHealthTest.Enable")); + EXPECT_EQ(string(pcParameterValue), _T("false")); + EXPECT_EQ(eDataType, WDMP_BOOLEAN); + return WDMP_SUCCESS; + })); + + //Invoke getHardwareTestResults + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHardwareTestResults"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"testResults\":\"test\",\"success\":true}")); +} + +extern "C" FILE* __real_popen(const char* command, const char* type); +extern "C" int __real_pclose(FILE* pipe); +TEST_F(WarehouseInitializedTest, getDeviceInfo) +{ + const string deviceInfoScript = _T("/lib/rdk/getDeviceDetails.sh"); + const uint8_t deviceInfoContent[] = "echo \"bluetooth_mac=12:34:56:78:90:AB\n" + "boxIP=192.168.1.0\n" + "build_type=VBN\n" + "estb_mac=12:34:56:78:90:AB\n" + "eth_mac=12:34:56:78:90:AB\n" + "friendly_id=Abc XYZ\n" + "imageVersion=ABCADS_VBN_2022010101sdy__MH_SPLASH_TEST_2\n" + "model_number=ABC123ADS\n" + "wifi_mac=12:34:56:78:90:AB\"\n"; + + ON_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_EQ(string(command), string(_T("sh /lib/rdk/getDeviceDetails.sh read"))); + return __real_popen(command, type); + })); + ON_CALL(*p_wrapsImplMock, pclose(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](FILE* pipe){ + return __real_pclose(pipe); + })); + + //Invoke getDeviceInfo + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true,\"error\":\"No such file or directory\"}")); + + //Create fake device info script & Invoke getDeviceInfo + Core::File file(deviceInfoScript); + file.Create(); + //file.Open(false); + file.Write(deviceInfoContent, sizeof(deviceInfoContent)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDeviceInfo"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"bluetooth_mac\":\"12:34:56:78:90:AB\"," + "\"boxIP\":\"192.168.1.0\"," + "\"build_type\":\"VBN\"," + "\"estb_mac\":\"12:34:56:78:90:AB\"," + "\"eth_mac\":\"12:34:56:78:90:AB\"," + "\"friendly_id\":\"Abc XYZ\"," + "\"imageVersion\":\"ABCADS_VBN_2022010101sdy__MH_SPLASH_TEST_2\"," + "\"version\":\"ABCADS_VBN_2022010101sdy__MH_SPLASH_TEST_2\"," + "\"software_version\":\"ABCADS_VBN_2022010101sdy__MH_SPLASH_TEST_2\"," + "\"model_number\":\"ABC123ADS\"," + "\"wifi_mac\":\"12:34:56:78:90:AB\"," + "\"success\":true" + "}")); + + file.Destroy(); +} + +TEST_F(WarehouseResetDeviceTest, statusChangeEvent) +{ + IARM_BUS_PWRMgr_WareHouseOpn_EventData_t eventData = {IARM_BUS_PWRMGR_WAREHOUSE_RESET, IARM_BUS_PWRMGR_WAREHOUSE_COMPLETED}; + whMgrStatusChangeEventsHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_WAREHOUSEOPS_STATUSCHANGED, &eventData, 0); + EXPECT_EQ(Core::ERROR_NONE, resetDone.Lock()); +} diff --git a/NetworkManager/Tests/L1Tests/tests/test_WifiManager.cpp b/NetworkManager/Tests/L1Tests/tests/test_WifiManager.cpp new file mode 100755 index 0000000000..99b8e54616 --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_WifiManager.cpp @@ -0,0 +1,591 @@ +#include +#include +#include "WifiManager.h" + +#include "ServiceMock.h" +#include "IarmBusMock.h" +#include "WrapsMock.h" +#include "FactoriesImplementation.h" +#include "WifiManagerDefines.h" + +using namespace WPEFramework; + +using ::testing::NiceMock; + +class WifiManagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + Core::JSONRPC::Message message; + WrapsImplMock *p_wrapsImplMock = nullptr ; + NiceMock iarmBusImplMock; + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + ServiceMock services; + + WifiManagerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + } + virtual ~WifiManagerTest() override + { + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } +}; + +class WifiInitializedEventTest : public WifiManagerTest { +protected: + FactoriesImplementation factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + + WifiInitializedEventTest() + : WifiManagerTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&services); + } + + virtual ~WifiInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + PluginHost::IFactories::Assign(nullptr); + + } +}; + + +TEST_F(WifiManagerTest, TestedAPIsShouldExist) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("connect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancelWPSPairing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("saveSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setSignalThresholdChangeEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSIDInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isPaired"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCurrentState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getConnectedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getQuirks"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isSignalThresholdChangeEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSupportedSecurityModes"))); +} + + +TEST_F(WifiManagerTest, setEnabled) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled))); + auto param = static_cast(arg); + EXPECT_EQ(param->isInterfaceEnabled, true); + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enable\":true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(WifiManagerTest, getCurrentState) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getCurrentState))); + auto param = static_cast(arg); + param->data.wifiStatus = WIFI_DISCONNECTED; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"state\":2,\"success\":true}")); // WIFI_PAIRING enum 3 +} + +TEST_F(WifiManagerTest, getPairedSSID) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSID, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ssid\":\"rdk.test.wifi.network\",\"success\":true}")); +} + +TEST_F(WifiManagerTest, getPairedSSIDi_cache) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSID, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ssid\":\"rdk.test.wifi.network\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"ssid\":\"rdk.test.wifi.network\",\"success\":true}")); +} + +TEST_F(WifiManagerTest, getPairedSSID_failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSID, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + return IARM_RESULT_IPCCORE_FAIL; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); +} + +TEST_F(WifiManagerTest, getPairedSSIDInfo) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSIDInfo.ssid, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + memcpy(¶m->data.getPairedSSIDInfo.bssid, "ff:ff:ff:ff:ff:ff", sizeof("ff:ff:ff:ff:ff:ff")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ssid\":\"rdk.test.wifi.network\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"bssid\":\"ff:ff:ff:ff:ff:ff\""))); +} + +TEST_F(WifiManagerTest, getPairedSSIDInfo_cache) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSIDInfo.ssid, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + memcpy(¶m->data.getPairedSSIDInfo.bssid, "ff:ff:ff:ff:ff:ff", sizeof("ff:ff:ff:ff:ff:ff")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ssid\":\"rdk.test.wifi.network\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"bssid\":\"ff:ff:ff:ff:ff:ff\""))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ssid\":\"rdk.test.wifi.network\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"bssid\":\"ff:ff:ff:ff:ff:ff\""))); +} + +TEST_F(WifiManagerTest, getPairedSSIDInfo_fail) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSIDInfo.ssid, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + memcpy(¶m->data.getPairedSSIDInfo.bssid, "ff:ff:ff:ff:ff:ff", sizeof("ff:ff:ff:ff:ff:ff")); + return IARM_RESULT_IPCCORE_FAIL; + }); + + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); +} + + +TEST_F(WifiManagerTest, getConnectedSSID) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getConnectedSSID))); + auto param = static_cast(arg); + memcpy(¶m->data.getConnectedSSID.ssid, "rdk.test.wifi.network", sizeof("rdk.test.wifi.network")); + memcpy(¶m->data.getConnectedSSID.bssid, "ff:ff:ff:ff:ff:ff", sizeof("ff:ff:ff:ff:ff:ff")); + param->data.getConnectedSSID.rate = 130.000; + param->data.getConnectedSSID.noise = -88.000; + param->data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + param->data.getConnectedSSID.signalStrength = -33.00; + param->data.getConnectedSSID.frequency = 2437.00; + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"ssid\":\"rdk.test.wifi.network\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"bssid\":\"ff:ff:ff:ff:ff:ff\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"rate\":\"130.000000\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"noise\":\"-88.000000\""))); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"frequency\":\"2.437000\""))); +} + +TEST_F(WifiManagerTest, connect) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_connect))); + auto param = static_cast(arg); + param->status = true; + EXPECT_EQ(string(param->data.connect.ssid), string(_T("123412341234"))); + EXPECT_EQ(string(param->data.connect.passphrase), string(_T("password"))); + EXPECT_EQ(param->data.connect.security_mode, NET_WIFI_SECURITY_WEP_128); //securityMode: 2 (NET_WIFI_SECURITY_WEP_128) + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("connect"), _T("{\"ssid\": \"123412341234\",\"passphrase\": \"password\",\"securityMode\": 2}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(WifiManagerTest, disconnect) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_disconnectSSID))); + auto param = static_cast(arg); + param->status = true; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("disconnect"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); +} + +TEST_F(WifiManagerTest, saveSSID) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_saveSSID))); + auto param = static_cast(arg); + param->status = true; + EXPECT_EQ(string(param->data.connect.ssid), string(_T("123412341234"))); + EXPECT_EQ(string(param->data.connect.passphrase), string(_T("password"))); + EXPECT_EQ(param->data.connect.security_mode, NET_WIFI_SECURITY_WEP_128); //securityMode: 2 (NET_WIFI_SECURITY_WEP_128) + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("saveSSID"), _T("{\"ssid\": \"123412341234\",\"passphrase\": \"password\",\"securityMode\": 2}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); +} + +TEST_F(WifiManagerTest, clearSSID) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_clearSSID))); + auto param = static_cast(arg); + param->status = true; + return IARM_RESULT_SUCCESS; + }); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); +} + +TEST_F(WifiManagerTest, isPaired) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSIDInfo.ssid, "123412341234", sizeof("123412341234")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); +} + +TEST_F(WifiManagerTest, isPaired_cache) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getPairedSSIDInfo))); + auto param = static_cast(arg); + memcpy(¶m->data.getPairedSSIDInfo.ssid, "123412341234", sizeof("123412341234")); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); +} + +TEST_F(WifiManagerTest, startScan) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startScan"), _T("{\"incremental\": false,\"ssid\": \"...\",\"frequency\": \"...\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsyncIncr))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startScan"), _T("{\"incremental\": true,\"ssid\": \"...\",\"frequency\": \"...\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(WifiManagerTest, stopScan) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopScan"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(WifiManagerTest, cancelWPSPairing) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_cancelWPSPairing))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("cancelWPSPairing"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":\"\",\"success\":true}")); +} + +TEST_F(WifiManagerTest, initiateWPSPairing) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_initiateWPSPairing))); + return IARM_RESULT_SUCCESS; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("initiateWPSPairing"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":\"\",\"success\":true}")); +} + +TEST_F(WifiManagerTest, initiateWPSPairing2) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call) + .Times(::testing::AnyNumber()) + .WillRepeatedly( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + EXPECT_EQ(string(ownerName), string(_T(IARM_BUS_NM_SRV_MGR_NAME))); + EXPECT_EQ(string(methodName), string(_T(IARM_BUS_WIFI_MGR_API_initiateWPSPairing2))); + return IARM_RESULT_SUCCESS; + }); + + + JsonObject jsonObj; + JsonObject res; + jsonObj["method"] = "PIN"; + jsonObj["wps_pin"] = "88888888"; + uint32_t result = plugin->initiateWPSPairing2(jsonObj,res); + EXPECT_EQ(result, 0); +} + + +TEST_F(WifiManagerTest, SignalThresholdChangeEnabled) +{ + ServiceMock service; + EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isSignalThresholdChangeEnabled"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":1,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setSignalThresholdChangeEnabled"), _T("{\"enabled\": true, \"interval\":2000}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isSignalThresholdChangeEnabled"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"result\":0,\"success\":true}")); + plugin->Deinitialize(&service); +} + +TEST_F(WifiManagerTest, getSupportedSecurityModes) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedSecurityModes"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(WifiManagerTest, getQuirks) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getQuirks"), _T("{}"), response)); + EXPECT_THAT(response, ::testing::ContainsRegex(_T("\"success\":true"))); +} + +TEST_F(WifiInitializedEventTest, onWIFIStateChanged) +{ + EXPECT_CALL(services, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.WifiManager.onWIFIStateChanged\",\"params\":{\"state\":1,\"isLNF\":false}}"))); + return Core::ERROR_NONE; + })); + WPEFramework::Plugin::WifiState intData = WPEFramework::Plugin::WifiState::DISABLED; + handler.Subscribe(0, _T("onWIFIStateChanged"), _T("org.rdk.WifiManager"), message); + plugin->onWIFIStateChanged(intData,false); + handler.Unsubscribe(0, _T("onWIFIStateChanged"), _T("org.rdk.WifiManager"), message); +} + +TEST_F(WifiInitializedEventTest, onSSIDsChanged) +{ + EXPECT_CALL(services, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.WifiManager.onSSIDsChanged\",\"params\":{}}"))); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onSSIDsChanged"), _T("org.rdk.WifiManager"), message); + plugin->onSSIDsChanged(); + handler.Unsubscribe(0, _T("onSSIDsChanged"), _T("org.rdk.WifiManager"), message); +} +TEST_F(WifiInitializedEventTest, onWifiSignalThresholdChanged) +{ + EXPECT_CALL(services, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.WifiManager.onWifiSignalThresholdChanged\",\"params\":{\"signalStrength\":\"-27.000000\",\"strength\":\"Excellent\"}}"))); + return Core::ERROR_NONE; + })); + handler.Subscribe(0, _T("onWifiSignalThresholdChanged"), _T("org.rdk.WifiManager"), message); + plugin->onWifiSignalThresholdChanged(-27.000000,"Excellent"); + handler.Unsubscribe(0, _T("onWifiSignalThresholdChanged"), _T("org.rdk.WifiManager"), message); +} + +TEST_F(WifiInitializedEventTest, onError) +{ + EXPECT_CALL(services, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.WifiManager.onError\",\"params\":{\"code\":2}}"))); + return Core::ERROR_NONE; + })); + WPEFramework::Plugin::ErrorCode intData = WPEFramework::Plugin::ErrorCode::CONNECTION_FAILED; + handler.Subscribe(0, _T("onError"), _T("org.rdk.WifiManager"), message); + plugin->onError(intData); + handler.Unsubscribe(0, _T("onError"), _T("org.rdk.WifiManager"), message); +} + + +TEST_F(WifiInitializedEventTest, onAvailableSSIDs) +{ + EXPECT_CALL(services, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.WifiManager.onAvailableSSIDs\",\"params\":{\"ssid\":\"123412341234\",\"security\":2,\"signalStrength\":\"-27.000000\",\"frequency\":\"2.442000\"}}"))); + return Core::ERROR_NONE; + })); + JsonObject jsonObj; + jsonObj["ssid"] = "123412341234"; + jsonObj["security"] = 2; + jsonObj["signalStrength"] = "-27.000000"; + jsonObj["frequency"] = "2.442000"; + handler.Subscribe(0, _T("onAvailableSSIDs"), _T("org.rdk.WifiManager"), message); + plugin->onAvailableSSIDs(jsonObj); + handler.Unsubscribe(0, _T("onAvailableSSIDs"), _T("org.rdk.WifiManager"), message); +} + diff --git a/NetworkManager/Tests/L1Tests/tests/test_XCast.cpp b/NetworkManager/Tests/L1Tests/tests/test_XCast.cpp new file mode 100755 index 0000000000..1fb8888e9e --- /dev/null +++ b/NetworkManager/Tests/L1Tests/tests/test_XCast.cpp @@ -0,0 +1,616 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "FactoriesImplementation.h" + +#include "XCast.h" +//#include "RtXcastConnector.h" +#include "RfcApiMock.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" + +#include "dsMgr.h" +#include "devicesettings.h" +#include "RtObjectBaseMock.h" +#include "FloatingRtFunctionsMock.h" +#include "RtObjectRefMock.h" +#include "RtArrayObjectMock.h" +#include "ServiceMock.h" +#include "DispatcherMock.h" + +//Required, xdialCastObj cannot be moved into the .h, as we don't +//want header includes to have access to the object +#include "RtXcastConnector.cpp" + +using namespace WPEFramework; + +using ::testing::NiceMock; +using ::testing::Eq; + +class XCastPreLoad : public ::testing::Test { + protected: + RfcApiImplMock *p_rfcApiImplMock = nullptr ; + + XCastPreLoad() + { + p_rfcApiImplMock = new NiceMock ; + RfcApi::setImpl(p_rfcApiImplMock); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + EXPECT_EQ(string(pcCallerID), string("Xcast")); + EXPECT_EQ(string(pcParameterName), string("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.Enable")); + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + pstParamData->type = WDMP_BOOLEAN; + return WDMP_SUCCESS; + })); + } + + virtual ~XCastPreLoad() override + { + RfcApi::setImpl(nullptr); + if (p_rfcApiImplMock != nullptr) + { + delete p_rfcApiImplMock; + p_rfcApiImplMock = nullptr; + } + } + +}; + +class XCastTest : public XCastPreLoad { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Connection connection; + string response; + + XCastTest() + : XCastPreLoad() + , plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , connection(1, 0) + { + + + } + virtual ~XCastTest() = default; +}; + +class XCastDsTest : public XCastTest { +protected: + rtObjectBaseMock *p_rtBaseMock = nullptr ; + + XCastDsTest() + : XCastTest() + { + rtObjectBase::setImpl(p_rtBaseMock); + } + virtual ~XCastDsTest() override + { + rtObjectBase::setImpl(nullptr); + if (p_rtBaseMock != nullptr) + { + delete p_rtBaseMock; + p_rtBaseMock = nullptr; + } + } +}; + +class XCastInitializedTest : public XCastTest { +protected: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + IARM_EventHandler_t dsHdmiEventHandler; + IARM_EventHandler_t dsHdmiStatusEventHandler; + IARM_EventHandler_t dsHdmiSignalStatusEventHandler; + IARM_EventHandler_t dsHdmiVideoModeEventHandler; + IARM_EventHandler_t dsHdmiGameFeatureStatusEventHandler; + + floatingRtFunctionsMock *p_rtFloatingMock = nullptr ; + rtObjectBaseMock *p_rtBaseMock = nullptr ; + rtObjectRefMock *p_rtRefMock = nullptr ; + rtArrayObjectMock *p_rtArrayMock = nullptr ; + + NiceMock service; + XCastInitializedTest() + : XCastTest() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + + p_rtBaseMock = new NiceMock ; + rtObjectBase::setImpl(p_rtBaseMock); + + p_rtRefMock = new NiceMock ; + rtObjectRef::setImpl(p_rtRefMock); + + p_rtFloatingMock = new NiceMock ; + floatingRtFunctions::setImpl(p_rtFloatingMock); + + p_rtArrayMock = new NiceMock ; + rtArrayObject::setImpl(p_rtArrayMock); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + return nullptr; + })); + + ON_CALL(*p_rtFloatingMock, rtRemoteLocateObject(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](rtRemoteEnvironment *env, const char* str, rtObjectRef& obj, int x, remoteDisconnectCallback back, void *cbdata=NULL) { + rtIObject rtIObj; + obj = &rtIObj; + return RT_OK; + })); + + ON_CALL(*p_rfcApiImplMock, getRFCParameter(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](char* pcCallerID, const char* pcParameterName, RFC_ParamData_t* pstParamData) { + EXPECT_EQ(string(pcCallerID), string("Xcast")); + EXPECT_EQ(string(pcParameterName), string("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.XDial.DynamicAppList")); + strncpy(pstParamData->value, "true", sizeof(pstParamData->value)); + pstParamData->type = WDMP_BOOLEAN; + return WDMP_SUCCESS; + })); + + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + /*if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_API_GetPowerState)) { + EXPECT_TRUE(handler != nullptr); + dsHdmiEventHandler = handler; + }*/ + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault( + [](const char* ownerName, const char* methodName, void* arg, size_t argLen) { + auto* param = static_cast(arg); + param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; + return IARM_RESULT_SUCCESS; + }); + + + ON_CALL(*p_rtRefMock, send(::testing::_, ::testing::_,::testing::_)) + .WillByDefault( + [](const char* messageName, const char* method, rtFunctionCallback* callback) { + delete callback; + callback = nullptr; + return RT_OK; + }); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + //Wait until threads populate xdialCastObj. + int iCounter = 0; + while ((xdialCastObj == NULL) && (iCounter < (5*10))) { //sleep for 2sec. + usleep (100 * 1000); //sleep for 100 milli sec + iCounter ++; + } + + //required to enable some backend processes for certain functions. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnabled"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + } + virtual ~XCastInitializedTest() override + { + plugin->Deinitialize(&service); + + floatingRtFunctions::setImpl(nullptr); + if (p_rtFloatingMock != nullptr) + { + delete p_rtFloatingMock; + p_rtFloatingMock = nullptr; + } + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + rtObjectBase::setImpl(nullptr); + if (p_rtBaseMock != nullptr) + { + delete p_rtBaseMock; + p_rtBaseMock = nullptr; + } + + rtObjectRef::setImpl(nullptr); + if (p_rtRefMock != nullptr) + { + delete p_rtRefMock; + p_rtRefMock = nullptr; + } + + rtArrayObject::setImpl(nullptr); + if (p_rtArrayMock != nullptr) + { + delete p_rtArrayMock; + p_rtArrayMock = nullptr; + } + } +}; + + +class XCastInitializedEventTest : public XCastInitializedTest { +protected: + NiceMock service; + Core::JSONRPC::Message message; + NiceMock factoriesImplementation; + PluginHost::IDispatcher* dispatcher; + + XCastInitializedEventTest() + : XCastInitializedTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PluginHost::IDispatcher::ID)); + dispatcher->Activate(&service); + } + + virtual ~XCastInitializedEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } +}; + +TEST_F(XCastTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getApiVersionNumber"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("onApplicationStateChanged"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStandbyBehavior"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setStandbyBehavior"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getFriendlyName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setFriendlyName"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getProtocolVersion"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("unregisterApplications"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getProtocolVersion"))); +} + + +TEST_F(XCastDsTest, getApiVersionNumber) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getApiVersionNumber"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"version\":1,\"success\":true}")); +} +TEST_F(XCastDsTest, getProtocolVersion) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getProtocolVersion"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"version\":\"2.1\",\"success\":true}")); +} + +TEST_F(XCastDsTest, getsetFriendlyName) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setFriendlyName"), _T("{\"friendlyname\": \"friendlyTest\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getFriendlyName"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"friendlyname\":\"friendlyTest\",\"success\":true}")); +} + +TEST_F(XCastDsTest, getsetStandbyBehavoir) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setStandbyBehavior"), _T("{\"standbybehavior\": \"active\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStandbyBehavior"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"standbybehavior\":\"active\",\"success\":true}")); +} + +TEST_F(XCastInitializedTest, onApplicationStateChanged) +{ + EXPECT_CALL(*p_rtBaseMock, set(::testing::_, ::testing::Matcher(::testing::_))) + .WillOnce(::testing::Invoke( + [](const char* name, const char* value) { + std::string cnv = value; + EXPECT_EQ("Netflix", cnv); + return RT_OK; + })) + .WillOnce(::testing::Invoke( + [](const char* name, const char* value) { + std::string cnv = value; + EXPECT_EQ("1234", cnv); + return RT_OK; + })) + .WillOnce(::testing::Invoke( + [](const char* name, const char* value) { + std::string cnv = value; + EXPECT_EQ("running", cnv); + return RT_OK; + })) + .WillOnce(::testing::Invoke( + [](const char* name, const char* value) { + std::string cnv = value; + EXPECT_EQ("", cnv); + return RT_OK; + })) + .WillRepeatedly(::testing::Invoke( + [](const char* name, const char* value) { + return RT_OK; + })); + ON_CALL(*p_rtRefMock, send(::testing::_, ::testing::Matcher(::testing::_))) + .WillByDefault(::testing::Invoke( + [](const char* messageName, rtObjectRef& ref) { + delete ref.mRef; + return RT_OK; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("onApplicationStateChanged"), _T("{\"applicationName\": \"NetflixApp\", \"state\":\"running\", \"applicationId\": \"1234\", \"error\": \"\"}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + +} + +TEST_F(XCastInitializedTest, getProtocolVersionInitialized) +{ + ON_CALL(*p_rtBaseMock, sendReturns(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* messageName, rtString& result) { + + std::string tmp = "test"; + result = tmp.c_str(); + + return RT_OK; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getProtocolVersion"), _T("{}"), response)); + EXPECT_EQ(response, string("{\"version\":\"test\",\"success\":true}")); +} + +TEST_F(XCastInitializedTest, unregisterApplications) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("unregisterApplications"), _T("{\"applications\": [\"NetflixApp\", \"NetFlixApp2\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(XCastInitializedTest, unRegisterAllApplications) +{ + + EXPECT_CALL(*p_rtArrayMock, pushBack(::testing::Matcher(::testing::_))) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("Youtube", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("myYouTube", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("youtube.com", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("Netflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("myNetflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("netflix.com", strValue); + })) + //First six are from the registerApplications call + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("Netflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("myNetflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("netflix.com", strValue); + })); + //Last three are the ones remaining afte youtube has been unregistered. + EXPECT_CALL(*p_rtBaseMock, set(::testing::_, ::testing::Matcher(::testing::_))) + .WillOnce(::testing::Invoke( + [](const char* name, bool value) { + bool testBool = true; + EXPECT_EQ(testBool, value); + + return RT_OK; + })) + .WillOnce(::testing::Invoke( + [](const char* name, bool value) { + bool testBool = true; + EXPECT_EQ(testBool, value); + + return RT_OK; + })) + //First two are form register Applications call. + .WillOnce(::testing::Invoke( + [](const char* name, bool value) { + bool testBool = true; + EXPECT_EQ(testBool, value); + + return RT_OK; + })); + //Last is from the remaining once Youtube has been unregistered. + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("registerApplications"), _T("{\"applications\": [{\"names\": [\"Youtube\"], \"prefixes\": [\"myYouTube\"], \"cors\": [\"youtube.com\"], \"properties\": {\"allowStop\": true}},{\"names\": [\"Netflix\"], \"prefixes\": [\"myNetflix\"], \"cors\": [\"netflix.com\"], \"properties\": {\"allowStop\": true}, \"launchParameters\": {\"query\":\"testquery\", \"payload\":\"testpayload\"}}]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("unregisterApplications"), _T("{\"applications\": [\"Youtube\"]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + +TEST_F(XCastInitializedTest, registerApplications) +{ + + EXPECT_CALL(*p_rtArrayMock, pushBack(::testing::Matcher(::testing::_))) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("Youtube", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("myYouTube", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("youtube.com", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("Netflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("myNetflix", strValue); + })) + .WillOnce(::testing::Invoke( + [](const char* value) { + std::string strValue = value; + EXPECT_EQ("netflix.com", strValue); + })); + //Last three are the ones remaining afte youtube has been unregistered. + EXPECT_CALL(*p_rtBaseMock, set(::testing::_, ::testing::Matcher(::testing::_))) + .WillOnce(::testing::Invoke( + [](const char* name, bool value) { + bool testBool = true; + EXPECT_EQ(testBool, value); + + return RT_OK; + })) + .WillOnce(::testing::Invoke( + [](const char* name, bool value) { + bool testBool = true; + EXPECT_EQ(testBool, value); + + return RT_OK; + })); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("registerApplications"), _T("{\"applications\": [{\"names\": [\"Youtube\"], \"prefixes\": [\"myYouTube\"], \"cors\": [\"youtube.com\"], \"properties\": {\"allowStop\": true}},{\"names\": [\"Netflix\"], \"prefixes\": [\"myNetflix\"], \"cors\": [\"netflix.com\"], \"properties\": {\"allowStop\": true}, \"launchParameters\": {\"query\":\"testquery\", \"payload\":\"testpayload\"}}]}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("unregisterApplications"), _T("{\"applications\": []}"), response)); + EXPECT_EQ(response, string("{\"success\":true}")); +} + + +TEST_F(XCastInitializedEventTest, onApplicationHideRequest) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onApplicationHideRequest\",\"params\":{\"applicationName\":\"NetflixApp\",\"applicationId\":\"1234\"}}"))); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onApplicationHideRequest"), _T("client.events"), message); + plugin->onXcastApplicationHideRequest("Netflix", "1234"); + handler.Unsubscribe(0, _T("onApplicationHideRequest"), _T("client.events"), message); +} +TEST_F(XCastInitializedEventTest, onApplicationStateRequest) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onApplicationStateRequest\",\"params\":{\"applicationName\":\"NetflixApp\",\"applicationId\":\"1234\"}}"))); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onApplicationStateRequest"), _T("client.events"), message); + plugin->onXcastApplicationStateRequest("Netflix", "1234"); + handler.Unsubscribe(0, _T("onApplicationStateRequest"), _T("client.events"), message); +} +TEST_F(XCastInitializedEventTest, onApplicationLaunchRequest) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onApplicationLaunchRequest\",\"params\":{\"applicationName\":\"Netflix\",\"parameters\":{\"url\":\"1234\"}}}"))); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onApplicationLaunchRequest"), _T("client.events"), message); + plugin->onXcastApplicationLaunchRequest("Netflix", "1234"); + handler.Unsubscribe(0, _T("onApplicationLaunchRequest"), _T("client.events"), message); +} +TEST_F(XCastInitializedEventTest, onApplicationResumeRequest) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onApplicationResumeRequest\",\"params\":{\"applicationName\":\"NetflixApp\",\"applicationId\":\"1234\"}}"))); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onApplicationResumeRequest"), _T("client.events"), message); + plugin->onXcastApplicationResumeRequest("Netflix", "1234"); + handler.Unsubscribe(0, _T("onApplicationResumeRequest"), _T("client.events"), message); +} +TEST_F(XCastInitializedEventTest, onApplicationStopRequest) +{ + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onApplicationStopRequest\",\"params\":{\"applicationName\":\"Netflix\",\"applicationId\":\"1234\"}}"))); + return Core::ERROR_NONE; + })); + + handler.Subscribe(0, _T("onApplicationStopRequest"), _T("client.events"), message); + plugin->onXcastApplicationStopRequest("Netflix", "1234"); + handler.Unsubscribe(0, _T("onApplicationStopRequest"), _T("client.events"), message); +} diff --git a/NetworkManager/Tests/clang.cmake b/NetworkManager/Tests/clang.cmake new file mode 100644 index 0000000000..f5a97f56a3 --- /dev/null +++ b/NetworkManager/Tests/clang.cmake @@ -0,0 +1,12 @@ +set(CMAKE_C_COMPILER "/usr/bin/clang") +set(CMAKE_CXX_COMPILER "/usr/bin/clang++") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=missing-braces") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=dangling-gsl") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-const-variable") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=inconsistent-missing-override") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-parameter") + +# clang Valgrind: debuginfo reader: ensure_valid failed +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -gdwarf-4") diff --git a/NetworkManager/Tests/gcc-with-coverage.cmake b/NetworkManager/Tests/gcc-with-coverage.cmake new file mode 100644 index 0000000000..cb8d689eb7 --- /dev/null +++ b/NetworkManager/Tests/gcc-with-coverage.cmake @@ -0,0 +1 @@ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/NetworkManager/Tests/mocks/CMakeLists.txt b/NetworkManager/Tests/mocks/CMakeLists.txt new file mode 100755 index 0000000000..5029fabefd --- /dev/null +++ b/NetworkManager/Tests/mocks/CMakeLists.txt @@ -0,0 +1,48 @@ +#if not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 Synamedia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.8) +set(MODULE_NAME TestMocklib) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/e39786088138f2749d64e9e90e0f9902daa77c40.zip +) +FetchContent_MakeAvailable(googletest) + + +add_library(${MODULE_NAME} SHARED + Rfc.cpp + Iarm.cpp + Wraps.cpp + RBus.cpp + Telemetry.cpp + devicesettings.cpp + Udev.cpp +) +target_link_libraries(${MODULE_NAME} PRIVATE gmock_main) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + + +install(TARGETS ${MODULE_NAME} + DESTINATION lib) + + diff --git a/NetworkManager/Tests/mocks/Iarm.cpp b/NetworkManager/Tests/mocks/Iarm.cpp new file mode 100755 index 0000000000..63afa6f610 --- /dev/null +++ b/NetworkManager/Tests/mocks/Iarm.cpp @@ -0,0 +1,104 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 Synamedia +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "Iarm.h" +#include + +IarmBusImpl* IarmBus::impl = nullptr; + +IarmBus::IarmBus() {} + +void IarmBus::setImpl(IarmBusImpl* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +IARM_Result_t IarmBus::IARM_Bus_Init(const char* name) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Init(name); +} + +IARM_Result_t IarmBus::IARM_Bus_Connect() +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Connect(); +} + +IARM_Result_t IarmBus::IARM_Bus_IsConnected(const char* memberName, int* isRegistered) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_IsConnected(memberName, isRegistered); +} + +IARM_Result_t IarmBus::IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RegisterEventHandler(ownerName, eventId, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_UnRegisterEventHandler(ownerName, eventId); +} + +IARM_Result_t IarmBus::IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RemoveEventHandler(ownerName, eventId, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Call(ownerName, methodName, arg, argLen); +} + +IARM_Result_t IarmBus::IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_BroadcastEvent(ownerName, eventId, arg, argLen); +} + + +IARM_Result_t IarmBus::IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RegisterCall(methodName, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Call_with_IPCTimeout(ownerName, methodName, arg, argLen, timeout); +} + +IARM_Result_t (*IARM_Bus_Init)(const char*) = &IarmBus::IARM_Bus_Init; +IARM_Result_t (*IARM_Bus_Connect)() = &IarmBus::IARM_Bus_Connect; +IARM_Result_t (*IARM_Bus_IsConnected)(const char*,int*) = &IarmBus::IARM_Bus_IsConnected; +IARM_Result_t (*IARM_Bus_RegisterEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t) = &IarmBus::IARM_Bus_RegisterEventHandler; +IARM_Result_t (*IARM_Bus_UnRegisterEventHandler)(const char*,IARM_EventId_t) = &IarmBus::IARM_Bus_UnRegisterEventHandler; +IARM_Result_t (*IARM_Bus_RemoveEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t) = &IarmBus::IARM_Bus_RemoveEventHandler; +IARM_Result_t (*IARM_Bus_Call)(const char*,const char*,void*,size_t) = &IarmBus::IARM_Bus_Call; +IARM_Result_t (*IARM_Bus_BroadcastEvent)(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) = &IarmBus::IARM_Bus_BroadcastEvent; +IARM_Result_t (*IARM_Bus_RegisterCall)(const char*,IARM_BusCall_t) = &IarmBus::IARM_Bus_RegisterCall; +IARM_Result_t (*IARM_Bus_Call_with_IPCTimeout)(const char*,const char*,void*,size_t,int) = &IarmBus::IARM_Bus_Call_with_IPCTimeout; diff --git a/NetworkManager/Tests/mocks/Iarm.h b/NetworkManager/Tests/mocks/Iarm.h new file mode 100644 index 0000000000..417a2bb418 --- /dev/null +++ b/NetworkManager/Tests/mocks/Iarm.h @@ -0,0 +1,754 @@ +#pragma once + +#include + +typedef int IARM_EventId_t; + +typedef enum _IARM_Result_t { + IARM_RESULT_SUCCESS, + IARM_RESULT_INVALID_PARAM, + IARM_RESULT_INVALID_STATE, + IARM_RESULT_IPCCORE_FAIL, + IARM_RESULT_OOM, +} IARM_Result_t; + +#define IARM_BUS_DAEMON_NAME "Daemon" + +typedef IARM_Result_t (*IARM_BusCall_t)(void* arg); +typedef void (*IARM_EventHandler_t)(const char* owner, IARM_EventId_t eventId, void* data, size_t len); + +class IarmBusImpl { +public: + virtual ~IarmBusImpl() = default; + + virtual IARM_Result_t IARM_Bus_Init(const char* name) = 0; + virtual IARM_Result_t IARM_Bus_Connect() = 0; + virtual IARM_Result_t IARM_Bus_IsConnected(const char* memberName, int* isRegistered) = 0; + virtual IARM_Result_t IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) = 0; + virtual IARM_Result_t IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId) = 0; + virtual IARM_Result_t IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) = 0; + virtual IARM_Result_t IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen) = 0; + virtual IARM_Result_t IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) = 0; + virtual IARM_Result_t IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler) = 0; + virtual IARM_Result_t IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout) = 0; +}; + +class IarmBus { +protected: + static IarmBusImpl* impl; +public: + IarmBus(); + IarmBus(const IarmBus &obj) = delete; // deleted copy constructor so that copy of the instance cannot be created. + static void setImpl(IarmBusImpl* newImpl); + static IARM_Result_t IARM_Bus_Init(const char* name); + static IARM_Result_t IARM_Bus_Connect(); + static IARM_Result_t IARM_Bus_IsConnected(const char* memberName, int* isRegistered); + static IARM_Result_t IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler); + static IARM_Result_t IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId); + static IARM_Result_t IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler); + static IARM_Result_t IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen); + static IARM_Result_t IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) ; + + static IARM_Result_t IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler); + static IARM_Result_t IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout); +}; + +extern IARM_Result_t (*IARM_Bus_Init)(const char*); +extern IARM_Result_t (*IARM_Bus_Connect)(); +extern IARM_Result_t (*IARM_Bus_IsConnected)(const char*,int*); +extern IARM_Result_t (*IARM_Bus_RegisterEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t); +extern IARM_Result_t (*IARM_Bus_UnRegisterEventHandler)(const char*,IARM_EventId_t); +extern IARM_Result_t (*IARM_Bus_RemoveEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t); +extern IARM_Result_t (*IARM_Bus_Call)(const char*,const char*,void*,size_t); +extern IARM_Result_t (*IARM_Bus_BroadcastEvent)(const char *,IARM_EventId_t,void *,size_t); +extern IARM_Result_t (*IARM_Bus_RegisterCall)(const char*,IARM_BusCall_t); +extern IARM_Result_t (*IARM_Bus_Call_with_IPCTimeout)(const char*,const char*,void*,size_t,int); + +#define IARM_BUS_COMMON_API_SysModeChange "SysModeChange" + +typedef enum _IARM_Bus_Daemon_PowerState_t { + IARM_BUS_PWRMGR_POWERSTATE_OFF, + IARM_BUS_PWRMGR_POWERSTATE_STANDBY, + IARM_BUS_PWRMGR_POWERSTATE_ON, + IARM_BUS_PWRMGR_POWERSTATE_STANDBY_LIGHT_SLEEP, + IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP +} IARM_Bus_PowerState_t; + +typedef IARM_Bus_PowerState_t IARM_Bus_PWRMgr_PowerState_t; + +typedef enum _IARM_Bus_Daemon_SysMode_t { + IARM_BUS_SYS_MODE_NORMAL, + IARM_BUS_SYS_MODE_EAS, + IARM_BUS_SYS_MODE_WAREHOUSE +} IARM_Bus_Daemon_SysMode_t; + +#define IARMBUS_AUDIOCAPTUREMGR_NAME "audiocapturemgr" +#define IARMBUS_AUDIOCAPTUREMGR_REQUEST_SAMPLE "requestSample" + +#define IARMBUS_AUDIOCAPTUREMGR_OPEN "open" +#define IARMBUS_AUDIOCAPTUREMGR_CLOSE "close" +#define IARMBUS_AUDIOCAPTUREMGR_START "start" +#define IARMBUS_AUDIOCAPTUREMGR_STOP "stop" +#define IARMBUS_AUDIOCAPTUREMGR_GET_DEFAULT_AUDIO_PROPS "getDefaultAudioProperties" +#define IARMBUS_AUDIOCAPTUREMGR_GET_AUDIO_PROPS "getAudioProperties" +#define IARMBUS_AUDIOCAPTUREMGR_GET_OUTPUT_PROPS "getOutputProperties" +#define IARMBUS_AUDIOCAPTUREMGR_SET_AUDIO_PROPERTIES "setAudioProperties" +#define IARMBUS_AUDIOCAPTUREMGR_SET_OUTPUT_PROPERTIES "setOutputProperties" + +#define AUDIOCAPTUREMGR_FILENAME_PREFIX "audio_sample" +#define AUDIOCAPTUREMGR_FILE_PATH "/opt/" + +#define DATA_CAPTURE_IARM_EVENT_AUDIO_CLIP_READY 100 + +#define ACM_RESULT_GENERAL_FAILURE 0 +#define ACM_RESULT_PRECAPTURE_NOT_SUPPORTED 1 +#define ACM_RESULT_STREAM_UNAVAILABLE 2 +#define ACM_RESULT_DURATION_OUT_OF_BOUNDS 3 +#define BUFFERED_FILE_OUTPUT "" + +enum Format { + acmFormate16BitStereo, + acmFormate16BitMonoLeft, + acmFormate16BitMonoRight, + acmFormate16BitMono, + acmFormate24BitStereo, + acmFormate24Bit5_1 +}; + +enum Sampling_frequency { + acmFreqe48000, + acmFreqe44100, + acmFreqe32000, + acmFreqe24000, + acmFreqe16000 +}; + +namespace audiocapturemgr { +using session_id_t = int; + +struct audio_properties_ifce_t { + Format format; + Sampling_frequency sampling_frequency; +}; +} + +struct iarmbus_notification_payload_t { + char dataLocator[64]; +}; + +struct iarmbus_acm_arg_t { + struct iarmbus_open_args { + int source; + std::string output_type; + }; + + struct iarmbus_request_payload_t { + float duration; + bool is_precapture; + }; + + struct output_t { + unsigned int buffer_duration; + unsigned int max_buffer_duration; + }; + + struct arg_output_props_t { + output_t output; + }; + + struct Details { + iarmbus_open_args arg_open; + audiocapturemgr::audio_properties_ifce_t arg_audio_properties; + iarmbus_request_payload_t arg_sample_request; + arg_output_props_t arg_output_props; + }; + + int session_id; + int result; + Details details; +}; + +#define IARM_BUS_CECMGR_NAME "CECMgr" +#define IARM_BUS_CECMGR_MAX_DATA_LENGTH 62 +#define IARM_BUS_CECMGR_API_Send "Send" + +typedef struct _IARM_Bus_CECMgr_Send_Param_t { + uint8_t length; + uint8_t data[IARM_BUS_CECMGR_MAX_DATA_LENGTH + 1]; + uint8_t retVal; +} IARM_Bus_CECMgr_Send_Param_t; + +#define IARM_BUS_DEEPSLEEPMGR_NAME "DEEPSLEEPMgr" + +#define IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupReason "GetLastWakeupReason" +#define IARM_BUS_DEEPSLEEPMGR_API_GetLastWakeupKeyCode "GetLastWakeupKeycode" + +typedef enum _DeepSleep_WakeupReason_t { + DEEPSLEEP_WAKEUPREASON_IR = 0, + DEEPSLEEP_WAKEUPREASON_RCU_BT, + DEEPSLEEP_WAKEUPREASON_RCU_RF4CE, + DEEPSLEEP_WAKEUPREASON_GPIO, + DEEPSLEEP_WAKEUPREASON_LAN, + DEEPSLEEP_WAKEUPREASON_WLAN, + DEEPSLEEP_WAKEUPREASON_TIMER, + DEEPSLEEP_WAKEUPREASON_FRONT_PANEL, + DEEPSLEEP_WAKEUPREASON_WATCHDOG, + DEEPSLEEP_WAKEUPREASON_SOFTWARE_RESET, + DEEPSLEEP_WAKEUPREASON_THERMAL_RESET, + DEEPSLEEP_WAKEUPREASON_WARM_RESET, + DEEPSLEEP_WAKEUPREASON_COLDBOOT, + DEEPSLEEP_WAKEUPREASON_STR_AUTH_FAILURE, + DEEPSLEEP_WAKEUPREASON_CEC, + DEEPSLEEP_WAKEUPREASON_PRESENCE, + DEEPSLEEP_WAKEUPREASON_VOICE, + DEEPSLEEP_WAKEUPREASON_UNKNOWN +} DeepSleep_WakeupReason_t; + +typedef struct _DeepSleepMgr_WakeupKeyCode_Param_t { + unsigned int keyCode; +} DeepSleepMgr_WakeupKeyCode_Param_t; + +#define IARM_BUS_MFRLIB_NAME "MFRLib" +#define IARM_BUS_MFRLIB_API_SetBootLoaderPattern "mfrSetBootloaderPattern" +#define IARM_BUS_MFRLIB_API_SetBlSplashScreen "mfrSetBlSplashScreen" +#define IARM_BUS_MFRLIB_API_GetSerializedData "mfrGetManufacturerData" + +typedef enum _mfrSerializedType_t { + mfrSERIALIZED_TYPE_MANUFACTURER = 0, + mfrSERIALIZED_TYPE_MANUFACTUREROUI, + mfrSERIALIZED_TYPE_MODELNAME, + mfrSERIALIZED_TYPE_DESCRIPTION, + mfrSERIALIZED_TYPE_PRODUCTCLASS, + mfrSERIALIZED_TYPE_SERIALNUMBER, + mfrSERIALIZED_TYPE_HARDWAREVERSION, + mfrSERIALIZED_TYPE_SOFTWAREVERSION, + mfrSERIALIZED_TYPE_PROVISIONINGCODE, + mfrSERIALIZED_TYPE_FIRSTUSEDATE, + mfrSERIALIZED_TYPE_DEVICEMAC, + mfrSERIALIZED_TYPE_MOCAMAC, + mfrSERIALIZED_TYPE_HDMIHDCP, + mfrSERIALIZED_TYPE_PDRIVERSION, + mfrSERIALIZED_TYPE_WIFIMAC, + mfrSERIALIZED_TYPE_BLUETOOTHMAC, + mfrSERIALIZED_TYPE_WPSPIN, + mfrSERIALIZED_TYPE_MANUFACTURING_SERIALNUMBER, + mfrSERIALIZED_TYPE_ETHERNETMAC, + mfrSERIALIZED_TYPE_ESTBMAC, + mfrSERIALIZED_TYPE_RF4CEMAC, + mfrSERIALIZED_TYPE_PROVISIONED_MODELNAME, + mfrSERIALIZED_TYPE_PMI, + mfrSERIALIZED_TYPE_HWID, + mfrSERIALIZED_TYPE_MODELNUMBER, + /* boot data */ + mfrSERIALIZED_TYPE_SOC_ID, + mfrSERIALIZED_TYPE_IMAGENAME, + mfrSERIALIZED_TYPE_IMAGETYPE, + mfrSERIALIZED_TYPE_BLVERSION, + /* provisional data */ + mfrSERIALIZED_TYPE_REGION, + /* other data */ + mfrSERIALIZED_TYPE_BDRIVERSION, + /* led data */ + mfrSERIALIZED_TYPE_LED_WHITE_LEVEL, + mfrSERIALIZED_TYPE_LED_PATTERN, + mfrSERIALIZED_TYPE_MAX, +#ifdef PANEL_SERIALIZATION_TYPES + mfrSERIALIZED_TYPE_COREBOARD_SERIALNUMBER=0x51, + mfrSERIALIZED_TYPE_FACTORYBOOT, + mfrSERIALIZED_TYPE_COUNTRYCODE, + mfrSERIALIZED_TYPE_LANGUAGECODE, + mfrSERIALIZED_TYPE_MANUFACTURERDATA, + mfrSERIALIZED_TYPE_CPD_SIZE, + mfrSERIALIZED_TYPE_PANEL_ID, + mfrSERIALIZED_TYPE_PANEL_TYPE, + mfrSERIALIZED_TYPE_PANEL_HDMI_WB_DATA_NORMAL, + mfrSERIALIZED_TYPE_PANEL_HDMI_WB_DATA_COLD, + mfrSERIALIZED_TYPE_PANEL_HDMI_WB_DATA_WARM, + mfrSERIALIZED_TYPE_PANEL_HDMI_WB_DATA_USER, + mfrSERIALIZED_TYPE_PANEL_TV_WB_DATA_NORMAL, + mfrSERIALIZED_TYPE_PANEL_TV_WB_DATA_COLD, + mfrSERIALIZED_TYPE_PANEL_TV_WB_DATA_WARM, + mfrSERIALIZED_TYPE_PANEL_TV_WB_DATA_USER, + mfrSERIALIZED_TYPE_PANEL_AV_WB_DATA_NORMAL, + mfrSERIALIZED_TYPE_PANEL_AV_WB_DATA_COLD, + mfrSERIALIZED_TYPE_PANEL_AV_WB_DATA_WARM, + mfrSERIALIZED_TYPE_PANEL_AV_WB_DATA_USER, + mfrSERIALIZED_TYPE_PANEL_DTB_VERSION, + mfrSERIALIZED_TYPE_PANEL_DTB_DATA_SIZE, + mfrSERIALIZED_TYPE_PANEL_DTB_DATA, + /* panel data*/ + mfrSERIALIZED_TYPE_PANEL_DATA_FUNCTION_STATUS, + mfrSERIALIZED_TYPE_PANEL_DATA_AGEING_TIME, + mfrSERIALIZED_TYPE_PANEL_DATA_POWER_ON_TIME, + mfrSERIALIZED_TYPE_PANEL_DATA_BACKLIGHT_TIME, + mfrSERIALIZED_TYPE_PANEL_DATA_VALID, + mfrSERIALIZED_TYPE_PANEL_DATA_TPV_APP_VERSION, + mfrSERIALIZED_TYPE_PANEL_ALS_CALIBRATION_INDEX0, + mfrSERIALIZED_TYPE_PANEL_ALS_CALIBRATION_INDEX1, + mfrSERIALIZED_TYPE_MAX_PANEL, +#endif +} mfrSerializedType_t; + +typedef enum _mfrBlPattern_t { + mfrBL_PATTERN_NORMAL = 0, + mfrBL_PATTERN_SILENT, + mfrBL_PATTERN_SILENT_LED_ON +} mfrBlPattern_t; + +typedef struct _IARM_Bus_MFRLib_SetBLPattern_Param_t { + mfrBlPattern_t pattern; +} IARM_Bus_MFRLib_SetBLPattern_Param_t; + +typedef struct _IARM_Bus_MFRLib_GetSerializedData_Param_t { + mfrSerializedType_t type; + char buffer[1280]; + int bufLen; +} IARM_Bus_MFRLib_GetSerializedData_Param_t; + +#define PWRMGR_MAX_REBOOT_REASON_LENGTH 100 + +#define MAX_PWR_STATE_BEF_REBOOR_STR_LEN (32) +#define IARM_BUS_PWRMGR_API_GetPowerStateBeforeReboot "GetPowerStateBeforeReboot" +#define IARM_BUS_PWRMGR_API_SetStandbyVideoState "SetStandbyVideoState" +#define IARM_BUS_PWRMGR_API_GetStandbyVideoState "GetStandbyVideoState" +#define IARM_BUS_PWRMGR_API_SetNetworkStandbyMode "SetNetworkStandbyMode" +#define IARM_BUS_PWRMGR_API_GetNetworkStandbyMode "GetNetworkStandbyMode" +#define IARM_BUS_PWRMGR_API_Reboot "performReboot" +#define IARM_BUS_PWRMGR_API_WareHouseClear "WarehouseClear" /*!< */ +#define IARM_BUS_PWRMGR_API_ColdFactoryReset "ColdFactoryReset" /*!< Reset the box to cold factory state*/ +#define IARM_BUS_PWRMGR_API_FactoryReset "FactoryReset" /*!< Reset the box to factory state*/ +#define IARM_BUS_PWRMGR_API_UserFactoryReset "UserFactoryReset" /*!< Reset the box to user factory state*/ +#define IARM_BUS_PWRMGR_API_WareHouseReset "WareHouseReset" /*!< Reset the box to warehouse state*/ + +typedef struct _IARM_Bus_PWRMgr_NetworkStandbyMode_Param_t { + bool bStandbyMode; +} IARM_Bus_PWRMgr_NetworkStandbyMode_Param_t; + +typedef struct _IARM_Bus_PWRMgr_GetPowerStateBeforeReboot_Param_t { + char powerStateBeforeReboot[MAX_PWR_STATE_BEF_REBOOR_STR_LEN]; +} IARM_Bus_PWRMgr_GetPowerStateBeforeReboot_Param_t; + +typedef struct _IARM_Bus_PWRMgr_SetDeepSleepTimeOut_Param_t { + unsigned int timeout; +} IARM_Bus_PWRMgr_SetDeepSleepTimeOut_Param_t; + +typedef enum _IARM_Bus_PWRMgr_ThermalState_t { + IARM_BUS_PWRMGR_TEMPERATURE_NORMAL = 0, + IARM_BUS_PWRMGR_TEMPERATURE_HIGH, + IARM_BUS_PWRMGR_TEMPERATURE_CRITICAL +} IARM_Bus_PWRMgr_ThermalState_t; + +typedef enum _WakeupSrcType_t { + WAKEUPSRC_VOICE = 0, + WAKEUPSRC_PRESENCE_DETECTION, + WAKEUPSRC_BLUETOOTH, + WAKEUPSRC_WIFI, + WAKEUPSRC_IR, + WAKEUPSRC_POWER_KEY, + WAKEUPSRC_TIMER, + WAKEUPSRC_CEC, + WAKEUPSRC_LAN, + WAKEUPSRC_MAX +} WakeupSrcType_t; + +typedef struct _PWRMgr_EventData_t { + union { + struct _MODE_DATA { + IARM_Bus_PWRMgr_PowerState_t curState; + IARM_Bus_PWRMgr_PowerState_t newState; + uint32_t deep_sleep_timeout; + bool nwStandbyMode; + } state; + struct _THERM_DATA { + IARM_Bus_PWRMgr_ThermalState_t curLevel; + IARM_Bus_PWRMgr_ThermalState_t newLevel; + float curTemperature; + } therm; + bool bNetworkStandbyMode; + int32_t reset_sequence_progress; + } data; +} IARM_Bus_PWRMgr_EventData_t; + +typedef struct _IARM_Bus_PWRMgr_GetThermalState_Param_t { + IARM_Bus_PWRMgr_ThermalState_t curLevel; + float curTemperature; +} IARM_Bus_PWRMgr_GetThermalState_Param_t; + +typedef struct _IARM_Bus_PWRMgr_GetTempThresholds_Param_t { + float tempHigh; + float tempCritical; +} IARM_Bus_PWRMgr_GetTempThresholds_Param_t; + +typedef struct _IARM_Bus_PWRMgr_SetTempThresholds_Param_t { + float tempHigh; + float tempCritical; +} IARM_Bus_PWRMgr_SetTempThresholds_Param_t; + +typedef struct _IARM_Bus_PWRMgr_GetOvertempGraceInterval_Param_t { + int graceInterval; +} IARM_Bus_PWRMgr_GetOvertempGraceInterval_Param_t; + +typedef struct _IARM_Bus_PWRMgr_SetOvertempGraceInterval_Param_t { + int graceInterval; +} IARM_Bus_PWRMgr_SetOvertempGraceInterval_Param_t; + +typedef struct _IARM_Bus_CommonAPI_SysModeChange_Param_t { + IARM_Bus_Daemon_SysMode_t oldMode; + IARM_Bus_Daemon_SysMode_t newMode; +} IARM_Bus_CommonAPI_SysModeChange_Param_t; + +typedef enum _PWRMgr_EventId_t { + IARM_BUS_PWRMGR_EVENT_MODECHANGED = 0, + IARM_BUS_PWRMGR_EVENT_DEEPSLEEP_TIMEOUT, + IARM_BUS_PWRMGR_EVENT_RESET_SEQUENCE, + IARM_BUS_PWRMGR_EVENT_REBOOTING, + IARM_BUS_PWRMGR_EVENT_THERMAL_MODECHANGED, + IARM_BUS_PWRMGR_EVENT_WAREHOUSEOPS_STATUSCHANGED, + IARM_BUS_PWRMGR_EVENT_NETWORK_STANDBYMODECHANGED, + IARM_BUS_PWRMGR_EVENT_MAX, +} IARM_Bus_PWRMgr_EventId_t; + +typedef struct _IARM_Bus_PWRMgr_RebootParam_t { + char reboot_reason_custom[PWRMGR_MAX_REBOOT_REASON_LENGTH]; + char reboot_reason_other[PWRMGR_MAX_REBOOT_REASON_LENGTH]; + char requestor[PWRMGR_MAX_REBOOT_REASON_LENGTH]; +} IARM_Bus_PWRMgr_RebootParam_t; + +#define IARM_BUS_PWRMGR_NAME "PWRMgr" +#define IARM_BUS_PWRMGR_API_SetPowerState "SetPowerState" +#define IARM_BUS_PWRMGR_API_GetPowerState "GetPowerState" + +typedef struct _IARM_Bus_PWRMgr_SetPowerState_Param_t { + IARM_Bus_PWRMgr_PowerState_t newState; + int keyCode; +} IARM_Bus_PWRMgr_SetPowerState_Param_t; + +typedef struct _IARM_Bus_PWRMgr_GetPowerState_Param_t { + IARM_Bus_PWRMgr_PowerState_t curState; +} IARM_Bus_PWRMgr_GetPowerState_Param_t; + +#define IARM_BUS_PWRMGR_API_GetThermalState "GetThermalState" +#define IARM_BUS_PWRMGR_API_GetTemperatureThresholds "GetTemperatureThresholds" +#define IARM_BUS_PWRMGR_API_SetTemperatureThresholds "SetTemperatureThresholds" +#define IARM_BUS_PWRMGR_API_GetOvertempGraceInterval "GetOvertempGraceInterval" +#define IARM_BUS_PWRMGR_API_SetOvertempGraceInterval "SetOvertempGraceInterval" + +/** + * @brief Structure which holds the wakeup source type and the value to be set and the power state. + */ +typedef struct _IARM_Bus_PWRMgr_WakeupSrcConfig_Param_t{ + uint32_t pwrMode; + uint32_t srcType; + uint32_t config; +} IARM_Bus_PWRMgr_WakeupSrcConfig_Param_t; +/** + * @brief Structure which holds the ware house reset time. + */ +typedef struct _IARM_Bus_PWRMgr_WareHouseReset_Param_t { + bool suppressReboot; /*!< STB should not be rebooted */ +} IARM_Bus_PWRMgr_WareHouseReset_Param_t; + +/** + * @brief Enumerator which represents the possible warehouse ops + */ +typedef enum _IARM_Bus_PWRMgr_WareHouseOpsStatus_t{ + IARM_BUS_PWRMGR_WAREHOUSE_COMPLETED = 0, /* warehouse operation completed sucessfully */ + IARM_BUS_PWRMGR_WAREHOUSE_INPROGRESS, /* warehouse operation in progress*/ + IARM_BUS_PWRMGR_WAREHOUSE_FAILED, /* warehouse operation failed.*/ +} IARM_Bus_PWRMgr_WareHouseOpsStatus_t; + +/** + * @brief Enumerator which represents the possible warehouse ops + */ +typedef enum _IARM_Bus_PWRMgr_WareHouseOps_t{ + IARM_BUS_PWRMGR_WAREHOUSE_RESET = 0, /* warehouse reset */ + IARM_BUS_PWRMGR_WAREHOUSE_CLEAR, /* warehouse clear*/ +} IARM_Bus_PWRMgr_WareHouseOps_t; + +/** + * @brief Structure which holds warehouse opn status value. + */ +typedef struct _IARM_BUS_PWRMgr_WareHouseOpn_EventData_t { + IARM_Bus_PWRMgr_WareHouseOps_t wareHouseOpn; /*!< WareHouse operation*/ + IARM_Bus_PWRMgr_WareHouseOpsStatus_t status; /*!< WareHouse operation status*/ +} IARM_BUS_PWRMgr_WareHouseOpn_EventData_t; + +#define IARM_BUS_PWRMGR_API_SetWakeupSrcConfig "setWakeupSrcConfig" +#define IARM_BUS_PWRMGR_API_GetWakeupSrcConfig "getWakeupSrcConfig" /*!< gets wakup configuration*/ + +#define IARM_BUS_SYSMGR_NAME "SYSMgr" +#define IARM_BUS_SYSMGR_API_GetSystemStates "GetSystemStates" + +/** + * @brief Structure which holds RFC device management update information. + */ +typedef struct _IARM_BUS_SYSMGR_DeviceMgtUpdateInfo_Param_t +{ + char source[10]; /*!< Device Management Update source. Ex: rfc */ + char type[10]; /*!< Device Management Update type. Ex: initial */ + bool status; /*!< Device Management Update status. true/false */ +} IARM_BUS_SYSMGR_DeviceMgtUpdateInfo_Param_t; + +typedef enum _SYSMgr_EventId_t { + IARM_BUS_SYSMGR_EVENT_SYSTEMSTATE, + IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_REQUEST, /*!< Xupnp data request frm Receiver to UPNP*/ + IARM_BUS_SYSMGR_EVENT_XUPNP_DATA_UPDATE, /*!< Xupnp data frm UPNP to Receiver*/ + IARM_BUS_SYSMGR_EVENT_IMAGE_DNLD, /*Image download status to Receiver */ + IARM_BUS_SYSMGR_EVENT_CARD_FWDNLD, /*!< CARD FW download event to Receiver - Valid on Cisco CA*/ + IARM_BUS_SYSMGR_EVENT_HDCP_PROFILE_UPDATE, /*!< HDCP Profile Update */ + IARM_BUS_SYSMGR_EVENT_INTRUSION, /*!< Intrusion Detection */ + IARM_BUS_SYSMGR_EVENT_EISS_FILTER_STATUS, /*!< EISS Filter status event */ + IARM_BUS_SYSMGR_EVENT_EISS_APP_ID_UPDATE, /*!< EISS App ID update */ + IARM_BUS_SYSMGR_EVENT_KEYCODE_LOGGING_CHANGED, /*!< Key Code logging status update */ + IARM_BUS_SYSMGR_EVENT_USB_MOUNT_CHANGED, /*!< Fires when USB mounts change */ + IARM_BUS_SYSMGR_EVENT_APP_RELEASE_FOCUS, /*!< Application fires event to release focus*/ + IARM_BUS_SYSMGR_EVENT_DEVICE_UPDATE_RECEIVED, /*!< Received Device Management update information */ + IARM_BUS_SYSMGR_EVENT_MAX /*!< Max Event Id */ +} IARM_Bus_SYSMgr_EventId_t; + +typedef struct _IARM_BUS_SYSMGR_KEYCodeLoggingInfo_Param_t { + int logStatus; /*!< HDCP Profile Data */ +} IARM_BUS_SYSMGR_KEYCodeLoggingInfo_Param_t; + +#define IARM_BUS_SYSMGR_API_GetKeyCodeLoggingPref "GetKeyCodeLoggingPref" +#define IARM_BUS_SYSMGR_API_SetKeyCodeLoggingPref "SetKeyCodeLoggingPref" + +typedef enum _SYSMgr_SystemState_t { + IARM_BUS_SYSMGR_SYSSTATE_CHANNELMAP, //0 + IARM_BUS_SYSMGR_SYSSTATE_DISCONNECTMGR, //1 + IARM_BUS_SYSMGR_SYSSTATE_TUNEREADY, //2 + IARM_BUS_SYSMGR_SYSSTATE_EXIT_OK, //3 + IARM_BUS_SYSMGR_SYSSTATE_CMAC, //4 + IARM_BUS_SYSMGR_SYSSTATE_MOTO_ENTITLEMENT, //5 + IARM_BUS_SYSMGR_SYSSTATE_MOTO_HRV_RX, //6 + IARM_BUS_SYSMGR_SYSSTATE_CARD_CISCO_STATUS, //7 + IARM_BUS_SYSMGR_SYSSTATE_VIDEO_PRESENTING, //8 + IARM_BUS_SYSMGR_SYSSTATE_HDMI_OUT, //9 + IARM_BUS_SYSMGR_SYSSTATE_HDCP_ENABLED, //10 + IARM_BUS_SYSMGR_SYSSTATE_HDMI_EDID_READ, //11 + IARM_BUS_SYSMGR_SYSSTATE_FIRMWARE_DWNLD, //12 + IARM_BUS_SYSMGR_SYSSTATE_TIME_SOURCE, //13 + IARM_BUS_SYSMGR_SYSSTATE_TIME_ZONE, //14 + IARM_BUS_SYSMGR_SYSSTATE_CA_SYSTEM, //15 + IARM_BUS_SYSMGR_SYSSTATE_ESTB_IP, //16 + IARM_BUS_SYSMGR_SYSSTATE_ECM_IP, //17 + IARM_BUS_SYSMGR_SYSSTATE_LAN_IP, //18 + IARM_BUS_SYSMGR_SYSSTATE_MOCA, //19 + IARM_BUS_SYSMGR_SYSSTATE_DOCSIS, //20 + IARM_BUS_SYSMGR_SYSSTATE_DSG_BROADCAST_CHANNEL, //21 + IARM_BUS_SYSMGR_SYSSTATE_DSG_CA_TUNNEL, //22 + IARM_BUS_SYSMGR_SYSSTATE_CABLE_CARD, //23 + IARM_BUS_SYSMGR_SYSSTATE_CABLE_CARD_DWNLD, //24 + IARM_BUS_SYSMGR_SYSSTATE_CVR_SUBSYSTEM, //25 + IARM_BUS_SYSMGR_SYSSTATE_DOWNLOAD, //26 + IARM_BUS_SYSMGR_SYSSTATE_VOD_AD, //27 + IARM_BUS_SYSMGR_SYSSTATE_DAC_INIT_TIMESTAMP, //28 + IARM_BUS_SYSMGR_SYSSTATE_CABLE_CARD_SERIAL_NO, //29 + IARM_BUS_SYSMGR_SYSSTATE_ECM_MAC, //30 + IARM_BUS_SYSMGR_SYSSTATE_DAC_ID, //31 + IARM_BUS_SYSMGR_SYSSTATE_PLANT_ID, //32 + IARM_BUS_SYSMGR_SYSSTATE_STB_SERIAL_NO, //33 + IARM_BUS_SYSMGR_SYSSTATE_BOOTUP, //34 + IARM_BUS_SYSMGR_SYSSTATE_GATEWAY_CONNECTION, //35 + IARM_BUS_SYSMGR_SYSSTATE_DST_OFFSET, //36 + IARM_BUS_SYSMGR_SYSSTATE_RF_CONNECTED, //37 + IARM_BUS_SYSMGR_SYSSTATE_PARTNERID_CHANGE, //38 + IARM_BUS_SYSMGR_SYSSTATE_IP_MODE, //39 + IARM_BUS_SYSMGR_SYSSTATE_LP_CONNECTION_RESET, //40 + IARM_BUS_SYSMGR_SYSSTATE_RWS_CONNECTION_RESET, //41 + IARM_BUS_SYSMGR_SYSSTATE_QAM_READY, //42 + IARM_BUS_SYSMGR_SYSSTATE_FIRMWARE_UPDATE_STATE, //43, Added as part of RDK-19978, As the IARM + IARM_BUS_SYSMGR_SYSSTATE_USB_DETECTED, //44 + IARM_BUS_SYSMGR_SYSSTATE_LOG_UPLOAD, //45 + IARM_BUS_SYSMGR_SYSSTATE_RED_RECOV_UPDATE_STATE, //46 +} IARM_Bus_SYSMgr_SystemState_t; + +typedef enum _SYSMgr_FirmwareUpdateState_t { + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_UNINITIALIZED = 0, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_REQUESTING = 1, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_DOWNLOADING = 2, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_FAILED = 3, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_DOWNLOAD_COMPLETE = 4, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_VALIDATION_COMPLETE = 5, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_PREPARING_TO_REBOOT = 6, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_ONHOLD_FOR_OPTOUT = 7, /* On Hold for opt-out */ + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_CRITICAL_REBOOT = 8, + IARM_BUS_SYSMGR_FIRMWARE_UPDATE_STATE_NO_UPGRADE_REQUIRED = 9 +} IARM_Bus_SYSMGR_FirmwareUpdateState_t; + +typedef enum _SYSMgr_RecoveryState_t { + IARM_BUS_SYSMGR_RECOVERY_STATE_COMPLETED = 0, + IARM_BUS_SYSMGR_RECOVERY_STATE_STARTED = 1, + IARM_BUS_SYSMGR_RECOVERY_STATE_DOWNLOADED = 2, + IARM_BUS_SYSMGR_RECOVERY_STATE_PROGRAMMED = 3, +} IARM_Bus_SYSMGR_RecoveryState_t; + +typedef enum _SYSMgr_LogUpload_t +{ + IARM_BUS_SYSMGR_LOG_UPLOAD_SUCCESS = 0, + IARM_BUS_SYSMGR_LOG_UPLOAD_FAILED = 1, + IARM_BUS_SYSMGR_LOG_UPLOAD_ABORTED = 2, +} IARM_Bus_SYSMGR_SYSMgr_LogUpload_t; + +typedef struct _IARM_BUS_SYSMgr_EventData_t { + union { + struct _CARD_FWDNLD_DATA { + char eventType; + char status; + } cardFWDNLD; + struct _IMAGE_FWDNLD_DATA { + char status; + } imageFWDNLD; + struct _XUPNP_DATA { + unsigned long deviceInfoLength; + } xupnpData; + struct _HDCP_PROFILE { + unsigned int hdcpProfile; + } hdcpProfileData; + struct _SystemStates { + IARM_Bus_SYSMgr_SystemState_t stateId; + int state; + int error; + char payload[128]; + } systemStates; + struct _EISS_STATUS { + int filterStatus; + } eissEventData; + struct _EISS_APP_ID { + unsigned char idList[4][6]; + int count; + } eissAppIDList; + struct _KEY_CODE_LOG { + int logStatus; + } keyCodeLogData; + struct _USB_MOUNT { + int mounted; + char device[128]; + char dir[256]; + } usbMountData; + + } data; +} IARM_Bus_SYSMgr_EventData_t; + +typedef struct _propertyValue { + int state; + int error; + char payload[128]; +} state_property; + +typedef struct _IARM_Bus_SYSMgr_GetSystemStates_Param_t { + state_property channel_map; + state_property disconnect_mgr_state; + state_property TuneReadyStatus; + state_property exit_ok_key_sequence; + state_property cmac; + state_property card_moto_entitlements; + state_property card_moto_hrv_rx; + state_property dac_init_timestamp; + state_property card_cisco_status; + state_property video_presenting; + state_property hdmi_out; + state_property hdcp_enabled; + state_property hdmi_edid_read; + state_property firmware_download; + state_property time_source; + state_property time_zone_available; + state_property ca_system; + state_property estb_ip; + state_property ecm_ip; + state_property lan_ip; + state_property moca; + state_property docsis; + state_property dsg_broadcast_tunnel; + state_property dsg_ca_tunnel; + state_property cable_card; + state_property cable_card_download; + state_property cvr_subsystem; + state_property download; + state_property vod_ad; + state_property card_serial_no; + state_property ecm_mac; + state_property dac_id; + state_property plant_id; + state_property stb_serial_no; + state_property bootup; + state_property dst_offset; + state_property rf_connected; + state_property ip_mode; + state_property qam_ready_status; + state_property firmware_update_state; + state_property red_recov_state; +} IARM_Bus_SYSMgr_GetSystemStates_Param_t; + +#define IARM_BUS_DSMGR_NAME "DSMgr" + +/*! Events published from DS Mananger */ +typedef enum _DSMgr_EventId_t { + IARM_BUS_DSMGR_EVENT_RES_PRECHANGE = 0, /*!< Resolution Pre Change Event */ + IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE, /*!< Resolution Post Change Event */ + IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS, /*!< Zoom Settings Events */ + IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, /*!< HDMI HPD DETECT Change Event */ + IARM_BUS_DSMGR_EVENT_AUDIO_MODE, /*!< HDMI HPD DETECT Change Event */ + IARM_BUS_DSMGR_EVENT_HDCP_STATUS, /*!< HDMI HDCP status */ + IARM_BUS_DSMGR_EVENT_RX_SENSE, /*!< HDMI Rx Sense status */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, /*!< HDMI IN HPD change event */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, /*!< HDMI IN signal status change event */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, /*!< HDMI IN status change event */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY, /*!< HDMI IN AV Latency Event */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, /*!< HDMI IN video mode update event */ + IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, /*!< HDMI IN ALLM mode update event */ + IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, /*!< COMPOSITE IN HPD change event */ + IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, /*!< COMPOSITE IN signal status change event */ + IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, /*!< COMPOSITE IN status change event */ + IARM_BUS_DSMGR_EVENT_TIME_FORMAT_CHANGE, /*!< Clock Time Format Change Event*/ + IARM_BUS_DSMGR_EVENT_AUDIO_LEVEL_CHANGED, /*!< Audio Level Change Event*/ + IARM_BUS_DSMGR_EVENT_AUDIO_OUT_HOTPLUG, /*!< AUDIO OUT HPD change event */ + IARM_BUS_DSMGR_EVENT_AUDIO_FORMAT_UPDATE, /*!< Audio Format change event */ + IARM_BUS_DSMGR_EVENT_AUDIO_PRIMARY_LANGUAGE_CHANGED, /*!< Audio Primary Language change event */ + IARM_BUS_DSMGR_EVENT_AUDIO_SECONDARY_LANGUAGE_CHANGED, /*!< Audio Secondary Language change event */ + IARM_BUS_DSMGR_EVENT_AUDIO_FADER_CONTROL_CHANGED, /*!< Audio Fader Control change event */ + IARM_BUS_DSMGR_EVENT_AUDIO_ASSOCIATED_AUDIO_MIXING_CHANGED, /*!< Audio Associated Audio Mixing change event */ + IARM_BUS_DSMGR_EVENT_VIDEO_FORMAT_UPDATE, /*!< Video Format change event */ + IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_PRECHANGE, /*!< Frame rate pre change */ + IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_POSTCHANGE, /*!< Frame rate post change */ + IARM_BUS_DSMGR_EVENT_AUDIO_PORT_STATE, /*!< Audio Port Init State */ + IARM_BUS_DSMGR_EVENT_SLEEP_MODE_CHANGED, /*!< Sleep Mode Change Event*/ + IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE, /*Register(__VA_ARGS__) + + + +#define IARM_BUS_SYSMGR_API_RunScript "RunScript" +/*! Parameter for RunScript call*/ +typedef struct _IARM_Bus_SYSMgr_RunScript_t{ + char script_path [256]; //[in] Null terminated path name of the script. + int return_value; //[out] Returns the ret value of system. +} IARM_Bus_SYSMgr_RunScript_t; + +typedef enum _CECMgr_EventId_t { + IARM_BUS_CECMGR_EVENT_SEND, + IARM_BUS_CECMGR_EVENT_RECV, + IARM_BUS_CECMGR_EVENT_ENABLE, + IARM_BUS_CECMGR_EVENT_DAEMON_INITIALIZED, + IARM_BUS_CECMGR_EVENT_MAX, + IARM_BUS_CECMGR_EVENT_STATUS_UPDATED +} IARM_Bus_CECMgr_EventId_t; + +typedef struct _IARM_Bus_CECMgr_Status_Updated_Param_t +{ + int logicalAddress; +}IARM_Bus_CECMgr_Status_Updated_Param_t; + +typedef struct _IARM_Bus_MFRLib_SetBLSplashScreen_Param{ + char path[255]; +} IARM_Bus_MFRLib_SetBLSplashScreen_Param_t; + +#define IARM_BUS_CECMGR_API_isAvailable "isAvailable" +#define IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs "dsHdmiInGetNumberOfInputs" +#define IARM_BUS_DSMGR_API_dsHdmiInGetStatus "dsHdmiInGetStatus" +#define IARM_BUS_DSMGR_API_dsGetHDMIARCPortId "dsGetHDMIARCPortId" diff --git a/NetworkManager/Tests/mocks/IarmBusMock.h b/NetworkManager/Tests/mocks/IarmBusMock.h new file mode 100644 index 0000000000..61d1c51367 --- /dev/null +++ b/NetworkManager/Tests/mocks/IarmBusMock.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "libIBus.h" + +class IarmBusImplMock : public IarmBusImpl { +public: + IarmBusImplMock() + : IarmBusImpl() + { + // Defaults: + ON_CALL(*this, IARM_Bus_IsConnected(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const char*, int* isRegistered) { + *isRegistered = 1; + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*this, IARM_Bus_Init(::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_Connect()) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_UnRegisterEventHandler(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_Call(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_BroadcastEvent(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_RegisterCall(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_Call_with_IPCTimeout(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + } + virtual ~IarmBusImplMock() = default; + + MOCK_METHOD(IARM_Result_t, IARM_Bus_Init, (const char* name), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Connect, (), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_IsConnected, (const char* memberName, int* isRegistered), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RegisterEventHandler, (const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_UnRegisterEventHandler, (const char* ownerName, IARM_EventId_t eventId), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RemoveEventHandler, (const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Call, (const char* ownerName, const char* methodName, void* arg, size_t argLen), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RegisterCall, (const char* methodName, IARM_BusCall_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_BroadcastEvent, (const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Call_with_IPCTimeout, (const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout), (override)); +}; diff --git a/NetworkManager/Tests/mocks/Udev.cpp b/NetworkManager/Tests/mocks/Udev.cpp new file mode 100755 index 0000000000..a6b8638b5b --- /dev/null +++ b/NetworkManager/Tests/mocks/Udev.cpp @@ -0,0 +1,124 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 Synamedia +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "Udev.h" +#include + +UdevImpl* Udev::impl = nullptr; + +Udev::Udev() {} + + void Udev::setImpl(UdevImpl* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +struct udev* Udev::udev_new() +{ + EXPECT_NE(impl, nullptr); + return impl->udev_new(); +} + +udev_enumerate* Udev::udev_enumerate_new(struct udev* udev) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_enumerate_new(udev); +} + +void Udev::udev_enumerate_add_match_subsystem(struct udev_enumerate* enumerate, const char* subsystem) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_enumerate_add_match_subsystem(enumerate, subsystem); +} + +void Udev::udev_enumerate_scan_devices(struct udev_enumerate* enumerate) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_enumerate_scan_devices(enumerate); +} + +struct udev_list_entry* Udev::udev_enumerate_get_list_entry(struct udev_enumerate* enumerate) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_enumerate_get_list_entry(enumerate); +} + +void Udev::udev_enumerate_unref(struct udev_enumerate* enumerate) + { + EXPECT_NE(impl, nullptr); + return impl->udev_enumerate_unref(enumerate); +} + +void Udev::udev_unref(struct udev* udev) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_unref(udev); +} + +const char* Udev::udev_list_entry_get_name(struct udev_list_entry* entry) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_list_entry_get_name(entry); +} + +struct udev_device* Udev::udev_device_new_from_syspath(struct udev* udev, const char* path) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_device_new_from_syspath(udev, path); +} + +void Udev::udev_device_unref(struct udev_device* dev) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_device_unref(dev); +} + +struct udev_device* Udev::udev_device_get_parent_with_subsystem_devtype(struct udev_device* dev, const char* subsystem, const char* devtype) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_device_get_parent_with_subsystem_devtype(dev, subsystem, devtype); +} + +const char* Udev::udev_device_get_devtype(struct udev_device* dev) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_device_get_devtype(dev); +} + +const char* Udev::udev_device_get_devnode(struct udev_device* dev) +{ + EXPECT_NE(impl, nullptr); + return impl->udev_device_get_devnode(dev); +} + +struct udev* (*udev_new)() = &Udev::udev_new; +udev_enumerate* (*udev_enumerate_new)(struct udev*) = &Udev::udev_enumerate_new; +void (*udev_enumerate_add_match_subsystem)(struct udev_enumerate*, const char*) = &Udev::udev_enumerate_add_match_subsystem; +void (*udev_enumerate_scan_devices)(struct udev_enumerate*) = &Udev::udev_enumerate_scan_devices; +struct udev_list_entry* (*udev_enumerate_get_list_entry)(struct udev_enumerate*) = &Udev::udev_enumerate_get_list_entry; +void (*udev_enumerate_unref)(struct udev_enumerate*) = &Udev::udev_enumerate_unref; +void (*udev_unref)(struct udev*) = &Udev::udev_unref; +const char* (*udev_list_entry_get_name)(struct udev_list_entry*) = &Udev::udev_list_entry_get_name; +struct udev_device* (*udev_device_new_from_syspath)(struct udev*, const char*) = &Udev::udev_device_new_from_syspath; +void (*udev_device_unref)(struct udev_device*) = &Udev::udev_device_unref; +struct udev_device* (*udev_device_get_parent_with_subsystem_devtype)(struct udev_device*, const char*, const char*) = &Udev::udev_device_get_parent_with_subsystem_devtype; +const char* (*udev_device_get_devtype)(struct udev_device*) = &Udev::udev_device_get_devtype; +const char* (*udev_device_get_devnode)(struct udev_device*) = &Udev::udev_device_get_devnode; diff --git a/NetworkManager/Tests/mocks/Udev.h b/NetworkManager/Tests/mocks/Udev.h new file mode 100644 index 0000000000..a9681734be --- /dev/null +++ b/NetworkManager/Tests/mocks/Udev.h @@ -0,0 +1,73 @@ +#pragma once + +struct udev { +}; + +struct udev_enumerate { +}; + +struct udev_list_entry { +}; + +struct udev_device { +}; + +class UdevImpl { +public: + virtual ~UdevImpl() = default; + + virtual struct udev* udev_new() = 0; + virtual struct udev_enumerate* udev_enumerate_new(struct udev* udev) = 0; + virtual void udev_enumerate_add_match_subsystem(struct udev_enumerate* enumerate, const char* subsystem) = 0; + virtual void udev_enumerate_scan_devices(struct udev_enumerate* enumerate) = 0; + virtual struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate* enumerate) = 0; + virtual void udev_enumerate_unref(struct udev_enumerate* enumerate) = 0; + virtual void udev_unref(struct udev* udev) = 0; + virtual const char* udev_list_entry_get_name(struct udev_list_entry* entry) = 0; + virtual struct udev_device* udev_device_new_from_syspath(struct udev* udev, const char* path) = 0; + virtual void udev_device_unref(struct udev_device* dev) = 0; + virtual struct udev_device* udev_device_get_parent_with_subsystem_devtype(struct udev_device* dev, const char* subsystem, const char* devtype) = 0; + virtual const char* udev_device_get_devtype(struct udev_device* dev) = 0; + virtual const char* udev_device_get_devnode(struct udev_device* dev) = 0; +}; + +class Udev { +protected: + static UdevImpl* impl; +public: + Udev(); + Udev(const Udev &obj) = delete; + static void setImpl(UdevImpl* newImpl); + static struct udev* udev_new(); + static udev_enumerate* udev_enumerate_new(struct udev* udev); + static void udev_enumerate_add_match_subsystem(struct udev_enumerate* enumerate, const char* subsystem); + static void udev_enumerate_scan_devices(struct udev_enumerate* enumerate); + static struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate* enumerate); + static void udev_enumerate_unref(struct udev_enumerate* enumerate); + static void udev_unref(struct udev* udev); + static const char* udev_list_entry_get_name(struct udev_list_entry* entry); + static struct udev_device* udev_device_new_from_syspath(struct udev* udev, const char* path); + static void udev_device_unref(struct udev_device* dev); + static struct udev_device* udev_device_get_parent_with_subsystem_devtype(struct udev_device* dev, const char* subsystem, const char* devtype); + static const char* udev_device_get_devtype(struct udev_device* dev); + static const char* udev_device_get_devnode(struct udev_device* dev); +}; + +extern struct udev* (*udev_new)(); +extern udev_enumerate* (*udev_enumerate_new)(struct udev*); +extern void (*udev_enumerate_add_match_subsystem)(struct udev_enumerate*, const char*); +extern void (*udev_enumerate_scan_devices)(struct udev_enumerate*); +extern struct udev_list_entry* (*udev_enumerate_get_list_entry)(struct udev_enumerate*); +extern void (*udev_enumerate_unref)(struct udev_enumerate*); +extern void (*udev_unref)(struct udev*); +extern const char* (*udev_list_entry_get_name)(struct udev_list_entry*); +extern struct udev_device* (*udev_device_new_from_syspath)(struct udev*, const char*); +extern void (*udev_device_unref)(struct udev_device*); +extern struct udev_device* (*udev_device_get_parent_with_subsystem_devtype)(struct udev_device*, const char*, const char*); +extern const char* (*udev_device_get_devtype)(struct udev_device*); +extern const char* (*udev_device_get_devnode)(struct udev_device*); + +#define udev_list_entry_foreach(list_entry, first_entry) \ + for (list_entry = first_entry; \ + list_entry; \ + list_entry = nullptr) diff --git a/NetworkManager/Tests/mocks/UdevMock.h b/NetworkManager/Tests/mocks/UdevMock.h new file mode 100644 index 0000000000..8f34275e61 --- /dev/null +++ b/NetworkManager/Tests/mocks/UdevMock.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "Udev.h" + +class UdevImplMock : public UdevImpl { +public: + virtual ~UdevImplMock() = default; + + MOCK_METHOD(struct udev*, udev_new, (), (override)); + MOCK_METHOD(struct udev_enumerate*, udev_enumerate_new, (struct udev * udev), (override)); + MOCK_METHOD(void, udev_enumerate_add_match_subsystem, (struct udev_enumerate * enumerate, const char* subsystem), (override)); + MOCK_METHOD(void, udev_enumerate_scan_devices, (struct udev_enumerate * enumerate), (override)); + MOCK_METHOD(struct udev_list_entry*, udev_enumerate_get_list_entry, (struct udev_enumerate * enumerate), (override)); + MOCK_METHOD(void, udev_enumerate_unref, (struct udev_enumerate * enumerate), (override)); + MOCK_METHOD(void, udev_unref, (struct udev * udev), (override)); + MOCK_METHOD(const char*, udev_list_entry_get_name, (struct udev_list_entry * entry), (override)); + MOCK_METHOD(struct udev_device*, udev_device_new_from_syspath, (struct udev * udev, const char* path), (override)); + MOCK_METHOD(void, udev_device_unref, (struct udev_device * dev), (override)); + MOCK_METHOD(struct udev_device*, udev_device_get_parent_with_subsystem_devtype, (struct udev_device * dev, const char* subsystem, const char* devtype), (override)); + MOCK_METHOD(const char*, udev_device_get_devtype, (struct udev_device * dev), (override)); + MOCK_METHOD(const char*, udev_device_get_devnode, (struct udev_device * dev), (override)); +}; diff --git a/NetworkManager/Tests/mocks/Wraps.cpp b/NetworkManager/Tests/mocks/Wraps.cpp new file mode 100644 index 0000000000..8a61086adf --- /dev/null +++ b/NetworkManager/Tests/mocks/Wraps.cpp @@ -0,0 +1,151 @@ +#include +#include +#include "Wraps.h" +#include +#include + +extern "C" int __wrap_system(const char* command) +{ + return Wraps::getInstance().system(command); +} + +extern "C" FILE* __wrap_popen(const char* command, const char* type) +{ + return Wraps::getInstance().popen(command, type); +} + +extern "C" int __wrap_pclose(FILE* pipe) +{ + return Wraps::getInstance().pclose(pipe); +} + +//This function will be called for syslog() in the code (added -Wl,-wrap,syslog) +extern "C" void __wrap_syslog(int pri, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Wraps::getInstance().syslog(pri, fmt, args); + vsyslog(pri, fmt, args); + va_end(args); +} + +extern "C" FILE* __wrap_setmntent(const char* command, const char* type) +{ + return Wraps::getInstance().setmntent(command, type); +} + +extern "C" struct mntent* __wrap_getmntent(FILE* pipe) +{ + return Wraps::getInstance().getmntent(pipe); +} + +extern "C" FILE * __wrap_v_secure_popen(const char *direction, const char *command, ...) +{ + va_list args; + FILE *retFp = nullptr; + va_start(args, command); + retFp = Wraps::getInstance().v_secure_popen(direction, command, args); + va_end(args); + return retFp; +} + + +extern "C" int __wrap_v_secure_pclose(FILE *file) +{ + return Wraps::getInstance().v_secure_pclose(file); +} + + +extern "C" int __wrap_v_secure_system(const char *command, ...) +{ + int ret; + va_list args; + va_start(args,command); + ret = Wraps::getInstance().v_secure_system(command, args); + va_end(args); + return ret; +} + +extern "C" ssize_t __wrap_readlink(const char *pathname, char *buf, size_t bufsiz) +{ + return Wraps::getInstance().readlink(pathname, buf, bufsiz); +} + +WrapsImpl* Wraps::impl = nullptr; + +Wraps::Wraps() {} + +void Wraps::setImpl(WrapsImpl* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +Wraps& Wraps::getInstance() +{ + static Wraps instance; + return instance; +} + +int Wraps::system(const char* command) +{ + EXPECT_NE(impl, nullptr); + return impl->system(command); +} + +FILE* Wraps::popen(const char* command, const char* type) +{ + EXPECT_NE(impl, nullptr); + return impl->popen(command, type); +} + +int Wraps::pclose(FILE* pipe) +{ + EXPECT_NE(impl, nullptr); + return impl->pclose(pipe); +} + +void Wraps::syslog(int pri, const char* fmt, va_list args) +{ + EXPECT_NE(impl, nullptr); + impl->syslog(pri, fmt, args); +} + +FILE* Wraps::setmntent(const char* command, const char* type) +{ + EXPECT_NE(impl, nullptr); + return impl->setmntent(command,type); +} + +struct mntent* Wraps::getmntent(FILE* pipe) +{ + EXPECT_NE(impl, nullptr); + return impl->getmntent(pipe); +} + +FILE * Wraps::v_secure_popen(const char *direction, const char *command, va_list args) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_popen(direction, command, args); +} + +int Wraps::v_secure_pclose(FILE *file) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_pclose(file); +} + +int Wraps::v_secure_system(const char *command, va_list args) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_system(command,args); +} + + +ssize_t Wraps::readlink(const char *pathname, char *buf, size_t bufsiz) +{ + EXPECT_NE(impl, nullptr); + return impl->readlink(pathname,buf,bufsiz); +} + diff --git a/NetworkManager/Tests/mocks/Wraps.h b/NetworkManager/Tests/mocks/Wraps.h new file mode 100644 index 0000000000..8dd7da37a7 --- /dev/null +++ b/NetworkManager/Tests/mocks/Wraps.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include "secure_wrappermock.h" + +class WrapsImpl { +public: + virtual ~WrapsImpl() = default; + + virtual int system(const char* command) = 0; + virtual FILE* popen(const char* command, const char* type) = 0; + virtual int pclose(FILE *pipe) = 0; + virtual void syslog(int pri, const char* fmt, va_list args) = 0; + virtual FILE* setmntent(const char* command, const char* type) = 0; + virtual struct mntent* getmntent(FILE *pipe) = 0; + virtual FILE *v_secure_popen(const char *direction, const char *command, va_list args) = 0; + virtual int v_secure_pclose(FILE *) = 0; + virtual int v_secure_system(const char *command, va_list args) =0; + virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) = 0; +}; + +class Wraps { +protected: + static WrapsImpl* impl; + +public: + Wraps(); + Wraps(const Wraps &obj) = delete; + static void setImpl(WrapsImpl* newImpl); + static Wraps& getInstance(); + + static int system(const char* command); + + static FILE* popen(const char* command, const char* type); + + static int pclose(FILE* pipe); + + static void syslog(int pri, const char* fmt, va_list args); + + static FILE* setmntent(const char* command, const char* type); + + static struct mntent* getmntent(FILE* pipe); + + static FILE *v_secure_popen(const char *direction, const char *command, va_list args); + + static int v_secure_pclose(FILE *file); + + static int v_secure_system(const char *command, va_list args); + + ssize_t readlink(const char *pathname, char *buf, size_t bufsiz); +}; diff --git a/NetworkManager/Tests/mocks/WrapsMock.h b/NetworkManager/Tests/mocks/WrapsMock.h new file mode 100644 index 0000000000..2041eab9ee --- /dev/null +++ b/NetworkManager/Tests/mocks/WrapsMock.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "Wraps.h" + +extern "C" FILE* __real_setmntent(const char* command, const char* type); + +class WrapsImplMock : public WrapsImpl { +public: + WrapsImplMock():WrapsImpl() + { + /*Setting up Default behavior for setmntent: + * We are mocking setmntent in this file below with __wrap_setmntent, + * and the actual setmntent will be called via this interface */ + ON_CALL(*this, setmntent(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + return __real_setmntent(command, type); + })); + } + virtual ~WrapsImplMock() = default; + + MOCK_METHOD(int, system, (const char* command), (override)); + MOCK_METHOD(FILE*, popen, (const char* command, const char* type), (override)); + MOCK_METHOD(int, pclose, (FILE* pipe), (override)); + MOCK_METHOD(void, syslog, (int pri, const char* fmt, va_list args), (override)); + MOCK_METHOD(FILE*, setmntent, (const char* command, const char* type), (override)); + MOCK_METHOD(struct mntent*, getmntent, (FILE* pipe), (override)); + MOCK_METHOD(FILE*, v_secure_popen, (const char *direction, const char *command, va_list args), (override)); + MOCK_METHOD(int, v_secure_pclose, (FILE *file), (override)); + MOCK_METHOD(int, v_secure_system,(const char *command, va_list args), (override)); + MOCK_METHOD(ssize_t, readlink, (const char *pathname, char *buf, size_t bufsiz), (override)); +}; \ No newline at end of file diff --git a/NetworkManager/Tests/mocks/thunder/COMLinkMock.h b/NetworkManager/Tests/mocks/thunder/COMLinkMock.h new file mode 100644 index 0000000000..a16d8701dc --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/COMLinkMock.h @@ -0,0 +1,18 @@ +#ifndef RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ +#define RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ + +#include + +#include "Module.h" + +class COMLinkMock : public WPEFramework::PluginHost::IShell::ICOMLink { +public: + virtual ~COMLinkMock() = default; + + MOCK_METHOD(void, Register, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(WPEFramework::RPC::IRemoteConnection*, RemoteConnection, (const uint32_t), (override)); + MOCK_METHOD(void*, Instantiate, (const WPEFramework::RPC::Object&, const uint32_t, uint32_t&, const string&, const string&), (override)); +}; + +#endif //RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ diff --git a/NetworkManager/Tests/mocks/thunder/DispatcherMock.h b/NetworkManager/Tests/mocks/thunder/DispatcherMock.h new file mode 100644 index 0000000000..df31c8a2da --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/DispatcherMock.h @@ -0,0 +1,37 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISPATCHERMOCK_H +#define DISPATCHERMOCK_H + +#include + +#include "Module.h" + + class DispatcherMock: public WPEFramework::PluginHost::IDispatcher{ + public: + virtual ~DispatcherMock() = default; + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (const uint32_t interfaceNummer), (override)); + MOCK_METHOD(void, Activate, (WPEFramework::PluginHost::IShell* service)); + MOCK_METHOD(void, Deactivate, ()); + MOCK_METHOD(WPEFramework::Core::ProxyType, Invoke, (const string&, uint32_t, const WPEFramework::Core::JSONRPC::Message&), (override)); +}; +#endif //DISPATCHERMOCK_H diff --git a/NetworkManager/Tests/mocks/thunder/FactoriesImplementation.h b/NetworkManager/Tests/mocks/thunder/FactoriesImplementation.h new file mode 100644 index 0000000000..e571fbb7eb --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/FactoriesImplementation.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include "Module.h" + +class FactoriesImplementation : public WPEFramework::PluginHost::IFactories { +public: + FactoriesImplementation(const FactoriesImplementation&) = delete; + FactoriesImplementation& operator=(const FactoriesImplementation&) = delete; + + FactoriesImplementation() + : _requestFactory(5) + , _responseFactory(5) + , _fileBodyFactory(5) + , _jsonRPCFactory(5) + { + // Defaults: + ON_CALL(*this, Request()) + .WillByDefault(::testing::Invoke( + [&]() { return (_requestFactory.Element()); })); + ON_CALL(*this, Response()) + .WillByDefault(::testing::Invoke( + [&]() { return (_responseFactory.Element()); })); + ON_CALL(*this, FileBody()) + .WillByDefault(::testing::Invoke( + [&]() { return (_fileBodyFactory.Element()); })); + ON_CALL(*this, JSONRPC()) + .WillByDefault(::testing::Invoke( + [&]() { + return (WPEFramework::Core::ProxyType>(_jsonRPCFactory.Element())); + })); + } + + virtual ~FactoriesImplementation() = default; + + MOCK_METHOD(WPEFramework::Core::ProxyType, Request, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType, Response, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType, FileBody, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType>, JSONRPC, (), (override)); + +private: + WPEFramework::Core::ProxyPoolType _requestFactory; + WPEFramework::Core::ProxyPoolType _responseFactory; + WPEFramework::Core::ProxyPoolType _fileBodyFactory; + WPEFramework::Core::ProxyPoolType _jsonRPCFactory; +}; diff --git a/NetworkManager/Tests/mocks/thunder/Module.cpp b/NetworkManager/Tests/mocks/thunder/Module.cpp new file mode 100644 index 0000000000..2d85ed902b --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/Module.cpp @@ -0,0 +1,3 @@ +#include "Module.h" + +MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/NetworkManager/Tests/mocks/thunder/Module.h b/NetworkManager/Tests/mocks/thunder/Module.h new file mode 100644 index 0000000000..289d820778 --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/Module.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef MODULE_NAME +#define MODULE_NAME RdkServicesL1Test +#endif + +#include +#include diff --git a/NetworkManager/Tests/mocks/thunder/ServiceMock.h b/NetworkManager/Tests/mocks/thunder/ServiceMock.h new file mode 100644 index 0000000000..47b9c28514 --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/ServiceMock.h @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICEMOCK_H +#define SERVICEMOCK_H + +#include + +#include "Module.h" + +class ServiceMock : public WPEFramework::PluginHost::IShell { +public: + virtual ~ServiceMock() = default; + + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(string, Versions, (), (const, override)); + MOCK_METHOD(string, Locator, (), (const, override)); + MOCK_METHOD(string, ClassName, (), (const, override)); + MOCK_METHOD(string, Callsign, (), (const, override)); + MOCK_METHOD(string, WebPrefix, (), (const, override)); + MOCK_METHOD(string, ConfigLine, (), (const, override)); + MOCK_METHOD(string, PersistentPath, (), (const, override)); + MOCK_METHOD(string, VolatilePath, (), (const, override)); + MOCK_METHOD(string, DataPath, (), (const, override)); + MOCK_METHOD(state, State, (), (const, override)); + MOCK_METHOD(bool, AutoStart, (), (const, override)); + MOCK_METHOD(bool, Resumed, (), (const, override)); + MOCK_METHOD(bool, IsSupported, (const uint8_t), (const, override)); + MOCK_METHOD(void, EnableWebServer, (const string&, const string&), (override)); + MOCK_METHOD(void, DisableWebServer, (), (override)); + MOCK_METHOD(WPEFramework::PluginHost::ISubSystem*, SubSystems, (), (override)); + MOCK_METHOD(uint32_t, Submit, (const uint32_t, const WPEFramework::Core::ProxyType&), (override)); + MOCK_METHOD(void, Notify, (const string&), (override)); + MOCK_METHOD(void*, QueryInterface, (const uint32_t), (override)); + MOCK_METHOD(void*, QueryInterfaceByCallsign, (const uint32_t, const string&), (override)); + MOCK_METHOD(void, Register, (WPEFramework::PluginHost::IPlugin::INotification*), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::PluginHost::IPlugin::INotification*), (override)); + MOCK_METHOD(string, Version, (), (const, override)); + MOCK_METHOD(string, Model, (), (const, override)); + MOCK_METHOD(bool, Background, (), (const, override)); + MOCK_METHOD(string, Accessor, (), (const, override)); + MOCK_METHOD(string, ProxyStubPath, (), (const, override)); + MOCK_METHOD(string, HashKey, (), (const, override)); + MOCK_METHOD(string, Substitute, (const string&), (const, override)); + MOCK_METHOD(WPEFramework::PluginHost::IShell::ICOMLink*, COMLink, (), (override)); + MOCK_METHOD(uint32_t, Activate, (const reason), (override)); + MOCK_METHOD(uint32_t, Deactivate, (const reason), (override)); + MOCK_METHOD(uint32_t, Unavailable, (const reason), (override)); + MOCK_METHOD(reason, Reason, (), (const, override)); + MOCK_METHOD(uint8_t, Major, (), (const, override)); + MOCK_METHOD(uint8_t, Minor, (), (const, override)); + MOCK_METHOD(uint8_t, Patch, (), (const, override)); + MOCK_METHOD(uint32_t, ConfigLine, (const string& config), (override)); + MOCK_METHOD(string, SystemRootPath, (), (const, override)); + MOCK_METHOD(uint32_t, SystemRootPath, (const string& systemRootPath), (override)); + MOCK_METHOD(uint32_t, Hibernate, (const string &processSequence, const uint32_t timeout), (override)); + MOCK_METHOD(uint32_t, Wakeup, (const string &processSequence, const uint32_t timeout), (override)); +}; + +#endif //SERVICEMOCK_H diff --git a/NetworkManager/Tests/mocks/thunder/SystemInfo.h b/NetworkManager/Tests/mocks/thunder/SystemInfo.h new file mode 100644 index 0000000000..db48b29484 --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/SystemInfo.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "Module.h" + +class SystemInfo : public WPEFramework::PluginHost::ISubSystem { +private: + SystemInfo(const SystemInfo&) = delete; + SystemInfo& operator=(const SystemInfo&) = delete; + +public: + SystemInfo() + : _flags(0) + { + // Defaults: + ON_CALL(*this, Set(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type, WPEFramework::Core::IUnknown* information) { + _subsystems.emplace(type, information); + + if (type >= NEGATIVE_START) { + _flags &= ~(1 << (type - NEGATIVE_START)); + } else { + _flags |= (1 << type); + } + })); + ON_CALL(*this, Get(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type) -> const WPEFramework::Core::IUnknown* { + const WPEFramework::Core::IUnknown* result(nullptr); + + auto it = _subsystems.find(type); + if (it != _subsystems.end()) { + result = it->second; + } + + return result; + })); + ON_CALL(*this, IsActive(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type) -> bool { + return ((type < END_LIST) && ((_flags & (1 << type)) != 0)); + })); + } + virtual ~SystemInfo() = default; + +public: + MOCK_METHOD(void, Register, (WPEFramework::PluginHost::ISubSystem::INotification * notification), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::PluginHost::ISubSystem::INotification * notification), (override)); + MOCK_METHOD(string, BuildTreeHash, (), (const, override)); + MOCK_METHOD(void, Set, (const subsystem type, WPEFramework::Core::IUnknown* information), (override)); + MOCK_METHOD(const WPEFramework::Core::IUnknown*, Get, (const subsystem type), (const, override)); + MOCK_METHOD(bool, IsActive, (const subsystem type), (const, override)); + + BEGIN_INTERFACE_MAP(SystemInfo) + INTERFACE_ENTRY(WPEFramework::PluginHost::ISubSystem) + END_INTERFACE_MAP + +private: + std::map _subsystems; + uint32_t _flags; +}; diff --git a/NetworkManager/Tests/mocks/thunder/WorkerPoolImplementation.h b/NetworkManager/Tests/mocks/thunder/WorkerPoolImplementation.h new file mode 100644 index 0000000000..dbc5b9e5b6 --- /dev/null +++ b/NetworkManager/Tests/mocks/thunder/WorkerPoolImplementation.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include "Module.h" + +class WorkerPoolImplementation : public WPEFramework::Core::WorkerPool { +private: + class Dispatcher : public WPEFramework::Core::ThreadPool::IDispatcher { + public: + Dispatcher(const Dispatcher&) = delete; + Dispatcher& operator=(const Dispatcher&) = delete; + + Dispatcher() = default; + ~Dispatcher() override = default; + + private: + void Initialize() override {} + void Deinitialize() override {} + void Dispatch(WPEFramework::Core::IDispatch* job) override + { + job->Dispatch(); + } + }; + +public: + WorkerPoolImplementation() = delete; + WorkerPoolImplementation(const WorkerPoolImplementation&) = delete; + WorkerPoolImplementation& operator=(const WorkerPoolImplementation&) = delete; + + WorkerPoolImplementation(const uint8_t threads, const uint32_t stackSize, const uint32_t queueSize) + : WPEFramework::Core::WorkerPool(threads - 1, stackSize, queueSize, &_dispatcher) + , _dispatcher() + { + } + + virtual ~WorkerPoolImplementation() + { + WPEFramework::Core::WorkerPool::Stop(); + } + +private: + Dispatcher _dispatcher; +};