New tests

added new tests,
modified old tests to have all non-japl code commented, so they can be
also ran using jpl
modified verbose to use the new -e flag instead of --stdout, so it
doesn't spam
This commit is contained in:
Productive2 2021-02-28 14:10:17 +01:00
parent 2e00dd181f
commit 88b4fa0d3a
47 changed files with 300 additions and 180 deletions

View File

@ -196,7 +196,7 @@ def build(path: str, flags: Optional[Dict[str, str]] = {}, options: Optional[Dic
logging.debug("Running tests") logging.debug("Running tests")
start = time() start = time()
# TODO: Find a better way of running the test suite # TODO: Find a better way of running the test suite
process = run_command(f"{tests_path} {'--stdout' if verbose else ''}", mode="run", shell=True, stderr=PIPE) process = run_command(f"{tests_path} {'-e' if verbose else ''}", mode="run", shell=True, stderr=PIPE)
if status != 0: if status != 0:
logging.error(f"Command '{command}' exited with non-0 exit code {status}, output below:\n{stderr.decode()}") logging.error(f"Command '{command}' exited with non-0 exit code {status}, output below:\n{stderr.decode()}")
return False return False

View File

@ -1,6 +1,8 @@
/*
[Test: all] [Test: all]
[skip] [skip]
[source: mixed] */
//[source: mixed]
// Example file to test JAPL's syntax // Example file to test JAPL's syntax
// Mathematical expressions // Mathematical expressions
@ -140,5 +142,5 @@ mark.greet();
"implicit start"[:5]; // From 0 to 5 "implicit start"[:5]; // From 0 to 5
"hello" + " world"; // Strings are immutable! "hello" + " world"; // Strings are immutable!
"hello" * 3; //hellohellohello "hello" * 3; //hellohellohello
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: arithmetic] //[Test: arithmetic]
[source: mixed] //[source: mixed]
//int arithmetic //int arithmetic
print(7+5); //stdout:12 print(7+5); //stdout:12
@ -34,5 +34,5 @@ print(64/-64);//stdout:-1.0
print(8/0);//stdout:inf print(8/0);//stdout:inf
print(8/-0);//stdout:inf print(8/-0);//stdout:inf
print(-8/0);//stdout:-inf print(-8/0);//stdout:-inf
[end] //[end]
[end] //[end]

View File

@ -0,0 +1,8 @@
//[Test: assignment expressions]
//[source: mixed]
var x;
var a = x = 5;
print(x);//stdout:5
print(a);//stdout:5
//[end]
//[end]

View File

@ -1,5 +1,5 @@
[Test: bitwise] //[Test: bitwise]
[source: mixed] //[source: mixed]
print(~5 | 5);//stdout:-1 print(~5 | 5);//stdout:-1
print(1 | 2);//stdout:3 print(1 | 2);//stdout:3
print(1 & 2);//stdout:0 print(1 & 2);//stdout:0
@ -9,5 +9,5 @@ print(32 | 64);//stdout:96
print(96 & 32);//stdout:32 print(96 & 32);//stdout:32
print(~0);//stdout:-1 print(~0);//stdout:-1
print(~356);//stdout:-357 print(~356);//stdout:-357
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: booleans] //[Test: booleans]
[source: mixed] //[source: mixed]
print(2 or 3);//stdout:2 print(2 or 3);//stdout:2
print(2 and 3);//stdout:3 print(2 and 3);//stdout:3
print(false or true);//stdout:true print(false or true);//stdout:true
@ -21,5 +21,5 @@ print(not false);//stdout:true
print(not 1);//stdout:false print(not 1);//stdout:false
print(not 1 and not 2);//stdout:false print(not 1 and not 2);//stdout:false
print(not (1 and false));//stdout:true print(not (1 and false));//stdout:true
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,7 @@
/*
[Test: callchain] [Test: callchain]
[source: mixed] */
//[source: mixed]
fun add2(x) fun add2(x)
{ {
return x + 2; return x + 2;
@ -14,8 +16,10 @@ fun mul2(x)
} }
print(add2(sub2(mul2(sub2(5))))); print(add2(sub2(mul2(sub2(5)))));
//5-2=3 //[end]
//3*2=6 /*
//stdout:6 [stdout]
6
[end] [end]
[end] [end]
*/

