diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..25b0820 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,9 @@ +test_dmd: + stage: test + image: mmcomando/ecs_enviroment + script: + - source $(/script/dlang/install.sh dmd -a) && dmd --version + - source $(/script/dlang/install.sh dmd -a) && dub -c unittest-runner -b unittest + artifacts: + reports: + junit: test_report.xml diff --git a/dub.json b/dub.json index 02ea4b2..1df36ba 100755 --- a/dub.json +++ b/dub.json @@ -83,6 +83,22 @@ "lflags-gdc": [ "-lpthread" ] + }, + + { + "name": "unittest-runner", + "targetType" : "executable", + "dflags": [ + "-betterC" + ], + "sourceFiles":[ + "tests/runner.d" + ], + "excludedSourceFiles":[ + "source\/win_dll.d" + ] } + + ] } \ No newline at end of file diff --git a/tests/runner.d b/tests/runner.d new file mode 100644 index 0000000..2b8597f --- /dev/null +++ b/tests/runner.d @@ -0,0 +1,207 @@ +// Example usage: dub -c unittest-runner -b unittest +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("\n"); + +} + +void writeResulEnd() +{ + writeToFile("\n"); +} + +void writeResult(ref TestSuite suite, ref Test result) +{ + writeToFile(" \n"); + } + else + { + writeToFile(">\n"); + writeToFile(" "); + + 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("\n"); + writeToFile(" \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 +}