Play-/tools/AutoTest/Main.cpp

327 lines
8.2 KiB
C++
Raw Normal View History

#include "PS2VM.h"
#include <boost/filesystem.hpp>
#include "StdStream.h"
2015-04-18 22:17:45 -04:00
#include "StdStreamUtils.h"
2015-05-05 00:12:39 -04:00
#include "JUnitTestReportWriter.h"
#include "gs/GSH_Null.h"
2017-05-28 22:48:36 -04:00
#ifdef _WIN32
#include "ui_win32/GSH_OpenGLWin32.h"
#include "ui_win32/GSH_Direct3D9.h"
#endif
#define GS_HANDLER_NAME_NULL "null"
#define GS_HANDLER_NAME_OGL "ogl"
#define GS_HANDLER_NAME_D3D9 "d3d9"
#define DEFAULT_GS_HANDLER_NAME GS_HANDLER_NAME_NULL
static std::set<std::string> g_validGsHandlersNames =
{
GS_HANDLER_NAME_NULL,
#ifdef _WIN32
GS_HANDLER_NAME_OGL,
GS_HANDLER_NAME_D3D9,
#endif
};
#ifdef _WIN32
class CTestWindow : public Framework::Win32::CWindow, public CSingleton<CTestWindow>
{
public:
CTestWindow()
{
Create(0, Framework::Win32::CDefaultWndClass::GetName(), _T(""), WS_OVERLAPPED, Framework::Win32::CRect(0, 0, 100, 100), NULL, NULL);
SetClassPtr();
}
};
#endif
CGSHandler::FactoryFunction GetGsHandlerFactoryFunction(const std::string& gsHandlerName)
{
if(gsHandlerName == GS_HANDLER_NAME_NULL)
{
return CGSH_Null::GetFactoryFunction();
}
#ifdef _WIN32
else if(gsHandlerName == GS_HANDLER_NAME_OGL)
{
return CGSH_OpenGLWin32::GetFactoryFunction(&CTestWindow::GetInstance());
}
else if(gsHandlerName == GS_HANDLER_NAME_D3D9)
{
return CGSH_Direct3D9::GetFactoryFunction(&CTestWindow::GetInstance());
}
#endif
else
{
throw std::runtime_error("Unknown GS handler name.");
}
}
2015-04-18 22:17:45 -04:00
std::vector<std::string> ReadLines(Framework::CStream& inputStream)
{
std::vector<std::string> lines;
lines.push_back(inputStream.ReadLine());
2015-04-18 22:17:45 -04:00
while(!inputStream.IsEOF())
{
lines.push_back(inputStream.ReadLine());
2015-04-18 22:17:45 -04:00
}
return lines;
}
TESTRESULT GetTestResult(const boost::filesystem::path& testFilePath)
2015-04-18 22:17:45 -04:00
{
TESTRESULT result;
result.succeeded = false;
2015-04-18 22:17:45 -04:00
try
{
auto resultFilePath = testFilePath;
resultFilePath.replace_extension(".result");
auto expectedFilePath = testFilePath;
expectedFilePath.replace_extension(".expected");
auto resultStream = Framework::CreateInputStdStream(resultFilePath.string());
auto expectedStream = Framework::CreateInputStdStream(expectedFilePath.string());
auto resultLines = ReadLines(resultStream);
auto expectedLines = ReadLines(expectedStream);
if(resultLines.size() != expectedLines.size()) return result;
2015-04-18 22:17:45 -04:00
for(unsigned int i = 0; i < resultLines.size(); i++)
{
if(resultLines[i] != expectedLines[i])
{
LINEDIFF lineDiff;
lineDiff.expected = expectedLines[i];
lineDiff.result = resultLines[i];
result.lineDiffs.push_back(lineDiff);
}
2015-04-18 22:17:45 -04:00
}
result.succeeded = result.lineDiffs.empty();
return result;
2015-04-18 22:17:45 -04:00
}
catch(...)
{
2015-04-18 22:17:45 -04:00
}
return result;
2015-04-18 22:17:45 -04:00
}
2017-05-28 22:48:36 -04:00
void ExecuteEeTest(const boost::filesystem::path& testFilePath, const std::string& gsHandlerName)
{
auto resultFilePath = testFilePath;
resultFilePath.replace_extension(".result");
auto resultStream = new Framework::CStdStream(resultFilePath.string().c_str(), "wb");
bool executionOver = false;
//Setup virtual machine
CPS2VM virtualMachine;
virtualMachine.Initialize();
virtualMachine.Reset();
2017-05-28 22:48:36 -04:00
virtualMachine.CreateGSHandler(GetGsHandlerFactoryFunction(gsHandlerName));
virtualMachine.m_ee->m_os->OnRequestExit.connect(
[&executionOver] ()
{
executionOver = true;
}
);
2017-11-07 08:25:10 -05:00
virtualMachine.m_ee->m_os->BootFromFile(testFilePath);
2015-07-03 22:18:29 -04:00
virtualMachine.m_iopOs->GetIoman()->SetFileStream(Iop::CIoman::FID_STDOUT, resultStream);
virtualMachine.Resume();
while(!executionOver)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
virtualMachine.Pause();
virtualMachine.DestroyGSHandler();
virtualMachine.Destroy();
}
void ExecuteIopTest(const boost::filesystem::path& testFilePath)
{
//Read in the module data
std::vector<uint8> moduleData;
{
auto moduleStream = Framework::CreateInputStdStream(testFilePath.native());
auto length = moduleStream.GetLength();
moduleData.resize(length);
moduleStream.Read(moduleData.data(), length);
}
auto resultFilePath = testFilePath;
resultFilePath.replace_extension(".result");
auto resultStream = new Framework::CStdStream(resultFilePath.string().c_str(), "wb");
bool executionOver = false;
//Setup virtual machine
CPS2VM virtualMachine;
virtualMachine.Initialize();
virtualMachine.Reset();
int32 rootModuleId = virtualMachine.m_iopOs->LoadModuleFromHost(moduleData.data());
virtualMachine.m_iopOs->OnModuleStarted.connect(
[&executionOver, &rootModuleId] (uint32 moduleId)
{
if(rootModuleId == moduleId)
{
executionOver = true;
}
}
);
virtualMachine.m_iopOs->StartModule(rootModuleId, "", nullptr, 0);
virtualMachine.m_iopOs->GetIoman()->SetFileStream(Iop::CIoman::FID_STDOUT, resultStream);
virtualMachine.Resume();
while(!executionOver)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
virtualMachine.Pause();
virtualMachine.Destroy();
}
2017-05-28 22:48:36 -04:00
void ScanAndExecuteTests(const boost::filesystem::path& testDirPath, const TestReportWriterPtr& testReportWriter, const std::string& gsHandlerName)
{
boost::filesystem::directory_iterator endIterator;
for(auto testPathIterator = boost::filesystem::directory_iterator(testDirPath);
testPathIterator != endIterator; testPathIterator++)
{
auto testPath = testPathIterator->path();
if(boost::filesystem::is_directory(testPath))
{
2017-05-28 22:48:36 -04:00
ScanAndExecuteTests(testPath, testReportWriter, gsHandlerName);
continue;
}
if(testPath.extension() == ".elf")
{
2015-04-18 22:17:45 -04:00
printf("Testing '%s': ", testPath.string().c_str());
2017-05-28 22:48:36 -04:00
ExecuteEeTest(testPath, gsHandlerName);
auto result = GetTestResult(testPath);
printf("%s.\r\n", result.succeeded ? "SUCCEEDED" : "FAILED");
if(testReportWriter)
{
testReportWriter->ReportTestEntry(testPath.string(), result);
}
}
else if(testPath.extension() == ".irx")
{
printf("Testing '%s': ", testPath.string().c_str());
ExecuteIopTest(testPath);
auto result = GetTestResult(testPath);
printf("%s.\r\n", result.succeeded ? "SUCCEEDED" : "FAILED");
2015-05-05 00:12:39 -04:00
if(testReportWriter)
{
testReportWriter->ReportTestEntry(testPath.string(), result);
2015-05-05 00:12:39 -04:00
}
}
}
}
int main(int argc, const char** argv)
{
if(argc < 2)
{
2017-05-28 22:48:36 -04:00
auto validGsHandlerNamesString =
[]()
{
std::string result;
for(auto nameIterator = g_validGsHandlersNames.begin();
nameIterator != g_validGsHandlersNames.end(); ++nameIterator)
{
if(nameIterator != g_validGsHandlersNames.begin())
{
result += "|";
}
result += *nameIterator;
}
return result;
}();
2015-05-05 00:12:39 -04:00
printf("Usage: AutoTest [options] testDir\r\n");
printf("Options: \r\n");
printf("\t --junitreport <path>\t Writes JUnit format report at <path>.\r\n");
2017-05-28 22:48:36 -04:00
printf("\t --gshandler <%s>\tSelects which GS handler to instantiate (default is '%s').\r\n",
validGsHandlerNamesString.c_str(), DEFAULT_GS_HANDLER_NAME);
return -1;
}
2015-05-05 00:12:39 -04:00
TestReportWriterPtr testReportWriter;
boost::filesystem::path autoTestRoot;
boost::filesystem::path reportPath;
2017-05-28 22:48:36 -04:00
std::string gsHandlerName = DEFAULT_GS_HANDLER_NAME;
assert(g_validGsHandlersNames.find(gsHandlerName) != std::end(g_validGsHandlersNames));
2015-05-05 00:12:39 -04:00
for(int i = 1; i < argc; i++)
{
if(!strcmp(argv[i], "--junitreport"))
{
if((i + 1) >= argc)
{
printf("Error: Path must be specified for --junitreport option.\r\n");
return -1;
}
testReportWriter = std::make_shared<CJUnitTestReportWriter>();
reportPath = boost::filesystem::path(argv[i + 1]);
i++;
}
2017-05-28 22:48:36 -04:00
else if(!strcmp(argv[i], "--gshandler"))
{
if((i + 1) >= argc)
{
printf("Error: GS handler name must be specified for --gshandler option.\r\n");
return -1;
}
gsHandlerName = argv[i + 1];
if(g_validGsHandlersNames.find(gsHandlerName) == std::end(g_validGsHandlersNames))
{
printf("Error: Invalid GS handler name '%s'.\r\n", gsHandlerName.c_str());
return -1;
}
i++;
}
2015-05-05 00:12:39 -04:00
else
{
autoTestRoot = argv[i];
break;
}
}
if(autoTestRoot.empty())
{
printf("Error: No test directory specified.\r\n");
return -1;
}
try
{
2017-05-28 22:48:36 -04:00
ScanAndExecuteTests(autoTestRoot, testReportWriter, gsHandlerName);
}
catch(const std::exception& exception)
{
printf("Error: Failed to execute tests: %s\r\n", exception.what());
return -1;
}
2015-05-05 00:12:39 -04:00
if(testReportWriter)
{
try
{
testReportWriter->Write(reportPath);
}
catch(const std::exception& exception)
{
printf("Error: Failed to write test report: %s\r\n", exception.what());
return -1;
}
}
return 0;
}