Commit df785dfa by Jamie Madill

dEQP: Add GoogleTest integration.

Use value-parameterized tests, loading a full test list from case files. BUG=angleproject:998 Change-Id: Iff65a2d722e9d105e22649b17a18cc74dccea2b1 Reviewed-on: https://chromium-review.googlesource.com/274421Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 4f3c14be
......@@ -781,6 +781,10 @@
[
'<(angle_path)/include',
],
'defines':
[
'ANGLE_DEQP_LIBTESTER_IMPLEMENTATION',
],
},
'msvs_settings':
{
......@@ -1124,6 +1128,41 @@
'deqp_support/angle_deqp_tests_main.cpp',
],
},
{
'target_name': 'angle_deqp_googletest',
'type': 'executable',
'dependencies':
[
'angle_deqp_libgles2',
'angle_test_support',
'angle_zlib',
'<(angle_path)/src/angle.gyp:angle_common',
],
'includes':
[
'../../build/common_defines.gypi',
],
'defines':
[
# Hard-code the path to dEQP. This lets the
# app locate the data folder without need
# for a copy. gyp recursive copies are not
# implemented properly on Windows.
'ANGLE_DEQP_DIR="<(DEPTH)/src/tests/<(deqp_dir)"',
],
'include_dirs':
[
'deqp_support',
],
'sources':
[
'deqp_support/angle_deqp_gtest_main.cpp',
],
},
], # targets
}], # OS == "win"
], # conditions
......
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// angle_deqp_gtest_main:
// dEQP and GoogleTest integration logic. Calls through to the random
// order executor.
#include <gtest/gtest.h>
#include <stdint.h>
#include <zlib.h>
#include <algorithm>
#include <fstream>
#include "angle_deqp_libtester.h"
#include "common/angleutils.h"
#include "common/debug.h"
namespace
{
class dEQPCaseList
{
public:
dEQPCaseList(const char *caseListPath);
struct CaseInfo
{
CaseInfo(const std::string &dEQPName,
const std::string &gTestName)
: mDEQPName(dEQPName),
mGTestName(gTestName)
{
}
std::string mDEQPName;
std::string mGTestName;
};
const CaseInfo &getCaseInfo(size_t caseIndex) const
{
ASSERT(caseIndex < mCaseInfoList.size());
return mCaseInfoList[caseIndex];
}
size_t numCases() const
{
return mCaseInfoList.size();
}
static dEQPCaseList *GetInstance();
static void FreeInstance();
private:
std::vector<CaseInfo> mCaseInfoList;
static dEQPCaseList *mInstance;
};
// static
dEQPCaseList *dEQPCaseList::mInstance = nullptr;
// static
dEQPCaseList *dEQPCaseList::GetInstance()
{
if (mInstance == nullptr)
{
mInstance = new dEQPCaseList("deqp_support/dEQP-GLES2-cases.txt.gz");
}
return mInstance;
}
// static
void dEQPCaseList::FreeInstance()
{
SafeDelete(mInstance);
}
dEQPCaseList::dEQPCaseList(const char *caseListPath)
{
std::stringstream caseListStream;
std::vector<char> buf(1024 * 1024 * 16);
gzFile *fi = static_cast<gzFile *>(gzopen(caseListPath, "rb"));
if (fi == nullptr)
{
return;
}
gzrewind(fi);
while (!gzeof(fi))
{
int len = gzread(fi, &buf[0], buf.size() - 1);
buf[len] = '\0';
caseListStream << &buf[0];
}
gzclose(fi);
while (!caseListStream.eof())
{
std::string inString;
std::getline(caseListStream, inString);
if (inString.substr(0, 4) == "TEST")
{
std::string dEQPName = inString.substr(6);
std::string gTestName = dEQPName.substr(11);
std::replace(gTestName.begin(), gTestName.end(), '.', '_');
// Occurs in some luminance tests
gTestName.erase(std::remove(gTestName.begin(), gTestName.end(), '-'), gTestName.end());
mCaseInfoList.push_back(CaseInfo(dEQPName, gTestName));
}
}
}
class dEQP_GLES2 : public testing::TestWithParam<size_t>
{
protected:
dEQP_GLES2() {}
void runTest()
{
const auto &caseInfo = dEQPCaseList::GetInstance()->getCaseInfo(GetParam());
std::cout << caseInfo.mDEQPName << std::endl;
ASSERT_TRUE(deqp_libtester_run(caseInfo.mDEQPName.c_str()));
}
};
// TODO(jmadill): add different platform configs, or ability to choose platform
TEST_P(dEQP_GLES2, Default)
{
runTest();
}
testing::internal::ParamGenerator<size_t> GetTestingRange()
{
return testing::Range<size_t>(0, dEQPCaseList::GetInstance()->numCases());
}
INSTANTIATE_TEST_CASE_P(, dEQP_GLES2, GetTestingRange());
}
int main(int argc, char **argv)
{
deqp_libtester_init_platform(argc, argv, ANGLE_DEQP_DIR "/data");
testing::InitGoogleTest(&argc, argv);
int rt = RUN_ALL_TESTS();
dEQPCaseList::FreeInstance();
deqp_libtester_shutdown_platform();
return rt;
}
//
// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// angle_deqp_libtester.h:
// Exports for the ANGLE dEQP libtester module.
#ifndef ANGLE_DEQP_LIBTESTER_H_
#define ANGLE_DEQP_LIBTESTER_H_
#if defined(_WIN32)
# if defined(ANGLE_DEQP_LIBTESTER_IMPLEMENTATION)
# define ANGLE_LIBTESTER_EXPORT __declspec(dllexport)
# else
# define ANGLE_LIBTESTER_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__)
# if defined(ANGLE_DEQP_LIBTESTER_IMPLEMENTATION)
# define ANGLE_LIBTESTER_EXPORT __attribute__((visibility ("default")))
# else
# define ANGLE_LIBTESTER_EXPORT
# endif
#else
# define ANGLE_LIBTESTER_EXPORT
#endif
// Exported to the tester app.
ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[]);
ANGLE_LIBTESTER_EXPORT void deqp_libtester_init_platform(int argc, char **argv, const char *deqpDataDir);
ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform();
ANGLE_LIBTESTER_EXPORT bool deqp_libtester_run(const char *caseName);
#endif // ANGLE_DEQP_LIBTESTER_H_
......@@ -3,14 +3,124 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// deqp_libtester_main.cpp: Entry point for tester DLL.
// Located in tcuMain.cc in dEQP's soruces.
#include <cstdio>
#include <iostream>
#include "angle_deqp_libtester.h"
#include "deMath.h"
#include "deUniquePtr.hpp"
#include "tcuApp.hpp"
#include "tcuCommandLine.hpp"
#include "tcuDefs.hpp"
#include "tcuPlatform.hpp"
#include "tcuRandomOrderExecutor.h"
#include "tcuResource.hpp"
#include "tcuTestLog.hpp"
// Located in tcuMain.cc in dEQP's sources.
int main(int argc, const char* argv[]);
tcu::Platform *createPlatform();
namespace
{
tcu::Platform *g_platform = nullptr;
tcu::CommandLine *g_cmdLine = nullptr;
tcu::DirArchive *g_archive = nullptr;
tcu::TestLog *g_log = nullptr;
tcu::TestContext *g_testCtx = nullptr;
tcu::TestPackageRoot *g_root = nullptr;
tcu::RandomOrderExecutor *g_executor = nullptr;
}
// Exported to the tester app.
__declspec(dllexport) int deqp_libtester_main(int argc, const char *argv[])
ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[])
{
return main(argc, argv);
}
ANGLE_LIBTESTER_EXPORT void deqp_libtester_init_platform(int argc, char **argv, const char *deqpDataDir)
{
try
{
#if (DE_OS != DE_OS_WIN32)
// Set stdout to line-buffered mode (will be fully buffered by default if stdout is pipe).
setvbuf(stdout, DE_NULL, _IOLBF, 4 * 1024);
#endif
g_platform = createPlatform();
if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST))
{
throw std::exception("Failed to set floating point rounding mode.");
}
// TODO(jmadill): filter arguments
g_cmdLine = new tcu::CommandLine(1, argv);
g_archive = new tcu::DirArchive(deqpDataDir);
g_log = new tcu::TestLog(g_cmdLine->getLogFileName(), g_cmdLine->getLogFlags());
g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, DE_NULL);
g_root = new tcu::TestPackageRoot(*g_testCtx, tcu::TestPackageRegistry::getSingleton());
g_executor = new tcu::RandomOrderExecutor(*g_root, *g_testCtx);
}
catch (const std::exception& e)
{
tcu::die("%s", e.what());
}
}
ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform()
{
delete g_executor;
delete g_root;
delete g_testCtx;
delete g_log;
delete g_archive;
delete g_cmdLine;
delete g_platform;
}
ANGLE_LIBTESTER_EXPORT bool deqp_libtester_run(const char *caseName)
{
if (!g_platform)
{
return false;
}
try
{
// Poll platform events
const bool platformOk = g_platform->processEvents();
if (platformOk)
{
const tcu::TestStatus &result = g_executor->execute(caseName);
switch (result.getCode())
{
case QP_TEST_RESULT_PASS:
case QP_TEST_RESULT_NOT_SUPPORTED:
return true;
case QP_TEST_RESULT_QUALITY_WARNING:
std::cout << "Quality warning! " << result.getDescription() << std::endl;
return true;
case QP_TEST_RESULT_COMPATIBILITY_WARNING:
std::cout << "Compatiblity warning! " << result.getDescription() << std::endl;
return true;
default:
return false;
}
}
else
{
std::cout << "Aborted test!" << std::endl;
}
}
catch (const std::exception &e)
{
std::cout << "Exception running test: " << e.what() << std::endl;
}
return false;
}
......@@ -9,9 +9,9 @@
#include <direct.h>
#include <stdio.h>
__declspec(dllimport) int deqp_libtester_main(int argc, const char* argv[]);
#include "angle_deqp_libtester.h"
int main(int argc, const char* argv[])
int main(int argc, const char *argv[])
{
const char * data_dir = ANGLE_DEQP_DIR "/data";
if (_chdir(data_dir) != 0)
......
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