Add betterC test runner

This commit is contained in:
mmcomando 2020-03-21 23:13:08 +01:00
parent 845f468d59
commit 67a785f2dc
2 changed files with 222 additions and 0 deletions

View file

@ -86,6 +86,22 @@
"lflags-gdc": [
"-lpthread"
]
}
},
{
"name": "unittest-runner",
"targetType" : "executable",
"dflags": [
"-betterC"
],
"sourceFiles":[
"tests/runner.d"
],
"excludedSourceFiles":[
"source\/win_dll.d"
]
}
]
}

206
tests/runner.d Normal file
View file

@ -0,0 +1,206 @@
module tests.runner;
import core.stdc.stdio;
import core.stdc.string;
import core.sys.posix.setjmp;
import ecs.vector;
import ecs.std;
unittest
{
assert(0, "AAAAAAAA");
}
enum int ASSERTED = 123;
enum string OUT_FILE = "test_report.xml";
__gshared jmp_buf gEnvBuffer;
__gshared TestSuite[2] gSuites;
__gshared AssertInfo gAssertInfo;
struct AssertInfo
{
const(char)* msg;
const(char)* file;
int line;
}
extern (C) void __assert(const char* msg, const char* file, int line)
{
gAssertInfo = AssertInfo(msg, file, line);
longjmp(gEnvBuffer, ASSERTED);
}
struct Test
{
string file;
string msg;
int fileLine;
string name;
int time;
bool passed;
bool executed;
}
struct TestSuite
{
string name;
Vector!Test tests;
}
void writeToFile(string data)
{
auto file = fopen(OUT_FILE, "a");
fwrite(data.ptr, 1, data.length, file);
fclose(file);
}
void writeToFile(int num)
{
auto file = fopen(OUT_FILE, "a");
fprintf(file, "%d", num);
fclose(file);
}
void writeResulStart(int num)
{
// Clear file
auto file = fopen(OUT_FILE, "w");
fclose(file);
writeToFile("<testsuite tests=\"");
writeToFile(num);
writeToFile("\">\n");
}
void writeResulEnd()
{
writeToFile("</testsuite>\n");
}
void writeResult(ref TestSuite suite, ref Test result)
{
writeToFile(" <testcase classname=\"");
writeToFile(suite.name);
writeToFile("\" name=\"");
writeToFile(result.name);
writeToFile("\" time=\"");
writeToFile(result.time);
writeToFile("\" ");
writeToFile(" executed=\"");
writeToFile(cast(int) result.executed);
writeToFile("\" ");
if (result.passed)
{
writeToFile("/>\n");
}
else
{
writeToFile(">\n");
writeToFile(" <failure type=\"Fail\">");
if (result.file.length != 0)
{
writeToFile("Assert! File: ");
writeToFile(result.file[0 .. $ - 1]);
writeToFile(":");
writeToFile(result.fileLine);
writeToFile(" Message: ");
writeToFile(result.msg[0 .. $ - 1]);
}
else
{
writeToFile("No Message");
}
writeToFile("</failure>\n");
writeToFile(" </testcase>\n");
}
}
void writeTests(TestSuite[] suites)
{
writeResulStart(cast(int) suites.length);
foreach (ref TestSuite suite; suites)
{
foreach (ref Test test; suite.tests)
{
writeResult(suite, test);
}
}
writeResulEnd();
}
string copyString(const char* str)
{
auto length = strlen(str);
char[] arr = cast(char[]) str[0 .. length + 1];
return cast(string) Mallocator.makeArray(arr);
}
void runTestSuite(alias testModule)(ref TestSuite suite)
{
suite.name = testModule.stringof;
foreach (index, testDelegate; __traits(getUnitTests, testModule))
{
suite.tests[index].executed = true;
writeTests(gSuites); // Save executed info
// Save calling environment for longjmp
int jmpRet = setjmp(gEnvBuffer);
if (jmpRet == ASSERTED)
{
suite.tests[index].passed = false;
suite.tests[index].file = copyString(gAssertInfo.file);
suite.tests[index].fileLine = gAssertInfo.line;
suite.tests[index].msg = copyString(gAssertInfo.msg);
}
else
{
testDelegate();
suite.tests[index].passed = true;
}
}
}
void addTestSuite(alias testModule)(ref TestSuite suite)
{
suite.name = testModule.stringof;
foreach (index, testDelegate; __traits(getUnitTests, testModule))
{
enum attributes = __traits(getAttributes, testDelegate);
static if (attributes.length == 0)
{
enum string testName = "No name";
}
else
{
enum string testName = attributes[0];
}
Test test;
test.name = testName;
suite.tests ~= test;
}
}
void main()
{
addTestSuite!(tests.runner)(gSuites[0]);
addTestSuite!(ecs.id_manager)(gSuites[1]);
writeTests(gSuites); // Save results in case that there are no tests
runTestSuite!(tests.runner)(gSuites[0]);
runTestSuite!(ecs.id_manager)(gSuites[1]);
writeTests(gSuites); // Save result of last test
}