lib/std/lang/scanner/tests.rad 14.5 KiB raw
1
use std::lang::strings;
2
use std::mem;
3
use std::testing;
4
5
/// String pool for testing.
6
static TEST_STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
7
8
/// Create a scanner for test source.
9
fn testScanner(source: *[u8]) -> super::Scanner {
10
    return super::scanner(super::SourceLoc::File("test.r"), source, &mut TEST_STRING_POOL);
11
}
12
13
@test fn testScanTokens() throws (testing::TestError) {
14
    let mut s = testScanner(
15
        "'x' < fnord fnord: 0 => >> mod and nil"
16
    );
17
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Char);
18
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Lt);
19
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
20
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
21
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Colon);
22
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Number);
23
    try testing::expect(super::next(&mut s).kind == super::TokenKind::FatArrow);
24
    try testing::expect(super::next(&mut s).kind == super::TokenKind::GtGt);
25
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Mod);
26
    try testing::expect(super::next(&mut s).kind == super::TokenKind::And);
27
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Nil);
28
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
29
}
30
31
@test fn testScanChars() throws (testing::TestError) {
32
    let mut s = testScanner(
33
        "'\\0'"
34
    );
35
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Char);
36
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
37
}
38
39
@test fn testScanWhitespace() throws (testing::TestError) {
40
    let mut s = testScanner(
41
        " X\n\nY //\n Z//1 \n"
42
    );
43
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
44
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
45
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
46
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
47
}
48
49
@test fn testScanIdentsAndKeywords() throws (testing::TestError) {
50
    let mut s = testScanner(
51
        "m mo mod modo"
52
    );
53
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
54
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
55
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Mod);
56
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
57
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
58
}
59
60
@test fn testScanIdentifiers() throws (testing::TestError) {
61
    let mut s = testScanner(
62
        "fnord::yikes no1 4j"
63
    );
64
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
65
    try testing::expect(super::next(&mut s).kind == super::TokenKind::ColonColon);
66
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
67
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
68
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Number);
69
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
70
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
71
}
72
73
@test fn testScanAtIdentifiers() throws (testing::TestError) {
74
    let mut s = testScanner(
75
        "@default @"
76
    );
77
    try testing::expect(super::next(&mut s).kind == super::TokenKind::AtIdent);
78
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Invalid);
79
}
80
81
@test fn testScanStrings() throws (testing::TestError) {
82
    let mut s = testScanner(
83
        "\"Hello World!\" \"\\\"\""
84
    );
85
    let mut t: super::Token = super::next(&mut s);
86
    try testing::expect(t.kind == super::TokenKind::String);
87
    try testing::expect(t.source.len == 14); // Includes quotes.
88
    try testing::expect(mem::eq(t.source, "\"Hello World!\""));
89
90
    set t = super::next(&mut s);
91
    try testing::expect(t.kind == super::TokenKind::String);
92
    try testing::expect(t.source.len == 4);
93
    try testing::expect(mem::eq(t.source, "\"\\\"\""));
94
}
95
96
@test fn testGetLocation() throws (testing::TestError) {
97
    let mut s = testScanner(
98
        "abc\n  def\n    ghi"
99
    );
100
    let mut tok: super::Token = super::next(&mut s);
101
    try testing::expect(tok.kind == super::TokenKind::Ident);
102
    try testing::expect(tok.source.len == 3);
103
104
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
105
        try testing::expect(loc.line == 1);
106
        try testing::expect(loc.col == 1);
107
    } else {
108
        try testing::expect(false);
109
    }
110
    set tok = super::next(&mut s);
111
    try testing::expect(tok.kind == super::TokenKind::Ident);
112
    try testing::expect(tok.source.len == 3);
113
114
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
115
        try testing::expect(loc.line == 2);
116
        try testing::expect(loc.col == 3);
117
    } else {
118
        try testing::expect(false);
119
    }
120
    set tok = super::next(&mut s);
121
    try testing::expect(tok.kind == super::TokenKind::Ident);
122
    try testing::expect(tok.source.len == 3);
123
124
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
125
        try testing::expect(loc.line == 3);
126
        try testing::expect(loc.col == 5);
127
    } else {
128
        try testing::expect(false);
129
    }
