Search Apps Documentation Source Content File Folder Download Copy

ufmt_test.gno

5.95 Kb · 191 lines
  1package ufmt
  2
  3import (
  4	"errors"
  5	"fmt"
  6	"testing"
  7)
  8
  9type stringer struct{}
 10
 11func (stringer) String() string {
 12	return "I'm a stringer"
 13}
 14
 15func TestSprintf(t *testing.T) {
 16	tru := true
 17	cases := []struct {
 18		format         string
 19		values         []interface{}
 20		expectedOutput string
 21	}{
 22		{"hello %s!", []interface{}{"planet"}, "hello planet!"},
 23		{"hi %%%s!", []interface{}{"worl%d"}, "hi %worl%d!"},
 24		{"%s %c %d %t", []interface{}{"foo", 'α', 421, true}, "foo α 421 true"},
 25		{"string [%s]", []interface{}{"foo"}, "string [foo]"},
 26		{"int [%d]", []interface{}{int(42)}, "int [42]"},
 27		{"int8 [%d]", []interface{}{int8(8)}, "int8 [8]"},
 28		{"int16 [%d]", []interface{}{int16(16)}, "int16 [16]"},
 29		{"int32 [%d]", []interface{}{int32(32)}, "int32 [32]"},
 30		{"int64 [%d]", []interface{}{int64(64)}, "int64 [64]"},
 31		{"uint [%d]", []interface{}{uint(42)}, "uint [42]"},
 32		{"uint8 [%d]", []interface{}{uint8(8)}, "uint8 [8]"},
 33		{"uint16 [%d]", []interface{}{uint16(16)}, "uint16 [16]"},
 34		{"uint32 [%d]", []interface{}{uint32(32)}, "uint32 [32]"},
 35		{"uint64 [%d]", []interface{}{uint64(64)}, "uint64 [64]"},
 36		{"bool [%t]", []interface{}{true}, "bool [true]"},
 37		{"bool [%t]", []interface{}{false}, "bool [false]"},
 38		{"no args", nil, "no args"},
 39		{"finish with %", nil, "finish with %"},
 40		{"stringer [%s]", []interface{}{stringer{}}, "stringer [I'm a stringer]"},
 41		{"â", nil, "â"},
 42		{"Hello, World! 😊", nil, "Hello, World! 😊"},
 43		{"unicode formatting: %s", []interface{}{"😊"}, "unicode formatting: 😊"},
 44		{"invalid hex [%x]", []interface{}{"invalid"}, "invalid hex [(unhandled)]"},
 45		{"rune as character [%c]", []interface{}{rune('A')}, "rune as character [A]"},
 46		{"int as character [%c]", []interface{}{int('B')}, "int as character [B]"},
 47		{"quoted string [%q]", []interface{}{"hello"}, "quoted string [\"hello\"]"},
 48		{"quoted string with escape [%q]", []interface{}{"\thello\nworld\\"}, "quoted string with escape [\"\\thello\\nworld\\\\\"]"},
 49		{"invalid quoted string [%q]", []interface{}{123}, "invalid quoted string [(unhandled)]"},
 50		{"type of bool [%T]", []interface{}{true}, "type of bool [bool]"},
 51		{"type of int [%T]", []interface{}{123}, "type of int [int]"},
 52		{"type of string [%T]", []interface{}{"hello"}, "type of string [string]"},
 53		{"type of []byte [%T]", []interface{}{[]byte{1, 2, 3}}, "type of []byte [[]byte]"},
 54		{"type of []rune [%T]", []interface{}{[]rune{'a', 'b', 'c'}}, "type of []rune [[]rune]"},
 55		{"type of unknown [%T]", []interface{}{struct{}{}}, "type of unknown [unknown]"},
 56		// mismatch printing
 57		{"%s", []interface{}{nil}, "%!s(<nil>)"},
 58		{"%s", []interface{}{421}, "%!s(int=421)"},
 59		{"%s", []interface{}{"z"}, "z"},
 60		{"%s", []interface{}{tru}, "%!s(bool=true)"},
 61		{"%s", []interface{}{'z'}, "%!s(int32=122)"},
 62
 63		{"%c", []interface{}{nil}, "%!c(<nil>)"},
 64		{"%c", []interface{}{421}, "ƥ"},
 65		{"%c", []interface{}{"z"}, "%!c(string=z)"},
 66		{"%c", []interface{}{tru}, "%!c(bool=true)"},
 67		{"%c", []interface{}{'z'}, "z"},
 68
 69		{"%d", []interface{}{nil}, "%!d(<nil>)"},
 70		{"%d", []interface{}{421}, "421"},
 71		{"%d", []interface{}{"z"}, "%!d(string=z)"},
 72		{"%d", []interface{}{tru}, "%!d(bool=true)"},
 73		{"%d", []interface{}{'z'}, "122"},
 74
 75		{"%t", []interface{}{nil}, "%!t(<nil>)"},
 76		{"%t", []interface{}{421}, "%!t(int=421)"},
 77		{"%t", []interface{}{"z"}, "%!t(string=z)"},
 78		{"%t", []interface{}{tru}, "true"},
 79		{"%t", []interface{}{'z'}, "%!t(int32=122)"},
 80	}
 81
 82	for _, tc := range cases {
 83		name := fmt.Sprintf(tc.format, tc.values...)
 84		t.Run(name, func(t *testing.T) {
 85			got := Sprintf(tc.format, tc.values...)
 86			if got != tc.expectedOutput {
 87				t.Errorf("got %q, want %q.", got, tc.expectedOutput)
 88			}
 89		})
 90	}
 91}
 92
 93func TestErrorf(t *testing.T) {
 94	tests := []struct {
 95		name     string
 96		format   string
 97		args     []interface{}
 98		expected string
 99	}{
100		{
101			name:     "simple string",
102			format:   "error: %s",
103			args:     []interface{}{"something went wrong"},
104			expected: "error: something went wrong",
105		},
106		{
107			name:     "integer value",
108			format:   "value: %d",
109			args:     []interface{}{42},
110			expected: "value: 42",
111		},
112		{
113			name:     "boolean value",
114			format:   "success: %t",
115			args:     []interface{}{true},
116			expected: "success: true",
117		},
118		{
119			name:     "multiple values",
120			format:   "error %d: %s (success=%t)",
121			args:     []interface{}{123, "failure occurred", false},
122			expected: "error 123: failure occurred (success=false)",
123		},
124		{
125			name:     "literal percent",
126			format:   "literal %%",
127			args:     []interface{}{},
128			expected: "literal %",
129		},
130	}
131
132	for _, tt := range tests {
133		t.Run(tt.name, func(t *testing.T) {
134			err := Errorf(tt.format, tt.args...)
135			if err.Error() != tt.expected {
136				t.Errorf("Errorf(%q, %v) = %q, expected %q", tt.format, tt.args, err.Error(), tt.expected)
137			}
138		})
139	}
140}
141
142func TestPrintErrors(t *testing.T) {
143	got := Sprintf("error: %s", errors.New("can I be printed?"))
144	expectedOutput := "error: can I be printed?"
145	if got != expectedOutput {
146		t.Errorf("got %q, want %q.", got, expectedOutput)
147	}
148}
149
150// NOTE: Currently, there is no way to get the output of Println without using os.Stdout,
151// so we can only test that it doesn't panic and print arguments well.
152func TestPrintln(t *testing.T) {
153	tests := []struct {
154		name     string
155		args     []interface{}
156		expected string
157	}{
158		{
159			name:     "Empty args",
160			args:     []interface{}{},
161			expected: "",
162		},
163		{
164			name:     "String args",
165			args:     []interface{}{"Hello", "World"},
166			expected: "Hello World",
167		},
168		{
169			name:     "Integer args",
170			args:     []interface{}{1, 2, 3},
171			expected: "1 2 3",
172		},
173		{
174			name:     "Mixed args",
175			args:     []interface{}{"Hello", 42, true, false, "World"},
176			expected: "Hello 42 true false World",
177		},
178		{
179			name:     "Unhandled type",
180			args:     []interface{}{"Hello", 3.14, []int{1, 2, 3}},
181			expected: "Hello (unhandled) (unhandled)",
182		},
183	}
184
185	// TODO: replace os.Stdout with a buffer to capture the output and test it.
186	for _, tt := range tests {
187		t.Run(tt.name, func(t *testing.T) {
188			Println(tt.args...)
189		})
190	}
191}