SmartTester  2.0.0
Smart Tester is unit testing and regression testing framework used for testing SmartCGMS system.
GenericUnitTester.h
1 //
2 // Author: markovd@students.zcu.cz
3 //
4 
5 #pragma once
6 
7 #ifndef _GENERIC_UNIT_TESTER_H_
8 #define _GENERIC_UNIT_TESTER_H_
9 
10 #include <map>
11 #include <mutex>
12 #include <functional>
13 #include <condition_variable>
14 #include <iface/UIIface.h>
15 #include <rtl/Dynamic_Library.h>
16 #include <rtl/hresult.h>
17 #include <utils/string_utils.h>
18 #include "../utils/TestFilter.h"
19 #include "../utils/Logger.h"
20 #include "FilterConfiguration.h"
21 #include "../utils/constants.h"
22 #include "../mappers/GuidFileMapper.h"
23 #include "../utils/EntityUtils.h"
24 
25 namespace tester {
29  class TestRunner {
30  protected: // protected attributes
31  std::mutex m_testMutex;
32  std::condition_variable m_testCv;
33  HRESULT m_lastTestResult = S_OK;
34  public: // public methods
40  void executeTest(const std::wstring& testName, const std::function<HRESULT(void)>& test);
41 
42  protected:
44  virtual HRESULT shutDownTest() = 0;
45  private: // private methods
46  HRESULT runTestInThread(const std::function<HRESULT(void)>& test);
47  virtual void runTest(const std::function<HRESULT(void)>& test);
48  };
49 
53  class ModuleUnitTester : public TestRunner {
54  private: // private attributes
56  static std::vector<std::string> s_testedModules;
58  static std::map<std::string, std::string> s_descriptorsToFactories;
60  std::map<std::string, std::function<HRESULT(void)>> m_descriptorsToTests {
61  {"do_get_filter_descriptors", std::bind(&ModuleUnitTester::filterCreationTest, this) },
62  {"do_get_signal_descriptors", std::bind(&ModuleUnitTester::signalCreationTest, this) },
63  {"do_get_metric_descriptors", std::bind(&ModuleUnitTester::metricCreationTest, this) },
64  {"do_get_solver_descriptors", std::bind(&ModuleUnitTester::solverCreationTest, this) },
65  {"do_get_approximator_descriptors", std::bind(&ModuleUnitTester::approxCreationTest, this) }
66  };
68  std::map<std::string, std::function<HRESULT(const std::string&)>> m_descriptorsToParamsTests {
69  {"do_get_filter_descriptors", std::bind(&ModuleUnitTester::descriptorsParamsTest<scgms::TGet_Filter_Descriptors , scgms::TFilter_Descriptor>, this, std::placeholders::_1) },
70  {"do_get_signal_descriptors", std::bind(&ModuleUnitTester::descriptorsParamsTest<scgms::TGet_Signal_Descriptors , scgms::TSignal_Descriptor>, this, std::placeholders::_1) },
71  {"do_get_metric_descriptors", std::bind(&ModuleUnitTester::descriptorsParamsTest<scgms::TGet_Metric_Descriptors , scgms::TMetric_Descriptor>, this, std::placeholders::_1) },
72  {"do_get_solver_descriptors", std::bind(&ModuleUnitTester::descriptorsParamsTest<scgms::TGet_Solver_Descriptors , scgms::TSolver_Descriptor>, this, std::placeholders::_1) },
73  {"do_get_approximator_descriptors", std::bind(&ModuleUnitTester::descriptorsParamsTest<scgms::TGet_Approx_Descriptors , scgms::TApprox_Descriptor>, this, std::placeholders::_1) },
74  };
76  std::string m_modulePath;
78  CDynamic_Library m_moduleLibrary;
80  std::vector<std::string> m_foundDescriptorsMethods;
81  public: // public methods
82  ModuleUnitTester() = default;
84  void executeModuleTests();
90  HRESULT descriptorsMethodsTest();
102  HRESULT factoryMethodsTest();
108  HRESULT entityCreationTest();
114  bool loadModule(const std::string& modulePath);
120  static bool isModuleTested(const std::string& module) ;
121 
122  private:
123  HRESULT shutDownTest() override;
124 
125  template<typename T, typename D>
126  HRESULT descriptorsParamsTest(const std::string& symbolName);
127  HRESULT filterCreationTest();
128  HRESULT signalCreationTest();
129  HRESULT metricCreationTest();
130  HRESULT solverCreationTest();
131  HRESULT approxCreationTest();
132  };
133 
138  template<typename T>
139  class EntityUnitTester : public TestRunner {
140  private: // private attributes
142  const GUID m_entityGuid;
144  T* m_testedEntity = nullptr;
146  CDynamic_Library m_entityLibrary;
148  std::wstring m_libraryPath;
149 
150  public: // public methods
151  explicit EntityUnitTester(const GUID& entityGuid) : m_entityGuid(entityGuid) {}
152  virtual ~EntityUnitTester() = default;
154  virtual void executeAllTests() = 0;
155 
160  bool isEntityLoaded() const noexcept {
161  return m_testedEntity != nullptr;
162  }
163 
168  CDynamic_Library& getEntityLib() noexcept {
169  return m_entityLibrary;
170  }
171 
176  const GUID& getEntityGuid() const noexcept {
177  return m_entityGuid;
178  }
179 
184  if (m_libraryPath.empty()) {
185  const wchar_t* file_name = GuidFileMapper::GetInstance().getFileName(m_entityGuid);
186  m_libraryPath = std::wstring(file_name) + cnst::LIB_EXTENSION;
187  }
188 
189  m_entityLibrary.Load(m_libraryPath);
190 
191  if (!m_entityLibrary.Is_Loaded()) {
192  std::wcerr << L"Couldn't load " << m_libraryPath << " library!\n";
193  Logger::getInstance().error(L"Couldn't load " + std::wstring(m_libraryPath) + L" library.");
194  }
195  }
196 
198  virtual void loadEntity() = 0;
199 
200  template<typename C, typename D>
201  const wchar_t* getEntityName(const std::string& symbolName) {
202  if (!getEntityLib().Is_Loaded()) {
204  }
205 
206  D* descriptor = tester::getEntityDescriptor<C, D>(m_entityLibrary, m_entityGuid, symbolName);
207  if (!descriptor) {
208  return nullptr;
209  }
210 
211  return descriptor->description;
212  }
213  protected: // protected methods
214 
215  void setEntityLib(const std::wstring& libPath) {
216  if (m_entityLibrary.Is_Loaded()) {
217  Logger::getInstance().error(L"Attempt to override loaded library! Forbidding...");
218  return;
219  }
220 
221  if (m_entityLibrary.Load(libPath)) {
222  m_libraryPath = libPath;
223  } else {
224  Logger::getInstance().error(std::wstring(L"Error while loading library ") + libPath);
225  }
226  }
227 
228  void setLibraryPath(const std::wstring& libraryPath) noexcept {
229  m_libraryPath = libraryPath;
230  }
231 
232  const std::wstring& getLibraryPath() const {
233  return m_libraryPath;
234  }
235 
236  T* getTestedEntity() noexcept {
237  return m_testedEntity;
238  }
239 
240  void setTestedEntity(T *entity) {
241  if (m_testedEntity) {
242  m_testedEntity->Release();
243  }
244 
245  m_testedEntity = entity;
246  }
247 
249  void runTest(const std::function<HRESULT ()> &test) override {
250  if (!m_entityLibrary.Is_Loaded()) {
252  }
253 
254  if (!isEntityLoaded()) {
255  loadEntity();
256  }
257 
258  if (isEntityLoaded()) {
259  m_lastTestResult = test();
260  shutDownTest();
261  } else {
262  Logger::getInstance().error(L"Filter is not loaded! Test will not be executed.");
263  m_lastTestResult = E_FAIL;
264  }
265 
266  m_testCv.notify_all();
267  }
268  };
269 
274  enum class EntityType : int16_t {
275  FILTER = 0,
276  MODEL
277  };
281 class FilterUnitTester : public EntityUnitTester<scgms::IFilter> {
282  private: // private attributes
284  EntityType m_entityType;
286  TestFilter m_testFilter;
287 
288  public: // public methods
289  FilterUnitTester(GUID guid, const EntityType& type);
290  virtual ~FilterUnitTester() = default;
295  HRESULT infoEventTest();
300  HRESULT warningEventTest();
305  HRESULT errorEventTest();
310  HRESULT warmResetEventTest();
317  HRESULT shutDownEventTest();
325  void executeConfigTest(const std::wstring& testName, const tester::FilterConfig& configuration, HRESULT expectedResult);
326  void executeAllTests() override;
327  void executeGenericTests();
329  virtual void executeSpecificTests() = 0;
330  protected:
340  HRESULT configurationTest(const tester::FilterConfig& config, HRESULT expectedResult);
341 
343  HRESULT shutDownTest() override;
349  HRESULT configureFilter(const tester::FilterConfig& configuration);
350  TestFilter& getTestFilter();
351  private: // private methods
352  HRESULT informativeEventsTest(const scgms::NDevice_Event_Code& eventCode);
353  void loadEntity() override;
354 
355  HRESULT runConfigTestInThread(const tester::FilterConfig& configuration, HRESULT expectedResult);
356  void runConfigTest(const tester::FilterConfig& configuration, HRESULT expectedResult);
357  };
358 
363  void executeModuleTests(const std::string& modulePath);
364 }
365 
366 
367 #endif // !_GENERIC_UNIT_TESTER_H_
368 
tester::ModuleUnitTester::isModuleTested
static bool isModuleTested(const std::string &module)
Definition: GenericUnitTester.cpp:345
tester::FilterUnitTester::shutDownEventTest
HRESULT shutDownEventTest()
Definition: GenericUnitTester.cpp:228
tester::FilterUnitTester::executeSpecificTests
virtual void executeSpecificTests()=0
Executes all tests for a specific filter. Needs to be implemented by derived class.
tester::EntityUnitTester::loadEntityLibrary
void loadEntityLibrary()
Definition: GenericUnitTester.h:183
tester::FilterUnitTester::warmResetEventTest
HRESULT warmResetEventTest()
Definition: GenericUnitTester.cpp:224
tester::TestRunner::executeTest
void executeTest(const std::wstring &testName, const std::function< HRESULT(void)> &test)
Definition: GenericUnitTester.cpp:84
tester::TestRunner
Definition: GenericUnitTester.h:29
tester::ModuleUnitTester::factoryMethodsTest
HRESULT factoryMethodsTest()
Definition: GenericUnitTester.cpp:406
tester::ModuleUnitTester::entityCreationTest
HRESULT entityCreationTest()
Definition: GenericUnitTester.cpp:435
tester::FilterUnitTester::executeAllTests
void executeAllTests() override
Every derived class has to override this method to execute all tests.
Definition: GenericUnitTester.cpp:44
tester::EntityUnitTester::runTest
void runTest(const std::function< HRESULT()> &test) override
We need special behavior of the test execution sequence, so we override this method.
Definition: GenericUnitTester.h:249
tester::FilterUnitTester::executeConfigTest
void executeConfigTest(const std::wstring &testName, const tester::FilterConfig &configuration, HRESULT expectedResult)
Definition: GenericUnitTester.cpp:90
tester::FilterUnitTester::warningEventTest
HRESULT warningEventTest()
Definition: GenericUnitTester.cpp:216
tester::EntityUnitTester::executeAllTests
virtual void executeAllTests()=0
Every derived class has to override this method to execute all tests.
tester::ModuleUnitTester::executeModuleTests
void executeModuleTests()
Executes all tests for the loaded module.
Definition: GenericUnitTester.cpp:329
GuidFileMapper::GetInstance
static GuidFileMapper & GetInstance()
Definition: GuidFileMapper.cpp:14
tester::EntityUnitTester::getEntityGuid
const GUID & getEntityGuid() const noexcept
Definition: GenericUnitTester.h:176
tester::ModuleUnitTester::loadModule
bool loadModule(const std::string &modulePath)
Definition: GenericUnitTester.cpp:318
tester::ModuleUnitTester::descriptorsMethodParamsTest
HRESULT descriptorsMethodParamsTest()
Definition: GenericUnitTester.cpp:377
tester::FilterUnitTester::infoEventTest
HRESULT infoEventTest()
Definition: GenericUnitTester.cpp:212
tester::FilterUnitTester::configureFilter
HRESULT configureFilter(const tester::FilterConfig &configuration)
Definition: GenericUnitTester.cpp:287
TestFilter
Definition: TestFilter.h:15
tester::FilterUnitTester::errorEventTest
HRESULT errorEventTest()
Definition: GenericUnitTester.cpp:220
tester::TestRunner::shutDownTest
virtual HRESULT shutDownTest()=0
Every derived class has to override the test shutdown mechanism.
tester::FilterUnitTester::shutDownTest
HRESULT shutDownTest() override
Creates shut down event and executes it with tested filter.
Definition: GenericUnitTester.cpp:96
tester::FilterUnitTester::configurationTest
HRESULT configurationTest(const tester::FilterConfig &config, HRESULT expectedResult)
Definition: GenericUnitTester.cpp:291
tester::EntityUnitTester::isEntityLoaded
bool isEntityLoaded() const noexcept
Definition: GenericUnitTester.h:160
tester::ModuleUnitTester::descriptorsMethodsTest
HRESULT descriptorsMethodsTest()
Definition: GenericUnitTester.cpp:353
GuidFileMapper::getFileName
const wchar_t * getFileName(const GUID &guid)
Definition: GuidFileMapper.cpp:19
tester::ModuleUnitTester
Definition: GenericUnitTester.h:53
tester::EntityUnitTester::getEntityLib
CDynamic_Library & getEntityLib() noexcept
Definition: GenericUnitTester.h:168
tester::EntityUnitTester::loadEntity
virtual void loadEntity()=0
Loads tested entity. Has to be implemented by derived classes.
tester::FilterConfig
Definition: FilterConfiguration.h:14
tester::FilterUnitTester
Definition: GenericUnitTester.h:281
tester::EntityUnitTester
Definition: GenericUnitTester.h:139