View File

@ -1,5 +1,5 @@
[Test: comparisons] //[Test: comparisons]
[source: mixed] //[source: mixed]
var x = 4; var x = 4;
var y = 5; var y = 5;
var z = 6; var z = 6;
@ -42,5 +42,25 @@ if (8 <= z)
print("15"); print("15");
else else
print("16");//stdout:16 print("16");//stdout:16
[end] //[end]
[end] //[end]
//[Test: multicomparisons]
//[skip]
//[source: mixed]
var x = 2 < 3 < 4;
print(x);//stdout:4
x = 1 > 3 < 5;
print(x);//stdout:false
x = 1 >= 0 >= 0;
print(x);//stdout:0
if ( 4 < x < 6 ) {
print("inside");
} else {
print("outside");//stdout:outside
}
//[end]
//[end]

View File

@ -1,5 +1,5 @@
[Test: compile_time_intern] //[Test: compile_time_intern]
[source: mixed] //[source: mixed]
//compile time interning //compile time interning
var a = "hello"; var a = "hello";
@ -11,6 +11,6 @@ print(a is b);//stdout:true
var x = "ex"; var x = "ex";
var y = "ey"; var y = "ey";
print(x is y);//stdout:false print(x is y);//stdout:false
[end] //[end]
[end] //[end]

View File

@ -1,8 +1,8 @@
[Test: read_in_own_init_regex] //[Test: read_in_own_init_regex]
[source: raw] //[source: raw]
var a = 1; { var a = a; } var a = 1; { var a = a; }
[end] [end]
[stderr: re] [stderr: re]
[[^\-]*-> cannot read local variable in its own initializer [[^\-]*-> cannot read local variable in its own initializer
[end] //[end]
[end] //[end]

View File

@ -1,10 +1,12 @@
[Test: undefname_raw] //[Test: undefname_raw]
[source: raw] //[source: raw]
var a = b; var a = b;
[end] //[end]
/*
[stderr] [stderr]
An unhandled exception occurred, traceback below: An unhandled exception occurred, traceback below:
File '''', line 1, in <module>: File '''', line 1, in <module>:
ReferenceError: undefined name 'b' ReferenceError: undefined name 'b'
[end] [end]
[end] */
//[end]

View File

@ -1,10 +1,12 @@
[Test: unsup_binary_instr] //[Test: unsup_binary_instr]
[source: raw] //[source: raw]
var a = 2 + "hey"; var a = 2 + "hey";
[end] //[end]
/*
[stderr] [stderr]
An unhandled exception occurred, traceback below: An unhandled exception occurred, traceback below:
File '''', line 1, in <module>: File '''', line 1, in <module>:
TypeError: unsupported binary operator '+' for objects of type 'integer' and 'string' TypeError: unsupported binary operator '+' for objects of type 'integer' and 'string'
[end] [end]
[end] */
//[end]

View File

@ -1,5 +1,5 @@
[Test: problem1] //[Test: problem1]
[source: mixed] //[source: mixed]
// Task: find the multiples of 3 and 5 below 1000, find their sum // Task: find the multiples of 3 and 5 below 1000, find their sum
var sum = 0; var sum = 0;
@ -11,5 +11,5 @@ for (var x = 3; x < 1001; x = x + 1)
} }
} }
print(sum);//stdout:234168 print(sum);//stdout:234168
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: problem2] //[Test: problem2]
[source: mixed] //[source: mixed]
// Sum of even valued fibonacci numbers that don't exceed 4M // Sum of even valued fibonacci numbers that don't exceed 4M
var a = 1; var a = 1;
@ -16,5 +16,5 @@ while (a < 4000000)
b = c; b = c;
} }
print(sum);//stdout:4613732 print(sum);//stdout:4613732
[end] //[end]
[end] //[end]

View File

@ -1,6 +1,6 @@
[Test: problem4] //[Test: problem4]
[skip] //[skip]
[source: mixed] //[source: mixed]
// Find the largest palindrome that is a product of two 3 digit numbers // Find the largest palindrome that is a product of two 3 digit numbers
fun isPalindrome(n) fun isPalindrome(n)
@ -66,5 +66,5 @@ for (var i = 100; i < 1000; i = i + 1)
} }
} }
print(largest); print(largest);
[end] //[end]
[end] //[end]

