diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c62a8bea4..2a9d75be2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -88,9 +88,15 @@ function(create_test testName) set(oneValueArgs "") set(multiValueArgs SOURCES LIBRARIES) CMAKE_PARSE_ARGUMENTS(CT "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - add_executable("${testName}" EXCLUDE_FROM_ALL ${CT_SOURCES} main.cpp) + add_executable("${testName}" EXCLUDE_FROM_ALL + ${CT_SOURCES} + TestLog.cpp + TestLog.h + main.cpp + ) + target_include_directories("${testName}" PRIVATE "${CMAKE_CURRENT_LIST_DIR}") set_property(TARGET "${testName}" PROPERTY FOLDER "Testing") - target_link_libraries("${testName}" gtest ${CT_LIBRARIES}) + target_link_libraries("${testName}" gtest gmock ${CT_LIBRARIES}) add_test(NAME "${testName}" COMMAND "${testName}") endfunction() diff --git a/tests/TestLog.cpp b/tests/TestLog.cpp new file mode 100644 index 000000000..77d5ab336 --- /dev/null +++ b/tests/TestLog.cpp @@ -0,0 +1,69 @@ +/* +* OpenClonk, http://www.openclonk.org +* +* Copyright (c) 2016, The OpenClonk Team and contributors +* +* Distributed under the terms of the ISC license; see accompanying file +* "COPYING" for details. +* +* "Clonk" is a registered trademark of Matthes Bender, used with permission. +* See accompanying file "TRADEMARK" for details. +* +* To redistribute this file separately, substitute the full license texts +* for the above references. +*/ + +// Proxies the logging functions into a class so we can test that something +// gets logged + +#include "TestLog.h" + +// Override ALL of the C4SimpleLog.cpp functions here because otherwise MSVC +// pulls the .obj in and will end up with multiple definitions of a symbol. +#define FORWARD_UNFORMATTED(func) bool func(const char *msg) { return TestLog::handler ? TestLog::handler->func(msg) : true; } +FORWARD_UNFORMATTED(Log) +FORWARD_UNFORMATTED(DebugLog) +FORWARD_UNFORMATTED(LogSilent) +FORWARD_UNFORMATTED(LogFatal) +#undef FORWARD_UNFORMATTED + +#define FORWARD_FORMATTED(func) bool func(const char *msg, ...) \ + { \ + va_list args; va_start(args, msg); \ + bool result = TestLog::handler ? TestLog::handler->func(msg, args) : true; \ + va_end(args); \ + return result; \ + } +FORWARD_FORMATTED(DebugLogF) +FORWARD_FORMATTED(LogF) +FORWARD_FORMATTED(LogSilentF) +#undef FORWARD_FORMATTED + +TestLog *TestLog::handler = 0; + +void TestLog::setHandler(TestLog *new_handler) +{ + handler = new_handler; +} + +TestLog::TestLog() +{ + setHandler(this); +} + +TestLog::~TestLog() +{ + // Make sure there's no deleted logging handler set + if (handler == this) + handler = 0; +} + +// Default implementation does nothing +bool TestLog::Log(const char * /* msg */) { return true; } +bool TestLog::DebugLog(const char * /* msg */) { return true; } +bool TestLog::LogFatal(const char * /* msg */) { return true; } +bool TestLog::LogSilent(const char * /* msg */) { return true; } + +bool TestLog::LogF(const char * /* msg */, va_list /* args */) { return true; } +bool TestLog::DebugLogF(const char * /* msg */, va_list /* args */) { return true; } +bool TestLog::LogSilentF(const char * /* msg */, va_list /* args */) { return true; } diff --git a/tests/TestLog.h b/tests/TestLog.h new file mode 100644 index 000000000..992f26747 --- /dev/null +++ b/tests/TestLog.h @@ -0,0 +1,59 @@ +/* +* OpenClonk, http://www.openclonk.org +* +* Copyright (c) 2016, The OpenClonk Team and contributors +* +* Distributed under the terms of the ISC license; see accompanying file +* "COPYING" for details. +* +* "Clonk" is a registered trademark of Matthes Bender, used with permission. +* See accompanying file "TRADEMARK" for details. +* +* To redistribute this file separately, substitute the full license texts +* for the above references. +*/ + +#include +#include + +class TestLog +{ +public: + virtual ~TestLog(); + static void setHandler(TestLog *new_handler); + +protected: + virtual bool Log(const char *msg) = 0; + virtual bool DebugLog(const char *msg) = 0; + virtual bool LogFatal(const char *msg) = 0; + virtual bool LogSilent(const char *msg) = 0; + + virtual bool LogF(const char *format, va_list args) = 0; + virtual bool DebugLogF(const char *format, va_list args) = 0; + virtual bool LogSilentF(const char *format, va_list args) = 0; + + TestLog(); + +private: + static TestLog *handler; + + friend bool Log(const char*); + friend bool DebugLog(const char*); + friend bool LogFatal(const char*); + friend bool LogSilent(const char*); + friend bool LogF(const char*, ...); + friend bool DebugLogF(const char*, ...); + friend bool LogSilentF(const char*, ...); +}; + +class LogMock : public TestLog +{ +public: + MOCK_METHOD1(Log, bool(const char*)); + MOCK_METHOD1(DebugLog, bool(const char*)); + MOCK_METHOD1(LogFatal, bool(const char*)); + MOCK_METHOD1(LogSilent, bool(const char*)); + MOCK_METHOD2(LogF, bool(const char*, va_list)); + MOCK_METHOD2(DebugLogF, bool(const char*, va_list)); + MOCK_METHOD2(LogSilentF, bool(const char*, va_list)); +}; diff --git a/tests/aul/AulPredefinedFunctionTest.cpp b/tests/aul/AulPredefinedFunctionTest.cpp index b3b52d729..a0527b97f 100644 --- a/tests/aul/AulPredefinedFunctionTest.cpp +++ b/tests/aul/AulPredefinedFunctionTest.cpp @@ -17,14 +17,24 @@ #include "C4Include.h" #include "AulTest.h" +#include "TestLog.h" #include "script/C4Aul.h" class AulPredefFunctionTest : public AulTest {}; +using ::testing::StartsWith; +using ::testing::AnyNumber; +using ::testing::_; + TEST_F(AulPredefFunctionTest, Translate) { + // Expect the engine to warn when it can't find a translation + LogMock log; + EXPECT_CALL(log, DebugLogF(R"(WARNING: Translate: no translation for string "%s")", _)); + EXPECT_CALL(log, DebugLog(StartsWith(" by: "))).Times(AnyNumber()); // ignore stack trace + EXPECT_EQ(C4VString("a"), RunExpr("Translate(\"a\")")); }