1 module tagion.testbench.tvm.wasm_testsuite; 2 // Default import list for bdd 3 import std.array; 4 import std.file : exists, fread = read, readText, fwrite = write; 5 import std.format; 6 import std.path; 7 import std.process; 8 import std.stdio; 9 import std.typecons : Tuple; 10 import tagion.basic.Types : FileExtension; 11 import tagion.behaviour; 12 import tagion.behaviour : check; 13 import tagion.hibon.Document; 14 import tagion.testbench.tools.Environment; 15 import tagion.wasm.WasmBetterC; 16 import tagion.wasm.WasmReader; 17 import tagion.wasm.WasmWriter; 18 import tagion.wasm.WastParser; 19 import tagion.wasm.WastTokenizer; 20 21 enum feature = Feature( 22 "Test of the wasm to betterc execution", 23 [ 24 "This feature test of transpiler from wasm to betterC parses of the testsuite.", 25 "Specified in [WebAssembly testsuite](https://github.com/WebAssembly/testsuite)" 26 ]); 27 28 alias FeatureContext = Tuple!( 29 ShouldConvertswastfileTestsuiteToWasmFileFormat, "ShouldConvertswastfileTestsuiteToWasmFileFormat", 30 ShouldLoadAwasmfileAndConvertItIntoBetterC, "ShouldLoadAwasmfileAndConvertItIntoBetterC", 31 ShouldTranspileTheWasmFileToBetterCFileAndExecutionIt, "ShouldTranspileTheWasmFileToBetterCFileAndExecutionIt", 32 FeatureGroup*, "result" 33 ); 34 35 static string testsuite; 36 @safe @Scenario("should converts #wast-file testsuite to wasm file format", 37 []) 38 class ShouldConvertswastfileTestsuiteToWasmFileFormat { 39 40 string wast_file; 41 string wasm_file; 42 WastTokenizer tokenizer; 43 WasmWriter writer; 44 this(const string wast_file) { 45 this.wast_file = buildPath(testsuite, wast_file); 46 wasm_file = buildPath(env.bdd_results, wast_file.baseName.setExtension("wasm")); 47 } 48 49 @Given("a wast testsuite file") 50 Document file() { 51 writefln("%s", __FUNCTION__); 52 immutable wast_text = wast_file.readText; 53 tokenizer = WastTokenizer(wast_text); 54 return result_ok; 55 } 56 57 @When("the wast file has successfully been converted to WebAssembly") 58 Document webAssembly() { 59 writer = new WasmWriter; 60 auto wast_parser = WastParser(writer); 61 wast_parser.parse(tokenizer); 62 return result_ok; 63 } 64 65 @Then("write the wasm-binary data of to a #wasm-file") 66 Document wasmfile() { 67 wasm_file = buildPath(env.bdd_results, wast_file.baseName.setExtension("wasm")); 68 writefln("wasm file %s", wasm_file); 69 wasm_file.fwrite(writer.serialize); 70 return result_ok; 71 } 72 73 } 74 75 @safe @Scenario("should load a #wasm-file and convert it into betterC", 76 []) 77 class ShouldLoadAwasmfileAndConvertItIntoBetterC { 78 string wasm_file; 79 string betterc_file; 80 WasmReader reader; 81 this(ShouldConvertswastfileTestsuiteToWasmFileFormat load_wasm) { 82 wasm_file = load_wasm.wasm_file; 83 betterc_file = wasm_file.setExtension("d"); 84 } 85 86 @Given("the testsuite file in #wasm-file format") 87 Document wasmfileFormat() @trusted { 88 writefln("%s", __FUNCTION__); 89 immutable data = cast(immutable(ubyte)[]) wasm_file.fread; 90 reader = WasmReader(data); 91 return result_ok; 92 } 93 94 @Then("convert the #wasm-file into betteC #dlang-file format") 95 Document dlangfileFormat() { 96 writefln("betterc_file=%s", betterc_file); 97 auto fout = File(betterc_file, "w"); 98 scope (exit) { 99 fout.close; 100 } 101 auto src_out = wasmBetterC(reader, fout); 102 src_out.module_name = betterc_file.baseName(FileExtension.dsrc); 103 src_out.imports = environment.get("imports", null).split.array; 104 src_out.attributes = environment.get("attributes", null).split.array; 105 src_out.serialize; 106 return result_ok; 107 } 108 109 } 110 111 @safe @Scenario("should transpile the wasm file to betterC file and execution it.", 112 []) 113 class ShouldTranspileTheWasmFileToBetterCFileAndExecutionIt { 114 string betterc_file; 115 string test_file; 116 this(ShouldLoadAwasmfileAndConvertItIntoBetterC transpiled) { 117 betterc_file = transpiled.betterc_file; 118 test_file = betterc_file.stripExtension; 119 } 120 121 @Given("the testsuite #dlang-file in betterC/D format.") 122 Document betterc_format() { 123 check(betterc_file.exists, format("%s not found", betterc_file)); 124 return result_ok; 125 } 126 127 @When("the #dlang-file has been compile in unittest mode.") 128 Document compile() { 129 auto cmd = environment["DCOMPILE"]; 130 131 cmd = [cmd, betterc_file, format("-of=%s", test_file)].join(" "); 132 auto pid = spawnShell(cmd); 133 writefln("%s", cmd); 134 const ret = wait(pid); 135 check(ret == 0, format("Compilation of %s faild", betterc_file)); 136 return result_ok; 137 } 138 139 @Then("execute the unittest file and check that all unittests parses.") 140 Document run_test() @trusted { 141 writefln("test_file %s", test_file); 142 auto pid = spawnShell(test_file); 143 const ret = wait(pid); 144 check(ret == 0, format("Test %s failed (see logfile)", test_file)); 145 return result_ok; 146 } 147 148 }