View File

@ -1,10 +1,10 @@
[Test: for] //[Test: for]
[source: mixed] //[source: mixed]
for (var x = 0; x < 2; x = x + 1) for (var x = 0; x < 2; x = x + 1)
{ {
print(x); print(x);
//stdout:0 //stdout:0
//stdout:1 //stdout:1
} }
[end] //[end]
[end] //[end]

View File

@ -1,6 +1,6 @@
[Test: forwithfunction] //[Test: forwithfunction]
[skip] //[skip]
[source: mixed] //[source: mixed]
var y = 0; //a global to keep track of state var y = 0; //a global to keep track of state
//does not need closures for this to work yet //does not need closures for this to work yet
@ -84,5 +84,5 @@ for (var i = 0; i != -1; i = next(i))
// y = 9 // y = 9
//stdout:10 //stdout:10
// y = 10 // y = 10
[end] //[end]
[end] //[end]

View File

@ -1,15 +1,17 @@
[Test: hellojapl] //[Test: hellojapl]
[source: mixed] //[source: mixed]
print("Hello, JAPL."); print("Hello, JAPL.");
//stdout:Hello, JAPL. //stdout:Hello, JAPL.
[end] //[end]
[end] //[end]
[Test: hello_second_way] //[Test: hello_second_way]
[source: raw] //[source: raw]
print("Hello, JAPL."); print("Hello, JAPL.");
[end] //[end]
/*
[stdout] [stdout]
Hello, JAPL. Hello, JAPL.
[end] [end]
[end] */
//[end]

View File

