master
1const std = @import("std");
2const mem = std.mem;
3const testing = std.testing;
4
5const yaml_mod = @import("../yaml.zig");
6const Yaml = yaml_mod.Yaml;
7
8test "simple list" {
9 const source =
10 \\- a
11 \\- b
12 \\- c
13 ;
14
15 var yaml = try Yaml.load(testing.allocator, source);
16 defer yaml.deinit();
17
18 try testing.expectEqual(yaml.docs.items.len, 1);
19
20 const list = yaml.docs.items[0].list;
21 try testing.expectEqual(list.len, 3);
22
23 try testing.expectEqualStrings("a", list[0].string);
24 try testing.expectEqualStrings("b", list[1].string);
25 try testing.expectEqualStrings("c", list[2].string);
26}
27
28test "simple list typed as array of strings" {
29 const source =
30 \\- a
31 \\- b
32 \\- c
33 ;
34
35 var yaml = try Yaml.load(testing.allocator, source);
36 defer yaml.deinit();
37
38 try testing.expectEqual(yaml.docs.items.len, 1);
39
40 const arr = try yaml.parse([3][]const u8);
41 try testing.expectEqual(3, arr.len);
42 try testing.expectEqualStrings("a", arr[0]);
43 try testing.expectEqualStrings("b", arr[1]);
44 try testing.expectEqualStrings("c", arr[2]);
45}
46
47test "simple list typed as array of ints" {
48 const source =
49 \\- 0
50 \\- 1
51 \\- 2
52 ;
53
54 var yaml = try Yaml.load(testing.allocator, source);
55 defer yaml.deinit();
56
57 try testing.expectEqual(yaml.docs.items.len, 1);
58
59 const arr = try yaml.parse([3]u8);
60 try testing.expectEqualSlices(u8, &[_]u8{ 0, 1, 2 }, &arr);
61}
62
63test "list of mixed sign integer" {
64 const source =
65 \\- 0
66 \\- -1
67 \\- 2
68 ;
69
70 var yaml = try Yaml.load(testing.allocator, source);
71 defer yaml.deinit();
72
73 try testing.expectEqual(yaml.docs.items.len, 1);
74
75 const arr = try yaml.parse([3]i8);
76 try testing.expectEqualSlices(i8, &[_]i8{ 0, -1, 2 }, &arr);
77}
78
79test "simple map untyped" {
80 const source =
81 \\a: 0
82 ;
83
84 var yaml = try Yaml.load(testing.allocator, source);
85 defer yaml.deinit();
86
87 try testing.expectEqual(yaml.docs.items.len, 1);
88
89 const map = yaml.docs.items[0].map;
90 try testing.expect(map.contains("a"));
91 try testing.expectEqual(@as(i64, 0), map.get("a").?.int);
92}
93
94test "simple map untyped with a list of maps" {
95 const source =
96 \\a: 0
97 \\b:
98 \\ - foo: 1
99 \\ bar: 2
100 \\ - foo: 3
101 \\ bar: 4
102 \\c: 1
103 ;
104
105 var yaml = try Yaml.load(testing.allocator, source);
106 defer yaml.deinit();
107
108 try testing.expectEqual(yaml.docs.items.len, 1);
109
110 const map = yaml.docs.items[0].map;
111 try testing.expect(map.contains("a"));
112 try testing.expect(map.contains("b"));
113 try testing.expect(map.contains("c"));
114 try testing.expectEqual(@as(i64, 0), map.get("a").?.int);
115 try testing.expectEqual(@as(i64, 1), map.get("c").?.int);
116 try testing.expectEqual(@as(i64, 1), map.get("b").?.list[0].map.get("foo").?.int);
117 try testing.expectEqual(@as(i64, 2), map.get("b").?.list[0].map.get("bar").?.int);
118 try testing.expectEqual(@as(i64, 3), map.get("b").?.list[1].map.get("foo").?.int);
119 try testing.expectEqual(@as(i64, 4), map.get("b").?.list[1].map.get("bar").?.int);
120}
121
122test "simple map untyped with a list of maps. no indent" {
123 const source =
124 \\b:
125 \\- foo: 1
126 \\c: 1
127 ;
128
129 var yaml = try Yaml.load(testing.allocator, source);
130 defer yaml.deinit();
131
132 try testing.expectEqual(yaml.docs.items.len, 1);
133
134 const map = yaml.docs.items[0].map;
135 try testing.expect(map.contains("b"));
136 try testing.expect(map.contains("c"));
137 try testing.expectEqual(@as(i64, 1), map.get("c").?.int);
138 try testing.expectEqual(@as(i64, 1), map.get("b").?.list[0].map.get("foo").?.int);
139}
140
141test "simple map untyped with a list of maps. no indent 2" {
142 const source =
143 \\a: 0
144 \\b:
145 \\- foo: 1
146 \\ bar: 2
147 \\- foo: 3
148 \\ bar: 4
149 \\c: 1
150 ;
151
152 var yaml = try Yaml.load(testing.allocator, source);
153 defer yaml.deinit();
154
155 try testing.expectEqual(yaml.docs.items.len, 1);
156
157 const map = yaml.docs.items[0].map;
158 try testing.expect(map.contains("a"));
159 try testing.expect(map.contains("b"));
160 try testing.expect(map.contains("c"));
161 try testing.expectEqual(@as(i64, 0), map.get("a").?.int);
162 try testing.expectEqual(@as(i64, 1), map.get("c").?.int);
163 try testing.expectEqual(@as(i64, 1), map.get("b").?.list[0].map.get("foo").?.int);
164 try testing.expectEqual(@as(i64, 2), map.get("b").?.list[0].map.get("bar").?.int);
165 try testing.expectEqual(@as(i64, 3), map.get("b").?.list[1].map.get("foo").?.int);
166 try testing.expectEqual(@as(i64, 4), map.get("b").?.list[1].map.get("bar").?.int);
167}
168
169test "simple map typed" {
170 const source =
171 \\a: 0
172 \\b: hello there
173 \\c: 'wait, what?'
174 ;
175
176 var yaml = try Yaml.load(testing.allocator, source);
177 defer yaml.deinit();
178
179 const simple = try yaml.parse(struct { a: usize, b: []const u8, c: []const u8 });
180 try testing.expectEqual(@as(usize, 0), simple.a);
181 try testing.expectEqualStrings("hello there", simple.b);
182 try testing.expectEqualStrings("wait, what?", simple.c);
183}
184
185test "typed nested structs" {
186 const source =
187 \\a:
188 \\ b: hello there
189 \\ c: 'wait, what?'
190 ;
191
192 var yaml = try Yaml.load(testing.allocator, source);
193 defer yaml.deinit();
194
195 const simple = try yaml.parse(struct {
196 a: struct {
197 b: []const u8,
198 c: []const u8,
199 },
200 });
201 try testing.expectEqualStrings("hello there", simple.a.b);
202 try testing.expectEqualStrings("wait, what?", simple.a.c);
203}
204
205test "single quoted string" {
206 const source =
207 \\- 'hello'
208 \\- 'here''s an escaped quote'
209 \\- 'newlines and tabs\nare not\tsupported'
210 ;
211
212 var yaml = try Yaml.load(testing.allocator, source);
213 defer yaml.deinit();
214
215 const arr = try yaml.parse([3][]const u8);
216 try testing.expectEqual(arr.len, 3);
217 try testing.expectEqualStrings("hello", arr[0]);
218 try testing.expectEqualStrings("here's an escaped quote", arr[1]);
219 try testing.expectEqualStrings("newlines and tabs\\nare not\\tsupported", arr[2]);
220}
221
222test "double quoted string" {
223 const source =
224 \\- "hello"
225 \\- "\"here\" are some escaped quotes"
226 \\- "newlines and tabs\nare\tsupported"
227 \\- "let's have
228 \\some fun!"
229 ;
230
231 var yaml = try Yaml.load(testing.allocator, source);
232 defer yaml.deinit();
233
234 const arr = try yaml.parse([4][]const u8);
235 try testing.expectEqual(arr.len, 4);
236 try testing.expectEqualStrings("hello", arr[0]);
237 try testing.expectEqualStrings(
238 \\"here" are some escaped quotes
239 , arr[1]);
240 try testing.expectEqualStrings("newlines and tabs\nare\tsupported", arr[2]);
241 try testing.expectEqualStrings(
242 \\let's have
243 \\some fun!
244 , arr[3]);
245}
246
247test "multidoc typed as a slice of structs" {
248 const source =
249 \\---
250 \\a: 0
251 \\---
252 \\a: 1
253 \\...
254 ;
255
256 var yaml = try Yaml.load(testing.allocator, source);
257 defer yaml.deinit();
258
259 {
260 const result = try yaml.parse([2]struct { a: usize });
261 try testing.expectEqual(result.len, 2);
262 try testing.expectEqual(result[0].a, 0);
263 try testing.expectEqual(result[1].a, 1);
264 }
265
266 {
267 const result = try yaml.parse([]struct { a: usize });
268 try testing.expectEqual(result.len, 2);
269 try testing.expectEqual(result[0].a, 0);
270 try testing.expectEqual(result[1].a, 1);
271 }
272}
273
274test "multidoc typed as a struct is an error" {
275 const source =
276 \\---
277 \\a: 0
278 \\---
279 \\b: 1
280 \\...
281 ;
282
283 var yaml = try Yaml.load(testing.allocator, source);
284 defer yaml.deinit();
285
286 try testing.expectError(Yaml.Error.TypeMismatch, yaml.parse(struct { a: usize }));
287 try testing.expectError(Yaml.Error.TypeMismatch, yaml.parse(struct { b: usize }));
288 try testing.expectError(Yaml.Error.TypeMismatch, yaml.parse(struct { a: usize, b: usize }));
289}
290
291test "multidoc typed as a slice of structs with optionals" {
292 const source =
293 \\---
294 \\a: 0
295 \\c: 1.0
296 \\---
297 \\a: 1
298 \\b: different field
299 \\...
300 ;
301
302 var yaml = try Yaml.load(testing.allocator, source);
303 defer yaml.deinit();
304
305 const result = try yaml.parse([]struct { a: usize, b: ?[]const u8, c: ?f16 });
306 try testing.expectEqual(result.len, 2);
307
308 try testing.expectEqual(result[0].a, 0);
309 try testing.expect(result[0].b == null);
310 try testing.expect(result[0].c != null);
311 try testing.expectEqual(result[0].c.?, 1.0);
312
313 try testing.expectEqual(result[1].a, 1);
314 try testing.expect(result[1].b != null);
315 try testing.expectEqualStrings("different field", result[1].b.?);
316 try testing.expect(result[1].c == null);
317}
318
319test "empty yaml can be represented as void" {
320 const source = "";
321 var yaml = try Yaml.load(testing.allocator, source);
322 defer yaml.deinit();
323 const result = try yaml.parse(void);
324 try testing.expect(@TypeOf(result) == void);
325}
326
327test "nonempty yaml cannot be represented as void" {
328 const source =
329 \\a: b
330 ;
331
332 var yaml = try Yaml.load(testing.allocator, source);
333 defer yaml.deinit();
334
335 try testing.expectError(Yaml.Error.TypeMismatch, yaml.parse(void));
336}
337
338test "typed array size mismatch" {
339 const source =
340 \\- 0
341 \\- 0
342 ;
343
344 var yaml = try Yaml.load(testing.allocator, source);
345 defer yaml.deinit();
346
347 try testing.expectError(Yaml.Error.ArraySizeMismatch, yaml.parse([1]usize));
348 try testing.expectError(Yaml.Error.ArraySizeMismatch, yaml.parse([5]usize));
349}
350
351test "comments" {
352 const source =
353 \\
354 \\key: # this is the key
355 \\# first value
356 \\
357 \\- val1
358 \\
359 \\# second value
360 \\- val2
361 ;
362
363 var yaml = try Yaml.load(testing.allocator, source);
364 defer yaml.deinit();
365
366 const simple = try yaml.parse(struct {
367 key: []const []const u8,
368 });
369 try testing.expect(simple.key.len == 2);
370 try testing.expectEqualStrings("val1", simple.key[0]);
371 try testing.expectEqualStrings("val2", simple.key[1]);
372}
373
374test "promote ints to floats in a list mixed numeric types" {
375 const source =
376 \\a_list: [0, 1.0]
377 ;
378
379 var yaml = try Yaml.load(testing.allocator, source);
380 defer yaml.deinit();
381
382 const simple = try yaml.parse(struct {
383 a_list: []const f64,
384 });
385 try testing.expectEqualSlices(f64, &[_]f64{ 0.0, 1.0 }, simple.a_list);
386}
387
388test "demoting floats to ints in a list is an error" {
389 const source =
390 \\a_list: [0, 1.0]
391 ;
392
393 var yaml = try Yaml.load(testing.allocator, source);
394 defer yaml.deinit();
395
396 try testing.expectError(error.TypeMismatch, yaml.parse(struct {
397 a_list: []const u64,
398 }));
399}
400
401test "duplicate map keys" {
402 const source =
403 \\a: b
404 \\a: c
405 ;
406 try testing.expectError(error.DuplicateMapKey, Yaml.load(testing.allocator, source));
407}
408
409fn testStringify(expected: []const u8, input: anytype) !void {
410 var output = std.array_list.Managed(u8).init(testing.allocator);
411 defer output.deinit();
412
413 try yaml_mod.stringify(testing.allocator, input, output.writer());
414 try testing.expectEqualStrings(expected, output.items);
415}
416
417test "stringify an int" {
418 try testStringify("128", @as(u32, 128));
419}
420
421test "stringify a simple struct" {
422 try testStringify(
423 \\a: 1
424 \\b: 2
425 \\c: 2.5
426 , struct { a: i64, b: f64, c: f64 }{ .a = 1, .b = 2.0, .c = 2.5 });
427}
428
429test "stringify a struct with an optional" {
430 try testStringify(
431 \\a: 1
432 \\b: 2
433 \\c: 2.5
434 , struct { a: i64, b: ?f64, c: f64 }{ .a = 1, .b = 2.0, .c = 2.5 });
435
436 try testStringify(
437 \\a: 1
438 \\c: 2.5
439 , struct { a: i64, b: ?f64, c: f64 }{ .a = 1, .b = null, .c = 2.5 });
440}
441
442test "stringify a struct with all optionals" {
443 try testStringify("", struct { a: ?i64, b: ?f64 }{ .a = null, .b = null });
444}
445
446test "stringify an optional" {
447 try testStringify("", null);
448 try testStringify("", @as(?u64, null));
449}
450
451test "stringify a union" {
452 const Dummy = union(enum) {
453 x: u64,
454 y: f64,
455 };
456 try testStringify("a: 1", struct { a: Dummy }{ .a = .{ .x = 1 } });
457 try testStringify("a: 2.1", struct { a: Dummy }{ .a = .{ .y = 2.1 } });
458}
459
460test "stringify a string" {
461 try testStringify("a: name", struct { a: []const u8 }{ .a = "name" });
462 try testStringify("name", "name");
463}
464
465test "stringify a list" {
466 try testStringify("[ 1, 2, 3 ]", @as([]const u64, &.{ 1, 2, 3 }));
467 try testStringify("[ 1, 2, 3 ]", .{ @as(i64, 1), 2, 3 });
468 try testStringify("[ 1, name, 3 ]", .{ 1, "name", 3 });
469
470 const arr: [3]i64 = .{ 1, 2, 3 };
471 try testStringify("[ 1, 2, 3 ]", arr);
472}