130
}
131
132
@test fn testScanEmptyInput() throws (testing::TestError) {
133
    let mut s = super::Scanner {
134
        sourceLoc: super::SourceLoc::File("test.r"),
135
        source: "",
136
        token: 0,
137
        cursor: 0,
138
        pool: &mut TEST_STRING_POOL,
139
    };
140
    let tok: super::Token = super::next(&mut s);
141
142
    try testing::expect(tok.kind == super::TokenKind::Eof);
143
    try testing::expect(tok.source.len == 0);
144
    try testing::expect(tok.offset == 0);
145
}
146
147
@test fn testScanSingleCharTokens() throws (testing::TestError) {
148
    let mut s = testScanner(
149
        "(){}[] ,;+-*~|&"
150
    );
151
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LParen);
152
    try testing::expect(super::next(&mut s).kind == super::TokenKind::RParen);
153
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LBrace);
154
    try testing::expect(super::next(&mut s).kind == super::TokenKind::RBrace);
155
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LBracket);
156
    try testing::expect(super::next(&mut s).kind == super::TokenKind::RBracket);
157
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Comma);
158
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Semicolon);
159
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Plus);
160
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Minus);
161
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Star);
162
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Tilde);
163
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Pipe);
164
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Amp);
165
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
166
}
167
168
@test fn testScanDoubleCharTokens() throws (testing::TestError) {
169
    let mut s = testScanner(
170
        "== <> <= >= < > >> << -> =>"
171
    );
172
    try testing::expect(super::next(&mut s).kind == super::TokenKind::EqualEqual);
173
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LtGt);
174
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LtEqual);
175
    try testing::expect(super::next(&mut s).kind == super::TokenKind::GtEqual);
176
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Lt);
177
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Gt);
178
    try testing::expect(super::next(&mut s).kind == super::TokenKind::GtGt);
179
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LtLt);
180
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Arrow);
181
    try testing::expect(super::next(&mut s).kind == super::TokenKind::FatArrow);