@ -1,5 +1,5 @@
[Test: if] //[Test: if]
[source: mixed] //[source: mixed]
var x = 5; var x = 5;
if (x > 2) if (x > 2)
{ {
@ -28,5 +28,5 @@ if (2 == x)
print("2"); print("2");
else else
print("not 2");//stdout:not 2 print("not 2");//stdout:not 2
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: ifchain] //[Test: ifchain]
[source: mixed] //[source: mixed]
fun printInt(x) { fun printInt(x) {
if (x == 1) if (x == 1)
print("one"); print("one");
@ -22,5 +22,5 @@ x = 7;
printInt(x); printInt(x);
x = 1; x = 1;
printInt(x);//stdout:one printInt(x);//stdout:one
[end] //[end]
[end] //[end]

View File

@ -1,8 +1,10 @@
/*
[Test: inputtesttwo] [Test: inputtesttwo]
[source: raw] */
//[source: raw]
print(readLine()); print(readLine());
[end] //[end]
/*
[stdin] [stdin]
Hello world! Hello world!
[end] [end]
@ -11,3 +13,4 @@ Hello world!
Hello world! Hello world!
[end] [end]
[end] [end]
*/

View File

@ -1,5 +1,5 @@
[Test: is] //[Test: is]
[source:mixed] //[source:mixed]
var x = 4; var x = 4;
var y = x; var y = x;
@ -21,5 +21,5 @@ print((l is z) is l);//stdout:true
var k; var k;
print(k is nil);//stdout:true print(k is nil);//stdout:true
[end] //[end]
[end] //[end]

View File

@ -1,21 +0,0 @@
[Test: lambdachain]
[source: mixed]
var add2 = lambda(x)
{
return x + 2;
};
var sub2 = lambda(x)
{
return x - 2;
};
var mul2 = lambda(x)
{
return x * 2;
};
print(add2(sub2(mul2(sub2(5)))));
//5-2=3
//3*2=6
//stdout:6
[end]
[end]

50
tests/japl/lambdas.jpl Normal file
View File

@ -0,0 +1,50 @@
/*
[Test: lambdachain]
*/
//[source: raw]
var add2 = lambda(x)
{
return x + 2;
};
var sub2 = lambda(x)
{
return x - 2;
};
var mul2 = lambda(x)
{
return x * 2;
};
print(add2(sub2(mul2(sub2(5)))));
//[end]
/*
[stdout]
6
[end]
[end]
[Test: simple lambdas]
*/
//[source: raw]
var identity = lambda(x) { return x; };
var comparison = lambda(x, y) {
if (x > y) {
return x;
} else {
return y;
}
};
var max = lambda(x, y, z) { return identity(comparison(comparison(x, y), z)); };
print(max(1, 5, 6));
print(max(6, 2, 9));
print(max(1.3, 7, 9.0));
print(max(-4, 3, 2));
//[end]
/*
[stdout]
6
9
9.0
3
[end]
[end]
*/

View File

@ -1,5 +1,5 @@
[Test: constant_long] //[Test: constant_long]
[source: mixed] //[source: mixed]
// Test for constants // Test for constants
var v_1 = 1; var v_1 = 1;
@ -130,5 +130,5 @@ var v_125 = 1;
var v_126 = 1; var v_126 = 1;
var v_127 = 1; var v_127 = 1;
var v_128 = 1; var v_128 = 1;
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: glob_assgn_read] //[Test: glob_assgn_read]
[source: mixed] //[source: mixed]
var a0 = 451; var a0 = 451;
var a1 = 5098; var a1 = 5098;
var a2 = 469; var a2 = 469;
@ -1501,5 +1501,5 @@ print(a151);//stdout:4839
print(a975);//stdout:7651 print(a975);//stdout:7651
print(a7);//stdout:2979 print(a7);//stdout:2979
print(a661);//stdout:8235 print(a661);//stdout:8235
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: glob_with_sets] //[Test: glob_with_sets]
[source: mixed] //[source: mixed]
var a0 = 829; var a0 = 829;
var a1 = 6820; var a1 = 6820;
var a2 = 114; var a2 = 114;
@ -5238,5 +5238,5 @@ print(a87);//stdout:1282
print(a445);//stdout:1726 print(a445);//stdout:1726
print(a790);//stdout:1140 print(a790);//stdout:1140
print(a961);//stdout:1708 print(a961);//stdout:1708
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: loc_assgn_read] //[Test: loc_assgn_read]
[source: mixed] //[source: mixed]
{ {
var a0 = 9103; var a0 = 9103;
var a1 = 4565; var a1 = 4565;
@ -1503,5 +1503,5 @@ print(a722);//stdout:5380
print(a538);//stdout:8625 print(a538);//stdout:8625
print(a809);//stdout:4506 print(a809);//stdout:4506
} }
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: loc_with_sets] //[Test: loc_with_sets]
[source: mixed] //[source: mixed]
{ {
var a0 = 8313; var a0 = 8313;
var a1 = 3509; var a1 = 3509;
@ -5186,5 +5186,5 @@ print(a380);//stdout:2145
print(a125);//stdout:4280 print(a125);//stdout:4280
print(a55);//stdout:6992 print(a55);//stdout:6992
} }
[end] //[end]
[end] //[end]

View File

@ -1,4 +1,4 @@
/*
[; This is a comment [; This is a comment
This is a comment as well. This is a comment as well.
@ -17,3 +17,4 @@ the test builder, but it should be a test with
the name "". the name "".
[end] [end]
*/

View File

@ -1,19 +1,21 @@
/*
[test: mixed] [test: mixed]
[source: mixed] */
//[source: mixed]
print("Hello", readLine()); print("Hello", readLine());
//stdout:Hello world //stdout:Hello world
//stdin:world //stdin:world
print("aaaaaa"); print("aaaaaa");
//stdoutre:a* //matchout:a*
printErr("Hello", readLine()); printErr("Hello", readLine());
//stderr:Hello error //stderr:Hello error
//stdin:error //stdin:error
printErr("bbbbbb"); printErr("bbbbbb");
//stderrre:b* //matcherr:b*
[end] //[end]
[end] //[end]

View File

@ -1,12 +1,13 @@
[Test: nw] //[Test: nw]
[source] //[source]
print("hey"); print("hey");
print("second line"); print("second line");
printErr("hey there"); printErr("hey there");
print("abcde"); print("abcde");
printErr("12345"); printErr("12345");
printErr("0123456789."); printErr("0123456789.");
[end] //[end]
/*
[stdout: nw] [stdout: nw]
hey hey
second line second line
@ -21,4 +22,5 @@ printErr("0123456789.");
[[0-9]* [[0-9]*
[0-9]*. [0-9]*.
[end] [end]
[end] */
//[end]

