v2 / vlib / v / tests / options / option_test.c.v
439 lines · 377 sloc · 6.5 KB · 26026bdc0b5c5df12a4980197e924e2523852096
Raw
1// TODO: remove this after the deprecation period for `?Type` representing both Result and Option passes.
2fn opt_err_with_code(code int) !string {
3 return error_with_code('hi', code)
4}
5
6fn test_err_with_code() {
7 if w := opt_err_with_code(137) {
8 assert false
9 _ := w
10 } else {
11 assert err.str() == 'hi; code: 137'
12 assert err.msg() == 'hi'
13 assert err.code() == 137
14 }
15 v := opt_err_with_code(56) or {
16 assert err.str() == 'hi; code: 56'
17 assert err.msg() == 'hi'
18 assert err.code() == 56
19 return
20 }
21 assert false
22 _ := v
23}
24
25fn opt_err() !string {
26 return error('hi')
27}
28
29fn test_err() {
30 v := opt_err() or {
31 assert err.msg() == 'hi'
32 return
33 }
34 assert false
35 println(v) // suppress not used error
36}
37
38fn err_call(ok bool) !int {
39 if !ok {
40 return error('Not ok!')
41 }
42 return 42
43}
44
45fn ret_none() ?int {
46 // return error('wtf') //none
47 return none
48}
49
50fn test_option_for_base_type_without_variable() {
51 mut val := err_call(true) or {
52 assert false
53 0
54 }
55 assert val == 42
56 val = ret_none() or { return }
57 assert false
58 // This is invalid:
59 // x := 5 or {
60 // return
61 // }
62}
63
64fn test_if_opt() {
65 if val := err_call(false) {
66 assert val == 42
67 }
68 assert 1 == 1
69}
70
71fn test_if_else_opt() {
72 if val := err_call(true) {
73 assert val == 42
74 } else {
75 assert false
76 }
77 if _ := err_call(false) {
78 assert false
79 } else {
80 assert err.msg().len != 0
81 }
82}
83
84fn for_opt_default() !string {
85 return error('awww')
86}
87
88fn test_opt_default() {
89 a := for_opt_default() or {
90 // panic(err)
91 'default'
92 }
93 assert a == 'default'
94}
95
96fn foo_ok() ?int {
97 return 777
98}
99
100fn foo_str() ?string {
101 return 'something'
102}
103
104fn propagate_option(b bool) !int {
105 a := err_call(b)!
106 return a
107}
108
109fn propagate_different_type(b bool) !bool {
110 err_call(b)!
111 return true
112}
113
114fn test_propagation() {
115 println(1)
116 a := propagate_option(true) or { 0 }
117 println(2)
118 assert a == 42
119 println(3)
120 if _ := propagate_option(false) {
121 assert false
122 }
123 println(4)
124 b := propagate_different_type(true) or { false }
125 assert b == true
126 println(5)
127 if _ := propagate_different_type(false) {
128 assert false
129 }
130 println(6)
131}
132
133fn test_q() {
134 assert foo_ok()? == 777
135}
136
137fn or_return_val() int {
138 a := ret_none() or { return 1 }
139 return a
140}
141
142fn or_return_error() !int {
143 a := ret_none() or { return error('Nope') }
144 return a
145}
146
147fn or_return_none() ?int {
148 a := ret_none() or { return none }
149 return a
150}
151
152fn test_or_return() {
153 assert or_return_val() == 1
154 if _ := or_return_error() {
155 assert false
156 } else {
157 assert err.msg().len != 0
158 }
159 if _ := or_return_none() {
160 assert false
161 } else {
162 assert err.msg().len == 0
163 }
164}
165
166fn test_reassignment() {
167 mut x2 := foo_ok() or {
168 assert false
169 return
170 }
171 assert x2 == 777
172 x2 = 100
173 assert x2 == 100
174 x2++
175 assert x2 == 101
176
177 mut x3 := 0
178 x3 = foo_ok() or {
179 assert false
180 return
181 }
182 assert x3 == 777
183}
184
185struct OptionFieldsStruct {
186mut:
187 text ?string
188 n ?int
189 n1 ?int = 1
190}
191
192fn get_opt_struct() ?OptionFieldsStruct {
193 return OptionFieldsStruct{}
194}
195
196fn test_option_field() ? {
197 mut v := OptionFieldsStruct{}
198 assert v.text or { 'default' } == 'default'
199 assert v.n or { 42 } == 42
200 assert v.n1 or { 42 } == 1
201 assert (v.n or { v.n1? }) == 1
202
203 if n := v.n {
204 assert false
205 } else {
206 assert true
207 }
208 if n1 := v.n1 {
209 assert n1 == 1
210 } else {
211 assert false
212 }
213
214 n := v.n or { 10 }
215 assert n == 10
216 n1 := v.n1 or { 10 }
217 assert n1 == 1
218 n1_1 := v.n1? + (v.n or { 10 })
219 assert n1_1 == 11
220
221 v.text = 'text'
222 assert v.text? == 'text'
223 v.n = 42
224 assert v.n? == 42
225 v.n1 = 43
226 assert v.n1? == 43
227
228 v = OptionFieldsStruct{
229 text: 'init'
230 n: 0
231 n1: none
232 }
233 assert v.text? == 'init'
234 assert v.n? == 0
235 assert v.n1 or { 42 } == 42
236
237 assert get_opt_struct()?.n1? == 1
238}
239
240fn opt_ptr(a &int) ?&int {
241 if isnil(a) {
242 return none
243 }
244 return unsafe { a }
245}
246
247fn test_opt_ptr() {
248 a := 3
249 mut r := opt_ptr(&a) or { unsafe { &int(0) } }
250 assert r == &a
251 r = opt_ptr(unsafe { &int(0) }) or { return }
252 assert false
253}
254
255/*
256// QTODO
257fn multi_return_opt(err bool) (string, string) {
258 if err {
259 return error('oops')
260 }
261 return 'hello', 'v'
262}
263
264fn test_multi_return_opt() {
265 a, b := multi_return_opt(false) or {
266 panic(err)
267 }
268 assert a == 'hello' && b == 'v'
269 _, _ := multi_return_opt(true) or {
270 assert err == 'oops'
271 return
272 }
273}
274*/
275
276fn test_option_val_with_empty_or() {
277 ret_none() or {}
278 assert true
279}
280
281fn test_option_void_return_types_of_anon_fn() {
282 f := fn (i int) ! {
283 if i == 0 {
284 return error('0')
285 }
286
287 return
288 }
289
290 f(0) or {
291 assert err.msg() == '0'
292 return
293 }
294}
295
296struct Foo {
297 f fn (int) ! = unsafe { nil }
298}
299
300fn test_option_void_return_types_of_anon_fn_in_struct() {
301 foo := Foo{
302 f: fn (i int) ! {
303 if i == 0 {
304 return error('0')
305 }
306
307 return
308 }
309 }
310
311 foo.f(0) or {
312 assert err.msg() == '0'
313 return
314 }
315}
316
317type AA = BB | CC
318
319struct BB {
320 str string
321}
322
323struct CC {
324 str string
325}
326
327fn option_sum_type(a int) !AA {
328 match a {
329 1 {
330 return BB{'Test'}
331 }
332 2 {
333 return CC{'Test'}
334 }
335 else {
336 return error('Wrong number')
337 }
338 }
339}
340
341fn test_option_sum_type() {
342 res1 := option_sum_type(1) or {
343 assert false
344 BB{}
345 }
346 res2 := option_sum_type(2) or {
347 assert false
348 CC{}
349 }
350 if res1 is BB {
351 assert res1.str == 'Test'
352 } else {
353 assert false
354 }
355 if res2 is CC {
356 assert res2.str == 'Test'
357 } else {
358 assert false
359 }
360 option_sum_type(3) or {
361 assert true
362 return
363 }
364 assert false
365}
366
367fn foo() ?int {
368 return 0
369}
370
371fn foo2() ?int {
372 for _ in 0 .. 5 {
373 return foo() or { continue }
374 }
375 return 0
376}
377
378fn test_return_or() {
379 x := foo2() or { return }
380 assert x == 0
381}
382
383// For issue #16058: cgen error: exists spaces in the name of the ?&C.struct
384fn get_opt_pointer_to_c_struct() ?&C.stat {
385 return none
386}
387
388fn test_option_ref_c_struct_gen() {
389 _ := get_opt_pointer_to_c_struct() or { &C.stat{} }
390}
391
392// For issue #16070: cgen error: missing * of option non-ref structs
393fn get_opt_to_c_struct() ?C.stat {
394 return none
395}
396
397fn test_option_c_struct_gen() {
398 _ := get_opt_to_c_struct() or { C.stat{} }
399}
400
401// For issue #16062: checker disallowed the return of voidptr(nil) in or block
402struct Bar {}
403
404fn get_bar(should_return_value bool) ?&Bar {
405 if should_return_value {
406 return unsafe { nil }
407 }
408 return none
409}
410
411fn test_allow_returning_an_optional_pointer_to_a_struct() {
412 a := get_bar(true)?
413 assert a == unsafe { nil }
414
415 x := get_bar(false) or {
416 assert true
417 unsafe { nil }
418 }
419 assert x == unsafe { nil }
420
421 get_bar(false) or { unsafe { nil } }
422 assert true
423}
424
425struct AFoo {
426mut:
427 name string
428}
429
430fn (mut f AFoo) opt_string(arr ?[]int) ?string {
431 return arr?.len.str()
432}
433
434fn test_creating_an_option_from_a_struct_value() {
435 mut m := ?AFoo(AFoo{})
436 assert m?.opt_string([1, 2, 3])? == '3'
437 m?.name = 'foo'
438 assert m?.name == 'foo'
439}
440