@@ -119,7 +119,8 @@ int main(string[] args)
119
119
120
120
foreach (file; specDir.dirEntries(" *.dd" , SpanMode.depth).parallel(1 ))
121
121
{
122
- auto allTests = findExamples(file, ddocKey).map! compileAndCheck;
122
+ CompileConfig compileConfig = {mode: CompileConfig.TestMode.compile};
123
+ auto allTests = findExamples(file, ddocKey).map! (e => compileAndCheck(e, compileConfig));
123
124
if (! allTests.empty)
124
125
{
125
126
writefln(" %s: %d examples found" , file.baseName, allTests.walkLength);
@@ -130,6 +131,15 @@ int main(string[] args)
130
131
return hasFailed;
131
132
}
132
133
134
+ struct CompileConfig
135
+ {
136
+ enum TestMode { run, compile, fail }
137
+ TestMode mode;
138
+ string [] args;
139
+ string expectedStdout;
140
+ string expectedStderr;
141
+ }
142
+
133
143
/**
134
144
Executes source code with a D compiler (compile-only)
135
145
@@ -138,13 +148,29 @@ Params:
138
148
139
149
Returns: the exit code of the compiler invocation.
140
150
*/
141
- auto compileAndCheck (R)(R buffer)
151
+ auto compileAndCheck (R)(R buffer, CompileConfig config )
142
152
{
143
153
import std.process ;
144
154
import std.uni : isWhite;
145
155
146
- auto pipes = pipeProcess([config.dmdBinPath, " -c" , " -o-" , " -" ],
147
- Redirect.stdin | Redirect.stdout | Redirect.stderr);
156
+ auto args = [.config.dmdBinPath];
157
+ args ~= config.args;
158
+ with (CompileConfig.TestMode)
159
+ final switch (config.mode)
160
+ {
161
+ case run:
162
+ args ~= [" -run" ];
163
+ break ;
164
+ case compile:
165
+ args ~= [" -c" , " -o-" ];
166
+ break ;
167
+ case fail:
168
+ args ~= [" -c" , " -o-" ];
169
+ break ;
170
+ }
171
+ args ~= " -" ;
172
+
173
+ auto pipes = pipeProcess(args, Redirect.all);
148
174
149
175
static mainRegex = regex(` (void|int)\s+main` );
150
176
const hasMain = ! buffer.matchFirst(mainRegex).empty;
@@ -160,15 +186,27 @@ auto compileAndCheck(R)(R buffer)
160
186
pipes.stdin.write(buffer);
161
187
pipes.stdin.close;
162
188
auto ret = wait(pipes.pid);
163
- if (ret != 0 )
189
+ if (config.mode == CompileConfig.TestMode.fail)
190
+ {
191
+ if (ret == 0 )
192
+ {
193
+ stderr.writefln(" Compilation should have failed for:\n %s" , buffer);
194
+ ret = 1 ;
195
+ }
196
+ else
197
+ {
198
+ ret = 0 ;
199
+ }
200
+ }
201
+ else if (ret != 0 )
164
202
{
165
- stderr.writeln(" --- " );
203
+ stderr.writeln(" ---" );
166
204
int lineNumber = 1 ;
167
205
buffer
168
206
.splitter(" \n " )
169
207
.each! ((a) {
170
208
const indent = hasMain ? " " : " " ;
171
- if (config.printLineNumbers)
209
+ if (. config.printLineNumbers)
172
210
stderr.writefln(" %3d: %s%s" , lineNumber++ , indent, a);
173
211
else
174
212
stderr.writefln(" %s%s" , indent, a);
@@ -177,5 +215,23 @@ auto compileAndCheck(R)(R buffer)
177
215
stderr.writeln(" ---" );
178
216
pipes.stderr.byLine.each! (e => stderr.writeln(e));
179
217
}
218
+ // check stdout or stderr
219
+ static foreach (stream; [" stdout" , " stderr" ])
220
+ {{
221
+ import std.ascii : toUpper;
222
+ import std.conv : to;
223
+ mixin (" auto expected = config.expected" ~ stream.front.toUpper.to! string ~ stream.dropOne~ " ;" );
224
+ if (expected)
225
+ {
226
+ mixin (" auto stream = pipes." ~ stream ~ " ;" );
227
+ auto obs = appender! string ;
228
+ stream.byChunk(4096 ).each! (c => obs.put(c));
229
+ scope (failure) {
230
+ stderr.writefln(" Expected: %s" , expected);
231
+ stderr.writefln(" Observed: %s" , obs.data);
232
+ }
233
+ assert (obs.data == expected);
234
+ }
235
+ }}
180
236
return ret;
181
237
}
0 commit comments