init
This commit is contained in:
+68
@@ -0,0 +1,68 @@
|
||||
#######################################################################
|
||||
# Software License Agreement (AGPL-3 License)
|
||||
#
|
||||
# OpenViBE SDK Test Software
|
||||
# Based on OpenViBE V1.1.0, Copyright (C) Inria, 2006-2015
|
||||
# Copyright (C) Inria, 2015-2017,V1.0
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License version 3,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#######################################################################
|
||||
|
||||
PROJECT(openvibe-module-system-test)
|
||||
|
||||
# ---------------------------------
|
||||
# Target macros
|
||||
# Defines target operating system, architecture and compiler
|
||||
# ---------------------------------
|
||||
SET_BUILD_PLATFORM()
|
||||
|
||||
# ----------------------
|
||||
# Configure test target
|
||||
# ----------------------
|
||||
|
||||
# Test that needs to called with parameters
|
||||
SET(TEST_WITH_PARAM
|
||||
)
|
||||
|
||||
# Test that needs to called without parameters
|
||||
SET(TEST_NO_PARAM
|
||||
uoTimeTest.cpp
|
||||
uoDynamicModuleTest.cpp
|
||||
)
|
||||
|
||||
# Create test sources list
|
||||
# This macro auto-generate ${PROJECT_NAME}.cpp
|
||||
# in the build tree. ${PROJECT_NAME}.cpp is
|
||||
# the test driver called by ctest to run
|
||||
# the different tests added to this target.
|
||||
CREATE_TEST_SOURCELIST (Tests
|
||||
${PROJECT_NAME}.cpp
|
||||
${TEST_WITH_PARAM}
|
||||
${TEST_NO_PARAM}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} ${Tests})
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindOpenViBEModuleSystem")
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${TESTS_FOLDER})
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OVT_UNIT_TOOLKIT_LIB} ${OV_LIBS} ${GTEST_BOTH_LIBRARIES})
|
||||
|
||||
# Add test without parameter to driver
|
||||
FOREACH(test ${TEST_NO_PARAM})
|
||||
GET_FILENAME_COMPONENT(TName ${test} NAME_WE)
|
||||
ADD_TEST(NAME ${TName} COMMAND ${PROJECT_NAME} ${TName})
|
||||
ENDFOREACH()
|
||||
|
||||
# Add test with parameter to driver
|
||||
Executable
+360
@@ -0,0 +1,360 @@
|
||||
/*********************************************************************
|
||||
* Software License Agreement (AGPL-3 License)
|
||||
*
|
||||
* OpenViBE SDK Test Software
|
||||
* Based on OpenViBE V1.1.0, Copyright (C) Inria, 2006-2015
|
||||
* Copyright (C) Inria, 2015-2017,V1.0
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "system/ovCDynamicModule.h"
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <winreg.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
#if defined TARGET_OS_Windows
|
||||
//const std::string LIB_PATH = OV_CMAKE_PATH_LIB;
|
||||
|
||||
// Microsoft specific
|
||||
const std::string EXISTING_MODULE_NAME = "NTDLL.dll";
|
||||
|
||||
std::string existingModulePath;
|
||||
|
||||
#if defined _WIN64
|
||||
#define CSIDL_SYSTEM_PLATFORM CSIDL_SYSTEM
|
||||
#else
|
||||
#define CSIDL_SYSTEM_PLATFORM CSIDL_SYSTEMX86
|
||||
#endif
|
||||
|
||||
std::string existingModulePathName;
|
||||
const std::string NON_EXISTING_MODULE_NAME = "randomRandomRandom.dll";
|
||||
const std::string NON_EXISTING_SYMBOL = "nonExistingSymbol";
|
||||
const std::string EXISTING_ENVIRONMENT_PATH = "PATH";
|
||||
const std::string EXISTING_REGISTRY_MODULE_NAME = EXISTING_MODULE_NAME;
|
||||
const std::string SYMBOL_NAME_NTDLL = "toupper";
|
||||
|
||||
const HKEY EXISTING_REGISTRY_KEY = HKEY_LOCAL_MACHINE; // 0x80000002
|
||||
const HKEY NON_EXISTING_REGISTRY_KEY = HKEY(ULONG_PTR(LONG(0x800000FF)));
|
||||
|
||||
const std::string EXISTING_REGISTRY_PATH = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer"; // Present on all Windows versions
|
||||
const std::string NON_EXISTING_REGISTRY_PATH = "SOFTWARE\\Random\\Random\\Random";
|
||||
|
||||
int (*toupperSymbol)(int c);
|
||||
bool (*randomRandomRandomSymbol)(int number);
|
||||
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
static const std::string EXISTING_SYMBOL = "createCSVLib";
|
||||
static const std::string NON_EXISTING_SYMBOL = "nonExistingSymbol";
|
||||
static const std::string LIB_PATH = OV_CMAKE_PATH_LIB;
|
||||
static const std::string EXISTING_MODULE_NAME = "libopenvibe-module-csv.so";
|
||||
static const std::string existingModulePath = LIB_PATH + "/";
|
||||
static const std::string existingModulePathName = existingModulePath + EXISTING_MODULE_NAME;
|
||||
static const std::string NON_EXISTING_MODULE_NAME = "randomRandomRandom.so";
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, loadFromExistingSuccessNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromExisting(EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = EXISTING_MODULE_NAME;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, loadFromExistingFailNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromExisting(NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_EQ(System::CDynamicModule::LogErrorCodes_FailToLoadModule, dynamicModule.getLastError());
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromPathSuccessNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromPath(existingModulePathName.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = existingModulePathName;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromPathFailNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromPath(NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_EQ(System::CDynamicModule::LogErrorCodes_FailToLoadModule, dynamicModule.getLastError());
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
|
||||
#if defined TARGET_OS_Windows // Must be tested on Linux
|
||||
TEST(DynamicModule_Test_Case, loadFromPathSuccessSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromPath(existingModulePathName.c_str(), SYMBOL_NAME_NTDLL.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = existingModulePathName;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromPathSymbolCheckFail)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromPath(existingModulePathName.c_str(), NON_EXISTING_SYMBOL.c_str()));
|
||||
ASSERT_EQ(System::CDynamicModule::LogErrorCodes_InvalidSymbol, dynamicModule.getLastError());
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, loadFromKnownPathSuccessNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromKnownPath(CSIDL_SYSTEM_PLATFORM, EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = existingModulePathName;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, SYMBOL_NAME_NTDLL.c_str(), &toupperSymbol));
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromKnownPathFailNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromKnownPath(CSIDL_SYSTEM_PLATFORM, NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_EQ(System::CDynamicModule::LogErrorCodes_FailToLoadModule, dynamicModule.getLastError());
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, loadFromEnvironmentSuccessNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromEnvironment(EXISTING_ENVIRONMENT_PATH.c_str(), EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = "C:\\WINDOWS\\system32\\ntdll.dll";
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
ASSERT_TRUE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, SYMBOL_NAME_NTDLL.c_str(), &toupperSymbol));
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromEnvironmentFailNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromEnvironment(EXISTING_ENVIRONMENT_PATH.c_str(), NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_EQ(System::CDynamicModule::LogErrorCodes_ModuleNotFound, dynamicModule.getLastError());
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, loadFromRegistrySuccessNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(
|
||||
dynamicModule.loadFromRegistry(EXISTING_REGISTRY_KEY, EXISTING_REGISTRY_PATH.c_str(), nullptr, KEY_READ | KEY_WOW64_64KEY, EXISTING_REGISTRY_MODULE_NAME
|
||||
.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = EXISTING_MODULE_NAME;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, SYMBOL_NAME_NTDLL.c_str(), &toupperSymbol));
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromRegistrySuccessSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(
|
||||
dynamicModule.loadFromRegistry(EXISTING_REGISTRY_KEY, EXISTING_REGISTRY_PATH.c_str(), nullptr, KEY_READ | KEY_WOW64_64KEY, EXISTING_REGISTRY_MODULE_NAME
|
||||
.c_str(), SYMBOL_NAME_NTDLL.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = EXISTING_MODULE_NAME;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
|
||||
ASSERT_TRUE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, SYMBOL_NAME_NTDLL.c_str(), &toupperSymbol));
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, loadFromRegistryFailNoSymbolCheck)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(
|
||||
dynamicModule.loadFromRegistry(NON_EXISTING_REGISTRY_KEY, EXISTING_REGISTRY_PATH.c_str(), nullptr, KEY_READ | KEY_WOW64_32KEY,
|
||||
EXISTING_REGISTRY_MODULE_NAME.c_str()));
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
|
||||
ASSERT_FALSE(
|
||||
dynamicModule.loadFromRegistry(EXISTING_REGISTRY_KEY, NON_EXISTING_REGISTRY_PATH.c_str(), nullptr, KEY_READ | KEY_WOW64_32KEY,
|
||||
EXISTING_REGISTRY_MODULE_NAME.c_str()));
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
|
||||
ASSERT_FALSE(
|
||||
dynamicModule.loadFromRegistry(NON_EXISTING_REGISTRY_KEY, EXISTING_REGISTRY_PATH.c_str(), nullptr, KEY_READ | KEY_WOW64_32KEY,
|
||||
EXISTING_REGISTRY_MODULE_NAME.c_str()));
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows // Must be tested on Linux
|
||||
TEST(DynamicModule_Test_Case, getSymbolSuccess)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromPath(existingModulePathName.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = existingModulePathName;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
ASSERT_TRUE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, SYMBOL_NAME_NTDLL.c_str(), &toupperSymbol));
|
||||
|
||||
const char lowerCase = 'r';
|
||||
char upperCase = char(toupperSymbol(lowerCase));
|
||||
|
||||
ASSERT_EQ(upperCase, 'R');
|
||||
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, getSymbolFail)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromPath(existingModulePathName.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.isLoaded());
|
||||
std::string moduleNameExpected = existingModulePathName;
|
||||
std::string moduleName = dynamicModule.getFilename();
|
||||
std::transform(moduleNameExpected.begin(), moduleNameExpected.end(), moduleNameExpected.begin(), tolower);
|
||||
std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), tolower);
|
||||
ASSERT_STREQ(moduleNameExpected.c_str(), moduleName.c_str());
|
||||
ASSERT_FALSE(System::CDynamicModuleSymbolLoader::getSymbol<>(dynamicModule, NON_EXISTING_SYMBOL.c_str(), &randomRandomRandomSymbol));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, isModulecompatibleSuccess)
|
||||
{
|
||||
#if defined _WIN64
|
||||
ASSERT_FALSE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x014c)); // x86
|
||||
ASSERT_TRUE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x8664)); // x64
|
||||
ASSERT_FALSE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x0200)); // ia64
|
||||
#else
|
||||
ASSERT_TRUE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x014c)); // x86
|
||||
ASSERT_FALSE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x8664)); // x64
|
||||
ASSERT_FALSE(System::CDynamicModule::isModuleCompatible(existingModulePathName.c_str(), 0x0200)); // ia64
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
TEST(DynamicModule_Test_Case, isModulecompatibleFail)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromPath(NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(DynamicModule_Test_Case, unloadSuccess)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_TRUE(dynamicModule.loadFromPath(existingModulePathName.c_str()));
|
||||
ASSERT_TRUE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
TEST(DynamicModule_Test_Case, unloadFail)
|
||||
{
|
||||
System::CDynamicModule dynamicModule;
|
||||
|
||||
ASSERT_FALSE(dynamicModule.loadFromPath(NON_EXISTING_MODULE_NAME.c_str()));
|
||||
ASSERT_FALSE(dynamicModule.isLoaded());
|
||||
ASSERT_FALSE(dynamicModule.unload());
|
||||
}
|
||||
|
||||
int uoDynamicModuleTest(int argc, char* argv[])
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
BOOL bIsWow64 = FALSE;
|
||||
|
||||
if (!IsWow64Process(GetCurrentProcess(), &bIsWow64)) { return false; }
|
||||
|
||||
existingModulePath = bIsWow64 ? "C:\\WINDOWS\\SysWOW64\\" : "C:\\WINDOWS\\system32\\";
|
||||
existingModulePathName = existingModulePath + EXISTING_MODULE_NAME;
|
||||
#endif
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
/*********************************************************************
|
||||
* Software License Agreement (AGPL-3 License)
|
||||
*
|
||||
* OpenViBE SDK Test Software
|
||||
* Based on OpenViBE V1.1.0, Copyright (C) Inria, 2006-2015
|
||||
* Copyright (C) Inria, 2015-2017,V1.0
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <tuple>
|
||||
#include <chrono>
|
||||
|
||||
#include "openvibe/CTime.hpp"
|
||||
#include "system/ovCTime.h"
|
||||
|
||||
#include "ovtAssert.h"
|
||||
|
||||
//
|
||||
// \note This test should be improved. Some improvements could be:
|
||||
// - Compare clock results to gold standard
|
||||
// - True testing of monotonic state
|
||||
// - Stress tests on longer period
|
||||
//
|
||||
|
||||
// \brief Calibrate sleep function to estimate the extra time not spent at sleeping
|
||||
uint64_t calibrateSleep(const size_t nSample, bool (*sleepFunction)(uint64_t), uint64_t (*timeFunction)())
|
||||
{
|
||||
uint64_t maxTime = 0;
|
||||
for (size_t i = 0; i < nSample; ++i)
|
||||
{
|
||||
const uint64_t preTime = timeFunction();
|
||||
sleepFunction(0);
|
||||
const uint64_t processingTime = timeFunction() - preTime;
|
||||
|
||||
if (processingTime > maxTime) { maxTime = processingTime; }
|
||||
}
|
||||
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
// \brief Record sleep function precision
|
||||
std::vector<uint64_t> testSleep(const std::vector<uint64_t>& sleepTimes, bool (*sleepFunction)(uint64_t), uint64_t (*timeFunction)())
|
||||
{
|
||||
std::vector<uint64_t> effectiveSleepTimes;
|
||||
for (auto time : sleepTimes)
|
||||
{
|
||||
const uint64_t preTime = timeFunction();
|
||||
sleepFunction(time);
|
||||
effectiveSleepTimes.push_back(timeFunction() - preTime);
|
||||
}
|
||||
|
||||
return effectiveSleepTimes;
|
||||
}
|
||||
|
||||
// \brief Return a warning count that is incremented when sleep function did not meet following requirements:
|
||||
// - sleep enough time
|
||||
// - sleep less than the expected time + delta
|
||||
size_t assessSleepTestResult(const std::vector<uint64_t>& expected, const std::vector<uint64_t>& result, const uint64_t delta, const uint64_t epsilon)
|
||||
{
|
||||
size_t warningCount = 0;
|
||||
for (size_t i = 0; i < expected.size(); ++i)
|
||||
{
|
||||
if (result[i] + epsilon < expected[i] || result[i] > (expected[i] + delta + epsilon))
|
||||
{
|
||||
std::cerr << "WARNING: Failure to sleep the right amount of time: [expected|result] = "
|
||||
<< OpenViBE::CTime(expected[i]) << "|" << OpenViBE::CTime(result[i]) << std::endl;
|
||||
warningCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return warningCount;
|
||||
}
|
||||
|
||||
// \brief Record clock function data (spin test taken from OpenViBE). Return a tuple with:
|
||||
// - bool = monotonic state
|
||||
// - std::vector<uint64_t> = all the cumulative steps
|
||||
std::tuple<bool, std::vector<uint64_t>> testClock(const uint64_t samplePeriod, const unsigned sampleCountGuess, uint64_t (*timeFunction)())
|
||||
{
|
||||
std::vector<uint64_t> cumulativeSteps;
|
||||
cumulativeSteps.reserve(sampleCountGuess);
|
||||
|
||||
bool monotonic = true;
|
||||
const uint64_t startTime = timeFunction();
|
||||
uint64_t nowTime = startTime;
|
||||
uint64_t previousTime = nowTime;
|
||||
|
||||
while (nowTime - startTime < samplePeriod)
|
||||
{
|
||||
nowTime = timeFunction();
|
||||
if (nowTime > previousTime) { cumulativeSteps.push_back(nowTime - previousTime); }
|
||||
else if (nowTime < previousTime)
|
||||
{
|
||||
monotonic = false;
|
||||
break;
|
||||
}
|
||||
previousTime = nowTime;
|
||||
}
|
||||
|
||||
return std::make_tuple(monotonic, cumulativeSteps);
|
||||
}
|
||||
|
||||
// \brief Compute jitter measurements for 32:32 time. Return a tuple with:
|
||||
// - double = mean
|
||||
// - double = max deviation from mean
|
||||
// - double = RMSE
|
||||
std::tuple<double, double, double> assessTimeClock(const std::vector<uint64_t>& measurements)
|
||||
{
|
||||
double jitterMax = 0.0;
|
||||
double jitterMSE = 0.0;
|
||||
double mean = 0.0;
|
||||
|
||||
// compute mean
|
||||
for (auto& data : measurements)
|
||||
{
|
||||
// convert data
|
||||
auto seconds = data >> 32;
|
||||
auto microseconds = ((data & 0xFFFFFFFFLL) * 1000000LL) >> 32;
|
||||
std::chrono::microseconds chronoData = std::chrono::seconds(seconds) + std::chrono::microseconds(microseconds);
|
||||
|
||||
mean += double(chronoData.count()) / (1000 * measurements.size());
|
||||
}
|
||||
|
||||
// compute deviations
|
||||
for (auto& data : measurements)
|
||||
{
|
||||
// convert data
|
||||
auto seconds = data >> 32;
|
||||
auto microseconds = ((data & 0xFFFFFFFFLL) * 1000000LL) >> 32;
|
||||
std::chrono::microseconds chronoData = std::chrono::seconds(seconds) + std::chrono::microseconds(microseconds);
|
||||
|
||||
const double deviation = std::abs(double(chronoData.count()) / 1000 - mean);
|
||||
jitterMSE += std::pow(deviation, 2) / measurements.size();
|
||||
|
||||
if (deviation - jitterMax > std::numeric_limits<double>::epsilon()) { jitterMax = deviation; }
|
||||
}
|
||||
|
||||
return std::make_tuple(mean, jitterMax, std::sqrt(jitterMSE));
|
||||
}
|
||||
|
||||
int uoTimeTest(int /*argc*/, char* /*argv*/[])
|
||||
{
|
||||
// This is a very theoretical test. But if it returns false, we can
|
||||
// assume that a steady clock is not available on the test
|
||||
// platform. If it returns true, it just means that the internal clock
|
||||
// says it is steady...
|
||||
OVT_ASSERT(System::Time::isClockSteady(), "Failure to retrieve a steady clock");
|
||||
|
||||
// Same as above.
|
||||
// The test is set to 1ms at it is a requirement for OpenViBE clocks
|
||||
OVT_ASSERT(System::Time::checkResolution(1), "Failure to check for resolution");
|
||||
|
||||
// A stress test to check no overflow happens
|
||||
OVT_ASSERT(System::Time::checkResolution(std::numeric_limits<size_t >::max()), "Failure to check for resolution");
|
||||
|
||||
//
|
||||
// zSleep() function test
|
||||
//
|
||||
|
||||
const std::vector<uint64_t> expectedSleepData = {
|
||||
0x80000000LL, 0x40000000LL, 0x20000000LL, 0x10000000LL,
|
||||
0x80000000LL, 0x40000000LL, 0x20000000LL, 0x10000000LL,
|
||||
0x08000000LL, 0x04000000LL, 0x02000000LL, 0x01000000LL,
|
||||
0x08000000LL, 0x04000000LL, 0x02000000LL, 0x01000000LL
|
||||
};
|
||||
|
||||
// calibrate sleep function
|
||||
const auto deltaTime = calibrateSleep(1000, System::Time::zsleep, System::Time::zgetTime);
|
||||
|
||||
std::cout << "INFO: Delta time for zsleep calibration = " << OpenViBE::CTime(deltaTime) << std::endl;
|
||||
|
||||
const auto resultSleepData = testSleep(expectedSleepData, System::Time::zsleep, System::Time::zgetTime);
|
||||
|
||||
OVT_ASSERT(resultSleepData.size() == expectedSleepData.size(), "Failure to run zsleep tests");
|
||||
|
||||
const size_t warningCount = assessSleepTestResult(expectedSleepData, resultSleepData, deltaTime, OpenViBE::CTime(0.005).time());
|
||||
|
||||
// relax this threshold in case there is some recurrent problems
|
||||
// according to the runtime environment
|
||||
OVT_ASSERT(warningCount <= 2, "Failure to zsleep the right amount of time");
|
||||
|
||||
//
|
||||
// zGetTime() function test
|
||||
//
|
||||
|
||||
// the sample count guess was found in an empiric way
|
||||
auto resultGetTimeData = testClock(OpenViBE::CTime(0.5).time(), 500000, System::Time::zgetTime);
|
||||
|
||||
OVT_ASSERT(std::get<0>(resultGetTimeData), "Failure in zgetTime() test: the clock is not monotonic");
|
||||
|
||||
auto clockMetrics = assessTimeClock(std::get<1>(resultGetTimeData));
|
||||
|
||||
std::cout << "INFO: Sample count for getTime() = " << std::get<1>(resultGetTimeData).size() << std::endl;
|
||||
std::cout << "INFO: Mean step in ms for getTime() = " << std::get<0>(clockMetrics) << std::endl;
|
||||
std::cout << "INFO: Max deviation in ms for getTime() = " << std::get<1>(clockMetrics) << std::endl;
|
||||
std::cout << "INFO: RMSE in ms for getTime() = " << std::get<2>(clockMetrics) << std::endl;
|
||||
|
||||
// We expect at least 1ms resolution
|
||||
const double resolutionDelta = std::get<0>(clockMetrics) - 1;
|
||||
OVT_ASSERT(resolutionDelta <= std::numeric_limits<double>::epsilon(), "Failure in zgetTime() test: the clock resolution does not match requirements");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user