182
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
183
}
184
185
@test fn testScanIdentifierLengths() throws (testing::TestError) {
186
    let mut s = testScanner(
187
        "sho xyz981 lal_lel"
188
    );
189
    let mut tok: super::Token = super::next(&mut s);
190
    try testing::expect(tok.kind == super::TokenKind::Ident);
191
    try testing::expect(tok.source.len == 3);
192
193
    set tok = super::next(&mut s);
194
    try testing::expect(tok.kind == super::TokenKind::Ident);
195
    try testing::expect(tok.source.len == 6);
196
197
    set tok = super::next(&mut s);
198
    try testing::expect(tok.kind == super::TokenKind::Ident);
199
    try testing::expect(tok.source.len == 7);
200
}
201
202
@test fn testScanNumbers() throws (testing::TestError) {
203
    let mut s = testScanner(
204
        "2 -2 +2 value-2 value+2 value--2 value+-2 value-+2 f(-2)"
205
    );
206
    let expected: [super::TokenKind; 29] = [
207
        super::TokenKind::Number,
208
        super::TokenKind::Minus, super::TokenKind::Number,
209
        super::TokenKind::Plus, super::TokenKind::Number,
210
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Number,
211
        super::TokenKind::Ident, super::TokenKind::Plus, super::TokenKind::Number,
212
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Minus,
213
            super::TokenKind::Number,
214
        super::TokenKind::Ident, super::TokenKind::Plus, super::TokenKind::Minus,
215
            super::TokenKind::Number,
216
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Plus,
217
            super::TokenKind::Number,
218
        super::TokenKind::Ident, super::TokenKind::LParen, super::TokenKind::Minus,
219
            super::TokenKind::Number, super::TokenKind::RParen,
220
        super::TokenKind::Eof,
221
    ];
222
    for expectedKind in expected {
223
        try testing::expect(super::next(&mut s).kind == expectedKind);
224
    }
225
}
226
227
@test fn testScanKeywords() throws (testing::TestError) {
228
    let mut s = testScanner("constant instantiate nil mod not static unsafe");
229
    let expected: [super::TokenKind; 8] = [
230
        super::TokenKind::Constant,
231
        super::TokenKind::Instantiate,
232
        super::TokenKind::Nil,
233
        super::TokenKind::Mod,
234
        super::TokenKind::Not,
235
        super::TokenKind::Static,
236
        super::TokenKind::Unsafe,
237
        super::TokenKind::Eof,
238
    ];
239
    for kind in expected {
240
        assert super::next(&mut s).kind == kind;
241
    }
242
}
243
244
@test fn testScanVoidAsIdent() throws (testing::TestError) {
245
    let mut s = testScanner("void");
246
    let tok: super::Token = super::next(&mut s);
247
    try testing::expect(tok.kind == super::TokenKind::Ident);
248
    try testing::expect(tok.source.len == 4);
249
}
250
251
@test fn testScanWhitespaceAndComments() throws (testing::TestError) {
252
    let mut s = testScanner(
253
        "  \t\n  // This is a comment..\n  42"
254
    );
255
    let tok: super::Token = super::next(&mut s);
256
    try testing::expect(tok.kind == super::TokenKind::Number);
257
    try testing::expect(tok.source.len == 2);
258
    try testing::expect(super::isEof(&s));
259
}
260
261
@test fn testScanInvalidCharacters() throws (testing::TestError) {
262
    let mut s = testScanner(
263
        "`#$"
264
    );
265
    let mut tok: super::Token = super::next(&mut s);
266
    try testing::expect(tok.kind == super::TokenKind::Invalid);
267
    try testing::expect(tok.offset == 0);
268
269
    set tok = super::next(&mut s);
270
    try testing::expect(tok.kind == super::TokenKind::Invalid);
271
    try testing::expect(tok.offset == 1);
272
273
    set tok = super::next(&mut s);
274
    try testing::expect(tok.kind == super::TokenKind::Invalid);
275
    try testing::expect(tok.offset == 2);
276
}
277
278
@test fn testScanUnterminatedString() throws (testing::TestError) {
279
    let mut s = testScanner("\"Hello World!");
280
    let tok: super::Token = super::next(&mut s);
281
282
    try testing::expect(tok.kind == super::TokenKind::Invalid);
283
    try testing::expect(tok.source == "unterminated string");
284
    try testing::expect(tok.offset == 0);
285
}
286
287
@test fn testScanUnderminatedStringEscape() throws (testing::TestError) {
288
    let mut s = testScanner("\"\\");
289
    let tok: super::Token = super::next(&mut s);
290
291
    try testing::expect(tok.kind == super::TokenKind::Invalid);
292
}
293
294
@test fn testScanFunctionDefinition() throws (testing::TestError) {
295
    let mut s = testScanner(
296
        "fn add(a: i32, b: i32) -> i32 { return a + b; }"
297
    );
298
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Fn);
299
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
300
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LParen);
301
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
302
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Colon);
303
    try testing::expect(super::next(&mut s).kind == super::TokenKind::I32);
304
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Comma);
305
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
306
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Colon);
307
    try testing::expect(super::next(&mut s).kind == super::TokenKind::I32);
308
    try testing::expect(super::next(&mut s).kind == super::TokenKind::RParen);
309
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Arrow);
310
    try testing::expect(super::next(&mut s).kind == super::TokenKind::I32);
311
    try testing::expect(super::next(&mut s).kind == super::TokenKind::LBrace);
312
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Return);
313
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
314
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Plus);
315
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
316
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Semicolon);
317
    try testing::expect(super::next(&mut s).kind == super::TokenKind::RBrace);
318
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
319
}
320
321
@test fn testScanGenericDelimiters() throws (testing::TestError) {
322
    let mut s = testScanner("Pair⟨T⟩");
323
    assert super::next(&mut s).kind == super::TokenKind::Ident;
324
    let open = super::next(&mut s);
325
    assert open.kind == super::TokenKind::LAngle;
326
    assert mem::eq(open.source, "⟨");
327
    assert super::next(&mut s).kind == super::TokenKind::Ident;
328
    let close = super::next(&mut s);
329
    assert close.kind == super::TokenKind::RAngle;
330
    assert mem::eq(close.source, "⟩");
331
    assert super::next(&mut s).kind == super::TokenKind::Eof;
332
}
333
334
@test fn testRejectGenericDelimiterLookalikes() throws (testing::TestError) {
335
    // U+3008 LEFT ANGLE BRACKET, not U+27E8 MATHEMATICAL LEFT ANGLE BRACKET.
336
    let source: [u8; 3] = [0xe3, 0x80, 0x88];
337
    let mut s = testScanner(&source[..]);
338
    assert super::next(&mut s).kind == super::TokenKind::Invalid;
339
}