Add public helper classes for UT mocking 76/2176/5
authorTimo Tietavainen <timo.tietavainen@nokia.com>
Thu, 9 Jan 2020 05:53:15 +0000 (07:53 +0200)
committerTimo Tietavainen <timo.tietavainen@nokia.com>
Thu, 9 Jan 2020 16:31:51 +0000 (18:31 +0200)
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 <timo.tietavainen@nokia.com>
Change-Id: Idf62b1397b049b4f56b8ed90c57b53ed615cd67c

12 files changed:
Doxyfile.in
Makefile.am
configure.ac
debian/changelog.in
docs/release-notes.rst
docs/user-guide.rst
include/sdl/doxygen.hpp
include/sdl/tst/mockableasyncstorage.hpp [new file with mode: 0644]
include/sdl/tst/mockablesyncstorage.hpp [new file with mode: 0644]
rpm/sdl.spec.in
tst/mockableasyncstorage_test.cpp [new file with mode: 0644]
tst/mockablesyncstorage_test.cpp [new file with mode: 0644]

index 6acdde3..41e0ee3 100644 (file)
@@ -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
index 9537ab8..1e75af9 100644 (file)
@@ -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 \
index bcb8d3f..f725e1b 100644 (file)
@@ -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])
index 277acc8..baf5140 100644 (file)
@@ -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 <timo.tietavainen@nokia.com>  Thu, 09 Jan 2020 11:28:07 +0200
+
+sdl (1.0.4-1) unstable; urgency=medium
 
   * Initial release
 
index 2efeb12..a109c43 100644 (file)
@@ -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.
index ed75ce1..a601b15 100644 (file)
@@ -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
 ==============
index c6488bf..e1a700a 100644 (file)
  * 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 (file)
index 0000000..7c0d0ea
--- /dev/null
@@ -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 <iostream>
+#include <cstdlib>
+#include <sdl/asyncstorage.hpp>
+
+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 (file)
index 0000000..d3f1d41
--- /dev/null
@@ -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 <iostream>
+#include <cstdlib>
+#include <sdl/syncstorage.hpp>
+
+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
index 2d2f89e..5709bb7 100755 (executable)
@@ -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 <rolf.badorek@nokia.com> - @PACKAGE_VERSION@-1
+* Thu Jan 09 2020 Timo Tietavainen <timo.tietavainen@nokia.com> - 1.1.0-1
+- Add public helper classes for UT mocking.
+
+* Tue Nov 12 2019 Rolf Badorek <rolf.badorek@nokia.com> - 1.0.4-1
 - first version
diff --git a/tst/mockableasyncstorage_test.cpp b/tst/mockableasyncstorage_test.cpp
new file mode 100644 (file)
index 0000000..0ec7992
--- /dev/null
@@ -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 <gtest/gtest.h>
+#include <sdl/tst/mockableasyncstorage.hpp>
+
+TEST(MockableAsyncStorageTest, CanCreateInstance)
+{
+    shareddatalayer::tst::MockableAsyncStorage mockableAsyncStorage;
+    static_cast<void>(mockableAsyncStorage);
+}
diff --git a/tst/mockablesyncstorage_test.cpp b/tst/mockablesyncstorage_test.cpp
new file mode 100644 (file)
index 0000000..a30320d
--- /dev/null
@@ -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 <gtest/gtest.h>
+#include <sdl/tst/mockablesyncstorage.hpp>
+
+TEST(MockableSyncStorageTest, CanCreateInstance)
+{
+    shareddatalayer::tst::MockableSyncStorage mockableSyncStorage;
+    static_cast<void>(mockableSyncStorage);
+}