Aul tests: Assert that Translate() warns when a translation is missing

I'm not a huge fan of testing for warnings by hijacking the logging
routines, but right now there's no way to exfiltrate warnings from Aul
any other way, so it'll have to do.

Overriding the logging functions from C4SimpleLog.cpp has the nice
additional advantage that expected runtime errors no longer get written
to stdout - this is okay because we're already checking that an
exception is thrown.
objectmenu
Nicolas Hake 2016-01-23 03:17:06 +01:00
parent 53fe0fa1cc
commit b7cffa5e82
4 changed files with 146 additions and 2 deletions

View File

@ -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()

69
tests/TestLog.cpp 100644
View File

@ -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; }

59
tests/TestLog.h 100644
View File

@ -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 <stdarg.h>
#include <gmock/gmock.h>
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));
};

View File

@ -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\")"));
}