From 91a224f190867869d2d0b14a5f96e44a0593e682 Mon Sep 17 00:00:00 2001 From: Timo Tietavainen Date: Thu, 9 Jan 2020 07:53:15 +0200 Subject: [PATCH] Add public helper classes for UT mocking Helper classes provide simple implementation for SDL public APIs. These classes can be used in SDL clients as base classes for SDL API mock implementations instead of deriving mock implementations from pure virtual API classes. This way mock implementations do not need to be changed every time SDL APIs change (if the change does not affect UT cases). Fixed also broken Doxygen include path and macro expansion. Signed-off-by: Timo Tietavainen Change-Id: Idf62b1397b049b4f56b8ed90c57b53ed615cd67c --- Doxyfile.in | 10 ++-- Makefile.am | 8 ++++ configure.ac | 10 ++-- debian/changelog.in | 8 +++- docs/release-notes.rst | 4 ++ docs/user-guide.rst | 8 ++++ include/sdl/doxygen.hpp | 8 ++++ include/sdl/tst/mockableasyncstorage.hpp | 82 ++++++++++++++++++++++++++++++++ include/sdl/tst/mockablesyncstorage.hpp | 76 +++++++++++++++++++++++++++++ rpm/sdl.spec.in | 7 ++- tst/mockableasyncstorage_test.cpp | 29 +++++++++++ tst/mockablesyncstorage_test.cpp | 29 +++++++++++ 12 files changed, 266 insertions(+), 13 deletions(-) create mode 100644 include/sdl/tst/mockableasyncstorage.hpp create mode 100644 include/sdl/tst/mockablesyncstorage.hpp create mode 100644 tst/mockableasyncstorage_test.cpp create mode 100644 tst/mockablesyncstorage_test.cpp diff --git a/Doxyfile.in b/Doxyfile.in index 6acdde3..41e0ee3 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -753,7 +753,7 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = @SRCDIR@/include/sdl +INPUT = @SRCDIR@/include/sdl @SRCDIR@/include/sdl/tst # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -1933,7 +1933,7 @@ ENABLE_PREPROCESSING = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # the macro expansion is limited to the macros specified with the PREDEFINED and @@ -1941,7 +1941,7 @@ MACRO_EXPANSION = NO # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES the includes files in the # INCLUDE_PATH will be searched if a #include is found. @@ -1955,7 +1955,7 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = @DOXYGEN_INCLUDE_PATHS@ @SRCDIR@/include/ # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -1982,7 +1982,7 @@ PREDEFINED = # definition found in the source code. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = SHAREDDATALAYER_ENUM_WITH_KNOWN_SIZE # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have diff --git a/Makefile.am b/Makefile.am index 9537ab8..1e75af9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -176,6 +176,12 @@ pkginclude_HEADERS = \ include/sdl/rejectedbysdl.hpp \ include/sdl/syncstorage.hpp +pkgtstincludedir = \ + $(includedir)/sdl/tst +pkgtstinclude_HEADERS = \ + include/sdl/tst/mockableasyncstorage.hpp \ + include/sdl/tst/mockablesyncstorage.hpp + pkgconfigdir = \ ${libdir}/pkgconfig nodist_pkgconfig_DATA = \ @@ -316,6 +322,8 @@ testrunner_SOURCES = \ tst/hostandport_test.cpp \ tst/invalidnamespace_test.cpp \ tst/main.cpp \ + tst/mockableasyncstorage_test.cpp \ + tst/mockablesyncstorage_test.cpp \ tst/namespaceconfigurations_test.cpp \ tst/namespaceconfigurationsimpl_test.cpp \ tst/namespacevalidator_test.cpp \ diff --git a/configure.ac b/configure.ac index bcb8d3f..f725e1b 100644 --- a/configure.ac +++ b/configure.ac @@ -10,8 +10,8 @@ # Change the numbers just before release. m4_define([SDL_MAJOR], [1]) -m4_define([SDL_MINOR], [0]) -m4_define([SDL_MICRO], [4]) +m4_define([SDL_MINOR], [1]) +m4_define([SDL_MICRO], [0]) # SDL ABI version with libtool # @@ -27,9 +27,9 @@ m4_define([SDL_MICRO], [4]) # # Change the numbers just before release. -m4_define([SDL_CURRENT], [1]) -m4_define([SDL_REVISION], [4]) -m4_define([SDL_AGE], [0]) +m4_define([SDL_CURRENT], [2]) +m4_define([SDL_REVISION], [5]) +m4_define([SDL_AGE], [1]) AC_INIT([shareddatalayer], [SDL_MAJOR.SDL_MINOR.SDL_MICRO], [], [], [https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/sdl]) AC_CONFIG_HEADERS([include/config.h]) diff --git a/debian/changelog.in b/debian/changelog.in index 277acc8..baf5140 100644 --- a/debian/changelog.in +++ b/debian/changelog.in @@ -1,4 +1,10 @@ -sdl (@PACKAGE_VERSION@-1) unstable; urgency=medium +sdl (1.1.0-1) unstable; urgency=medium + + * Add public helper classes for UT mocking. + + -- Timo Tietavainen Thu, 09 Jan 2020 11:28:07 +0200 + +sdl (1.0.4-1) unstable; urgency=medium * Initial release diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 2efeb12..a109c43 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -30,6 +30,10 @@ ric-plt/sdl. Version history --------------- +[1.1.0] - 2020-01-09 + +* Add public helper classes for UT mocking. + [1.0.4] - 2019-11-13 * Add PackageCloud.io publishing to CI scripts. diff --git a/docs/user-guide.rst b/docs/user-guide.rst index ed75ce1..a601b15 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -469,6 +469,14 @@ Building Clients Using SDL * Use *pkg-config* tool to acquire needed compilation and linking flags, instead of hardcoding them. This ensures that flags are always up-to-date. See more information from `here <#building-clients-using-sdl>`_. +* If you want to mock SDL APIs in unit testing, SDL provides helper classes + for that. By using these helper classes you need to implement mock + implementation only for those SDL API functions which you use in the unit + tests. See more information from `doxygen documentation <#doxygen-generated-sdl-api-documentation>`_ + of the helper classes: + + * *include/sdl/tst/mockableasyncstorage.hpp: MockableAsyncStorage* + * *include/sdl/tst/mockablesyncstorage.hpp: MockableSyncStorage* Using SDL APIs ============== diff --git a/include/sdl/doxygen.hpp b/include/sdl/doxygen.hpp index c6488bf..e1a700a 100644 --- a/include/sdl/doxygen.hpp +++ b/include/sdl/doxygen.hpp @@ -79,4 +79,12 @@ * Functionally it is similar to AsyncStorage, with an exception that functions are blocking while * waiting response(s) from database. * + * @subsection unit_testing_sec Unit Testing + * + * SDL provides helper classes for clients to mock SDL APIs. + * + * shareddatalayer::tst::MockableAsyncStorage to mock shareddatalayer::AsyncStorage API. + * + * shareddatalayer::tst::MockableSyncStorage to mock shareddatalayer::SyncStorage API. + * */ diff --git a/include/sdl/tst/mockableasyncstorage.hpp b/include/sdl/tst/mockableasyncstorage.hpp new file mode 100644 index 0000000..7c0d0ea --- /dev/null +++ b/include/sdl/tst/mockableasyncstorage.hpp @@ -0,0 +1,82 @@ +/* + Copyright (c) 2018-2020 Nokia. + + 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. +*/ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). +*/ + +#ifndef SHAREDDATALAYER_TST_MOCKABLEASYNCSTORAGE_HPP_ +#define SHAREDDATALAYER_TST_MOCKABLEASYNCSTORAGE_HPP_ + +#include +#include +#include + +namespace shareddatalayer +{ + namespace tst + { + /** + * @brief Helper class for mocking AsyncStorage + * + * MockableAsyncStorage can be used in application's unit tests to mock AsyncStorage. + * MockableAsyncStorage guarantees that even if new functions are added into + * AsyncStorage, existing unit test cases do not have to be modified unless + * those new functions are used. + * + * If a function is not mocked but called in unit tests, then the call + * will be logged and the process will abort. + */ + class MockableAsyncStorage: public AsyncStorage + { + public: + MockableAsyncStorage() { } + + virtual int fd() const override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void handleEvents() override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void waitReadyAsync(const Namespace&, const ReadyAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void setAsync(const Namespace&, const DataMap&, const ModifyAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void setIfAsync(const Namespace&, const Key&, const Data&, const Data&, const ModifyIfAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void setIfNotExistsAsync(const Namespace&, const Key&, const Data&, const ModifyIfAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void getAsync(const Namespace&, const Keys&, const GetAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void removeAsync(const Namespace&, const Keys&, const ModifyAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void removeIfAsync(const Namespace&, const Key&, const Data&, const ModifyIfAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void findKeysAsync(const Namespace&, const std::string&, const FindKeysAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void removeAllAsync(const Namespace&, const ModifyAck&) override { logAndAbort(__PRETTY_FUNCTION__); } + + private: + static void logAndAbort(const char* function) noexcept __attribute__ ((__noreturn__)) + { + std::cerr << "MockableAsyncStorage: calling not-mocked function " + << function << ", aborting" << std::endl; + abort(); + } + }; + } +} + +#endif diff --git a/include/sdl/tst/mockablesyncstorage.hpp b/include/sdl/tst/mockablesyncstorage.hpp new file mode 100644 index 0000000..d3f1d41 --- /dev/null +++ b/include/sdl/tst/mockablesyncstorage.hpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2018-2020 Nokia. + + 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. +*/ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). +*/ + +#ifndef SHAREDDATALAYER_TST_MOCKABLESYNCSTORAGE_HPP_ +#define SHAREDDATALAYER_TST_MOCKABLESYNCSTORAGE_HPP_ + +#include +#include +#include + +namespace shareddatalayer +{ + namespace tst + { + /** + * @brief Helper class for mocking SyncStorage + * + * MockableSyncStorage can be used in application's unit tests to mock SyncStorage. + * MockableSyncStorage guarantees that even if new functions are added into + * SyncStorage, existing unit test cases do not have to be modified unless + * those new functions are used. + * + * If a function is not mocked but called in unit tests, then the call + * will be logged and the process will abort. + */ + class MockableSyncStorage: public SyncStorage + { + public: + MockableSyncStorage() { } + + virtual void set(const Namespace&, const DataMap&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual bool setIf(const Namespace&, const Key&, const Data&, const Data&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual bool setIfNotExists(const Namespace&, const Key&, const Data&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual DataMap get(const Namespace&, const Keys&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void remove(const Namespace&, const Keys&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual bool removeIf(const Namespace&, const Key&, const Data&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual Keys findKeys(const Namespace&, const std::string&) override { logAndAbort(__PRETTY_FUNCTION__); } + + virtual void removeAll(const Namespace&) override { logAndAbort(__PRETTY_FUNCTION__); } + + private: + static void logAndAbort(const char* function) noexcept __attribute__ ((__noreturn__)) + { + std::cerr << "MockableSyncStorage: calling not-mocked function " + << function << ", aborting" << std::endl; + abort(); + } + }; + } +} + +#endif diff --git a/rpm/sdl.spec.in b/rpm/sdl.spec.in index 2d2f89e..5709bb7 100755 --- a/rpm/sdl.spec.in +++ b/rpm/sdl.spec.in @@ -1,5 +1,5 @@ Name: sdl -Version: @PACKAGE_VERSION@ +Version: 1.1.0 Release: 1%{?dist} Summary: C++ API library for Shared Data Layer clients @@ -50,5 +50,8 @@ rm -f %{buildroot}%{_libdir}/lib*.*a %{_includedir}/sdl %changelog -* Tue Nov 12 2019 Rolf Badorek - @PACKAGE_VERSION@-1 +* Thu Jan 09 2020 Timo Tietavainen - 1.1.0-1 +- Add public helper classes for UT mocking. + +* Tue Nov 12 2019 Rolf Badorek - 1.0.4-1 - first version diff --git a/tst/mockableasyncstorage_test.cpp b/tst/mockableasyncstorage_test.cpp new file mode 100644 index 0000000..0ec7992 --- /dev/null +++ b/tst/mockableasyncstorage_test.cpp @@ -0,0 +1,29 @@ +/* + Copyright (c) 2018-2020 Nokia. + + 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. +*/ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). +*/ + +#include +#include + +TEST(MockableAsyncStorageTest, CanCreateInstance) +{ + shareddatalayer::tst::MockableAsyncStorage mockableAsyncStorage; + static_cast(mockableAsyncStorage); +} diff --git a/tst/mockablesyncstorage_test.cpp b/tst/mockablesyncstorage_test.cpp new file mode 100644 index 0000000..a30320d --- /dev/null +++ b/tst/mockablesyncstorage_test.cpp @@ -0,0 +1,29 @@ +/* + Copyright (c) 2018-2020 Nokia. + + 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. +*/ + +/* + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). +*/ + +#include +#include + +TEST(MockableSyncStorageTest, CanCreateInstance) +{ + shareddatalayer::tst::MockableSyncStorage mockableSyncStorage; + static_cast(mockableSyncStorage); +} -- 2.16.6