1 /++ 2 A module containing the process runner 3 4 Copyright: © 2018 Szabo Bogdan 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Szabo Bogdan 7 +/ 8 module trial.executor.process; 9 10 import trial.reporters.visualtrial; 11 import trial.executor.single; 12 public import trial.interfaces; 13 14 import std.process; 15 import std.path; 16 import std.file; 17 import std.datetime; 18 import std.conv; 19 import std.stdio; 20 21 void testProcessRuner(string suiteName, string testName, VisualTrialReporterParser parser) { 22 TestResult testResult; 23 24 auto command = [ thisExePath, 25 "-s", suiteName, 26 "-t", testName, 27 "-r", "visualtrial", 28 "-e", "default" ]; 29 30 auto pipes = pipeProcess(command, Redirect.stdout | Redirect.stderrToStdout); 31 32 foreach(line; pipes.stdout.byLine) { 33 parser.add(line.to!string); 34 35 if(testResult is null && parser.testResult !is null) { 36 testResult = parser.testResult; 37 } 38 } 39 40 auto code = wait(pipes.pid); 41 42 if(testResult !is null && testResult.throwable is null && code != 0) { 43 testResult.throwable = new Exception("The process exited with code `" ~ code.to!string ~ "`", testResult.fileName, testResult.line); 44 testResult.status = TestResult.Status.failure; 45 } 46 } 47 48 /// An executor that will run every test in a separate 49 /// process 50 class ProcessExecutor : DefaultExecutor { 51 alias runTest = DefaultExecutor.runTest; 52 53 /// A function that should spawn a process that will run the test 54 alias TestProcessRun = void function(string suiteName, string testName, VisualTrialReporterParser parser); 55 56 private { 57 TestProcessRun testProcessRun; 58 VisualTrialReporterParser parser; 59 } 60 61 /// Instantiate the executor with a custom process runner 62 this(TestProcessRun testProcessRun) { 63 super(); 64 65 this.parser = new VisualTrialReporterParser(); 66 this.parser.onOutput = &this.onOutput; 67 this.testProcessRun = testProcessRun; 68 } 69 70 /// Instantiate the executor with a custom process runner 71 this() { 72 this(&testProcessRuner); 73 } 74 75 void onOutput(string line) { 76 writeln(line); 77 } 78 79 /// Run a test case 80 override 81 void runTest(ref const(TestCase) testCase, TestResult testResult) { 82 this.parser.testResult = testResult; 83 testProcessRun(testCase.suiteName, testCase.name, parser); 84 } 85 }