typeutil_test.gno
22.05 Kb ยท 1071 lines
1package typeutil
2
3import (
4 "std"
5 "strings"
6 "testing"
7 "time"
8)
9
10type testStringer struct {
11 value string
12}
13
14func (t testStringer) String() string {
15 return "test:" + t.value
16}
17
18func TestToString(t *testing.T) {
19 // setup test data
20 str := "hello"
21 num := 42
22 b := true
23 now := time.Now()
24 addr := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
25 stringer := testStringer{value: "hello"}
26
27 type testCase struct {
28 name string
29 input any
30 expected string
31 }
32
33 tests := []testCase{
34 // basic types
35 {"string", "hello", "hello"},
36 {"empty_string", "", ""},
37 {"nil", nil, ""},
38
39 // integer types
40 {"int", 42, "42"},
41 {"int8", int8(8), "8"},
42 {"int16", int16(16), "16"},
43 {"int32", int32(32), "32"},
44 {"int64", int64(64), "64"},
45 {"uint", uint(42), "42"},
46 {"uint8", uint8(8), "8"},
47 {"uint16", uint16(16), "16"},
48 {"uint32", uint32(32), "32"},
49 {"uint64", uint64(64), "64"},
50
51 // float types
52 {"float32", float32(3.14), "3.14"},
53 {"float64", 3.14159, "3.14159"},
54
55 // boolean
56 {"bool_true", true, "true"},
57 {"bool_false", false, "false"},
58
59 // special types
60 {"time", now, now.String()},
61 {"address", addr, string(addr)},
62 {"bytes", []byte("hello"), "hello"},
63 {"stringer", stringer, "test:hello"},
64
65 // slices
66 {"empty_slice", []string{}, "[]"},
67 {"string_slice", []string{"a", "b"}, "[a b]"},
68 {"int_slice", []int{1, 2}, "[1 2]"},
69 {"int32_slice", []int32{1, 2}, "[1 2]"},
70 {"int64_slice", []int64{1, 2}, "[1 2]"},
71 {"float32_slice", []float32{1.1, 2.2}, "[1.1 2.2]"},
72 {"float64_slice", []float64{1.1, 2.2}, "[1.1 2.2]"},
73 {"bytes_slice", [][]byte{[]byte("a"), []byte("b")}, "[a b]"},
74 {"time_slice", []time.Time{now, now}, "[" + now.String() + " " + now.String() + "]"},
75 {"address_slice", []std.Address{addr, addr}, "[" + string(addr) + " " + string(addr) + "]"},
76 {"interface_slice", []any{1, "a", true}, "[1 a true]"},
77
78 // empty slices
79 {"empty_string_slice", []string{}, "[]"},
80 {"empty_int_slice", []int{}, "[]"},
81 {"empty_int32_slice", []int32{}, "[]"},
82 {"empty_int64_slice", []int64{}, "[]"},
83 {"empty_float32_slice", []float32{}, "[]"},
84 {"empty_float64_slice", []float64{}, "[]"},
85 {"empty_bytes_slice", [][]byte{}, "[]"},
86 {"empty_time_slice", []time.Time{}, "[]"},
87 {"empty_address_slice", []std.Address{}, "[]"},
88 {"empty_interface_slice", []any{}, "[]"},
89
90 // maps
91 {"empty_string_map", map[string]string{}, "map[]"},
92 {"string_map", map[string]string{"a": "1", "b": "2"}, "map[a:1 b:2]"},
93 {"empty_interface_map", map[string]any{}, "map[]"},
94 {"interface_map", map[string]any{"a": 1, "b": "2"}, "map[a:1 b:2]"},
95
96 // edge cases
97 {"empty_bytes", []byte{}, ""},
98 {"nil_interface", any(nil), ""},
99 {"empty_struct", struct{}{}, "{}"},
100 {"unknown_type", struct{ foo string }{}, "<unknown>"},
101
102 // pointer types
103 {"nil_string_ptr", (*string)(nil), ""},
104 {"string_ptr", &str, "hello"},
105 {"nil_int_ptr", (*int)(nil), ""},
106 {"int_ptr", &num, "42"},
107 {"nil_bool_ptr", (*bool)(nil), ""},
108 {"bool_ptr", &b, "true"},
109 // {"nil_time_ptr", (*time.Time)(nil), ""}, // TODO: fix this
110 {"time_ptr", &now, now.String()},
111 // {"nil_address_ptr", (*std.Address)(nil), ""}, // TODO: fix this
112 {"address_ptr", &addr, string(addr)},
113 }
114
115 for _, tt := range tests {
116 t.Run(tt.name, func(t *testing.T) {
117 got := ToString(tt.input)
118 if got != tt.expected {
119 t.Errorf("%s: ToString(%v) = %q, want %q", tt.name, tt.input, got, tt.expected)
120 }
121 })
122 }
123}
124
125func TestToBool(t *testing.T) {
126 str := "true"
127 num := 42
128 b := true
129 now := time.Now()
130 addr := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
131 zero := 0
132 empty := ""
133 falseVal := false
134
135 type testCase struct {
136 name string
137 input any
138 expected bool
139 }
140
141 tests := []testCase{
142 // basic types
143 {"true", true, true},
144 {"false", false, false},
145 {"nil", nil, false},
146
147 // strings
148 {"empty_string", "", false},
149 {"zero_string", "0", false},
150 {"false_string", "false", false},
151 {"f_string", "f", false},
152 {"no_string", "no", false},
153 {"n_string", "n", false},
154 {"off_string", "off", false},
155 {"space_string", " ", false},
156 {"true_string", "true", true},
157 {"yes_string", "yes", true},
158 {"random_string", "hello", true},
159
160 // numbers
161 {"zero_int", 0, false},
162 {"positive_int", 1, true},
163 {"negative_int", -1, true},
164 {"zero_float", 0.0, false},
165 {"positive_float", 0.1, true},
166 {"negative_float", -0.1, true},
167
168 // special types
169 {"empty_bytes", []byte{}, false},
170 {"non_empty_bytes", []byte{1}, true},
171 /*{"zero_time", time.Time{}, false},*/ // TODO: fix this
172 {"empty_address", std.Address(""), false},
173
174 // slices
175 {"empty_slice", []string{}, false},
176 {"non_empty_slice", []string{"a"}, true},
177
178 // maps
179 {"empty_map", map[string]string{}, false},
180 {"non_empty_map", map[string]string{"a": "b"}, true},
181
182 // pointer types
183 {"nil_bool_ptr", (*bool)(nil), false},
184 {"true_ptr", &b, true},
185 {"false_ptr", &falseVal, false},
186 {"nil_string_ptr", (*string)(nil), false},
187 {"string_ptr", &str, true},
188 {"empty_string_ptr", &empty, false},
189 {"nil_int_ptr", (*int)(nil), false},
190 {"int_ptr", &num, true},
191 {"zero_int_ptr", &zero, false},
192 // {"nil_time_ptr", (*time.Time)(nil), false}, // TODO: fix this
193 {"time_ptr", &now, true},
194 // {"nil_address_ptr", (*std.Address)(nil), false}, // TODO: fix this
195 {"address_ptr", &addr, true},
196 }
197
198 for _, tt := range tests {
199 t.Run(tt.name, func(t *testing.T) {
200 got := ToBool(tt.input)
201 if got != tt.expected {
202 t.Errorf("%s: ToBool(%v) = %v, want %v", tt.name, tt.input, got, tt.expected)
203 }
204 })
205 }
206}
207
208func TestIsZero(t *testing.T) {
209 str := "hello"
210 num := 42
211 b := true
212 now := time.Now()
213 addr := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5")
214 zero := 0
215 empty := ""
216 falseVal := false
217
218 type testCase struct {
219 name string
220 input any
221 expected bool
222 }
223
224 tests := []testCase{
225 // basic types
226 {"true", true, false},
227 {"false", false, true},
228 {"nil", nil, true},
229
230 // strings
231 {"empty_string", "", true},
232 {"non_empty_string", "hello", false},
233
234 // numbers
235 {"zero_int", 0, true},
236 {"non_zero_int", 1, false},
237 {"zero_float", 0.0, true},
238 {"non_zero_float", 0.1, false},
239
240 // special types
241 {"empty_bytes", []byte{}, true},
242 {"non_empty_bytes", []byte{1}, false},
243 /*{"zero_time", time.Time{}, true},*/ // TODO: fix this
244 {"empty_address", std.Address(""), true},
245
246 // slices
247 {"empty_slice", []string{}, true},
248 {"non_empty_slice", []string{"a"}, false},
249
250 // maps
251 {"empty_map", map[string]string{}, true},
252 {"non_empty_map", map[string]string{"a": "b"}, false},
253
254 // pointer types
255 {"nil_bool_ptr", (*bool)(nil), true},
256 {"false_ptr", &falseVal, true},
257 {"true_ptr", &b, false},
258 {"nil_string_ptr", (*string)(nil), true},
259 {"empty_string_ptr", &empty, true},
260 {"string_ptr", &str, false},
261 {"nil_int_ptr", (*int)(nil), true},
262 {"zero_int_ptr", &zero, true},
263 {"int_ptr", &num, false},
264 // {"nil_time_ptr", (*time.Time)(nil), true}, // TODO: fix this
265 {"time_ptr", &now, false},
266 // {"nil_address_ptr", (*std.Address)(nil), true}, // TODO: fix this
267 {"address_ptr", &addr, false},
268 }
269
270 for _, tt := range tests {
271 t.Run(tt.name, func(t *testing.T) {
272 got := IsZero(tt.input)
273 if got != tt.expected {
274 t.Errorf("%s: IsZero(%v) = %v, want %v", tt.name, tt.input, got, tt.expected)
275 }
276 })
277 }
278}
279
280func TestToInterfaceSlice(t *testing.T) {
281 tests := []struct {
282 name string
283 input any
284 expected []any
285 compare func([]any, []any) bool
286 }{
287 {
288 name: "nil",
289 input: nil,
290 expected: nil,
291 compare: compareNil,
292 },
293 {
294 name: "empty_interface_slice",
295 input: []any{},
296 expected: []any{},
297 compare: compareEmpty,
298 },
299 {
300 name: "interface_slice",
301 input: []any{1, "two", true},
302 expected: []any{1, "two", true},
303 compare: compareInterfaces,
304 },
305 {
306 name: "string_slice",
307 input: []string{"a", "b", "c"},
308 expected: []any{"a", "b", "c"},
309 compare: compareStrings,
310 },
311 {
312 name: "int_slice",
313 input: []int{1, 2, 3},
314 expected: []any{1, 2, 3},
315 compare: compareInts,
316 },
317 {
318 name: "int32_slice",
319 input: []int32{1, 2, 3},
320 expected: []any{int32(1), int32(2), int32(3)},
321 compare: compareInt32s,
322 },
323 {
324 name: "int64_slice",
325 input: []int64{1, 2, 3},
326 expected: []any{int64(1), int64(2), int64(3)},
327 compare: compareInt64s,
328 },
329 {
330 name: "float32_slice",
331 input: []float32{1.1, 2.2, 3.3},
332 expected: []any{float32(1.1), float32(2.2), float32(3.3)},
333 compare: compareFloat32s,
334 },
335 {
336 name: "float64_slice",
337 input: []float64{1.1, 2.2, 3.3},
338 expected: []any{1.1, 2.2, 3.3},
339 compare: compareFloat64s,
340 },
341 {
342 name: "bool_slice",
343 input: []bool{true, false, true},
344 expected: []any{true, false, true},
345 compare: compareBools,
346 },
347 /* {
348 name: "time_slice",
349 input: []time.Time{now},
350 expected: []any{now},
351 compare: compareTimes,
352 }, */ // TODO: fix this
353 /* {
354 name: "address_slice",
355 input: []std.Address{addr},
356 expected: []any{addr},
357 compare: compareAddresses,
358 },*/ // TODO: fix this
359 /* {
360 name: "bytes_slice",
361 input: [][]byte{[]byte("hello"), []byte("world")},
362 expected: []any{[]byte("hello"), []byte("world")},
363 compare: compareBytes,
364 },*/ // TODO: fix this
365 }
366
367 for _, tt := range tests {
368 t.Run(tt.name, func(t *testing.T) {
369 got := ToInterfaceSlice(tt.input)
370 if !tt.compare(got, tt.expected) {
371 t.Errorf("ToInterfaceSlice() = %v, want %v", got, tt.expected)
372 }
373 })
374 }
375}
376
377func compareNil(a, b []any) bool {
378 return a == nil && b == nil
379}
380
381func compareEmpty(a, b []any) bool {
382 return len(a) == 0 && len(b) == 0
383}
384
385func compareInterfaces(a, b []any) bool {
386 if len(a) != len(b) {
387 return false
388 }
389 for i := range a {
390 if a[i] != b[i] {
391 return false
392 }
393 }
394 return true
395}
396
397func compareStrings(a, b []any) bool {
398 if len(a) != len(b) {
399 return false
400 }
401 for i := range a {
402 as, ok1 := a[i].(string)
403 bs, ok2 := b[i].(string)
404 if !ok1 || !ok2 || as != bs {
405 return false
406 }
407 }
408 return true
409}
410
411func compareInts(a, b []any) bool {
412 if len(a) != len(b) {
413 return false
414 }
415 for i := range a {
416 ai, ok1 := a[i].(int)
417 bi, ok2 := b[i].(int)
418 if !ok1 || !ok2 || ai != bi {
419 return false
420 }
421 }
422 return true
423}
424
425func compareInt32s(a, b []any) bool {
426 if len(a) != len(b) {
427 return false
428 }
429 for i := range a {
430 ai, ok1 := a[i].(int32)
431 bi, ok2 := b[i].(int32)
432 if !ok1 || !ok2 || ai != bi {
433 return false
434 }
435 }
436 return true
437}
438
439func compareInt64s(a, b []any) bool {
440 if len(a) != len(b) {
441 return false
442 }
443 for i := range a {
444 ai, ok1 := a[i].(int64)
445 bi, ok2 := b[i].(int64)
446 if !ok1 || !ok2 || ai != bi {
447 return false
448 }
449 }
450 return true
451}
452
453func compareFloat32s(a, b []any) bool {
454 if len(a) != len(b) {
455 return false
456 }
457 for i := range a {
458 ai, ok1 := a[i].(float32)
459 bi, ok2 := b[i].(float32)
460 if !ok1 || !ok2 || ai != bi {
461 return false
462 }
463 }
464 return true
465}
466
467func compareFloat64s(a, b []any) bool {
468 if len(a) != len(b) {
469 return false
470 }
471 for i := range a {
472 ai, ok1 := a[i].(float64)
473 bi, ok2 := b[i].(float64)
474 if !ok1 || !ok2 || ai != bi {
475 return false
476 }
477 }
478 return true
479}
480
481func compareBools(a, b []any) bool {
482 if len(a) != len(b) {
483 return false
484 }
485 for i := range a {
486 ab, ok1 := a[i].(bool)
487 bb, ok2 := b[i].(bool)
488 if !ok1 || !ok2 || ab != bb {
489 return false
490 }
491 }
492 return true
493}
494
495func compareTimes(a, b []any) bool {
496 if len(a) != len(b) {
497 return false
498 }
499 for i := range a {
500 at, ok1 := a[i].(time.Time)
501 bt, ok2 := b[i].(time.Time)
502 if !ok1 || !ok2 || !at.Equal(bt) {
503 return false
504 }
505 }
506 return true
507}
508
509func compareAddresses(a, b []any) bool {
510 if len(a) != len(b) {
511 return false
512 }
513 for i := range a {
514 aa, ok1 := a[i].(std.Address)
515 ba, ok2 := b[i].(std.Address)
516 if !ok1 || !ok2 || aa != ba {
517 return false
518 }
519 }
520 return true
521}
522
523func compareBytes(a, b []any) bool {
524 if len(a) != len(b) {
525 return false
526 }
527 for i := range a {
528 ab, ok1 := a[i].([]byte)
529 bb, ok2 := b[i].([]byte)
530 if !ok1 || !ok2 || string(ab) != string(bb) {
531 return false
532 }
533 }
534 return true
535}
536
537// compareStringInterfaceMaps compares two map[string]any for equality
538func compareStringInterfaceMaps(a, b map[string]any) bool {
539 if len(a) != len(b) {
540 return false
541 }
542 for k, v1 := range a {
543 v2, ok := b[k]
544 if !ok {
545 return false
546 }
547 // Compare values based on their type
548 switch val1 := v1.(type) {
549 case string:
550 val2, ok := v2.(string)
551 if !ok || val1 != val2 {
552 return false
553 }
554 case int:
555 val2, ok := v2.(int)
556 if !ok || val1 != val2 {
557 return false
558 }
559 case float64:
560 val2, ok := v2.(float64)
561 if !ok || val1 != val2 {
562 return false
563 }
564 case bool:
565 val2, ok := v2.(bool)
566 if !ok || val1 != val2 {
567 return false
568 }
569 case []any:
570 val2, ok := v2.([]any)
571 if !ok || len(val1) != len(val2) {
572 return false
573 }
574 for i := range val1 {
575 if val1[i] != val2[i] {
576 return false
577 }
578 }
579 case map[string]any:
580 val2, ok := v2.(map[string]any)
581 if !ok || !compareStringInterfaceMaps(val1, val2) {
582 return false
583 }
584 default:
585 return false
586 }
587 }
588 return true
589}
590
591func TestToMapStringInterface(t *testing.T) {
592 tests := []struct {
593 name string
594 input any
595 expected map[string]any
596 wantErr bool
597 }{
598 {
599 name: "map[string]any",
600 input: map[string]any{
601 "key1": "value1",
602 "key2": 42,
603 },
604 expected: map[string]any{
605 "key1": "value1",
606 "key2": 42,
607 },
608 wantErr: false,
609 },
610 {
611 name: "map[string]string",
612 input: map[string]string{
613 "key1": "value1",
614 "key2": "value2",
615 },
616 expected: map[string]any{
617 "key1": "value1",
618 "key2": "value2",
619 },
620 wantErr: false,
621 },
622 {
623 name: "map[string]int",
624 input: map[string]int{
625 "key1": 1,
626 "key2": 2,
627 },
628 expected: map[string]any{
629 "key1": 1,
630 "key2": 2,
631 },
632 wantErr: false,
633 },
634 {
635 name: "map[string]float64",
636 input: map[string]float64{
637 "key1": 1.1,
638 "key2": 2.2,
639 },
640 expected: map[string]any{
641 "key1": 1.1,
642 "key2": 2.2,
643 },
644 wantErr: false,
645 },
646 {
647 name: "map[string]bool",
648 input: map[string]bool{
649 "key1": true,
650 "key2": false,
651 },
652 expected: map[string]any{
653 "key1": true,
654 "key2": false,
655 },
656 wantErr: false,
657 },
658 {
659 name: "map[string][]string",
660 input: map[string][]string{
661 "key1": {"a", "b"},
662 "key2": {"c", "d"},
663 },
664 expected: map[string]any{
665 "key1": []any{"a", "b"},
666 "key2": []any{"c", "d"},
667 },
668 wantErr: false,
669 },
670 {
671 name: "nested map[string]map[string]string",
672 input: map[string]map[string]string{
673 "key1": {"nested1": "value1"},
674 "key2": {"nested2": "value2"},
675 },
676 expected: map[string]any{
677 "key1": map[string]any{"nested1": "value1"},
678 "key2": map[string]any{"nested2": "value2"},
679 },
680 wantErr: false,
681 },
682 {
683 name: "unsupported type",
684 input: 42, // not a map
685 expected: nil,
686 wantErr: true,
687 },
688 }
689
690 for _, tt := range tests {
691 t.Run(tt.name, func(t *testing.T) {
692 got, err := ToMapStringInterface(tt.input)
693 if (err != nil) != tt.wantErr {
694 t.Errorf("ToMapStringInterface() error = %v, wantErr %v", err, tt.wantErr)
695 return
696 }
697 if !tt.wantErr {
698 if !compareStringInterfaceMaps(got, tt.expected) {
699 t.Errorf("ToMapStringInterface() = %v, expected %v", got, tt.expected)
700 }
701 }
702 })
703 }
704}
705
706// Test error messages
707func TestToMapStringInterfaceErrors(t *testing.T) {
708 _, err := ToMapStringInterface(42)
709 if err == nil || !strings.Contains(err.Error(), "unsupported map type") {
710 t.Errorf("Expected error containing 'unsupported map type', got %v", err)
711 }
712}
713
714// compareIntInterfaceMaps compares two map[int]any for equality
715func compareIntInterfaceMaps(a, b map[int]any) bool {
716 if len(a) != len(b) {
717 return false
718 }
719 for k, v1 := range a {
720 v2, ok := b[k]
721 if !ok {
722 return false
723 }
724 // Compare values based on their type
725 switch val1 := v1.(type) {
726 case string:
727 val2, ok := v2.(string)
728 if !ok || val1 != val2 {
729 return false
730 }
731 case int:
732 val2, ok := v2.(int)
733 if !ok || val1 != val2 {
734 return false
735 }
736 case float64:
737 val2, ok := v2.(float64)
738 if !ok || val1 != val2 {
739 return false
740 }
741 case bool:
742 val2, ok := v2.(bool)
743 if !ok || val1 != val2 {
744 return false
745 }
746 case []any:
747 val2, ok := v2.([]any)
748 if !ok || len(val1) != len(val2) {
749 return false
750 }
751 for i := range val1 {
752 if val1[i] != val2[i] {
753 return false
754 }
755 }
756 case map[string]any:
757 val2, ok := v2.(map[string]any)
758 if !ok || !compareStringInterfaceMaps(val1, val2) {
759 return false
760 }
761 default:
762 return false
763 }
764 }
765 return true
766}
767
768func TestToMapIntInterface(t *testing.T) {
769 tests := []struct {
770 name string
771 input any
772 expected map[int]any
773 wantErr bool
774 }{
775 {
776 name: "map[int]any",
777 input: map[int]any{
778 1: "value1",
779 2: 42,
780 },
781 expected: map[int]any{
782 1: "value1",
783 2: 42,
784 },
785 wantErr: false,
786 },
787 {
788 name: "map[int]string",
789 input: map[int]string{
790 1: "value1",
791 2: "value2",
792 },
793 expected: map[int]any{
794 1: "value1",
795 2: "value2",
796 },
797 wantErr: false,
798 },
799 {
800 name: "map[int]int",
801 input: map[int]int{
802 1: 10,
803 2: 20,
804 },
805 expected: map[int]any{
806 1: 10,
807 2: 20,
808 },
809 wantErr: false,
810 },
811 {
812 name: "map[int]float64",
813 input: map[int]float64{
814 1: 1.1,
815 2: 2.2,
816 },
817 expected: map[int]any{
818 1: 1.1,
819 2: 2.2,
820 },
821 wantErr: false,
822 },
823 {
824 name: "map[int]bool",
825 input: map[int]bool{
826 1: true,
827 2: false,
828 },
829 expected: map[int]any{
830 1: true,
831 2: false,
832 },
833 wantErr: false,
834 },
835 {
836 name: "map[int][]string",
837 input: map[int][]string{
838 1: {"a", "b"},
839 2: {"c", "d"},
840 },
841 expected: map[int]any{
842 1: []any{"a", "b"},
843 2: []any{"c", "d"},
844 },
845 wantErr: false,
846 },
847 {
848 name: "map[int]map[string]any",
849 input: map[int]map[string]any{
850 1: {"nested1": "value1"},
851 2: {"nested2": "value2"},
852 },
853 expected: map[int]any{
854 1: map[string]any{"nested1": "value1"},
855 2: map[string]any{"nested2": "value2"},
856 },
857 wantErr: false,
858 },
859 {
860 name: "unsupported type",
861 input: 42, // not a map
862 expected: nil,
863 wantErr: true,
864 },
865 }
866
867 for _, tt := range tests {
868 t.Run(tt.name, func(t *testing.T) {
869 got, err := ToMapIntInterface(tt.input)
870 if (err != nil) != tt.wantErr {
871 t.Errorf("ToMapIntInterface() error = %v, wantErr %v", err, tt.wantErr)
872 return
873 }
874 if !tt.wantErr {
875 if !compareIntInterfaceMaps(got, tt.expected) {
876 t.Errorf("ToMapIntInterface() = %v, expected %v", got, tt.expected)
877 }
878 }
879 })
880 }
881}
882
883func TestToStringSlice(t *testing.T) {
884 tests := []struct {
885 name string
886 input any
887 expected []string
888 }{
889 {
890 name: "nil input",
891 input: nil,
892 expected: nil,
893 },
894 {
895 name: "empty slice",
896 input: []string{},
897 expected: []string{},
898 },
899 {
900 name: "string slice",
901 input: []string{"a", "b", "c"},
902 expected: []string{"a", "b", "c"},
903 },
904 {
905 name: "int slice",
906 input: []int{1, 2, 3},
907 expected: []string{"1", "2", "3"},
908 },
909 {
910 name: "int32 slice",
911 input: []int32{1, 2, 3},
912 expected: []string{"1", "2", "3"},
913 },
914 {
915 name: "int64 slice",
916 input: []int64{1, 2, 3},
917 expected: []string{"1", "2", "3"},
918 },
919 {
920 name: "uint slice",
921 input: []uint{1, 2, 3},
922 expected: []string{"1", "2", "3"},
923 },
924 {
925 name: "uint8 slice",
926 input: []uint8{1, 2, 3},
927 expected: []string{"1", "2", "3"},
928 },
929 {
930 name: "uint16 slice",
931 input: []uint16{1, 2, 3},
932 expected: []string{"1", "2", "3"},
933 },
934 {
935 name: "uint32 slice",
936 input: []uint32{1, 2, 3},
937 expected: []string{"1", "2", "3"},
938 },
939 {
940 name: "uint64 slice",
941 input: []uint64{1, 2, 3},
942 expected: []string{"1", "2", "3"},
943 },
944 {
945 name: "float32 slice",
946 input: []float32{1.1, 2.2, 3.3},
947 expected: []string{"1.1", "2.2", "3.3"},
948 },
949 {
950 name: "float64 slice",
951 input: []float64{1.1, 2.2, 3.3},
952 expected: []string{"1.1", "2.2", "3.3"},
953 },
954 {
955 name: "bool slice",
956 input: []bool{true, false, true},
957 expected: []string{"true", "false", "true"},
958 },
959 {
960 name: "[]byte slice",
961 input: [][]byte{[]byte("hello"), []byte("world")},
962 expected: []string{"hello", "world"},
963 },
964 {
965 name: "interface slice",
966 input: []any{1, "hello", true},
967 expected: []string{"1", "hello", "true"},
968 },
969 {
970 name: "time slice",
971 input: []time.Time{{}, {}},
972 expected: []string{"0001-01-01 00:00:00 +0000 UTC", "0001-01-01 00:00:00 +0000 UTC"},
973 },
974 {
975 name: "address slice",
976 input: []std.Address{"addr1", "addr2"},
977 expected: []string{"addr1", "addr2"},
978 },
979 {
980 name: "non-slice input",
981 input: 42,
982 expected: nil,
983 },
984 }
985
986 for _, tt := range tests {
987 t.Run(tt.name, func(t *testing.T) {
988 result := ToStringSlice(tt.input)
989 if !slicesEqual(result, tt.expected) {
990 t.Errorf("ToStringSlice(%v) = %v, want %v", tt.input, result, tt.expected)
991 }
992 })
993 }
994}
995
996// Helper function to compare string slices
997func slicesEqual(a, b []string) bool {
998 if len(a) != len(b) {
999 return false
1000 }
1001 for i := range a {
1002 if a[i] != b[i] {
1003 return false
1004 }
1005 }
1006 return true
1007}
1008
1009func TestToStringAdvanced(t *testing.T) {
1010 tests := []struct {
1011 name string
1012 input any
1013 expected string
1014 }{
1015 {
1016 name: "slice with mixed basic types",
1017 input: []any{
1018 42,
1019 "hello",
1020 true,
1021 3.14,
1022 },
1023 expected: "[42 hello true 3.14]",
1024 },
1025 {
1026 name: "map with basic types",
1027 input: map[string]any{
1028 "int": 42,
1029 "str": "hello",
1030 "bool": true,
1031 "float": 3.14,
1032 },
1033 expected: "map[bool:true float:3.14 int:42 str:hello]",
1034 },
1035 {
1036 name: "mixed types map",
1037 input: map[any]any{
1038 42: "number",
1039 "string": 123,
1040 true: []int{1, 2, 3},
1041 struct{}{}: "empty",
1042 },
1043 expected: "map[42:number string:123 true:[1 2 3] {}:empty]",
1044 },
1045 {
1046 name: "nested maps",
1047 input: map[string]any{
1048 "a": map[string]int{
1049 "x": 1,
1050 "y": 2,
1051 },
1052 "b": []any{1, "two", true},
1053 },
1054 expected: "map[a:map[x:1 y:2] b:[1 two true]]",
1055 },
1056 {
1057 name: "empty struct",
1058 input: struct{}{},
1059 expected: "{}",
1060 },
1061 }
1062
1063 for _, tt := range tests {
1064 t.Run(tt.name, func(t *testing.T) {
1065 result := ToString(tt.input)
1066 if result != tt.expected {
1067 t.Errorf("\nToString(%v) =\n%v\nwant:\n%v", tt.input, result, tt.expected)
1068 }
1069 })
1070 }
1071}