Commit 776a75b4 by Jamie Madill Committed by Commit Bot

Make Platform errors trigger test failures.

This can be useful in the Vulkan back-end to make validation layer errors cause test cases to fail. BUG=angleproject:1319 Change-Id: I523f3c874e892a2646600e4c5c554319ed8d770c Reviewed-on: https://chromium-review.googlesource.com/342050Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent be815a4f
...@@ -80,6 +80,9 @@ class EGLX11VisualHintTest : public ::testing::TestWithParam<angle::PlatformPara ...@@ -80,6 +80,9 @@ class EGLX11VisualHintTest : public ::testing::TestWithParam<angle::PlatformPara
// Test that display creation fails if the visual ID passed in invalid. // Test that display creation fails if the visual ID passed in invalid.
TEST_P(EGLX11VisualHintTest, InvalidVisualID) TEST_P(EGLX11VisualHintTest, InvalidVisualID)
{ {
// The test platform will log an error in this negative test.
IgnoreANGLEPlatformMessages();
static const int gInvalidVisualId = -1; static const int gInvalidVisualId = -1;
auto attributes = getDisplayAttributes(gInvalidVisualId); auto attributes = getDisplayAttributes(gInvalidVisualId);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "ANGLETest.h" #include "ANGLETest.h"
#include "EGLWindow.h" #include "EGLWindow.h"
#include "OSWindow.h" #include "OSWindow.h"
#include "system_utils.h" #include "platform/Platform.h"
namespace angle namespace angle
{ {
...@@ -28,6 +28,59 @@ float ColorNorm(GLubyte channelValue) ...@@ -28,6 +28,59 @@ float ColorNorm(GLubyte channelValue)
{ {
return static_cast<float>(channelValue) / 255.0f; return static_cast<float>(channelValue) / 255.0f;
} }
// Use a custom ANGLE platform class to capture and report internal errors.
class TestPlatform : public angle::Platform
{
public:
TestPlatform() : mIgnoreMessages(false) {}
void logError(const char *errorMessage) override;
void logWarning(const char *warningMessage) override;
void logInfo(const char *infoMessage) override;
void ignoreMessages();
void enableMessages();
private:
bool mIgnoreMessages;
};
void TestPlatform::logError(const char *errorMessage)
{
if (mIgnoreMessages)
return;
FAIL() << errorMessage;
}
void TestPlatform::logWarning(const char *warningMessage)
{
if (mIgnoreMessages)
return;
std::cerr << "Warning: " << warningMessage << std::endl;
}
void TestPlatform::logInfo(const char *infoMessage)
{
if (mIgnoreMessages)
return;
angle::WriteDebugMessage("%s\n", infoMessage);
}
void TestPlatform::ignoreMessages()
{
mIgnoreMessages = true;
}
void TestPlatform::enableMessages()
{
mIgnoreMessages = false;
}
TestPlatform g_testPlatformInstance;
} // anonymous namespace } // anonymous namespace
GLColor::GLColor() : R(0), G(0), B(0), A(0) GLColor::GLColor() : R(0), G(0), B(0), A(0)
...@@ -93,6 +146,8 @@ ANGLETest::~ANGLETest() ...@@ -93,6 +146,8 @@ ANGLETest::~ANGLETest()
void ANGLETest::SetUp() void ANGLETest::SetUp()
{ {
angle::g_testPlatformInstance.enableMessages();
// Resize the window before creating the context so that the first make current // Resize the window before creating the context so that the first make current
// sets the viewport and scissor box to the right size. // sets the viewport and scissor box to the right size.
bool needSwap = false; bool needSwap = false;
...@@ -637,6 +692,17 @@ OSWindow *ANGLETest::mOSWindow = NULL; ...@@ -637,6 +692,17 @@ OSWindow *ANGLETest::mOSWindow = NULL;
void ANGLETestEnvironment::SetUp() void ANGLETestEnvironment::SetUp()
{ {
mGLESLibrary.reset(angle::loadLibrary("libGLESv2"));
if (mGLESLibrary)
{
auto initFunc = reinterpret_cast<ANGLEPlatformInitializeFunc>(
mGLESLibrary->getSymbol("ANGLEPlatformInitialize"));
if (initFunc)
{
initFunc(&angle::g_testPlatformInstance);
}
}
if (!ANGLETest::InitTestWindow()) if (!ANGLETest::InitTestWindow())
{ {
FAIL() << "Failed to create ANGLE test window."; FAIL() << "Failed to create ANGLE test window.";
...@@ -646,4 +712,20 @@ void ANGLETestEnvironment::SetUp() ...@@ -646,4 +712,20 @@ void ANGLETestEnvironment::SetUp()
void ANGLETestEnvironment::TearDown() void ANGLETestEnvironment::TearDown()
{ {
ANGLETest::DestroyTestWindow(); ANGLETest::DestroyTestWindow();
if (mGLESLibrary)
{
auto shutdownFunc = reinterpret_cast<ANGLEPlatformShutdownFunc>(
mGLESLibrary->getSymbol("ANGLEPlatformShutdown"));
if (shutdownFunc)
{
shutdownFunc();
}
}
}
void IgnoreANGLEPlatformMessages()
{
// Negative tests may trigger expected errors/warnings in the ANGLE Platform.
angle::g_testPlatformInstance.ignoreMessages();
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "angle_test_configs.h" #include "angle_test_configs.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "shader_utils.h" #include "shader_utils.h"
#include "system_utils.h"
#include "Vector.h" #include "Vector.h"
#define EXPECT_GL_ERROR(err) EXPECT_EQ(static_cast<GLenum>(err), glGetError()) #define EXPECT_GL_ERROR(err) EXPECT_EQ(static_cast<GLenum>(err), glGetError())
...@@ -186,8 +187,12 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -186,8 +187,12 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
class ANGLETestEnvironment : public testing::Environment class ANGLETestEnvironment : public testing::Environment
{ {
public: public:
virtual void SetUp(); void SetUp() override;
virtual void TearDown(); void TearDown() override;
private:
// For loading and freeing platform
std::unique_ptr<angle::Library> mGLESLibrary;
}; };
bool IsIntel(); bool IsIntel();
...@@ -203,4 +208,7 @@ bool IsD3DSM3(); ...@@ -203,4 +208,7 @@ bool IsD3DSM3();
bool IsLinux(); bool IsLinux();
bool IsOSX(); bool IsOSX();
// Negative tests may trigger expected errors/warnings in the ANGLE Platform.
void IgnoreANGLEPlatformMessages();
#endif // ANGLE_TESTS_ANGLE_TEST_H_ #endif // ANGLE_TESTS_ANGLE_TEST_H_
...@@ -39,4 +39,9 @@ std::string GetExecutableDirectory() ...@@ -39,4 +39,9 @@ std::string GetExecutableDirectory()
return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : ""; return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
} }
std::string GetSharedLibraryExtension()
{
return "so";
}
} // namespace angle } // namespace angle
...@@ -42,4 +42,9 @@ std::string GetExecutableDirectory() ...@@ -42,4 +42,9 @@ std::string GetExecutableDirectory()
return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : ""; return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
} }
std::string GetSharedLibraryExtension()
{
return "dylib";
}
} // namespace angle } // namespace angle
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "system_utils.h" #include "system_utils.h"
#include <sys/resource.h> #include <sys/resource.h>
#include <dlfcn.h>
#include <sched.h> #include <sched.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
...@@ -46,4 +47,45 @@ void WriteDebugMessage(const char *format, ...) ...@@ -46,4 +47,45 @@ void WriteDebugMessage(const char *format, ...)
// TODO(jmadill): Implement this // TODO(jmadill): Implement this
} }
class PosixLibrary : public Library
{
public:
PosixLibrary(const std::string &libraryName);
~PosixLibrary() override;
void *getSymbol(const std::string &symbolName) override;
private:
void *mModule;
};
PosixLibrary::PosixLibrary(const std::string &libraryName) : mModule(nullptr)
{
const auto &fullName = libraryName + "." + GetSharedLibraryExtension();
mModule = dlopen(fullName.c_str(), RTLD_NOW);
}
PosixLibrary::~PosixLibrary()
{
if (mModule)
{
dlclose(mModule);
}
}
void *PosixLibrary::getSymbol(const std::string &symbolName)
{
if (!mModule)
{
return nullptr;
}
return dlsym(mModule, symbolName.c_str());
}
Library *loadLibrary(const std::string &libraryName)
{
return new PosixLibrary(libraryName);
}
} // namespace angle } // namespace angle
...@@ -6,16 +6,19 @@ ...@@ -6,16 +6,19 @@
// system_utils.h: declaration of OS-specific utility functions // system_utils.h: declaration of OS-specific utility functions
#ifndef SAMPLE_UTIL_PATH_UTILS_H #ifndef UTIL_SYSTEM_UTILS_H_
#define SAMPLE_UTIL_PATH_UTILS_H #define UTIL_SYSTEM_UTILS_H_
#include <string> #include <string>
#include "common/angleutils.h"
namespace angle namespace angle
{ {
std::string GetExecutablePath(); std::string GetExecutablePath();
std::string GetExecutableDirectory(); std::string GetExecutableDirectory();
std::string GetSharedLibraryExtension();
// Cross platform equivalent of the Windows Sleep function // Cross platform equivalent of the Windows Sleep function
void Sleep(unsigned int milliseconds); void Sleep(unsigned int milliseconds);
...@@ -25,6 +28,15 @@ void SetLowPriorityProcess(); ...@@ -25,6 +28,15 @@ void SetLowPriorityProcess();
// Write a debug message, either to a standard output or Debug window. // Write a debug message, either to a standard output or Debug window.
void WriteDebugMessage(const char *format, ...); void WriteDebugMessage(const char *format, ...);
class Library : angle::NonCopyable
{
public:
virtual ~Library() {}
virtual void *getSymbol(const std::string &symbolName) = 0;
};
Library *loadLibrary(const std::string &libraryName);
} // namespace angle } // namespace angle
#endif // SAMPLE_UTIL_PATH_UTILS_H #endif // UTIL_SYSTEM_UTILS_H_
...@@ -31,6 +31,11 @@ std::string GetExecutableDirectory() ...@@ -31,6 +31,11 @@ std::string GetExecutableDirectory()
return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : ""; return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
} }
std::string GetSharedLibraryExtension()
{
return "dll";
}
void Sleep(unsigned int milliseconds) void Sleep(unsigned int milliseconds)
{ {
::Sleep(static_cast<DWORD>(milliseconds)); ::Sleep(static_cast<DWORD>(milliseconds));
......
...@@ -19,4 +19,45 @@ void SetLowPriorityProcess() ...@@ -19,4 +19,45 @@ void SetLowPriorityProcess()
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
} }
class Win32Library : public Library
{
public:
Win32Library(const std::string &libraryName);
~Win32Library() override;
void *getSymbol(const std::string &symbolName) override;
private:
HMODULE mModule;
};
Win32Library::Win32Library(const std::string &libraryName) : mModule(nullptr)
{
const auto &fullName = libraryName + "." + GetSharedLibraryExtension();
mModule = LoadLibraryA(fullName.c_str());
}
Win32Library::~Win32Library()
{
if (mModule)
{
FreeLibrary(mModule);
}
}
void *Win32Library::getSymbol(const std::string &symbolName)
{
if (!mModule)
{
return nullptr;
}
return GetProcAddress(mModule, symbolName.c_str());
}
Library *loadLibrary(const std::string &libraryName)
{
return new Win32Library(libraryName);
}
} // namespace angle } // namespace angle
...@@ -19,4 +19,10 @@ void SetLowPriorityProcess() ...@@ -19,4 +19,10 @@ void SetLowPriorityProcess()
// No equivalent to this in WinRT // No equivalent to this in WinRT
} }
Library *loadLibrary(const std::string &libraryName)
{
// WinRT cannot load code dynamically.
return nullptr;
}
} // namespace angle } // namespace angle
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment