lib/std/lang/module/tests.rad 10.2 KiB raw
1
//! Tests for the module loader.
2
3
use std::mem;
4
use std::testing;
5
use std::lang::ast;
6
use std::lang::strings;
7
8
/// Test arena backing storage.
9
static TEST_ARENA: [u8; 4096] = undefined;
10
/// Interned string pool.
11
static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
12
13
fn expectSliceEq(actual: *[u8], expected: *[u8])
14
    throws (testing::TestError)
15
{
16
    if not mem::eq(actual, expected) {
17
        throw testing::TestError::Failed;
18
    }
19
}
20
21
fn expectPathSegments(entry: *super::ModuleEntry, expected: *[*[u8]])
22
    throws (testing::TestError)
23
{
24
    let actual = super::moduleQualifiedPath(entry);
25
    try testing::expect(actual.len == expected.len);
26
    for i in 0..expected.len {
27
        try expectSliceEq(actual[i], expected[i]);
28
    }
29
}
30
31
@test fn testRegisterChildren() throws (testing::TestError) {
32
    let mut storage: [super::ModuleEntry; 4] = undefined;
33
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
34
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
35
36
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "src/root.rad") catch {
37
        throw testing::TestError::Failed;
38
    };
39
    let root = super::get(&graph, rootId) else {
40
        throw testing::TestError::Failed;
41
    };
42
    try expectPathSegments(root, &["root"]);
43
44
    // First child.
45
    let firstId = try super::registerFromPath(&mut graph, 0, rootId, "src/root/first.rad") catch {
46
        throw testing::TestError::Failed;
47
    };
48
    let first = super::get(&graph, firstId) else {
49
        throw testing::TestError::Failed;
50
    };
51
    try expectSliceEq(first.filePath, "src/root/first.rad");
52
    try expectSliceEq(first.name, "first");
53
    try expectPathSegments(first, &["root", "first"]);
54
55
    // Second child.
56
    let secondId = try super::registerFromPath(&mut graph, 0, rootId, "src/root/second.rad") catch {
57
        throw testing::TestError::Failed;
58
    };
59
    let second = super::get(&graph, secondId) else {
60
        throw testing::TestError::Failed;
61
    };
62
    try expectSliceEq(second.filePath, "src/root/second.rad");
63
    try expectSliceEq(second.name, "second");
64
    try expectPathSegments(second, &["root", "second"]);
65
66
    let parent = super::get(&graph, rootId) else {
67
        throw testing::TestError::Failed;
68
    };
69
    try testing::expect(graph.entriesLen == 3);
70
    try testing::expect(parent.childrenLen == 2);
71
    try testing::expect(super::childAt(parent, 0) == firstId);
72
    try testing::expect(super::childAt(parent, 1) == secondId);
73
}
74
75
@test fn testRegisterChildReusesExisting() throws (testing::TestError) {
76
    let mut storage: [super::ModuleEntry; 4] = undefined;
77
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
78
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
79
80
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "src/main.rad") catch {
81
        throw testing::TestError::Failed;
82
    };
83
    let firstId = try super::registerFromPath(&mut graph, 0, rootId, "src/main/util.rad") catch {
84
        throw testing::TestError::Failed;
85
    };
86
    let secondId = try super::registerFromPath(&mut graph, 0, rootId, "src/main/util.rad") catch {
87
        throw testing::TestError::Failed;
88
    };
89
    try testing::expect(firstId == secondId);
90
91
    let parent = super::get(&graph, rootId) else {
92
        throw testing::TestError::Failed;
93
    };
94
    try testing::expect(graph.entriesLen == 2);
95
    try testing::expect(parent.childrenLen == 1);
