diff --git a/.github/workflows/L1test.yml b/.github/workflows/L1test.yml index 49f0d527..0612729f 100644 --- a/.github/workflows/L1test.yml +++ b/.github/workflows/L1test.yml @@ -1,8 +1,9 @@ + name: l1-test on: push: - branches: [ main, develop, 'topic/**'] + branches: [ main, develop] pull_request: branches: [ main, develop] @@ -191,9 +192,7 @@ jobs: -DEXCEPTIONS_ENABLE=ON -I ${{github.workspace}}/networkmanagerTests/headers -I ${{github.workspace}}/networkmanager/Tests/headers/rdk/iarmbus - -I ${{github.workspace}}/networkmanager/Tests/headers/network - -Wall -Werror -Wno-error=format= - -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog" + -I ${{github.workspace}}/networkmanager/Tests/headers/network" -DCMAKE_DISABLE_FIND_PACKAGE_IARMBus=ON -DENABLE_GNOME_NETWORKMANAGER=OFF -DENABLE_NETWORKMANAGER_UNIT_TEST=ON diff --git a/CMakeLists.txt b/CMakeLists.txt index 911b2f12..d86862f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,9 +32,12 @@ if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBNM REQUIRED libnm) else() -find_package(IARMBus REQUIRED) +find_package(IARMBus) endif () +if(ENABLE_NETWORKMANAGER_UNIT_TEST) + include(cmake/UnitTest.cmake) +endif() message("Setup ProxyStub for INetworkManager.h") find_package(CompileSettingsDebug CONFIG REQUIRED) diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 32316f39..dca3d637 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -538,7 +538,6 @@ namespace WPEFramework } void NetworkManagerImplementation::threadEventRegistration() { - IARM_Result_t res = IARM_RESULT_SUCCESS; IARM_Result_t retVal = IARM_RESULT_SUCCESS; do { @@ -599,7 +598,7 @@ namespace WPEFramework usleep(500*1000); retry++; } - }while((retVal != IARM_RESULT_SUCCESS) && (retry < 3)); + }while((retVal != IARM_RESULT_SUCCESS) && (retry < 10)); if(retVal != IARM_RESULT_SUCCESS) { @@ -1216,7 +1215,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (!signalStrength.empty()) { signalStrengthOut = std::stof(signalStrength.c_str()); - NMLOG_INFO ("WiFiSignalStrength in dB = %s",signalStrengthOut); + NMLOG_INFO ("WiFiSignalStrength in dB = %f",signalStrengthOut); } if (signalStrengthOut == 0) @@ -1311,7 +1310,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Result_t retVal = IARM_RESULT_SUCCESS; IARM_Bus_WiFiSrvMgr_Param_t param; memset(¶m, 0, sizeof(param)); diff --git a/NetworkManagerStunClient.cpp b/NetworkManagerStunClient.cpp index 999f14e8..263cff01 100644 --- a/NetworkManagerStunClient.cpp +++ b/NetworkManagerStunClient.cpp @@ -360,7 +360,7 @@ bool client::bind( auto time_in_cache = std::chrono::duration_cast( std::chrono::steady_clock::now() - m_last_cache_time); - verbose("client::bind cache time=%lld\n", time_in_cache.count()); + verbose("client::bind cache time=%ld\n", time_in_cache.count()); if(time_in_cache.count() < m_cache_timeout) { @@ -672,7 +672,7 @@ std::unique_ptr client::send_binding_request(std::chrono::milliseconds std::unique_ptr client::send_binding_request(sockaddr_storage const & addr, std::chrono::milliseconds wait_time) { - this->verbose("sending binding request with wait time:%lld ms\n", wait_time.count()); + this->verbose("sending binding request with wait time:%ld ms\n", wait_time.count()); this->create_udp_socket(addr.ss_family); std::unique_ptr binding_request(message_factory::create_binding_request()); std::unique_ptr binding_response(this->send_message(addr, *binding_request, wait_time)); diff --git a/Tests/L1 Tests/.lcovrc_l1 b/Tests/L1 Tests/.lcovrc_l1 new file mode 100644 index 00000000..879fe2ce --- /dev/null +++ b/Tests/L1 Tests/.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/Tests/L1 Tests/tests/CMakeLists.txt b/Tests/L1 Tests/CMakeLists.txt similarity index 100% rename from Tests/L1 Tests/tests/CMakeLists.txt rename to Tests/L1 Tests/CMakeLists.txt diff --git a/Tests/gcc-with-coverage.cmake b/Tests/gcc-with-coverage.cmake new file mode 100644 index 00000000..cb8d689e --- /dev/null +++ b/Tests/gcc-with-coverage.cmake @@ -0,0 +1 @@ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/Tests/mocks/CMakeLists.txt b/Tests/mocks/CMakeLists.txt new file mode 100644 index 00000000..310b5075 --- /dev/null +++ b/Tests/mocks/CMakeLists.txt @@ -0,0 +1,46 @@ +#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/mocks/Iarm.cpp b/Tests/mocks/Iarm.cpp similarity index 100% rename from mocks/Iarm.cpp rename to Tests/mocks/Iarm.cpp diff --git a/mocks/Iarm.h b/Tests/mocks/Iarm.h similarity index 100% rename from mocks/Iarm.h rename to Tests/mocks/Iarm.h diff --git a/mocks/IarmBusMock.h b/Tests/mocks/IarmBusMock.h similarity index 100% rename from mocks/IarmBusMock.h rename to Tests/mocks/IarmBusMock.h diff --git a/mocks/Udev.cpp b/Tests/mocks/Udev.cpp similarity index 100% rename from mocks/Udev.cpp rename to Tests/mocks/Udev.cpp diff --git a/mocks/Udev.h b/Tests/mocks/Udev.h similarity index 100% rename from mocks/Udev.h rename to Tests/mocks/Udev.h diff --git a/mocks/UdevMock.h b/Tests/mocks/UdevMock.h similarity index 100% rename from mocks/UdevMock.h rename to Tests/mocks/UdevMock.h diff --git a/Tests/mocks/Wraps.cpp b/Tests/mocks/Wraps.cpp new file mode 100644 index 00000000..1f12e72e --- /dev/null +++ b/Tests/mocks/Wraps.cpp @@ -0,0 +1,150 @@ +#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/Tests/mocks/Wraps.h b/Tests/mocks/Wraps.h new file mode 100644 index 00000000..8dd7da37 --- /dev/null +++ b/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/Tests/mocks/WrapsMock.h b/Tests/mocks/WrapsMock.h new file mode 100644 index 00000000..3c3e7603 --- /dev/null +++ b/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)); +}; diff --git a/Tests/mocks/thunder/COMLinkMock.h b/Tests/mocks/thunder/COMLinkMock.h new file mode 100644 index 00000000..a16d8701 --- /dev/null +++ b/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/Tests/mocks/thunder/DispatcherMock.h b/Tests/mocks/thunder/DispatcherMock.h new file mode 100644 index 00000000..df31c8a2 --- /dev/null +++ b/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/Tests/mocks/thunder/FactoriesImplementation.h b/Tests/mocks/thunder/FactoriesImplementation.h new file mode 100644 index 00000000..e571fbb7 --- /dev/null +++ b/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/Tests/mocks/thunder/Module.cpp b/Tests/mocks/thunder/Module.cpp new file mode 100644 index 00000000..2d85ed90 --- /dev/null +++ b/Tests/mocks/thunder/Module.cpp @@ -0,0 +1,3 @@ +#include "Module.h" + +MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/Tests/mocks/thunder/Module.h b/Tests/mocks/thunder/Module.h new file mode 100644 index 00000000..289d8207 --- /dev/null +++ b/Tests/mocks/thunder/Module.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef MODULE_NAME +#define MODULE_NAME RdkServicesL1Test +#endif + +#include +#include diff --git a/Tests/mocks/thunder/ServiceMock.h b/Tests/mocks/thunder/ServiceMock.h new file mode 100644 index 00000000..47b9c285 --- /dev/null +++ b/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/Tests/mocks/thunder/SystemInfo.h b/Tests/mocks/thunder/SystemInfo.h new file mode 100644 index 00000000..db48b294 --- /dev/null +++ b/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/Tests/mocks/thunder/WorkerPoolImplementation.h b/Tests/mocks/thunder/WorkerPoolImplementation.h new file mode 100644 index 00000000..dbc5b9e5 --- /dev/null +++ b/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; +}; diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 0230095b..0461ff4d 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -99,7 +99,6 @@ namespace WPEFramework isRunning = true; monitorThread = std::thread(&WiFiSignalStrengthMonitor::monitorThreadFunction, this, interval); monitorThread.detach(); - std::thread::id threadId = monitorThread.get_id(); NMLOG_INFO("Thread started with interval: %d seconds", interval); } diff --git a/cmake/UnitTest.cmake b/cmake/UnitTest.cmake new file mode 100644 index 00000000..4466647a --- /dev/null +++ b/cmake/UnitTest.cmake @@ -0,0 +1,50 @@ +message("Building for unit tests...") + +message("Generating empty headers to suppress compiler errors") + +file(GLOB BASEDIR Tests) +set(BASEDIR ${BASEDIR}/headers) +set(EMPTY_HEADERS_DIRS + ${BASEDIR} + ${BASEDIR}/rdk/iarmbus + ${BASEDIR}/network + ) + +set(EMPTY_HEADERS + ${BASEDIR}/rdk/iarmbus/libIARM.h + ${BASEDIR}/rdk/iarmbus/libIBus.h + ${BASEDIR}/rdk/iarmbus/libIBusDaemon.h + ${BASEDIR}/network/wifiSrvMgrIarmIf.h + ${BASEDIR}/network/netsrvmgrIarm.h + ) + +file(MAKE_DIRECTORY ${EMPTY_HEADERS_DIRS}) + +file(GLOB_RECURSE EMPTY_HEADERS_AVAILABLE "${BASEDIR}/*") +if (EMPTY_HEADERS_AVAILABLE) + message("Skip already generated headers to avoid rebuild") + list(REMOVE_ITEM EMPTY_HEADERS ${EMPTY_HEADERS_AVAILABLE}) +endif () +if (EMPTY_HEADERS) + file(TOUCH ${EMPTY_HEADERS}) +endif () + +include_directories(${EMPTY_HEADERS_DIRS}) + +message("Adding compiler and linker options for all targets") + +file(GLOB BASEDIR Tests/mocks) +set(FAKE_HEADERS + ${BASEDIR}/Iarm.h + ) + +foreach (file ${FAKE_HEADERS}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include ${file}") +endforeach () + +add_compile_options(-Wall -Werror) + +add_link_options(-Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,pclose -Wl,-wrap,getmntent -Wl,-wrap,setmntent -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system) + +message("Setting build options") +set(CMAKE_DISABLE_FIND_PACKAGE_IARMBus ON)