View File

@ -1,11 +1,12 @@
[Test: raw] //[Test: raw]
[source: raw] //[source: raw]
print("Hi", readLine()); print("Hi", readLine());
print("aaaaaaa"); print("aaaaaaa");
printErr("Bye", readLine()); printErr("Bye", readLine());
printErr("bbbbbbb"); printErr("bbbbbbb");
//stdout:This is not a part of the expected output //stdout:This is not a part of the expected output
[end] //[end]
/*
[stdin] [stdin]
person person
very important person very important person
@ -23,3 +24,4 @@ Bye very important person
b* b*
[end] [end]
[end] [end]
*/

View File

@ -1,7 +1,8 @@
[test: skipped] //[test: skipped]
[skip] //[skip]
/*
[stdout] [stdout]
Hello this text won't be matched. Hello this text won't be matched.
[end] [end]
[end] */
//[end]

View File

@ -1,9 +1,11 @@
[Test: nan] //[Test: nan]
[source: raw] //[source: raw]
print((5/0)*0); print((5/0)*0);
[end] //[end]
/*
[stdout] [stdout]
nan nan
[end] [end]
[end] */
//[end]

13
tests/japl/nested.jpl Normal file
View File

@ -0,0 +1,13 @@
//[Test: nested multiline comments]
//[source: raw]
/* first
/* second
/* third
/* fourth
*/
*/
*/
*/
//[end]
//[end]

13
tests/japl/procedures.jpl Normal file
View File

@ -0,0 +1,13 @@
//[Test: functions without parentheses]
//[source: mixed]
fun sayhi {
print("hi");
}
fun saybye {
print("bye");
}
sayhi();//stdout:hi
saybye();//stdout:bye
//[end]
//[end]

View File

@ -1,5 +1,5 @@
[Test: reassignment] //[Test: reassignment]
[source: mixed] //[source: mixed]
{ {
var x = 5; var x = 5;
var y = x; var y = x;
@ -25,5 +25,5 @@ fun resetter(x) {
var q = 5; var q = 5;
resetter(q);//stdout:7 resetter(q);//stdout:7
print(q);//stdout:5 print(q);//stdout:5
[end] //[end]
[end] //[end]

View File

@ -1,6 +1,6 @@
[Test: runtimeinterning] //[Test: runtimeinterning]
[skip] //[skip]
[source: mixed] //[source: mixed]
//runtime interning //runtime interning
var f = "leafy"; var f = "leafy";
@ -14,5 +14,5 @@ print(h is j);//stdout:true
var x = "ex"; var x = "ex";
var y = "ey"; var y = "ey";
print(x is y);//stdout:false print(x is y);//stdout:false
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: shadowing] //[Test: shadowing]
[source: mixed] //[source: mixed]
//similar to vars.jpl, but more focused on shadowing //similar to vars.jpl, but more focused on shadowing
// simple shadowing // simple shadowing
@ -76,5 +76,5 @@ eat();//stdout:nom nom nom
print(eat);//stdout:5 print(eat);//stdout:5
} }
eat();//stdout:nom nom nom eat();//stdout:nom nom nom
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: strings] //[Test: strings]
[source: mixed] //[source: mixed]
var left = "left"; var left = "left";
var right = "right"; var right = "right";
var directions = left + " " + right; var directions = left + " " + right;
@ -12,5 +12,15 @@ left = left + " side";
print(left);//stdout:left side print(left);//stdout:left side
right = "side: " + right; right = "side: " + right;
print(right);//stdout:side: right print(right);//stdout:side: right
[end] //[end]
[end] //[end]
//[Test: string slicing]
//[skip]
//[source: mixed]
var longstring = "a very long string that will be sliced";
var part = longstring[0:5];
print(part);//stdout:a ver
var part2 = longstring[0..4];
print(part2);//stdout:a ver
//[end]
//[end]

View File