96
}
97
98
@test fn testTrimExtensionWithRadExtension() throws (testing::TestError) {
99
    let input = "parser.rad";
100
    let result = super::trimExtension(input)
101
        else throw testing::TestError::Failed;
102
    try expectSliceEq(result, "parser");
103
}
104
105
@test fn testTrimExtensionWithoutExtension() throws (testing::TestError) {
106
    let input = "parser";
107
    let result = super::trimExtension(input);
108
    try testing::expect(result == nil);
109
}
110
111
@test fn testTrimExtensionWithWrongExtension() throws (testing::TestError) {
112
    let input = "parser.txt";
113
    let result = super::trimExtension(input);
114
    try testing::expect(result == nil);
115
}
116
117
@test fn testParsePathSingleComponent() throws (testing::TestError) {
118
    let path = "std.rad";
119
    let mut components: [*[u8]; 8] = undefined;
120
    let count = super::parsePath(path, &mut components[..]) else {
121
        throw testing::TestError::Failed;
122
    };
123
    try testing::expect(count == 1);
124
    try expectSliceEq(components[0], "std");
125
}
126
127
@test fn testParsePathMultipleComponents() throws (testing::TestError) {
128
    let path = "std/lang/parser.rad";
129
    let mut components: [*[u8]; 8] = undefined;
130
    let count = super::parsePath(path, &mut components[..]) else {
131
        throw testing::TestError::Failed;
132
    };
133
    try testing::expect(count == 3);
134
    try expectSliceEq(components[0], "std");
135
    try expectSliceEq(components[1], "lang");
136
    try expectSliceEq(components[2], "parser");
137
}
138
139
@test fn testParsePathWithoutExtension() throws (testing::TestError) {
140
    let path = "std/lang/parser";
141
    let mut components: [*[u8]; 8] = undefined;
142
    let result = super::parsePath(path, &mut components[..]);
143
    try testing::expect(result == nil);
144
}
145
146
@test fn testRegisterFromPathHierarchy() throws (testing::TestError) {
147
    let mut storage: [super::ModuleEntry; 8] = undefined;
148
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
149
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
150
151
    // Register root module.
152
    let stdId = try super::registerFromPath(&mut graph, 0, nil, "lib/std.rad") catch {
153
        throw testing::TestError::Failed;
154
    };
155
    let std = super::get(&graph, stdId) else {
156
        throw testing::TestError::Failed;
157
    };
158
    try expectSliceEq(std.filePath, "lib/std.rad");
159
    try expectSliceEq(super::moduleDir(std), "lib/");
160
    try expectPathSegments(std, &["std"]);
161
162
    // Register child of root.
163
    let langId = try super::registerFromPath(&mut graph, 0, stdId, "lib/std/lang.rad") catch {
164
        throw testing::TestError::Failed;
165
    };
166
    let lang = super::get(&graph, langId) else {
167
        throw testing::TestError::Failed;
168
    };
169
    try expectSliceEq(lang.filePath, "lib/std/lang.rad");
170
    try expectSliceEq(lang.name, "lang");
171
    try expectSliceEq(super::moduleDir(lang), "lib/std/");
172
    try expectPathSegments(lang, &["std", "lang"]);
173
174
    // Register grandchild.
175
    let parserId = try super::registerFromPath(&mut graph, 0, stdId, "lib/std/lang/parser.rad") catch {
176
        throw testing::TestError::Failed;
177
    };
178
    let parser = super::get(&graph, parserId) else {
179
        throw testing::TestError::Failed;
180
    };
181
    try expectSliceEq(parser.filePath, "lib/std/lang/parser.rad");
182
    try expectSliceEq(parser.name, "parser");
183
    try expectSliceEq(super::moduleDir(parser), "lib/std/lang/");
184
    try expectPathSegments(parser, &["std", "lang", "parser"]);
185
186
    // Verify parent-child relationships.
187
    try testing::expect(graph.entriesLen == 3);
188
    try testing::expect(std.childrenLen == 1);
189
    try testing::expect(super::childAt(std, 0) == langId);
190
    try testing::expect(lang.childrenLen == 1);
191
    try testing::expect(super::childAt(lang, 0) == parserId);
192
    try testing::expect(parser.childrenLen == 0);
193
}
194
195
@test fn testRegisterFromPathMissingParent() throws (testing::TestError) {
196
    let mut storage: [super::ModuleEntry; 8] = undefined;
197
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
198
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
199
200
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "std.rad") catch {
201
        throw testing::TestError::Failed;
202
    };
203
    let _ = try super::registerFromPath(&mut graph, 0, rootId, "std/lang/parser.rad") catch {
204
        // Expected to fail due to missing intermediate parent.
205
        return;
206
    };
207
    throw testing::TestError::Failed;
208
}
209
210
@test fn testRegisterFromPathDuplicateRoot() throws (testing::TestError) {
211
    let mut storage: [super::ModuleEntry; 8] = undefined;
212
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
213
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
214
215
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "std.rad") catch {
216
        throw testing::TestError::Failed;
217
    };
218
    let _ = try super::registerFromPath(&mut graph, 0, rootId, "parser.rad") catch {
219
        // Expected to fail due to missing intermediate parent.
220
        return;
221
    };
222
    throw testing::TestError::Failed;
223
}
224
225
@test fn testRegisterFromPathRegistersRoot() throws (testing::TestError) {
226
    let mut storage: [super::ModuleEntry; 8] = undefined;
227
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
228
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
229
230
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "lib/std.rad") catch {
231
        throw testing::TestError::Failed;
232
    };
233
    // Verify root module was registered with correct ID.
234
    try testing::expect(rootId == 0);
235
236
    let root = super::get(&graph, rootId) else {
237
        throw testing::TestError::Failed;
238
    };
239
    try expectSliceEq(root.name, "std");
240
    try expectSliceEq(root.filePath, "lib/std.rad");
241
    try expectPathSegments(root, &["std"]);
242
}
243
244
@test fn testRegisterFromPathIgnoresLeadingDirectories() throws (testing::TestError) {
245
    let mut storage: [super::ModuleEntry; 8] = undefined;
246
    let mut arena = ast::nodeArena(&mut TEST_ARENA[..]);
247
    let mut graph = super::moduleGraph(&mut storage[..], &mut STRING_POOL, &mut arena);
248
249
    let rootId = try super::registerFromPath(&mut graph, 0, nil, "src/pkg/root.rad") catch {
250
        throw testing::TestError::Failed;
251
    };
252
    // Verify root module was registered with correct ID.
253
    try testing::expect(rootId == 0);
254
255
    let langId = try super::registerFromPath(&mut graph, 0, rootId, "src/pkg/root/lang.rad") catch {
256
        throw testing::TestError::Failed;
257
    };
258
    let lang = super::get(&graph, langId) else {
259
        throw testing::TestError::Failed;
260
    };
261
    try expectSliceEq(lang.name, "lang");
262
    try expectPathSegments(lang, &["root", "lang"]);
263
264
    let parserId = try super::registerFromPath(&mut graph, 0, rootId, "src/pkg/root/lang/parser.rad") catch {
265
        throw testing::TestError::Failed;
266
    };
267
    let parser = super::get(&graph, parserId) else {
268
        throw testing::TestError::Failed;
269
    };
270
    try expectSliceEq(parser.name, "parser");
271
    try expectPathSegments(parser, &["root", "lang", "parser"]);
272
}