github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/conv/conv_test.go (about) 1 package conv 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestBool(t *testing.T) { 13 testdata := []struct { 14 in string 15 out bool 16 }{ 17 {"", false}, 18 {"asdf", false}, 19 {"1234", false}, 20 {"False", false}, 21 {"0", false}, 22 {"false", false}, 23 {"F", false}, 24 {"f", false}, 25 {"true", true}, 26 {"True", true}, 27 {"t", true}, 28 {"T", true}, 29 {"1", true}, 30 } 31 for _, d := range testdata { 32 assert.Equal(t, d.out, Bool(d.in)) 33 } 34 } 35 36 func TestSlice(t *testing.T) { 37 expected := []string{"foo", "bar"} 38 actual := Slice("foo", "bar") 39 assert.Equal(t, expected[0], actual[0]) 40 assert.Equal(t, expected[1], actual[1]) 41 } 42 43 func TestJoin(t *testing.T) { 44 testdata := []struct { 45 in interface{} 46 sep string 47 out string 48 }{ 49 {[]interface{}{"foo", "bar"}, ",", "foo,bar"}, 50 {[]interface{}{"foo", "bar"}, ",\n", "foo,\nbar"}, 51 // Join handles all kinds of scalar types too... 52 {[]interface{}{42, uint64(18446744073709551615)}, "-", "42-18446744073709551615"}, 53 {[]int{42, 100}, ",", "42,100"}, 54 {[]int64{42, 100}, ",", "42,100"}, 55 {[]uint64{42, 100}, ",", "42,100"}, 56 {[]bool{true, false}, ",", "true,false"}, 57 {[]float64{1, 2}, ",", "1,2"}, 58 {[]interface{}{1, "", true, 3.14, "foo", nil}, ",", "1,,true,3.14,foo,nil"}, 59 // and best-effort with weird types 60 {[]interface{}{[]string{"foo"}, "bar"}, ",", "[foo],bar"}, 61 } 62 for _, d := range testdata { 63 out, err := Join(d.in, d.sep) 64 require.NoError(t, err) 65 assert.Equal(t, d.out, out) 66 } 67 } 68 69 func TestHas(t *testing.T) { 70 in := map[string]interface{}{ 71 "foo": "bar", 72 "baz": map[string]interface{}{ 73 "qux": "quux", 74 }, 75 } 76 77 testdata := []struct { 78 in interface{} 79 key interface{} 80 out bool 81 }{ 82 {in, "foo", true}, 83 {in, "bar", false}, 84 {in["baz"], "qux", true}, 85 {[]string{"foo", "bar", "baz"}, "bar", true}, 86 {[]interface{}{"foo", "bar", "baz"}, "bar", true}, 87 {[]interface{}{"foo", "bar", "baz"}, 42, false}, 88 {[]int{1, 2, 42}, 42, true}, 89 } 90 91 for _, d := range testdata { 92 assert.Equal(t, d.out, Has(d.in, d.key)) 93 } 94 } 95 96 func TestMustParseInt(t *testing.T) { 97 for _, i := range []string{"0", "-0", "foo", "", "*&^%"} { 98 assert.Equal(t, 0, int(MustParseInt(i, 10, 64))) 99 } 100 assert.Equal(t, 1, int(MustParseInt("1", 10, 64))) 101 assert.Equal(t, -1, int(MustParseInt("-1", 10, 64))) 102 } 103 104 func TestMustAtoi(t *testing.T) { 105 for _, i := range []string{"0", "-0", "foo", "", "*&^%"} { 106 assert.Equal(t, 0, MustAtoi(i)) 107 } 108 assert.Equal(t, 1, MustAtoi("1")) 109 assert.Equal(t, -1, MustAtoi("-1")) 110 } 111 112 func TestMustParseUint(t *testing.T) { 113 for _, i := range []string{"0", "-0", "-1", "foo", "", "*&^%"} { 114 assert.Equal(t, uint64(0), MustParseUint(i, 10, 64)) 115 } 116 assert.Equal(t, uint64(1), MustParseUint("1", 10, 64)) 117 } 118 119 func TestMustParseFloat(t *testing.T) { 120 for _, i := range []string{"0", "-0", "foo", "", "*&^%"} { 121 assert.Zero(t, MustParseFloat(i, 64)) 122 } 123 assert.InEpsilon(t, 1.0, MustParseFloat("1", 64), 1e-12) 124 assert.InEpsilon(t, -1.0, MustParseFloat("-1", 64), 1e-12) 125 } 126 127 func TestToInt64(t *testing.T) { 128 assert.Equal(t, int64(1), ToInt64(1)) 129 assert.Equal(t, int64(1), ToInt64(int32(1))) 130 assert.Equal(t, int64(1), ToInt64(int64(1))) 131 assert.Equal(t, int64(1), ToInt64(float32(1))) 132 assert.Equal(t, int64(1), ToInt64(float64(1))) 133 assert.Equal(t, int64(42), ToInt64(42)) 134 assert.Equal(t, int64(42), ToInt64("42.0")) 135 assert.Equal(t, int64(3), ToInt64("3.5")) 136 assert.Equal(t, int64(-1), ToInt64(uint64(math.MaxUint64))) 137 assert.Equal(t, int64(0xFF), ToInt64(uint8(math.MaxUint8))) 138 139 assert.Equal(t, int64(0), ToInt64(nil)) 140 assert.Equal(t, int64(0), ToInt64(false)) 141 assert.Equal(t, int64(1), ToInt64(true)) 142 assert.Equal(t, int64(0), ToInt64("")) 143 assert.Equal(t, int64(0), ToInt64("foo")) 144 assert.Equal(t, int64(0xFFFF), ToInt64("0xFFFF")) 145 assert.Equal(t, int64(8), ToInt64("010")) 146 assert.Equal(t, int64(4096), ToInt64("4,096")) 147 assert.Equal(t, int64(-4096), ToInt64("-4,096.00")) 148 } 149 150 func TestToInt(t *testing.T) { 151 assert.Equal(t, 1, ToInt(1)) 152 assert.Equal(t, 1, ToInt(int32(1))) 153 assert.Equal(t, 1, ToInt(int64(1))) 154 assert.Equal(t, 1, ToInt(float32(1))) 155 assert.Equal(t, 1, ToInt(float64(1))) 156 assert.Equal(t, 42, ToInt(42)) 157 assert.Equal(t, -1, ToInt(uint64(math.MaxUint64))) 158 assert.Equal(t, 0xFF, ToInt(uint8(math.MaxUint8))) 159 160 assert.Equal(t, 0, ToInt(nil)) 161 assert.Equal(t, 0, ToInt(false)) 162 assert.Equal(t, 1, ToInt(true)) 163 assert.Equal(t, 0, ToInt("")) 164 assert.Equal(t, 0, ToInt("foo")) 165 assert.Equal(t, 0xFFFF, ToInt("0xFFFF")) 166 assert.Equal(t, 8, ToInt("010")) 167 assert.Equal(t, 4096, ToInt("4,096")) 168 assert.Equal(t, -4096, ToInt("-4,096.00")) 169 } 170 171 func TestToInt64s(t *testing.T) { 172 assert.Equal(t, []int64{}, ToInt64s()) 173 174 assert.Equal(t, []int64{0}, ToInt64s("")) 175 assert.Equal(t, []int64{0}, ToInt64s("0")) 176 assert.Equal(t, []int64{42, 15}, ToInt64s("42", "15")) 177 assert.Equal(t, []int64{0, 0, 0, 1, 1, 2, 3, 5, 8, 13, -1000}, 178 ToInt64s(nil, false, "", true, 1, 2.0, uint8(3), int64(5), float32(8), "13", "-1,000")) 179 } 180 181 func TestToInts(t *testing.T) { 182 assert.Equal(t, []int{}, ToInts()) 183 184 assert.Equal(t, []int{0}, ToInts("")) 185 assert.Equal(t, []int{0}, ToInts("0")) 186 assert.Equal(t, []int{42, 15}, ToInts("42", "15")) 187 assert.Equal(t, []int{0, 0, 0, 1, 1, 2, 3, 5, 8, 13, 42000}, 188 ToInts(nil, false, "", true, 1, 2.0, uint8(3), int64(5), float32(8), "13", "42,000")) 189 } 190 191 func TestToFloat64(t *testing.T) { 192 z := []interface{}{0, 0.0, nil, false, float32(0), "", "0", "foo", int64(0), uint(0), "0x0", "00", "0,000"} 193 for _, n := range z { 194 assert.Zero(t, ToFloat64(n)) 195 } 196 assert.InEpsilon(t, 1.0, ToFloat64(true), 1e-12) 197 z = []interface{}{42, 42.0, float32(42), "42", "42.0", uint8(42), "0x2A", "052"} 198 for _, n := range z { 199 assert.InEpsilon(t, 42.0, ToFloat64(n), 1e-12) 200 } 201 z = []interface{}{1000.34, "1000.34", "1,000.34"} 202 for _, n := range z { 203 assert.InEpsilon(t, 1000.34, ToFloat64(n), 1e-12) 204 } 205 } 206 207 func TestToFloat64s(t *testing.T) { 208 assert.Equal(t, []float64{}, ToFloat64s()) 209 assert.Equal(t, []float64{0, 1.0, 2.0, math.Pi, 4.0}, ToFloat64s(nil, true, "2", math.Pi, uint8(4))) 210 } 211 212 type foo struct { 213 val string 214 } 215 216 func (f foo) String() string { 217 return f.val 218 } 219 220 func TestToString(t *testing.T) { 221 var p *string 222 f := "foo" 223 p = &f 224 225 var n *string 226 227 testdata := []struct { 228 in interface{} 229 out string 230 }{ 231 {nil, "nil"}, 232 {"", ""}, 233 {"foo", "foo"}, 234 {true, "true"}, 235 {42, "42"}, 236 {3.14, "3.14"}, 237 {-127, "-127"}, 238 {0xFF, "255"}, 239 {uint8(42), "42"}, 240 {math.Pi, "3.141592653589793"}, 241 {math.NaN(), "NaN"}, 242 {math.Inf(1), "+Inf"}, 243 {math.Inf(-1), "-Inf"}, 244 {foo{"bar"}, "bar"}, 245 {p, "foo"}, 246 {fmt.Errorf("hi"), "hi"}, 247 {n, "<nil>"}, 248 {[]byte("hello world"), "hello world"}, 249 } 250 251 for _, d := range testdata { 252 d := d 253 t.Run(fmt.Sprintf("%T/%#v == %s", d.in, d.in, d.out), func(t *testing.T) { 254 out := ToString(d.in) 255 assert.Equal(t, d.out, out) 256 }) 257 } 258 } 259 260 func TestToBool(t *testing.T) { 261 trueData := []interface{}{ 262 true, 263 1, 264 int8(1), 265 uint8(1), 266 int32(1), 267 uint32(1), 268 int64(1), 269 uint64(1), 270 float32(1), 271 float64(1), 272 "1", 273 "0x1", 274 "1.0", 275 "01", 276 "true", 277 "True", 278 "T", 279 "t", 280 "TrUe", 281 "yes", 282 "YES", 283 } 284 for _, d := range trueData { 285 out := ToBool(d) 286 assert.True(t, out) 287 } 288 289 falseData := []interface{}{ 290 nil, 291 false, 292 42, 293 uint64(math.MaxUint64), 294 uint8(math.MaxUint8), 295 "", 296 "false", 297 "foo", 298 "0xFFFF", 299 "010", 300 "4,096", 301 "-4,096.00", 302 } 303 for _, d := range falseData { 304 out := ToBool(d) 305 assert.False(t, out) 306 } 307 } 308 309 func TestDict(t *testing.T) { 310 testdata := []struct { 311 expected map[string]interface{} 312 args []interface{} 313 }{ 314 {expected: map[string]interface{}{}}, 315 { 316 args: []interface{}{}, 317 expected: map[string]interface{}{}, 318 }, 319 { 320 args: []interface{}{"foo"}, 321 expected: map[string]interface{}{"foo": ""}, 322 }, 323 { 324 args: []interface{}{42}, 325 expected: map[string]interface{}{"42": ""}, 326 }, 327 { 328 args: []interface{}{"foo", nil}, 329 expected: map[string]interface{}{"foo": nil}, 330 }, 331 { 332 args: []interface{}{"foo", "bar"}, 333 expected: map[string]interface{}{"foo": "bar"}, 334 }, 335 { 336 args: []interface{}{"foo", "bar", "baz", true}, 337 expected: map[string]interface{}{ 338 "foo": "bar", 339 "baz": true, 340 }, 341 }, 342 } 343 344 for _, d := range testdata { 345 actual, _ := Dict(d.args...) 346 assert.Equal(t, d.expected, actual) 347 } 348 }