-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathspectest.main.v3
120 lines (116 loc) · 3.56 KB
/
spectest.main.v3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2020 Ben L. Titzer. All rights reserved.
// See LICENSE for details of Apache 2.0 license.
// Parses and runs binary WebAssembly spec tests (.bin.wast).
def OUT = Trace.OUT;
component spectest {
def group = OptionsRegistry.newGroup("SPECTEST", null);
def expected = Strings.newMap<bool>();
def HELP = group.newFlag("help", printHelp, "Print command-line help.");
def SKIP_ACTIONS = group.newBoolOption("skip-actions", false, "Parse only and skip actions.");
def EXPECTED = group.newPathOption("expected", null, "File containing expected failures to be ignored.")
.onSet(TestUtil.loadExpectedFile(expected, _));
def trace = TraceBuilder.new();
var helped = false;
def main(args: Array<string>) -> int {
var count = 0;
var engine = Engine.new();
var err = ErrorGen.new("spectest");
err.abs(u64.!(0));
OptionsRegistry.filterArgs(args, err);
engine.extensions = EngineOptions.extensions;
for (i < args.length) {
var a = args[i];
if (a == null) continue;
if (Strings.endsWith(a, ".wast")) count++;
}
if (helped) return 0;
if (count == 0) {
System.puts("spectest: no input files\n");
return 3;
}
if (count > 1) {
OUT.puts("##>");
OUT.putd(count);
OUT.ln();
}
var result = 0;
for (a in args) {
if (a == null) continue;
if (Strings.endsWith(a, ".wast")) result |= runTest(engine, a);
}
Metrics.report();
return result;
}
def printHelp(str: string) {
helped = true;
Trace.OUT.puts("Wizard Engine ").puts(Version.version).putc('.').putd(Version.minorVersion).ln();
Trace.OUT.puts("Usage: spectest [options] <.bin.wast files>\n\n");
OptionsRegistry.print();
}
def runTest(engine: Engine, filename: string) -> int {
OUT.puts("##+");
OUT.puts(filename);
OUT.ln();
var input = System.fileLoad(filename);
if (input == null) {
OUT.puts("##-fail: could not load file").ln();
return 1;
}
var before = System.ticksUs();
var p = SpecTestParser.new(filename, input, makeExternRef(Vector.new(), _));
p.parseFile();
if (Trace.test) {
var diff = System.ticksUs() - before;
OUT.puts("##@");
OUT.puts(filename);
OUT.puts(" : ");
OUT.putd(diff);
OUT.puts(" us\n");
}
if (p.ok) {
var ip = SpecTestInterpreter.new(engine, filename);
ip.skip_actions = SKIP_ACTIONS.val;
ip.ignore_failure = expected[filename];
if (ip.run(p.commands)) {
OUT.puts("##-ok").ln();
} else {
return 1;
}
} else if (expected[filename]) {
OUT.put3("##-ok: (ignored expected failure: @ %d:%d %s)", p.error_loc.0, p.error_loc.1, p.error_msg).ln();
} else {
OUT.put1("##-fail: %s ", filename);
OUT.put3("%d:%d %s", p.error_loc.0, p.error_loc.1, p.error_msg).ln();
return 1;
}
return 0;
}
def makeExternRef(cache: Vector<HostObject>, i: int) -> HostObject {
if (i >= cache.length || cache[i] == null) {
cache.set(i, NumberedObject.new(i));
}
return cache[i];
}
def renderBinaryModule(data: Array<byte>, pos: int, length: int) {
OUT.puts("(module binary");
for (i < length) {
if (i % 16 == 0) {
if (i > 0) OUT.puts("\"");
OUT.puts("\n \"");
}
OUT.put1("\\%x", data[pos + i]);
}
OUT.puts("\")").ln();
}
def filterOptions(args: Array<string>, func: string -> bool) {
for (i < args.length) {
var a = args[i];
if (a != null && func(a)) args[i] = null;
}
}
}
class NumberedObject(num: int) extends HostObject {
def render(buf: StringBuilder) -> StringBuilder {
return buf.put1("#%d", num);
}
}