@ -1,5 +1,5 @@
[Test: vars] //[Test: vars]
[source: mixed] //[source: mixed]
var x = 1; var x = 1;
var y = 2; var y = 2;
print(x);//stdout:1 print(x);//stdout:1
@ -30,5 +30,5 @@ longName = "hello";
print(longName); //stdout:hello print(longName); //stdout:hello
longName = longName + " world"; longName = longName + " world";
print(longName); //stdout:hello world print(longName); //stdout:hello world
[end] //[end]
[end] //[end]

View File

@ -1,5 +1,5 @@
[Test: while] //[Test: while]
[source: mixed] //[source: mixed]
var x = 5; var x = 5;
while (x > 0) while (x > 0)
{ {
@ -20,5 +20,5 @@ while (x < 10)
string = string + "A"; string = string + "A";
} }
print(string);//stdout:hAAAAAAAAAA print(string);//stdout:hAAAAAAAAAA
[end] //[end]
[end] //[end]

View File

@ -107,6 +107,7 @@ type Buffer* = ref object
## Represents an updateable line on the terminal ## Represents an updateable line on the terminal
contents: string contents: string
previous: string previous: string
termwidth: int
proc newBuffer*: Buffer = proc newBuffer*: Buffer =
## Creates a Buffer, hides the cursor ## Creates a Buffer, hides the cursor
@ -131,6 +132,8 @@ proc updateProgressBar*(buf: Buffer, text: string, total: int, current: int) =
let w = terminalWidth() let w = terminalWidth()
if w > newline.len(): if w > newline.len():
newline &= " ".repeat(w - newline.len() - 1) newline &= " ".repeat(w - newline.len() - 1)
else:
newline = newline[0..w-2]
buf.contents = newline buf.contents = newline
proc clearLineAndWrite(text: string, oldsize: int) = proc clearLineAndWrite(text: string, oldsize: int) =

View File

@ -194,8 +194,7 @@ proc buildTests*(testDir: string): seq[Test] =
else: else:
fatal "test dir/file doesn't exist" fatal "test dir/file doesn't exist"
for candidateObj in walkDir(testDir): for kind, candidate in walkDir(testDir):
let candidate = candidateObj.path
if dirExists(candidate): if dirExists(candidate):
log(LogLevel.Debug, &"Descending into dir {candidate}") log(LogLevel.Debug, &"Descending into dir {candidate}")
result &= buildTests(candidate) result &= buildTests(candidate)

View File

@ -147,13 +147,13 @@ added to add lines to the expected stdout/stderr or
the stdin of the test using the legacy test format. the stdin of the test using the legacy test format.
They are defined by the sequences `//stdout:`, They are defined by the sequences `//stdout:`,
`//stderr:`, `//stdin:`, `//stdoutre:` and `//stderr:`, `//stdin:`, `//matchout:` and
`//stderrre:`. Every character after the colon and `//matcherr:`. Every character after the colon and
before the end of the line is appended to the respective before the end of the line is appended to the respective
field of the test. `stdout` adds a raw line to be field of the test. `stdout` adds a raw line to be
matched to the expected stdout of the test. `stdoutre` matched to the expected stdout of the test. `matchout`
adds a regex to match a line of the stdout of the test. adds a regex to match a line of the stdout of the test.
`stderr` and `stderrre` are the stderr equivalents. `stderr` and `matcherr` are the stderr equivalents.
`stdin` adds a line to the stdin that the JAPL source `stdin` adds a line to the stdin that the JAPL source
can read from. can read from.

View File

@ -71,10 +71,10 @@ proc compileExpectedOutput(source: string, rawkw: string, rekw: string): seq[Exp
result &= genEL(matches[0], ExpectedLineKind.Regex) result &= genEL(matches[0], ExpectedLineKind.Regex)
proc compileExpectedOutput(source: string): seq[ExpectedLine] = proc compileExpectedOutput(source: string): seq[ExpectedLine] =
compileExpectedOutput(source, "stdout", "stdoutre") compileExpectedOutput(source, "stdout", "matchout")
proc compileExpectedError(source: string): seq[ExpectedLine] = proc compileExpectedError(source: string): seq[ExpectedLine] =
compileExpectedOutput(source, "stderr", "stderrre") compileExpectedOutput(source, "stderr", "matcherr")
proc compileInput(source: string): string = proc compileInput(source: string): string =
for line in source.split('\n'): for line in source.split('\n'):