/********************************************************************* * 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 . */ #include "gtest/gtest.h" #include "system/ovCDynamicModule.h" #if defined TARGET_OS_Windows #include #endif #include 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(); }