v2 / vlib / v / tests / structs / struct_test.v
476 lines · 414 sloc · 7.7 KB · b68465f404e5ef5c55c5c2e03d142dfe9564ef52
Raw
1struct Aa {
2mut:
3 val int
4 nums []int
5}
6
7struct Bb {
8mut:
9 a Aa
10}
11
12struct Cu {
13mut:
14 b Bb
15 nums []int
16 aarr []Aa
17 num int
18}
19
20struct Lol {
21 b []string @[json: lol]
22 c string @[json: cc]
23 d int
24}
25
26struct User {
27 name string
28mut:
29 age int
30}
31
32struct Foo {
33 typ string
34}
35
36struct Empty {
37}
38
39// We need to make sure that this compiles with all the reserved names.
40struct ReservedKeywords {
41 delete int
42 exit int
43 unix int
44 error int
45 malloc int
46 calloc int
47 free int
48 panic int
49 auto int
50 char int
51 do int
52 double int
53 extern int
54 float int
55 inline int
56 long int
57 register int
58 restrict int
59 short int
60 signed int
61 typedef int
62 unsigned int
63 void int
64 while int
65}
66
67fn test_empty_struct() {
68 d := &Empty{}
69 d2 := Empty{}
70 println('&empty:')
71 println(d) // != voidptr(0)
72 println('empty:')
73 println(d2) // empty struct print
74 println(sizeof(Empty)) // == 0
75}
76
77fn test_struct_levels() {
78 mut c := Cu{}
79 println(c.nums.len)
80 assert c.nums.len == 0
81 c.nums << 3
82 assert c.nums.len == 1
83 assert c.nums[0] == 3
84 c.nums[0] = 4
85 assert c.nums[0] == 4
86 c.b.a.val = 34
87 assert c.b.a.val == 34
88 c.b.a.nums = [0].repeat(0)
89 c.b.a.nums << 0
90 c.b.a.nums << 2
91 assert c.b.a.nums.len == 2
92 assert c.b.a.nums[0] == 0
93 assert c.b.a.nums[1] == 2
94 c.b.a.nums[0] = 7
95 assert c.b.a.nums[0] == 7
96 c.aarr << Aa{
97 val: 8
98 }
99 assert c.aarr.len == 1
100 assert c.aarr[0].val == 8
101 c.num = 20
102 assert c.num == 20
103 c.aarr[0].val = 10
104 assert c.aarr[0].val == 10
105}
106
107fn test_struct_str() {
108 u := User{'Bob', 30}
109 println(u) // make sure the struct is printable
110 // assert u.str() == '{name:"Bob", age:30}' // QTODO
111}
112
113fn test_at() {
114 foo := Foo{
115 typ: 'test'
116 }
117 // type: 'test'
118 println(foo.typ)
119}
120
121fn test_reserved_keywords() {
122 // Make sure we can initialize them correctly using full syntax.
123 rk_holder :=
124 ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
125 // Test a few as it'll take too long to test all. If it's initialized
126 // correctly, other fields are also probably valid.
127 assert rk_holder.unix == 5
128 assert rk_holder.while == 3
129 rk_holder2 := ReservedKeywords{
130 inline: 9
131 }
132 // Make sure partial initialization works too.
133 assert rk_holder2.inline == 9
134 assert rk_holder2.while == 0 // Zero value as not specified.
135}
136
137struct User2 {
138mut:
139 name string
140}
141
142fn test_mutable_fields() {
143 mut u := User2{}
144 u.name = 'Peter'
145 assert u.name == 'Peter'
146}
147
148struct Def {
149 a int
150 b int = 7
151}
152
153fn test_default_vals() {
154 d := Def{}
155 assert d.a == 0
156 assert d.b == 7
157 d2 := Def{10, 20}
158 assert d2.a == 10
159 assert d2.b == 20
160}
161
162fn test_assoc_with_vars() {
163 def2 := Def{
164 a: 12
165 }
166 mut merged := Def{
167 ...def2
168 a: 42
169 }
170 assert merged.a == 42
171 assert merged.b == 7
172 merged = Def{
173 ...def2
174 b: 9
175 }
176 assert merged == Def{12, 9}
177
178 def3 := &Def{100, 200}
179 merged1 := Def{
180 ...(*def3)
181 }
182 merged2 := &Def{
183 ...(*def3)
184 }
185 assert merged1.a == 100
186 assert merged1.b == 200
187 assert merged2.a == 100
188 assert merged2.b == 200
189}
190
191const const_def = Def{
192 a: 100
193}
194
195fn test_assoc_with_constants() {
196 println(1)
197 /*
198 TODO:
199 merged := { const_def | a: 42 }
200 assert merged.a == 42
201 assert merged.b == 7
202
203 again := { const_def | b: 22 }
204 assert again.a == 100
205 assert again.b == 22
206 */
207}
208
209struct AttrTest {
210 a int // private immutable (default)
211mut:
212 b int // private mutable
213 c int // (you can list multiple fields with the same access modifier)
214pub:
215 d int // public immutable (readonly)
216pub mut:
217 e int // public, but mutable only in parent module
218 f int // public and mutable both inside and outside parent module
219}
220
221fn fooo() {
222 _ := AttrTest{1, 2, 3, 4, 5, 6}
223}
224
225/*
226@[typedef]
227pub struct C.fixed {
228 points [10]C.point
229}
230
231@[typedef]
232pub struct C.point {
233 x int
234 y int
235}
236
237fn test_fixed_field() {
238 f := &C.fixed{}
239 p := f.points[0]
240 //f.nums[0] = 10
241 //println(f.nums[0])
242 println(p.x)
243 //nums: [10]int
244 //}
245}
246*/
247struct C.issue24102_child {
248 x int
249}
250
251struct C.issue24102_parent {
252 count int
253 Child C.issue24102_child
254}
255
256fn test_plain_c_struct_definition_with_nested_selector_and_str() {
257 parent := C.issue24102_parent{
258 count: 3
259 Child: C.issue24102_child{
260 x: 7
261 }
262 }
263 assert parent.count == 3
264 assert parent.Child.x == 7
265 rendered := '${parent}'
266 assert rendered.contains('count: 3')
267 assert rendered.contains('Child:')
268 assert rendered.contains('x: 7')
269}
270
271@[params]
272struct Config {
273mut:
274 n int
275 def int = 10
276}
277
278fn foo_config(def int, c Config) {
279 assert c.def == def
280}
281
282fn bar_config(c Config, def int) {
283 assert c.def == def
284}
285
286fn foo_user(u User) {}
287
288fn foo_mut_user(mut u User) {
289 u.age++
290}
291
292fn test_struct_literal_args() {
293 foo_config(20,
294 n: 10
295 def: 20
296 )
297 foo_config(10)
298 foo_config(10, n: 40)
299 foo_config(40, n: 30, def: 40)
300
301 bar_config(Config{}, 10)
302 bar_config(Config{ def: 4 }, 4)
303
304 foo_user(name: 'Peter')
305 foo_user(name: 'Peter')
306 foo_user(age: 7)
307 foo_user(name: 'Stew', age: 50)
308
309 mut user := User{'Stew', 50}
310 foo_mut_user(mut user)
311 assert user.age == 51
312}
313
314struct City {
315 name string
316 population int
317}
318
319struct Country {
320 name string
321 capital City
322}
323
324fn test_levels() {
325 _ := Country{
326 name: 'UK'
327 capital: City{
328 name: 'London'
329 population: 10
330 }
331 }
332}
333
334// Struct where an initialized field is after a non-initialized field.
335struct StructWithDefaultValues1 {
336 field_uninitialized int
337 field_initialized int = 5
338}
339
340// Struct where an initialized field is before a non-initialized field.
341struct StructWithDefaultValues2 {
342 field_initialized int = 3
343 field_uninitialized int
344}
345
346// Struct where an initialized field is before several non-initialized fields.
347struct StructWithDefaultValues3 {
348 field_initialized int = 2
349 field_uninitialized int
350 field_uninitialized_too int
351}
352
353fn test_struct_with_default_values_init() {
354 s1 := StructWithDefaultValues1{
355 field_uninitialized: 5
356 }
357 s2 := StructWithDefaultValues2{
358 field_uninitialized: 5
359 }
360 // Partially initialized
361 s3 := StructWithDefaultValues3{
362 field_uninitialized: 5
363 }
364
365 assert s1.field_initialized == 5
366 assert s2.field_initialized == 3
367 assert s3.field_initialized == 2
368}
369
370fn test_struct_with_default_values_no_init() {
371 // Don't inititialize
372 s1 := StructWithDefaultValues1{}
373 s2 := StructWithDefaultValues2{}
374 s3 := StructWithDefaultValues3{}
375
376 assert s1.field_initialized == 5
377 assert s2.field_initialized == 3
378 assert s3.field_initialized == 2
379}
380
381struct FieldsWithOptionVoidReturnType {
382 f fn () ! @[required]
383 g fn () ? @[required]
384}
385
386fn test_fields_anon_fn_with_option_void_return_type() {
387 foo := FieldsWithOptionVoidReturnType{
388 f: fn () ! {
389 return error('oops')
390 }
391 g: fn () ? {
392 return
393 }
394 }
395
396 foo.f() or { assert err.msg() == 'oops' }
397
398 foo.g() or { assert false }
399}
400
401struct Commands {
402 show []fn () string
403}
404
405fn a() string {
406 return 'HELLOW'
407}
408
409fn b() string {
410 return 'WOLLEH'
411}
412
413fn test_fields_array_of_fn() {
414 commands := Commands{
415 show: [a, b]
416 }
417 println(commands.show)
418 assert '${commands.show}' == '[fn () string, fn () string]'
419}
420
421fn test_struct_update() {
422 c := Country{
423 name: 'test'
424 }
425 c2 := Country{
426 ...c
427 capital: City{
428 name: 'city'
429 }
430 }
431 assert c2.capital.name == 'city'
432 assert c2.name == 'test'
433}
434
435// Test anon structs
436struct Book {
437 x Foo
438 author struct {
439 name string
440 age int
441 }
442
443 title string
444}
445
446fn test_anon() {
447 empty_book := Book{}
448 assert empty_book.author.age == 0
449 assert empty_book.author.name == ''
450 println(empty_book.author.age)
451
452 book := Book{
453 author: struct {'Peter Brown', 23}
454 }
455 assert book.author.name == 'Peter Brown'
456 assert book.author.age == 23
457 println(book.author.name)
458
459 book2 := Book{
460 author: struct {
461 name: 'Samantha Black'
462 age: 24
463 }
464 }
465 assert book2.author.name == 'Samantha Black'
466 assert book2.author.age == 24
467 println(book2.author.name)
468}
469
470fn test_anon_auto_stringify() {
471 b := Book{}
472 s := b.str()
473 assert s.contains('author: ')
474 assert s.contains('name: ')
475 assert s.contains('age: 0')
476}
477