v2 / vlib / builtin / string_test.v
1749 lines · 1577 sloc · 42.44 KB · 3642cd580846f35344ea0c2248e74adc47ad4698
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4
5struct Foo {
6 bar int
7mut:
8 str string
9}
10
11fn test_add() {
12 mut a := 'a'
13 a += 'b'
14 assert a == ('ab')
15 a = 'a'
16 for i := 1; i < 1000; i++ {
17 a += 'b'
18 }
19 assert a.len == 1000
20 assert a.ends_with('bbbbb')
21 a += '123'
22 assert a.ends_with('3')
23}
24
25fn test_len_utf8() {
26 assert 'Vlang'.len_utf8() == 5
27 assert 'María'.len_utf8() == 5
28 assert '姓名'.len_utf8() == 2
29 assert 'Слово'.len_utf8() == 5
30 assert 'Λέξη'.len_utf8() == 4
31}
32
33fn test_is_pure_ascii() {
34 assert 'Vlang'.is_pure_ascii()
35 assert !'María'.is_pure_ascii()
36 assert !'姓名'.is_pure_ascii()
37 assert !'Слово'.is_pure_ascii()
38 assert !'Λέξη'.is_pure_ascii()
39}
40
41fn test_ends_with() {
42 a := 'browser.v'
43 assert a.ends_with('.v')
44
45 s := 'V Programming Language'
46 assert s.ends_with('guage') == true
47 assert s.ends_with('Language') == true
48 assert s.ends_with('Programming Language') == true
49 assert s.ends_with('V') == false
50}
51
52fn test_between() {
53 s := 'hello [man] how you doing'
54 assert s.find_between('[', ']') == 'man'
55 assert s.find_between('[', 'A') == ''
56 assert s.find_between('A', ']') == ''
57}
58
59fn test_compare() {
60 a := 'Music'
61 b := 'src'
62 assert b >= a
63}
64
65fn test_lt() {
66 a := ''
67 b := 'a'
68 c := 'a'
69 d := 'b'
70 e := 'aa'
71 f := 'ab'
72 assert a < b
73 assert !(b < c)
74 assert c < d
75 assert !(d < e)
76 assert c < e
77 assert e < f
78}
79
80fn test_ge() {
81 a := 'aa'
82 b := 'aa'
83 c := 'ab'
84 d := 'abc'
85 e := 'aaa'
86 assert b >= a
87 assert c >= b
88 assert d >= c
89 assert !(c >= d)
90 assert e >= a
91}
92
93fn test_compare_strings() {
94 a := 'aa'
95 b := 'aa'
96 c := 'ab'
97 d := 'abc'
98 e := 'aaa'
99 assert compare_strings(a, b) == 0
100 assert compare_strings(b, c) == -1
101 assert compare_strings(c, d) == -1
102 assert compare_strings(d, e) == 1
103 assert compare_strings(a, e) == -1
104 assert compare_strings(e, a) == 1
105}
106
107fn test_eq_with_freed_string() {
108 mut s := 'abc'.clone()
109 unsafe {
110 s.free()
111 }
112 assert (s == 'abc') == false
113 assert ('abc' == s) == false
114}
115
116fn test_eq_empty_with_freed_string() {
117 mut s := 'abc'.clone()
118 unsafe {
119 s.free()
120 }
121 assert (s == '') == true
122 assert ('' == s) == true
123}
124
125fn test_sort() {
126 mut vals := [
127 'arr',
128 'an',
129 'a',
130 'any',
131 ]
132 len := vals.len
133 vals.sort()
134 assert len == vals.len
135 assert vals[0] == 'a'
136 assert vals[1] == 'an'
137 assert vals[2] == 'any'
138 assert vals[3] == 'arr'
139}
140
141fn test_sort_reverse() {
142 mut vals := [
143 'arr',
144 'an',
145 'a',
146 'any',
147 ]
148 len := vals.len
149 vals.sort(b > a)
150 assert len == vals.len
151 assert vals[0] == 'a'
152 assert vals[1] == 'an'
153 assert vals[2] == 'any'
154 assert vals[3] == 'arr'
155}
156
157fn test_ranges() {
158 s := 'test'
159 s1 := s[0..20] or { 'both' }
160 s2 := s[..20] or { 'last' }
161 s3 := s[10..] or { 'first' }
162 s4 := ranges_propagate_both(s) or { 'both' }
163 s5 := ranges_propagate_last(s) or { 'last' }
164 s6 := ranges_propagate_first(s) or { 'first' }
165 assert s1 == 'both'
166 assert s2 == 'last'
167 assert s3 == 'first'
168 assert s4 == 'both'
169 assert s5 == 'last'
170 assert s6 == 'first'
171}
172
173fn ranges_propagate_first(s string) !string {
174 return s[10..]!
175}
176
177fn ranges_propagate_last(s string) !string {
178 return s[..20]!
179}
180
181fn ranges_propagate_both(s string) !string {
182 return s[1..20]!
183}
184
185fn test_split_nth() {
186 a := '1,2,3'
187 assert a.split(',').len == 3
188 assert a.split_nth(',', -1).len == 3
189 assert a.split_nth(',', 0).len == 3
190 assert a.split_nth(',', 1).len == 1
191 assert a.split_nth(',', 2).len == 2
192 assert a.split_nth(',', 10).len == 3
193 b := '1::2::3'
194 assert b.split('::').len == 3
195 assert b.split_nth('::', -1).len == 3
196 assert b.split_nth('::', 0).len == 3
197 assert b.split_nth('::', 1).len == 1
198 assert b.split_nth('::', 2).len == 2
199 assert b.split_nth('::', 10).len == 3
200 c := 'ABCDEF'
201 assert c.split('').len == 6
202 assert c.split_nth('', 3).len == 3
203 assert c.split_nth('BC', -1).len == 2
204 d := ','
205 assert d.split(',').len == 2
206 assert d.split_nth('', 3).len == 1
207 assert d.split_nth(',', -1).len == 2
208 assert d.split_nth(',', 3).len == 2
209 e := ',,,0,,,,,a,,b,'
210 assert e.split(',,').len == 5
211 assert e.split_nth(',,', 3).len == 3
212 assert e.split_nth(',', -1).len == 12
213 assert e.split_nth(',', 3).len == 3
214 f := '1:2:3'
215 assert f.split_nth(':', 2) == ['1', '2:3']
216 assert f.rsplit_nth(':', 2) == ['3', '1:2']
217 g := '123'
218 assert g.split_nth('', 2) == ['1', '23']
219 assert g.rsplit_nth('', 2) == ['3', '12']
220 h := ''
221 assert h.split_nth('', 2) == []
222 assert h.rsplit_nth('', 2) == []
223}
224
225fn test_rsplit_nth() {
226 a := '1,2,3'
227 assert a.rsplit(',').len == 3
228 assert a.rsplit_nth(',', -1).len == 3
229 assert a.rsplit_nth(',', 0).len == 3
230 assert a.rsplit_nth(',', 1).len == 1
231 assert a.rsplit_nth(',', 2).len == 2
232 assert a.rsplit_nth(',', 10).len == 3
233 b := '1::2::3'
234 assert b.rsplit('::').len == 3
235 assert b.rsplit_nth('::', -1).len == 3
236 assert b.rsplit_nth('::', 0).len == 3
237 assert b.rsplit_nth('::', 1).len == 1
238 assert b.rsplit_nth('::', 2).len == 2
239 assert b.rsplit_nth('::', 10).len == 3
240 c := 'ABCDEF'
241 assert c.rsplit('').len == 6
242 assert c.rsplit_nth('', 3).len == 3
243 assert c.rsplit_nth('BC', -1).len == 2
244 d := ','
245 assert d.rsplit(',').len == 2
246 assert d.rsplit_nth('', 3).len == 1
247 assert d.rsplit_nth(',', -1).len == 2
248 assert d.rsplit_nth(',', 3).len == 2
249 e := ',,,0,,,,,a,,b,'
250 assert e.rsplit(',,').len == 5
251 assert e.rsplit_nth(',,', 3).len == 3
252 assert e.rsplit_nth(',', -1).len == 12
253 assert e.rsplit_nth(',', 3).len == 3
254}
255
256fn test_split_nth_values() {
257 line := 'CMD=eprintln(phase=1)'
258
259 a0 := line.split_nth('=', 0)
260 assert a0.len == 3
261 assert a0[0] == 'CMD'
262 assert a0[1] == 'eprintln(phase'
263 assert a0[2] == '1)'
264
265 a1 := line.split_nth('=', 1)
266 assert a1.len == 1
267 assert a1[0] == 'CMD=eprintln(phase=1)'
268
269 a2 := line.split_nth('=', 2)
270 assert a2.len == 2
271 assert a2[0] == 'CMD'
272 assert a2[1] == 'eprintln(phase=1)'
273
274 a3 := line.split_nth('=', 3)
275 assert a3.len == 3
276 assert a3[0] == 'CMD'
277 assert a3[1] == 'eprintln(phase'
278 assert a3[2] == '1)'
279
280 a4 := line.split_nth('=', 4)
281 assert a4.len == 3
282 assert a4[0] == 'CMD'
283 assert a4[1] == 'eprintln(phase'
284 assert a4[2] == '1)'
285}
286
287fn test_rsplit_nth_values() {
288 line := 'CMD=eprintln(phase=1)'
289
290 a0 := line.rsplit_nth('=', 0)
291 assert a0.len == 3
292 assert a0[0] == '1)'
293 assert a0[1] == 'eprintln(phase'
294 assert a0[2] == 'CMD'
295
296 a1 := line.rsplit_nth('=', 1)
297 assert a1.len == 1
298 assert a1[0] == 'CMD=eprintln(phase=1)'
299
300 a2 := line.rsplit_nth('=', 2)
301 assert a2.len == 2
302 assert a2[0] == '1)'
303 assert a2[1] == 'CMD=eprintln(phase'
304
305 a3 := line.rsplit_nth('=', 3)
306 assert a3.len == 3
307 assert a0[0] == '1)'
308 assert a0[1] == 'eprintln(phase'
309 assert a0[2] == 'CMD'
310
311 a4 := line.rsplit_nth('=', 4)
312 assert a4.len == 3
313 assert a0[0] == '1)'
314 assert a0[1] == 'eprintln(phase'
315 assert a0[2] == 'CMD'
316}
317
318fn test_split() {
319 mut s := 'volt/twitch.v:34'
320 mut vals := s.split(':')
321 assert vals.len == 2
322 assert vals[0] == 'volt/twitch.v'
323 assert vals[1] == '34'
324 // /////////
325 s = '2018-01-01z13:01:02'
326 vals = s.split('z')
327 assert vals.len == 2
328 assert vals[0] == '2018-01-01'
329 assert vals[1] == '13:01:02'
330 // //////////
331 s = '4627a862c3dec29fb3182a06b8965e0025759e18___1530207969___blue'
332 vals = s.split('___')
333 assert vals.len == 3
334 assert vals[0] == '4627a862c3dec29fb3182a06b8965e0025759e18'
335 assert vals[1] == '1530207969'
336 assert vals[2] == 'blue'
337 // /////////
338 s = 'lalala'
339 vals = s.split('a')
340 assert vals.len == 4
341 assert vals[0] == 'l'
342 assert vals[1] == 'l'
343 assert vals[2] == 'l'
344 assert vals[3] == ''
345 // /////////
346 s = 'awesome'
347 a := s.split('')
348 assert a.len == 7
349 assert a[0] == 'a'
350 assert a[1] == 'w'
351 assert a[2] == 'e'
352 assert a[3] == 's'
353 assert a[4] == 'o'
354 assert a[5] == 'm'
355 assert a[6] == 'e'
356 // /////////
357 s = 'wavy turquoise bags'
358 vals = s.split(' bags')
359 assert vals.len == 2
360 assert vals[0] == 'wavy turquoise'
361 assert vals[1] == ''
362 // /////////
363 s = 'aaaa'
364 vals = s.split('aa')
365 assert vals.len == 3
366 assert vals[0] == ''
367 assert vals[1] == ''
368 assert vals[2] == ''
369}
370
371fn test_rsplit() {
372 mut s := 'volt/twitch.v:34'
373 mut vals := s.rsplit(':')
374 assert vals.len == 2
375 assert vals[0] == '34'
376 assert vals[1] == 'volt/twitch.v'
377 // /////////
378 s = '2018-01-01z13:01:02'
379 vals = s.rsplit('z')
380 assert vals.len == 2
381 assert vals[0] == '13:01:02'
382 assert vals[1] == '2018-01-01'
383 // //////////
384 s = '4627a862c3dec29fb3182a06b8965e0025759e18___1530207969___blue'
385 vals = s.rsplit('___')
386 assert vals.len == 3
387 assert vals[0] == 'blue'
388 assert vals[1] == '1530207969'
389 assert vals[2] == '4627a862c3dec29fb3182a06b8965e0025759e18'
390 // /////////
391 s = 'lalala'
392 vals = s.rsplit('a')
393 assert vals.len == 4
394 assert vals[0] == ''
395 assert vals[1] == 'l'
396 assert vals[2] == 'l'
397 assert vals[3] == 'l'
398 // /////////
399 s = 'awesome'
400 a := s.rsplit('')
401 assert a.len == 7
402 assert a[0] == 'e'
403 assert a[1] == 'm'
404 assert a[2] == 'o'
405 assert a[3] == 's'
406 assert a[4] == 'e'
407 assert a[5] == 'w'
408 assert a[6] == 'a'
409 // /////////
410 s = 'wavy turquoise bags'
411 vals = s.rsplit('wavy ')
412 assert vals.len == 2
413 assert vals[0] == 'turquoise bags'
414 assert vals[1] == ''
415}
416
417fn test_split_any() {
418 assert 'ABC'.split_any('') == ['A', 'B', 'C']
419 assert ''.split_any(' ') == []
420 assert ' '.split_any(' ') == ['']
421 assert ' '.split_any(' ') == ['', '']
422 assert 'Ciao come stai? '.split_any(' ') == ['Ciao', 'come', 'stai?']
423 assert 'Ciao+come*stai? '.split_any('+*') == ['Ciao', 'come', 'stai? ']
424 assert 'Ciao+come*stai? '.split_any('+* ') == ['Ciao', 'come', 'stai?']
425 assert 'first row\nsecond row'.split_any(' \n') == ['first', 'row', 'second', 'row']
426}
427
428fn test_rsplit_any() {
429 assert 'ABC'.rsplit_any('') == ['C', 'B', 'A']
430 assert ''.rsplit_any(' ') == []
431 assert ' '.rsplit_any(' ') == ['']
432 assert ' '.rsplit_any(' ') == ['', '']
433 assert ' Ciao come stai?'.rsplit_any(' ') == ['stai?', 'come', 'Ciao']
434 assert ' Ciao+come*stai?'.rsplit_any('+*') == ['stai?', 'come', ' Ciao']
435 assert ' Ciao+come*stai?'.rsplit_any('+* ') == ['stai?', 'come', 'Ciao']
436 assert 'first row\nsecond row'.rsplit_any(' \n') == ['row', 'second', 'row', 'first']
437}
438
439fn test_split_once() ? {
440 path1, ext1 := 'home/dir/lang.zip'.split_once('.')?
441 assert path1 == 'home/dir/lang'
442 assert ext1 == 'zip'
443 path2, ext2 := 'home/dir/lang.ts.dts'.split_once('.')?
444 assert path2 == 'home/dir/lang'
445 assert ext2 == 'ts.dts'
446 path3, ext3 := 'home/dir'.split_once('.') or { '', '' }
447 assert path3 == ''
448 assert ext3 == ''
449}
450
451fn test_rsplit_once() ? {
452 path1, ext1 := 'home/dir/lang.zip'.rsplit_once('.')?
453 assert path1 == 'home/dir/lang'
454 assert ext1 == 'zip'
455 path2, ext2 := 'home/dir/lang.ts.dts'.rsplit_once('.')?
456 assert path2 == 'home/dir/lang.ts'
457 assert ext2 == 'dts'
458 path3, ext3 := 'home/dir'.rsplit_once('.') or { '', '' }
459 assert path3 == ''
460 assert ext3 == ''
461}
462
463fn test_split_by_space() {
464 assert 'a b c'.split_by_space() == ['a', 'b', 'c']
465 assert ' a\t\tb\tc'.split_by_space() == ['a', 'b', 'c']
466 assert 'a b c \n\r'.split_by_space() == ['a', 'b', 'c']
467 assert '\ta b \t \tc \r\n'.split_by_space() == ['a', 'b', 'c']
468}
469
470fn test_is_bin() {
471 assert ''.is_bin() == false
472 assert '0b1'.is_bin() == true
473 assert '0b0'.is_bin() == true
474 assert '0b'.is_bin() == false
475 assert '-0b'.is_bin() == false
476 assert '-0b1'.is_bin() == true
477 assert '-0b0'.is_bin() == true
478 assert '-0b1101'.is_bin() == true
479 assert '-0b0101'.is_bin() == true
480 assert '-324'.is_bin() == false
481 assert '-0'.is_bin() == false
482 assert '0x1'.is_bin() == false
483 assert '0x1A'.is_bin() == false
484 assert '+0b1101'.is_bin() == true
485 assert '+0b1'.is_bin() == true
486 assert '-0x1'.is_bin() == false
487 assert '-0x1A'.is_bin() == false
488 assert '0x'.is_bin() == false
489 assert '0'.is_bin() == false
490 assert '0xFF'.is_bin() == false
491 assert '0xG'.is_bin() == false
492 assert '-'.is_bin() == false
493 assert '+'.is_bin() == false
494 assert '-0xFF'.is_bin() == false
495 assert '0.34'.is_bin() == false
496 assert '0o23'.is_bin() == false
497 assert 'vlang'.is_bin() == false
498}
499
500fn test_is_oct() {
501 assert ''.is_oct() == false
502 assert '0o0'.is_oct() == true
503 assert '0o1'.is_oct() == true
504 assert '0o2'.is_oct() == true
505 assert '-0o0'.is_oct() == true
506 assert '-0o1'.is_oct() == true
507 assert '-0o2'.is_oct() == true
508
509 assert '0o04'.is_oct() == true
510 assert '0o16'.is_oct() == true
511 assert '0o23'.is_oct() == true
512 assert '-0o05'.is_oct() == true
513 assert '-0o13'.is_oct() == true
514 assert '-0o22'.is_oct() == true
515
516 assert '0o8'.is_oct() == false
517 assert '0o9'.is_oct() == false
518 assert '-0o8'.is_oct() == false
519 assert '-0o9'.is_oct() == false
520 assert '0o84'.is_oct() == false
521 assert '0o96'.is_oct() == false
522 assert '-0o83'.is_oct() == false
523 assert '-0o2923'.is_oct() == false
524 assert '0b1'.is_oct() == false
525 assert '0b0'.is_oct() == false
526 assert '0b'.is_oct() == false
527 assert '-0b'.is_oct() == false
528 assert '-0b1'.is_oct() == false
529 assert '-0b0'.is_oct() == false
530 assert '-0b1101'.is_oct() == false
531 assert '+0o234'.is_oct() == true
532 assert '+0o432'.is_oct() == true
533 assert '-'.is_oct() == false
534 assert '+'.is_oct() == false
535 assert '-0b0101'.is_oct() == false
536 assert '-324'.is_oct() == false
537 assert '-0'.is_oct() == false
538 assert '0x1'.is_oct() == false
539 assert '0x1A'.is_oct() == false
540 assert '-0x1'.is_oct() == false
541 assert '-0x1A'.is_oct() == false
542 assert '0x'.is_oct() == false
543 assert '0'.is_oct() == false
544 assert '0xFF'.is_oct() == false
545 assert '0xG'.is_oct() == false
546 assert '-0xFF'.is_oct() == false
547 assert '0.34'.is_oct() == false
548 assert 'vlang'.is_oct() == false
549}
550
551fn test_is_hex() {
552 assert ''.is_hex() == false
553 assert '-324'.is_hex() == false
554 assert '-0'.is_hex() == false
555 assert '0x1'.is_hex() == true
556 assert '0x1A'.is_hex() == true
557 assert '-0x1'.is_hex() == true
558 assert '-0x1A'.is_hex() == true
559 assert '+0x1'.is_hex() == true
560 assert '+0x1A'.is_hex() == true
561 assert '0x'.is_hex() == false
562 assert '0'.is_hex() == false
563 assert '-'.is_hex() == false
564 assert '+'.is_hex() == false
565 assert '0xFF'.is_hex() == true
566 assert '0xG'.is_hex() == false
567 assert '-0xFF'.is_hex() == true
568 assert '0b1101'.is_hex() == false
569 assert '0.34'.is_hex() == false
570 assert '0o23'.is_hex() == false
571 assert 'vlang'.is_hex() == false
572}
573
574fn test_is_int() {
575 assert ''.is_int() == false
576 assert '-324'.is_int() == true
577 assert '234'.is_int() == true
578 assert '-0'.is_int() == true
579 assert '-b'.is_int() == false
580 assert '-123456789'.is_int() == true
581 assert '123456789'.is_int() == true
582 assert '0x1'.is_int() == false
583 assert '0b1101'.is_int() == false
584 assert '0.34'.is_int() == false
585 assert '0o23'.is_int() == false
586 assert 'vlang'.is_int() == false
587
588 assert '0o0'.is_int() == false
589 assert '0o1'.is_int() == false
590 assert '0o2'.is_int() == false
591 assert '-0o0'.is_int() == false
592 assert '-0o1'.is_int() == false
593 assert '-0o2'.is_int() == false
594
595 assert '0o04'.is_int() == false
596 assert '0o16'.is_int() == false
597 assert '0o23'.is_int() == false
598 assert '-0o05'.is_int() == false
599 assert '-0o13'.is_int() == false
600 assert '-0o22'.is_int() == false
601
602 assert '0o8'.is_int() == false
603 assert '0o9'.is_int() == false
604 assert '-0o8'.is_int() == false
605 assert '-0o9'.is_int() == false
606 assert '0o84'.is_int() == false
607 assert '0o96'.is_int() == false
608 assert '-0o83'.is_int() == false
609 assert '-0o2923'.is_int() == false
610 assert '0b1'.is_int() == false
611 assert '0b0'.is_int() == false
612 assert '0b'.is_int() == false
613 assert '-0b'.is_int() == false
614 assert '-0b1'.is_int() == false
615 assert '-0b0'.is_int() == false
616 assert '-0b1101'.is_int() == false
617 assert '-0b0101'.is_int() == false
618 assert '-324'.is_int() == true
619 assert '-0'.is_int() == true
620 assert '0x1'.is_int() == false
621 assert '0x1A'.is_int() == false
622 assert '-0x1'.is_int() == false
623 assert '-0x1A'.is_oct() == false
624 assert '0x'.is_int() == false
625 assert '0'.is_int() == true
626 assert '0xFF'.is_int() == false
627 assert '0xG'.is_int() == false
628 assert '-0xFF'.is_int() == false
629 assert '0.34'.is_int() == false
630 assert '-'.is_int() == false
631 assert '+'.is_int() == false
632 assert '+3'.is_int() == true
633 assert '+3232'.is_int() == true
634}
635
636fn test_trim_space() {
637 a := ' a '
638 assert a.trim_space() == 'a'
639 assert a.trim_space_left() == 'a '
640 assert a.trim_space_right() == ' a'
641
642 code := '
643\t
644fn main() {
645 println(2)
646}
647
648'
649 code_clean := 'fn main() {
650 println(2)
651}'
652 code_trim_right := '
653\t
654fn main() {
655 println(2)
656}'
657 code_trim_left := 'fn main() {
658 println(2)
659}
660
661'
662 assert code.trim_space() == code_clean
663 assert code.trim_space_right() == code_trim_right
664 assert code.trim_space_left() == code_trim_left
665}
666
667fn test_join() {
668 mut strs := ['a', 'b', 'c']
669 mut s := strs.join(' ')
670 assert s == 'a b c'
671 strs = [
672 'one
673two ',
674 'three!
675four!',
676 ]
677 s = strs.join(' ')
678 assert s.contains('one') && s.contains('two ') && s.contains('four')
679 empty := []string{len: 0}
680 assert empty.join('A') == ''
681}
682
683fn test_clone() {
684 mut a := 'a'
685 a += 'a'
686 a += 'a'
687 b := a
688 c := a.clone()
689 assert c == a
690 assert c == 'aaa'
691 assert b == 'aaa'
692}
693
694fn test_replace() {
695 a := 'hello man!'
696 mut b := a.replace('man', 'world')
697 assert b == ('hello world!')
698 b = b.replace('!', '')
699 assert b == ('hello world')
700 b = b.replace('h', 'H')
701 assert b == ('Hello world')
702 b = b.replace('foo', 'bar')
703 assert b == ('Hello world')
704 s := 'hey man how are you'
705 assert s.replace('man ', '') == 'hey how are you'
706 lol := 'lol lol lol'
707 assert lol.replace('lol', 'LOL') == 'LOL LOL LOL'
708 b = 'oneBtwoBBthree'
709 assert b.replace('B', '') == 'onetwothree'
710 b = '*charptr'
711 assert b.replace('charptr', 'byteptr') == '*byteptr'
712 c := 'abc'
713 assert c.replace('', '-') == c
714 v := 'a b c d'
715 assert v.replace(' ', ' ') == 'a b c d'
716}
717
718fn test_replace_each() {
719 s := 'hello man man :)'
720 q := s.replace_each([
721 'man',
722 'dude',
723 'hello',
724 'hey',
725 ])
726 assert q == 'hey dude dude :)'
727 bb := '[b]bold[/b] [code]code[/code]'
728 assert bb.replace_each([
729 '[b]',
730 '<b>',
731 '[/b]',
732 '</b>',
733 '[code]',
734 '<code>',
735 '[/code]',
736 '</code>',
737 ]) == '<b>bold</b> <code>code</code>'
738 bb2 := '[b]cool[/b]'
739 assert bb2.replace_each([
740 '[b]',
741 '<b>',
742 '[/b]',
743 '</b>',
744 ]) == '<b>cool</b>'
745 t := 'aaaaaaaa'
746 y := t.replace_each([
747 'aa',
748 'b',
749 ])
750 assert y == 'bbbb'
751 s2 := 'hello_world hello'
752 assert s2.replace_each(['hello_world', 'aaa', 'hello', 'bbb']) == 'aaa bbb'
753}
754
755fn test_format() {
756 template := 'First: {0}, First again: {0}, Second: {1}, Third: {2}'
757 assert template.format('A', 'B', 'C') == 'First: A, First again: A, Second: B, Third: C'
758 assert template.format('R', 'G', 'B') == 'First: R, First again: R, Second: G, Third: B'
759 assert 'Escaped {{0}} and {{braces}}'.format('unused') == 'Escaped {0} and {braces}'
760 assert '{0} {3} {1}'.format('A', 'B') == 'A {3} B'
761 assert '{10}-{2}'.format('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10') == '10-2'
762 assert 'keep {name} and {1'.format('A', 'B') == 'keep {name} and {1'
763}
764
765fn test_replace_char() {
766 assert 'azert'.replace_char(`z`, `s`, 2) == 'assert'
767 assert '\rHello!\r'.replace_char(`\r`, `\n`, 1) == '\nHello!\n'
768 assert 'Hello!'.replace_char(`l`, `e`, 4) == 'Heeeeeeeeeo!'
769 assert '1141'.replace_char(`1`, `8`, 2) == '8888488'
770}
771
772fn test_normalize_tabs() {
773 assert '\t\tHello!'.normalize_tabs(4) == ' Hello!'
774 assert '\t\tHello!\t; greeting'.normalize_tabs(1) == ' Hello! ; greeting'
775}
776
777fn test_expand_tabs() {
778 assert 'AB\tHello!'.expand_tabs(4) == 'AB Hello!'
779 assert 'AB\t\tHello!\t; greeting'.expand_tabs(4) == 'AB Hello! ; greeting'
780}
781
782fn test_itoa() {
783 num := 777
784 assert num.str() == '777'
785 big := 7779998
786 assert big.str() == '7779998'
787 a := 3
788 assert a.str() == '3'
789 b := 5555
790 assert b.str() == '5555'
791 zero := 0
792 assert zero.str() == '0'
793 neg := -7
794 assert neg.str() == '-7'
795}
796
797fn test_reassign() {
798 a := 'hi'
799 mut b := a
800 b += '!'
801 assert a == 'hi'
802 assert b == 'hi!'
803}
804
805fn test_runes() {
806 s := 'привет'
807 assert s.len == 12
808 s2 := 'privet'
809 assert s2.len == 6
810 u := s.runes()
811 assert u.len == 6
812 assert s2.substr(1, 4).len == 3
813 assert s2.substr(1, 4) == 'riv'
814 assert s2[1..4].len == 3
815 assert s2[1..4] == 'riv'
816 assert s2[..4].len == 4
817 assert s2[..4] == 'priv'
818 assert s2[2..].len == 4
819 assert s2[2..] == 'ivet'
820 assert u[1..4].string().len == 6
821 assert u[1..4].string() == 'рив'
822 assert s2.substr(1, 2) == 'r'
823 assert u[1..2].string() == 'р'
824 assert s2.runes()[1] == `r`
825 assert u[1] == `р`
826 first := u[0]
827 last := u[u.len - 1]
828 assert first.str().len == 2
829 assert last.str().len == 2
830}
831
832fn test_contains() {
833 s := 'view.v'
834 assert s.contains('vi')
835 assert !s.contains('random')
836 assert ''.contains('')
837 assert 'abc'.contains('')
838}
839
840fn test_contains_any() {
841 assert !'team'.contains_any('i')
842 assert 'fail'.contains_any('ui')
843 assert 'ure'.contains_any('ui')
844 assert 'failure'.contains_any('ui')
845 assert !'foo'.contains_any('')
846 assert !''.contains_any('')
847}
848
849fn test_contains_only() {
850 assert '23885'.contains_only('0123456789')
851 assert '23gg885'.contains_only('01g23456789')
852 assert !'hello;'.contains_only('hello')
853 assert !''.contains_only('')
854}
855
856fn test_contains_any_substr() {
857 s := 'Some random text'
858 assert s.contains_any_substr(['false', 'not', 'rand'])
859 assert !s.contains_any_substr(['ABC', 'invalid'])
860 assert ''.contains_any_substr([])
861 assert 'abc'.contains_any_substr([''])
862}
863
864fn test_arr_contains() {
865 a := ['a', 'b', 'c']
866 assert a.contains('b')
867 ints := [1, 2, 3]
868 assert ints.contains(2)
869}
870
871fn test_to_num() {
872 s := '7'
873 assert s.int() == 7
874 assert s.u8() == 7
875 assert s.u64() == 7
876 f := '71.5 hasdf'
877 // QTODO
878 assert f.f32() == 71.5
879 vals := ['9']
880 assert vals[0].int() == 9
881 big := '93993993939322'
882 assert big.u64() == 93993993939322
883 assert big.i64() == 93993993939322
884}
885
886fn test_to_u8_array() {
887 // empty string
888 assert ''.u8_array() == []
889 assert '0x'.u8_array() == []
890 assert '0X'.u8_array() == []
891 assert '0b'.u8_array() == []
892 assert '0B'.u8_array() == []
893 // invalid digit
894 assert '-123'.u8_array() == []
895 assert '1_2xt'.u8_array() == []
896 assert 'd1_2xt'.u8_array() == []
897
898 // ---------------------------------
899 // hex test
900 // invalid hex digit
901 assert '0X-123'.u8_array() == []
902 assert '0O12'.u8_array() == []
903 // odd number of digits
904 assert '0x1'.u8_array() == [u8(0x01)]
905 assert '0x123'.u8_array() == [u8(0x01), 0x23]
906 assert '0x1_23'.u8_array() == [u8(0x01), 0x23]
907
908 // long digits
909 long_u8 := [u8(0x00), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
910 0xdd, 0xee, 0xff]
911 assert '0x00112233445566778899aabbccddeeff'.u8_array() == long_u8
912 assert '0x00_112_2334455667788_99aabbccddeeff'.u8_array() == long_u8
913 assert '0x00112233445566778899AABBCCDDEEFF'.u8_array() == long_u8
914 assert '0x001_12233445566778899A_ABBCCDDEEFF'.u8_array() == long_u8
915
916 // ---------------------------------
917 // bin test
918 // invalid bin digit
919 assert '0b-123'.u8_array() == []
920 assert '0B12'.u8_array() == []
921 // not enough length
922 assert '0b0'.u8_array() == [u8(0x00)]
923 assert '0b1'.u8_array() == [u8(0x01)]
924 assert '0b101'.u8_array() == [u8(0x05)]
925 assert '0b0101'.u8_array() == [u8(0x05)]
926 // long digits
927 assert '0b0101_0101'.u8_array() == [u8(0x55)]
928 assert '0b0101010110101010'.u8_array() == [u8(0x55), 0xaa]
929 assert '0b0101010110101010_0101010110101010'.u8_array() == [u8(0x55), 0xaa, 0x55, 0xaa]
930}
931
932fn test_inter_format_string() {
933 float_num := 1.52345
934 float_num_string := '-${float_num:.3f}-'
935 assert float_num_string == '-1.523-'
936 int_num := 7
937 int_num_string := '-${int_num:03d}-'
938 assert int_num_string == '-007-'
939 ch := `a`
940 ch_string := '-${ch:c}-'
941 assert ch_string == '-a-'
942 hex_n := 192
943 hex_n_string := '-${hex_n:x}-'
944 assert hex_n_string == '-c0-'
945 oct_n := 192
946 oct_n_string := '-${oct_n:o}-'
947 assert oct_n_string == '-300-'
948 str := 'abc'
949 str_string := '-${str:s}-'
950 assert str_string == '-abc-'
951}
952
953fn test_hash() {
954 s := '10000'
955 assert s.hash() == 46730161
956 s2 := '24640'
957 assert s2.hash() == 47778736
958 s3 := 'Content-Type'
959 assert s3.hash() == 949037134
960 s4 := 'bad_key'
961 assert s4.hash() == $if new_int ? && x64 {
962 3948330789
963 } $else {
964 -346636507
965 }
966 s5 := '24640'
967 // From a map collision test
968 assert s5.hash() % ((1 << 20) - 1) == s.hash() % ((1 << 20) - 1)
969 assert s5.hash() % ((1 << 20) - 1) == 592861
970}
971
972fn test_trim() {
973 assert 'banana'.trim('bna') == ''
974 assert 'abc'.trim('ac') == 'b'
975 assert 'aaabccc'.trim('ac') == 'b'
976 assert 'あいうえお'.trim('あい') == 'うえお'
977}
978
979fn test_trim_indexes() {
980 mut left, mut right := 0, 0
981 left, right = '- -- - '.trim_indexes(' -')
982 assert left == 0 && right == 0
983 left, right = '- hello-world!\t'.trim_indexes(' -\t')
984 assert left == 2 && right == 14
985 left, right = 'abc'.trim_indexes('ac')
986 assert left == 1 && right == 2
987}
988
989fn test_trim_left() {
990 mut s := 'module main'
991 assert s.trim_left(' ') == 'module main'
992 s = ' module main'
993 assert s.trim_left(' ') == 'module main'
994 // test cutset
995 s = 'banana'
996 assert s.trim_left('ba') == 'nana'
997 assert s.trim_left('ban') == ''
998 assert 'あいうえお'.trim_left('あい') == 'うえお'
999}
1000
1001fn test_trim_right() {
1002 mut s := 'module main'
1003 assert s.trim_right(' ') == 'module main'
1004 s = 'module main '
1005 assert s.trim_right(' ') == 'module main'
1006 // test cutset
1007 s = 'banana'
1008 assert s.trim_right('na') == 'b'
1009 assert s.trim_right('ban') == ''
1010 assert 'あいうえお'.trim_right('うえお') == 'あい'
1011}
1012
1013fn test_all_before() {
1014 s := 'fn hello fn'
1015 assert s.all_before(' ') == 'fn'
1016 assert s.all_before('2') == s
1017 assert s.all_before('') == s
1018}
1019
1020fn test_all_before_last() {
1021 s := 'fn hello fn'
1022 assert s.all_before_last(' ') == 'fn hello'
1023 assert s.all_before_last('2') == s
1024 assert s.all_before_last('') == s
1025}
1026
1027fn test_all_after() {
1028 s := 'fn hello'
1029 assert s.all_after('fn ') == 'hello'
1030 assert s.all_after('test') == s
1031 assert s.all_after('') == s
1032 assert s.after('e') == 'llo'
1033 x := s.after('e')
1034 assert x == 'llo'
1035}
1036
1037fn test_reverse() {
1038 assert 'hello'.reverse() == 'olleh'
1039 assert ''.reverse() == ''
1040 assert 'a'.reverse() == 'a'
1041}
1042
1043fn test_bytes_to_string() {
1044 mut buf := vcalloc(10)
1045 unsafe {
1046 buf[0] = `h`
1047 buf[1] = `e`
1048 buf[2] = `l`
1049 buf[3] = `l`
1050 buf[4] = `o`
1051 }
1052 assert unsafe { buf.vstring() } == 'hello'
1053 assert unsafe { buf.vstring_with_len(2) } == 'he'
1054 bytes := [u8(`h`), `e`, `l`, `l`, `o`]
1055 assert bytes.bytestr() == 'hello'
1056}
1057
1058fn test_charptr() {
1059 foo := &char(c'VLANG')
1060 assert typeof(foo).name == '&char'
1061 assert unsafe { foo.vstring() } == 'VLANG'
1062 assert unsafe { foo.vstring_with_len(3) } == 'VLA'
1063}
1064
1065fn test_count() {
1066 assert ''.count('') == 0
1067 assert ''.count('a') == 0
1068 assert 'a'.count('') == 0
1069 assert 'aa'.count('a') == 2
1070 assert 'aa'.count('aa') == 1
1071 assert 'aabbaa'.count('aa') == 2
1072 assert 'bbaabb'.count('aa') == 1
1073}
1074
1075fn test_lower() {
1076 mut s := 'A'
1077 assert !s.is_lower()
1078 assert s.to_lower() == 'a'
1079 assert s.to_lower().len == 1
1080 s = 'HELLO'
1081 assert !s.is_lower()
1082 assert s.to_lower() == 'hello'
1083 assert s.to_lower().len == 5
1084 s = 'Aloha'
1085 assert !s.is_lower()
1086 assert s.to_lower() == 'aloha'
1087 s = 'Have A nice Day!'
1088 assert !s.is_lower()
1089 assert s.to_lower() == 'have a nice day!'
1090 s = 'hi'
1091 assert s.is_lower()
1092 assert s.to_lower() == 'hi'
1093 assert 'aloha!'[0] == `a`
1094 assert 'aloha!'[5] == `!`
1095 s = '123'
1096 assert !s.is_lower()
1097 assert s.to_lower() == '123'
1098 s = ''
1099 assert !s.is_lower()
1100}
1101
1102fn test_lower_ascii() {
1103 mut s := 'A'
1104 assert !s.is_lower()
1105 assert s.to_lower_ascii() == 'a'
1106 assert s.to_lower_ascii().len == 1
1107 s = 'HELLO'
1108 assert !s.is_lower()
1109 assert s.to_lower_ascii() == 'hello'
1110 assert s.to_lower_ascii().len == 5
1111 s = 'Aloha'
1112 assert !s.is_lower()
1113 assert s.to_lower_ascii() == 'aloha'
1114 s = 'Have A nice Day!'
1115 assert !s.is_lower()
1116 assert s.to_lower_ascii() == 'have a nice day!'
1117 s = 'hi'
1118 assert s.is_lower()
1119 assert s.to_lower_ascii() == 'hi'
1120 assert 'aloha!'[0] == `a`
1121 assert 'aloha!'[5] == `!`
1122 s = '123'
1123 assert !s.is_lower()
1124 assert s.to_lower_ascii() == '123'
1125 s = ''
1126 assert !s.is_lower()
1127}
1128
1129fn test_upper() {
1130 mut s := 'a'
1131 assert !s.is_upper()
1132 assert s.to_upper() == 'A'
1133 assert s.to_upper().len == 1
1134 s = 'hello'
1135 assert !s.is_upper()
1136 assert s.to_upper() == 'HELLO'
1137 assert s.to_upper().len == 5
1138 s = 'Aloha'
1139 assert !s.is_upper()
1140 assert s.to_upper() == 'ALOHA'
1141 s = 'have a nice day!'
1142 assert !s.is_upper()
1143 assert s.to_upper() == 'HAVE A NICE DAY!'
1144 s = 'HI'
1145 assert s.is_upper()
1146 assert s.to_upper() == 'HI'
1147 s = '1, 2, 3, 4 GO!'
1148 assert s.is_upper()
1149 assert s.to_upper() == '1, 2, 3, 4 GO!'
1150 s = '123'
1151 assert !s.is_upper()
1152 assert s.to_upper() == '123'
1153 s = ''
1154 assert !s.is_upper()
1155}
1156
1157fn test_upper_ascii() {
1158 mut s := 'a'
1159 assert !s.is_upper()
1160 assert s.to_upper_ascii() == 'A'
1161 assert s.to_upper_ascii().len == 1
1162 s = 'hello'
1163 assert !s.is_upper()
1164 assert s.to_upper_ascii() == 'HELLO'
1165 assert s.to_upper_ascii().len == 5
1166 s = 'Aloha'
1167 assert !s.is_upper()
1168 assert s.to_upper_ascii() == 'ALOHA'
1169 s = 'have a nice day!'
1170 assert !s.is_upper()
1171 assert s.to_upper_ascii() == 'HAVE A NICE DAY!'
1172 s = 'HI'
1173 assert s.is_upper()
1174 assert s.to_upper_ascii() == 'HI'
1175 s = '123'
1176 assert !s.is_upper()
1177 assert s.to_upper_ascii() == '123'
1178 s = ''
1179 assert !s.is_upper()
1180}
1181
1182fn test_runes_to_upper() {
1183 assert 'água'.to_upper() == 'ÁGUA'
1184}
1185
1186fn test_runes_to_lower() {
1187 assert 'ÁGUA'.to_lower() == 'água'
1188}
1189
1190fn test_capitalize() {
1191 assert ''.capitalize() == ''
1192 assert 'a'.capitalize() == 'A'
1193 assert 'A'.capitalize() == 'A'
1194 mut s := 'hello'
1195 assert !s.is_capital()
1196 assert s.capitalize() == 'Hello'
1197 s = 'test'
1198 assert !s.is_capital()
1199 assert s.capitalize() == 'Test'
1200 s = 'i am ray'
1201 assert !s.is_capital()
1202 assert s.capitalize() == 'I am ray'
1203 s = ''
1204 assert !s.is_capital()
1205 assert s.capitalize() == ''
1206 s = 'TEST IT'
1207 assert !s.is_capital()
1208 assert s.capitalize() == 'TEST IT'
1209 s = 'Test it'
1210 assert s.is_capital()
1211 assert s.capitalize() == 'Test it'
1212 assert 'GameMission_t'.capitalize() == 'GameMission_t'
1213 assert 'чорба'.capitalize() == 'Чорба'
1214 assert 'ä ö å æ ã ø ô é ë'.title() == 'Ä Ö Å Æ Ã Ø Ô É Ë'
1215}
1216
1217fn test_uncapitalize() {
1218 assert ''.uncapitalize() == ''
1219 assert 'a'.uncapitalize() == 'a'
1220 assert 'A'.uncapitalize() == 'a'
1221 assert 'hello'.uncapitalize() == 'hello'
1222 assert 'Hello'.uncapitalize() == 'hello'
1223 assert 'HELLO'.uncapitalize() == 'hELLO'
1224 assert 'чорба'.uncapitalize() == 'чорба'
1225 assert 'Чорба'.uncapitalize() == 'чорба'
1226 assert 'ЧОРБА'.uncapitalize() == 'чОРБА'
1227}
1228
1229fn test_title() {
1230 mut s := 'hello world'
1231 assert !s.is_title()
1232 assert s.title() == 'Hello World'
1233 s = 'HELLO WORLD'
1234 assert !s.is_title()
1235 assert s.title() == 'HELLO WORLD'
1236 s = 'Hello World'
1237 assert s.is_title()
1238 assert s.title() == 'Hello World'
1239 assert 'пет корита ябълки'.title() == 'Пет Корита Ябълки'
1240}
1241
1242fn test_for_loop() {
1243 mut i := 0
1244 s := 'abcd'
1245
1246 for c in s {
1247 assert c == s[i]
1248 i++
1249 }
1250}
1251
1252fn test_for_loop_two() {
1253 s := 'abcd'
1254
1255 for i, c in s {
1256 assert c == s[i]
1257 }
1258}
1259
1260fn test_quote() {
1261 a := `'`
1262 b := 'hi'
1263 assert b == 'hi'
1264 assert a.str() == "'"
1265}
1266
1267fn test_limit() {
1268 s := 'hello'
1269 assert s.limit(2) == 'he'
1270 assert s.limit(9) == s
1271 assert s.limit(0) == ''
1272 // assert s.limit(-1) == ''
1273}
1274
1275fn test_repeat() {
1276 s1 := 'V! '
1277 assert s1.repeat(5) == 'V! V! V! V! V! '
1278 assert s1.repeat(1) == s1
1279 assert s1.repeat(0) == ''
1280 s2 := ''
1281 assert s2.repeat(5) == s2
1282 assert s2.repeat(1) == s2
1283 assert s2.repeat(0) == s2
1284 // TODO: Add test for negative values
1285}
1286
1287fn test_starts_with() {
1288 s := 'V Programming Language'
1289 assert s.starts_with('V') == true
1290 assert s.starts_with('V Programming') == true
1291 assert s.starts_with('Language') == false
1292}
1293
1294fn test_starts_with_capital() {
1295 assert 'A sentence'.starts_with_capital()
1296 assert 'A paragraph. It also does.'.starts_with_capital()
1297 assert ''.starts_with_capital() == false
1298 assert 'no'.starts_with_capital() == false
1299 assert ' No'.starts_with_capital() == false
1300}
1301
1302fn test_trim_string_left() {
1303 s := 'V Programming Language'
1304 assert s.trim_string_left('V ') == 'Programming Language'
1305 assert s.trim_string_left('V Programming ') == 'Language'
1306 assert s.trim_string_left('Language') == s
1307
1308 s2 := 'TestTestTest'
1309 assert s2.trim_string_left('Test') == 'TestTest'
1310 assert s2.trim_string_left('TestTest') == 'Test'
1311
1312 s3 := '123Test123Test'
1313 assert s3.trim_string_left('123') == 'Test123Test'
1314 assert s3.trim_string_left('123Test') == '123Test'
1315}
1316
1317fn test_trim_string_right() {
1318 s := 'V Programming Language'
1319 assert s.trim_string_right(' Language') == 'V Programming'
1320 assert s.trim_string_right(' Programming Language') == 'V'
1321 assert s.trim_string_right('V') == s
1322
1323 s2 := 'TestTestTest'
1324 assert s2.trim_string_right('Test') == 'TestTest'
1325 assert s2.trim_string_right('TestTest') == 'Test'
1326
1327 s3 := '123Test123Test'
1328 assert s3.trim_string_right('123') == s3
1329 assert s3.trim_string_right('123Test') == '123Test'
1330}
1331
1332fn test_raw() {
1333 raw := r'raw\nstring'
1334 lines := raw.split('\n')
1335 assert lines.len == 1
1336
1337 raw2 := r'Hello V\0'
1338 assert raw2[7] == `\\`
1339 assert raw2[8] == `0`
1340
1341 raw3 := r'Hello V\x00'
1342 assert raw3[7] == `\\`
1343 assert raw3[8] == `x`
1344 assert raw3[9] == `0`
1345 assert raw3[10] == `0`
1346}
1347
1348fn test_raw_with_quotes() {
1349 raw := r"some'" + r'"thing' // " should be escaped in the generated C code
1350 assert raw[0] == `s`
1351 assert raw[5] == `"`
1352 assert raw[6] == `t`
1353}
1354
1355fn test_escape() {
1356 a := 10
1357 assert "\"${a}" == '"10'
1358}
1359
1360fn test_atoi() {
1361 assert '234232'.int() == 234232
1362 assert '-9009'.int() == -9009
1363 assert '0'.int() == 0
1364 for n in -10000 .. 100000 {
1365 s := n.str()
1366 assert s.int() == n
1367 }
1368}
1369
1370fn test_raw_inter() {
1371 world := 'world'
1372 s := r'hello\n$world'
1373 assert s == r'hello\n$world'
1374 assert s.contains('$')
1375}
1376
1377fn test_c_r() {
1378 // This used to break because of r'' and c''
1379 c := 42
1380 cs := '${c}'
1381 r := 50
1382 rs := '${r}'
1383}
1384
1385fn test_inter_before_comptime_if() {
1386 s := '123'
1387 // This used to break ('123 $....')
1388 $if linux {
1389 }
1390 assert s == '123'
1391}
1392
1393fn test_double_quote_inter() {
1394 a := 1
1395 b := 2
1396 assert '${a} ${b}' == '1 2'
1397 assert '${a} ${b}' == '1 2'
1398}
1399
1400fn foo(b u8) u8 {
1401 return b - 10
1402}
1403
1404fn filter(b u8) bool {
1405 return b != `a`
1406}
1407
1408fn test_split_into_lines() {
1409 line_content := 'line content'
1410
1411 text_cr := '${line_content}\r${line_content}\r${line_content}'
1412 lines_cr := text_cr.split_into_lines()
1413
1414 assert lines_cr.len == 3
1415 for line in lines_cr {
1416 assert line == line_content
1417 }
1418
1419 text_crlf := '${line_content}\r\n${line_content}\r\n${line_content}'
1420 lines_crlf := text_crlf.split_into_lines()
1421
1422 assert lines_crlf.len == 3
1423 for line in lines_crlf {
1424 assert line == line_content
1425 }
1426
1427 text_lf := '${line_content}\n${line_content}\n${line_content}'
1428 lines_lf := text_lf.split_into_lines()
1429
1430 assert lines_lf.len == 3
1431 for line in lines_lf {
1432 assert line == line_content
1433 }
1434
1435 text_mixed := '${line_content}\n${line_content}\r${line_content}'
1436 lines_mixed := text_mixed.split_into_lines()
1437
1438 assert lines_mixed.len == 3
1439 for line in lines_mixed {
1440 assert line == line_content
1441 }
1442
1443 text_mixed_trailers := '${line_content}\n${line_content}\r${line_content}\r\r\r\n\n\n\r\r'
1444 lines_mixed_trailers := text_mixed_trailers.split_into_lines()
1445
1446 assert lines_mixed_trailers.len == 9
1447 for line in lines_mixed_trailers {
1448 assert line == line_content || line == ''
1449 }
1450}
1451
1452const single_backslash = '\\'
1453const double_backslash = '\\\\'
1454const newline = '\n'
1455
1456// vfmt off
1457fn test_string_literal_with_backslash_followed_by_newline() {
1458 // Note `\` is followed *directly* by a newline, then some more whitespace, then a non whitespace string.
1459 // In this case, the \ is treated as line breaking, and the whitespace after that on the new line,
1460 // should be just ignored.
1461 //
1462 // See also https://doc.rust-lang.org/reference/tokens.html#string-literals
1463 // >> Both byte sequences are normally translated to U+000A, but as a special exception,
1464 // when an unescaped U+005C character occurs immediately before the line-break,
1465 // the U+005C character, the line-break, and all whitespace at the beginning of the
1466 // next line are ignored.
1467 a := 'Hello\
1468 World'
1469 assert a == 'HelloWorld'
1470
1471 // Here, `\\\` means `\\` followed by `\`, followed by a newline.
1472 // the first is a single escaped \, that should go into the literal, the second together with
1473 // the newline and the whitespace after it, is a line-break, and should be simply ignored.
1474 // Same with `\\\\\`, which is `\\\\`, followed by `\`, i.e. an escaped double backslash,
1475 // and a line-break after it:
1476 b := 'One \
1477 Two Three \\\
1478 Four \\\\
1479 Five \\\\\
1480 end'
1481 assert b == 'One Two Three ${single_backslash}Four ${double_backslash}${newline} Five ${double_backslash}end'
1482
1483 // Note `\\` is followed *directly* by a newline, but `\\` is just an escape for `\`,
1484 // and thus the newline has no special meaning, and should go into the string literal.
1485 c := 'Hello\\
1486 World'
1487 assert c == 'Hello\\\n World'
1488
1489 d := 'One\\
1490 Two Three \\
1491 Four'
1492 assert d == 'One\\\n Two Three \\\n Four'
1493}
1494// vfmt on
1495
1496type MyString = string
1497
1498fn test_string_alias() {
1499 s := MyString('hi')
1500 ss := s + '!'
1501 assert ss == 'hi!'
1502}
1503
1504// sort an array of structs, by their string field values
1505
1506struct Ka {
1507 s string
1508 i int
1509}
1510
1511fn test_sorter() {
1512 mut arr := [
1513 Ka{
1514 s: 'bbb'
1515 i: 100
1516 },
1517 Ka{
1518 s: 'aaa'
1519 i: 101
1520 },
1521 Ka{
1522 s: 'ccc'
1523 i: 102
1524 },
1525 ]
1526 cmp := fn (a &Ka, b &Ka) int {
1527 return compare_strings(a.s, b.s)
1528 }
1529 arr.sort_with_compare(cmp)
1530 assert arr[0].s == 'aaa'
1531 assert arr[0].i == 101
1532 assert arr[1].s == 'bbb'
1533 assert arr[1].i == 100
1534 assert arr[2].s == 'ccc'
1535 assert arr[2].i == 102
1536}
1537
1538fn test_fields() {
1539 assert 'a bcde'.fields() == ['a', 'bcde']
1540 assert ' sss \t ssss '.fields() == ['sss', 'ssss']
1541 assert '\n xyz \t abc def'.fields() == ['xyz', 'abc', 'def']
1542 assert 'hello'.fields() == ['hello']
1543 assert ''.fields() == []
1544}
1545
1546fn test_interpolation_after_quoted_variable_still_works() {
1547 rr := 'abc'
1548 tt := 'xyz'
1549
1550 // Basic interpolation, no internal quotes
1551 yy := 'Replacing ${rr} with ${tt}'
1552 assert yy == 'Replacing abc with xyz'
1553
1554 // Interpolation after quoted variable ending with 'r'quote
1555 // that may be mistaken with the start of a raw string,
1556 // ensure that it is not.
1557 ss := 'Replacing "${rr}" with "${tt}"'
1558 assert ss == 'Replacing "abc" with "xyz"'
1559 zz := "Replacing '${rr}' with '${tt}'"
1560 assert zz == "Replacing 'abc' with 'xyz'"
1561
1562 // Interpolation after quoted variable ending with 'c'quote
1563 // may be mistaken with the start of a c string, so
1564 // check it is not.
1565 cc := 'abc'
1566 ccc := "Replacing '${cc}' with '${tt}'"
1567 assert ccc == "Replacing 'abc' with 'xyz'"
1568 cccq := 'Replacing "${cc}" with "${tt}"'
1569 assert cccq == 'Replacing "abc" with "xyz"'
1570}
1571
1572fn test_emoji_to_runes() {
1573 x := '👋'
1574 assert x.runes()[0] == `👋`
1575}
1576
1577fn test_graphemes() {
1578 assert '\u006E\u0303'.graphemes() == ['ñ']
1579 assert '\U0001F3F3\uFE0F\u200D\U0001F308'.graphemes() == ['🏳️‍🌈']
1580 assert 'ห์'.graphemes() == ['ห์']
1581 assert 'ปีเตอร์'.graphemes() == ['ปี', 'เ', 'ต', 'อ', 'ร์']
1582 assert '🇺🇳'.graphemes() == ['🇺🇳']
1583 assert '👩🏽‍💻'.graphemes() == ['👩🏽‍💻']
1584 assert 'a\r\nb'.graphemes() == ['a', '\r\n', 'b']
1585}
1586
1587fn test_string_to_rune() {
1588 x := 'Hello World 👋'
1589 assert x.runes().len == 13
1590}
1591
1592fn test_index_any() {
1593 x := 'abcdefghij'
1594 assert x.index_any('ef') == 4
1595 assert x.index_any('fe') == 4
1596}
1597
1598fn test_string_f64() {
1599 assert ''.f64() == 0
1600 assert '123'.f64() == 123
1601 assert '-123'.f64() == -123
1602 assert '-123.456'.f64() == -123.456
1603}
1604
1605const f32_epsilon = 0.0000000001
1606
1607fn test_string_f32() {
1608 assert ''.f32() - 0 <= f32_epsilon
1609 assert '123'.f32() - 123 < f32_epsilon
1610 assert '-123'.f32() - (-123) < f32_epsilon
1611 assert '-123.456'.f32() - (-123.456) <= f32_epsilon
1612}
1613
1614fn test_string_is_ascii() {
1615 assert ''.is_ascii() == true
1616 assert ' '.is_ascii() == true
1617 assert '~~'.is_ascii() == true
1618 assert ' Az~'.is_ascii() == true
1619 assert ' Aö~'.is_ascii() == false
1620 assert '👋'.is_ascii() == false
1621 assert 'a👋bc'.is_ascii() == false
1622}
1623
1624fn test_string_is_identifier() {
1625 assert ''.is_identifier() == false
1626 assert ' '.is_identifier() == false
1627 assert '~~'.is_identifier() == false
1628 assert '_Az~'.is_identifier() == false
1629 assert '_Aö~'.is_identifier() == false
1630 assert '👋'.is_identifier() == false
1631 assert 'a👋bc'.is_identifier() == false
1632 assert '9'.is_identifier() == false
1633 assert '_9'.is_identifier() == true
1634 assert 'a 9'.is_identifier() == false
1635 assert 't'.is_identifier() == true
1636}
1637
1638fn test_string_with_zero_byte_escape() {
1639 assert '\x00'.bytes() == [u8(0)]
1640}
1641
1642fn test_is_blank() {
1643 assert ''.is_blank()
1644 assert ' '.is_blank()
1645 assert ' \t'.is_blank()
1646 assert ' \t
1647
1648'.is_blank()
1649 assert ' \t\r'.is_blank()
1650 assert ' \t\r
1651
1652'.is_blank()
1653}
1654
1655fn test_indent_width() {
1656 assert 'abc'.indent_width() == 0
1657 assert ' abc'.indent_width() == 1
1658 assert ' abc'.indent_width() == 2
1659 assert '\tabc'.indent_width() == 1
1660 assert '\t abc'.indent_width() == 2
1661 assert '\t\tabc'.indent_width() == 2
1662 assert '\t\t abc'.indent_width() == 3
1663}
1664
1665fn test_index_u8() {
1666 assert 'abcabca'.index_u8(`a`) == 0
1667 assert 'abcabca'.index_u8(`b`) == 1
1668 assert 'abcabca'.index_u8(`c`) == 2
1669
1670 assert 'abc'.index_u8(`d`) == -1
1671 assert 'abc'.index_u8(`A`) == -1
1672 assert 'abc'.index_u8(`B`) == -1
1673 assert 'abc'.index_u8(`C`) == -1
1674}
1675
1676fn test_last_index() {
1677 assert 'abcabca'.last_index('ca')? == 5
1678 assert 'abcabca'.last_index('ab')? == 3
1679 assert 'abcabca'.last_index('b')? == 4
1680 assert 'Zabcabca'.last_index('Z')? == 0
1681 x := 'Zabcabca'.last_index('Y')
1682 assert x == none
1683 assert 'Zabcabca'.last_index('Y') == none
1684}
1685
1686fn test_last_index_u8() {
1687 assert 'abcabca'.last_index_u8(`a`) == 6
1688 assert 'abcabca'.last_index_u8(`c`) == 5
1689 assert 'abcabca'.last_index_u8(`b`) == 4
1690 assert 'Zabcabca'.last_index_u8(`Z`) == 0
1691 //
1692 assert 'abc'.last_index_u8(`d`) == -1
1693 assert 'abc'.last_index_u8(`A`) == -1
1694 assert 'abc'.last_index_u8(`B`) == -1
1695 assert 'abc'.last_index_u8(`C`) == -1
1696}
1697
1698fn test_contains_byte() {
1699 assert 'abc abca'.contains_u8(`a`)
1700 assert 'abc abca'.contains_u8(`b`)
1701 assert 'abc abca'.contains_u8(`c`)
1702 assert 'abc abca'.contains_u8(` `)
1703 assert !'abc abca'.contains_u8(`A`)
1704}
1705
1706fn test_camel_to_snake() {
1707 assert 'Abcd'.camel_to_snake() == 'abcd'
1708 assert 'aBcd'.camel_to_snake() == 'a_bcd'
1709 assert 'AAbb'.camel_to_snake() == 'aa_bb'
1710 assert 'aaBB'.camel_to_snake() == 'aa_bb'
1711 assert 'BBaa'.camel_to_snake() == 'bb_aa'
1712 assert 'aaBbCcDD'.camel_to_snake() == 'aa_bb_cc_dd'
1713 assert 'AAbbCC'.camel_to_snake() == 'aa_bb_cc'
1714 assert 'aaBBcc'.camel_to_snake() == 'aa_bb_cc'
1715 assert 'aa_BB'.camel_to_snake() == 'aa_bb'
1716 assert 'aa__BB'.camel_to_snake() == 'aa__bb'
1717 assert 'JVM_PUBLIC_ACC'.camel_to_snake() == 'jvm_public_acc'
1718 assert '_ISspace'.camel_to_snake() == '_is_space'
1719 assert '_aBcd'.camel_to_snake() == '_a_bcd'
1720 assert '_a_Bcd'.camel_to_snake() == '_a_bcd'
1721 assert '_AbCDe_'.camel_to_snake() == '_ab_cd_e_'
1722 assert 'HTTPServer'.camel_to_snake() == 'http_server'
1723 assert 'HTTP2Server'.camel_to_snake() == 'http2_server'
1724 assert 'XML2JSON'.camel_to_snake() == 'xml_2_json'
1725}
1726
1727fn test_snake_to_camel() {
1728 assert 'abcd'.snake_to_camel() == 'Abcd'
1729 assert 'ab_cd'.snake_to_camel() == 'AbCd'
1730 assert 'ab_cd_efg'.snake_to_camel() == 'AbCdEfg'
1731 assert '_abcd'.snake_to_camel() == 'Abcd'
1732 assert '_abcd_'.snake_to_camel() == 'Abcd'
1733}
1734
1735fn test_string_wrap() {
1736 assert 'Hello World'.wrap(width: 10) == 'Hello\nWorld'
1737 assert 'Hello World'.wrap(width: 10, end: '<linea-break>') == 'Hello<linea-break>World'
1738 assert 'The V programming language'.wrap(width: 20, end: '|') == 'The V programming|language'
1739 assert 'Hello, my name is Carl and I am a delivery'.wrap(width: 20) == 'Hello, my name is\nCarl and I am a\ndelivery'
1740}
1741
1742fn test_hex() {
1743 assert 'Hello World!'.hex() == '48656c6c6f20576f726c6421'
1744 assert 'VLANG'.hex() == '564c414e47'
1745 assert 'VLANG'.hex() == 'VLANG'.bytes().hex()
1746 for c in u8(0) .. 255 {
1747 assert c.ascii_str().hex() == [c].hex()
1748 }
1749}
1750