16ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include "gles_conformance_tests.h"
26ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include "GTFMain.h"
36ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
46ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include <stdio.h>
56ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include <stdlib.h>
66ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include <vector>
76ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include <sstream>
86ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang#include <stdarg.h>
96ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
106ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langstatic ConformanceConfig kCurrentConfig = { 64, 64, EGL_DEFAULT_DISPLAY };
116ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
126ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langvoid SetCurrentConfig(const ConformanceConfig& config)
136ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang{
146ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    kCurrentConfig = config;
156ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang}
166ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
176ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langconst ConformanceConfig& GetCurrentConfig()
186ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang{
196ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    return kCurrentConfig;
206ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang}
216ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
226ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langstatic std::vector<char> FormatArg(const char* fmt, ...)
236ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang{
246ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    va_list vararg;
256ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    va_start(vararg, fmt);
266ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    int len = vsnprintf(NULL, 0, fmt, vararg);
276ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    va_end(vararg);
286ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
296ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> buf(len + 1);
306ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
316ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    va_start(vararg, fmt);
326ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    vsnprintf(buf.data(), buf.size(), fmt, vararg);
336ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    va_end(vararg);
346ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
356ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    return buf;
366ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang}
376ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
386ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langstatic std::string GetExecutableDirectory()
396ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang{
406ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> executableFileBuf(MAX_PATH);
416ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    DWORD executablePathLen = GetModuleFileNameA(NULL, executableFileBuf.data(), executableFileBuf.size());
426ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    if (executablePathLen == 0)
436ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    {
446ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        return false;
456ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    }
466ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
476ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::string executableLocation = executableFileBuf.data();
486ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    size_t lastPathSepLoc = executableLocation.find_last_of("\\/");
496ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    if (lastPathSepLoc != std::string::npos)
506ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    {
516ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        executableLocation = executableLocation.substr(0, lastPathSepLoc);
526ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    }
536ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    else
546ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    {
556ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        executableLocation = "";
566ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    }
576ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
586ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    return executableLocation;
596ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang}
606ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
616ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Langvoid RunConformanceTest(const std::string &testPath, const ConformanceConfig& config)
626ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang{
636ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char*> args;
646ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
656ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    // Empty first argument for the program name
666ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    args.push_back("");
676ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
686ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> widthArg = FormatArg("-width=%u", config.width);
696ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    args.push_back(widthArg.data());
706ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
716ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> heightArg = FormatArg("-height=%u", config.height);
726ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    args.push_back(heightArg.data());
736ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
746ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> displayArg = FormatArg("-d=%u", config.displayType);
756ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    args.push_back(displayArg.data());
766ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
776ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::vector<char> runArg = FormatArg("-run=%s/conformance_tests/%s", GetExecutableDirectory().c_str(), testPath.c_str());
786ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    args.push_back(runArg.data());
796ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
806ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    // Redirect cout
816ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
826ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::ostringstream strCout;
836ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::cout.rdbuf(strCout.rdbuf());
846ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
856ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    if (GTFMain(args.size(), args.data()) != 0)
866ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    {
876ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        FAIL() << "GTFMain failed.";
886ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    }
896ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
906ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    // Restore old cout
916ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::cout.rdbuf(oldCoutStreamBuf);
926ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::string log = strCout.str();
936ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
946ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    // Look for failures
956ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    size_t offset = 0;
966ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    std::string offsetSearchString = "failure = ";
976ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    while ((offset = log.find("failure = ", offset)) != std::string::npos)
986ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    {
996ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        offset += offsetSearchString.length();
1006ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang
1016ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        size_t failureCount = atoll(log.c_str() + offset);
1026ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang        EXPECT_EQ(0, failureCount) << log;
1036ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang    }
1046ba49d9460a0071f1e95ba09a428addb9e3931b0Geoff Lang}
105