github.com/shohhei1126/hugo@v0.42.2-0.20180623210752-3d5928889ad7/tpl/collections/collections_test.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package collections 15 16 import ( 17 "errors" 18 "fmt" 19 "html/template" 20 "io/ioutil" 21 "log" 22 "math/rand" 23 "os" 24 "reflect" 25 "testing" 26 "time" 27 28 "github.com/gohugoio/hugo/config" 29 "github.com/gohugoio/hugo/deps" 30 "github.com/gohugoio/hugo/helpers" 31 "github.com/gohugoio/hugo/hugofs" 32 "github.com/gohugoio/hugo/langs" 33 jww "github.com/spf13/jwalterweatherman" 34 "github.com/spf13/viper" 35 "github.com/stretchr/testify/assert" 36 "github.com/stretchr/testify/require" 37 ) 38 39 type tstNoStringer struct{} 40 41 func TestAfter(t *testing.T) { 42 t.Parallel() 43 44 ns := New(&deps.Deps{}) 45 46 for i, test := range []struct { 47 index interface{} 48 seq interface{} 49 expect interface{} 50 }{ 51 {int(2), []string{"a", "b", "c", "d"}, []string{"c", "d"}}, 52 {int32(3), []string{"a", "b"}, false}, 53 {int64(2), []int{100, 200, 300}, []int{300}}, 54 {100, []int{100, 200}, false}, 55 {"1", []int{100, 200, 300}, []int{200, 300}}, 56 {int64(-1), []int{100, 200, 300}, false}, 57 {"noint", []int{100, 200, 300}, false}, 58 {1, nil, false}, 59 {nil, []int{100}, false}, 60 {1, t, false}, 61 {1, (*string)(nil), false}, 62 } { 63 errMsg := fmt.Sprintf("[%d] %v", i, test) 64 65 result, err := ns.After(test.index, test.seq) 66 67 if b, ok := test.expect.(bool); ok && !b { 68 require.Error(t, err, errMsg) 69 continue 70 } 71 72 require.NoError(t, err, errMsg) 73 assert.Equal(t, test.expect, result, errMsg) 74 } 75 } 76 77 func TestDelimit(t *testing.T) { 78 t.Parallel() 79 80 ns := New(&deps.Deps{}) 81 82 for i, test := range []struct { 83 seq interface{} 84 delimiter interface{} 85 last interface{} 86 expect template.HTML 87 }{ 88 {[]string{"class1", "class2", "class3"}, " ", nil, "class1 class2 class3"}, 89 {[]int{1, 2, 3, 4, 5}, ",", nil, "1,2,3,4,5"}, 90 {[]int{1, 2, 3, 4, 5}, ", ", nil, "1, 2, 3, 4, 5"}, 91 {[]string{"class1", "class2", "class3"}, " ", " and ", "class1 class2 and class3"}, 92 {[]int{1, 2, 3, 4, 5}, ",", ",", "1,2,3,4,5"}, 93 {[]int{1, 2, 3, 4, 5}, ", ", ", and ", "1, 2, 3, 4, and 5"}, 94 // test maps with and without sorting required 95 {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", nil, "10--20--30--40--50"}, 96 {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", nil, "30--20--10--40--50"}, 97 {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", nil, "10--20--30--40--50"}, 98 {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", nil, "30--20--10--40--50"}, 99 {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", nil, "50--40--10--30--20"}, 100 {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", nil, "10--20--30--40--50"}, 101 {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", nil, "30--20--10--40--50"}, 102 {map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, "--", nil, "30--20--10--40--50"}, 103 // test maps with a last delimiter 104 {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", "--and--", "10--20--30--40--and--50"}, 105 {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", "--and--", "30--20--10--40--and--50"}, 106 {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", "--and--", "10--20--30--40--and--50"}, 107 {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", "--and--", "30--20--10--40--and--50"}, 108 {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", "--and--", "50--40--10--30--and--20"}, 109 {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", "--and--", "10--20--30--40--and--50"}, 110 {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", "--and--", "30--20--10--40--and--50"}, 111 {map[float64]string{3.5: "10", 2.5: "20", 1.5: "30", 4.5: "40", 5.5: "50"}, "--", "--and--", "30--20--10--40--and--50"}, 112 } { 113 errMsg := fmt.Sprintf("[%d] %v", i, test) 114 115 var result template.HTML 116 var err error 117 118 if test.last == nil { 119 result, err = ns.Delimit(test.seq, test.delimiter) 120 } else { 121 result, err = ns.Delimit(test.seq, test.delimiter, test.last) 122 } 123 124 require.NoError(t, err, errMsg) 125 assert.Equal(t, test.expect, result, errMsg) 126 } 127 } 128 129 func TestDictionary(t *testing.T) { 130 t.Parallel() 131 132 ns := New(&deps.Deps{}) 133 134 for i, test := range []struct { 135 values []interface{} 136 expect interface{} 137 }{ 138 {[]interface{}{"a", "b"}, map[string]interface{}{"a": "b"}}, 139 {[]interface{}{"a", 12, "b", []int{4}}, map[string]interface{}{"a": 12, "b": []int{4}}}, 140 // errors 141 {[]interface{}{5, "b"}, false}, 142 {[]interface{}{"a", "b", "c"}, false}, 143 } { 144 errMsg := fmt.Sprintf("[%d] %v", i, test.values) 145 146 result, err := ns.Dictionary(test.values...) 147 148 if b, ok := test.expect.(bool); ok && !b { 149 require.Error(t, err, errMsg) 150 continue 151 } 152 153 require.NoError(t, err, errMsg) 154 assert.Equal(t, test.expect, result, errMsg) 155 } 156 } 157 158 func TestEchoParam(t *testing.T) { 159 t.Parallel() 160 161 ns := New(&deps.Deps{}) 162 163 for i, test := range []struct { 164 a interface{} 165 key interface{} 166 expect interface{} 167 }{ 168 {[]int{1, 2, 3}, 1, int64(2)}, 169 {[]uint{1, 2, 3}, 1, uint64(2)}, 170 {[]float64{1.1, 2.2, 3.3}, 1, float64(2.2)}, 171 {[]string{"foo", "bar", "baz"}, 1, "bar"}, 172 {[]TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}}, 1, ""}, 173 {map[string]int{"foo": 1, "bar": 2, "baz": 3}, "bar", int64(2)}, 174 {map[string]uint{"foo": 1, "bar": 2, "baz": 3}, "bar", uint64(2)}, 175 {map[string]float64{"foo": 1.1, "bar": 2.2, "baz": 3.3}, "bar", float64(2.2)}, 176 {map[string]string{"foo": "FOO", "bar": "BAR", "baz": "BAZ"}, "bar", "BAR"}, 177 {map[string]TstX{"foo": {A: "a", B: "b"}, "bar": {A: "c", B: "d"}, "baz": {A: "e", B: "f"}}, "bar", ""}, 178 {map[string]interface{}{"foo": nil}, "foo", ""}, 179 {(*[]string)(nil), "bar", ""}, 180 } { 181 errMsg := fmt.Sprintf("[%d] %v", i, test) 182 183 result := ns.EchoParam(test.a, test.key) 184 185 assert.Equal(t, test.expect, result, errMsg) 186 } 187 } 188 189 func TestFirst(t *testing.T) { 190 t.Parallel() 191 192 ns := New(&deps.Deps{}) 193 194 for i, test := range []struct { 195 limit interface{} 196 seq interface{} 197 expect interface{} 198 }{ 199 {int(2), []string{"a", "b", "c"}, []string{"a", "b"}}, 200 {int32(3), []string{"a", "b"}, []string{"a", "b"}}, 201 {int64(2), []int{100, 200, 300}, []int{100, 200}}, 202 {100, []int{100, 200}, []int{100, 200}}, 203 {"1", []int{100, 200, 300}, []int{100}}, 204 {int64(-1), []int{100, 200, 300}, false}, 205 {"noint", []int{100, 200, 300}, false}, 206 {1, nil, false}, 207 {nil, []int{100}, false}, 208 {1, t, false}, 209 {1, (*string)(nil), false}, 210 } { 211 errMsg := fmt.Sprintf("[%d] %v", i, test) 212 213 result, err := ns.First(test.limit, test.seq) 214 215 if b, ok := test.expect.(bool); ok && !b { 216 require.Error(t, err, errMsg) 217 continue 218 } 219 220 require.NoError(t, err, errMsg) 221 assert.Equal(t, test.expect, result, errMsg) 222 } 223 } 224 225 func TestIn(t *testing.T) { 226 t.Parallel() 227 228 ns := New(&deps.Deps{}) 229 230 for i, test := range []struct { 231 l1 interface{} 232 l2 interface{} 233 expect bool 234 }{ 235 {[]string{"a", "b", "c"}, "b", true}, 236 {[]interface{}{"a", "b", "c"}, "b", true}, 237 {[]interface{}{"a", "b", "c"}, "d", false}, 238 {[]string{"a", "b", "c"}, "d", false}, 239 {[]string{"a", "12", "c"}, 12, false}, 240 {[]string{"a", "b", "c"}, nil, false}, 241 {[]int{1, 2, 4}, 2, true}, 242 {[]interface{}{1, 2, 4}, 2, true}, 243 {[]interface{}{1, 2, 4}, nil, false}, 244 {[]interface{}{nil}, nil, false}, 245 {[]int{1, 2, 4}, 3, false}, 246 {[]float64{1.23, 2.45, 4.67}, 1.23, true}, 247 {[]float64{1.234567, 2.45, 4.67}, 1.234568, false}, 248 {[]float64{1, 2, 3}, 1, true}, 249 {[]float32{1, 2, 3}, 1, true}, 250 {"this substring should be found", "substring", true}, 251 {"this substring should not be found", "subseastring", false}, 252 {nil, "foo", false}, 253 } { 254 255 errMsg := fmt.Sprintf("[%d] %v", i, test) 256 257 result := ns.In(test.l1, test.l2) 258 assert.Equal(t, test.expect, result, errMsg) 259 } 260 } 261 262 type page struct { 263 Title string 264 } 265 266 func (p page) String() string { 267 return "p-" + p.Title 268 } 269 270 type pagesPtr []*page 271 type pagesVals []page 272 273 func TestIntersect(t *testing.T) { 274 t.Parallel() 275 276 ns := New(&deps.Deps{}) 277 278 var ( 279 p1 = &page{"A"} 280 p2 = &page{"B"} 281 p3 = &page{"C"} 282 p4 = &page{"D"} 283 284 p1v = page{"A"} 285 p2v = page{"B"} 286 p3v = page{"C"} 287 p4v = page{"D"} 288 ) 289 290 for i, test := range []struct { 291 l1, l2 interface{} 292 expect interface{} 293 }{ 294 {[]string{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []string{"a", "b"}}, 295 {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b"}}, 296 {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{}}, 297 {[]string{}, []string{}, []string{}}, 298 {[]string{"a", "b"}, nil, []interface{}{}}, 299 {nil, []string{"a", "b"}, []interface{}{}}, 300 {nil, nil, []interface{}{}}, 301 {[]string{"1", "2"}, []int{1, 2}, []string{}}, 302 {[]int{1, 2}, []string{"1", "2"}, []int{}}, 303 {[]int{1, 2, 4}, []int{2, 4}, []int{2, 4}}, 304 {[]int{2, 4}, []int{1, 2, 4}, []int{2, 4}}, 305 {[]int{1, 2, 4}, []int{3, 6}, []int{}}, 306 {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4}}, 307 308 // errors 309 {"not array or slice", []string{"a"}, false}, 310 {[]string{"a"}, "not array or slice", false}, 311 312 // []interface{} ∩ []interface{} 313 {[]interface{}{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b"}}, 314 {[]interface{}{1, 2, 3}, []interface{}{1, 2, 2}, []interface{}{1, 2}}, 315 {[]interface{}{int8(1), int8(2), int8(3)}, []interface{}{int8(1), int8(2), int8(2)}, []interface{}{int8(1), int8(2)}}, 316 {[]interface{}{int16(1), int16(2), int16(3)}, []interface{}{int16(1), int16(2), int16(2)}, []interface{}{int16(1), int16(2)}}, 317 {[]interface{}{int32(1), int32(2), int32(3)}, []interface{}{int32(1), int32(2), int32(2)}, []interface{}{int32(1), int32(2)}}, 318 {[]interface{}{int64(1), int64(2), int64(3)}, []interface{}{int64(1), int64(2), int64(2)}, []interface{}{int64(1), int64(2)}}, 319 {[]interface{}{float32(1), float32(2), float32(3)}, []interface{}{float32(1), float32(2), float32(2)}, []interface{}{float32(1), float32(2)}}, 320 {[]interface{}{float64(1), float64(2), float64(3)}, []interface{}{float64(1), float64(2), float64(2)}, []interface{}{float64(1), float64(2)}}, 321 322 // []interface{} ∩ []T 323 {[]interface{}{"a", "b", "c"}, []string{"a", "b", "b"}, []interface{}{"a", "b"}}, 324 {[]interface{}{1, 2, 3}, []int{1, 2, 2}, []interface{}{1, 2}}, 325 {[]interface{}{int8(1), int8(2), int8(3)}, []int8{1, 2, 2}, []interface{}{int8(1), int8(2)}}, 326 {[]interface{}{int16(1), int16(2), int16(3)}, []int16{1, 2, 2}, []interface{}{int16(1), int16(2)}}, 327 {[]interface{}{int32(1), int32(2), int32(3)}, []int32{1, 2, 2}, []interface{}{int32(1), int32(2)}}, 328 {[]interface{}{int64(1), int64(2), int64(3)}, []int64{1, 2, 2}, []interface{}{int64(1), int64(2)}}, 329 {[]interface{}{uint(1), uint(2), uint(3)}, []uint{1, 2, 2}, []interface{}{uint(1), uint(2)}}, 330 {[]interface{}{float32(1), float32(2), float32(3)}, []float32{1, 2, 2}, []interface{}{float32(1), float32(2)}}, 331 {[]interface{}{float64(1), float64(2), float64(3)}, []float64{1, 2, 2}, []interface{}{float64(1), float64(2)}}, 332 333 // []T ∩ []interface{} 334 {[]string{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []string{"a", "b"}}, 335 {[]int{1, 2, 3}, []interface{}{1, 2, 2}, []int{1, 2}}, 336 {[]int8{1, 2, 3}, []interface{}{int8(1), int8(2), int8(2)}, []int8{1, 2}}, 337 {[]int16{1, 2, 3}, []interface{}{int16(1), int16(2), int16(2)}, []int16{1, 2}}, 338 {[]int32{1, 2, 3}, []interface{}{int32(1), int32(2), int32(2)}, []int32{1, 2}}, 339 {[]int64{1, 2, 3}, []interface{}{int64(1), int64(2), int64(2)}, []int64{1, 2}}, 340 {[]float32{1, 2, 3}, []interface{}{float32(1), float32(2), float32(2)}, []float32{1, 2}}, 341 {[]float64{1, 2, 3}, []interface{}{float64(1), float64(2), float64(2)}, []float64{1, 2}}, 342 343 // Structs 344 {pagesPtr{p1, p4, p2, p3}, pagesPtr{p4, p2, p2}, pagesPtr{p4, p2}}, 345 {pagesVals{p1v, p4v, p2v, p3v}, pagesVals{p1v, p3v, p3v}, pagesVals{p1v, p3v}}, 346 {[]interface{}{p1, p4, p2, p3}, []interface{}{p4, p2, p2}, []interface{}{p4, p2}}, 347 {[]interface{}{p1v, p4v, p2v, p3v}, []interface{}{p1v, p3v, p3v}, []interface{}{p1v, p3v}}, 348 {pagesPtr{p1, p4, p2, p3}, pagesPtr{}, pagesPtr{}}, 349 {pagesVals{}, pagesVals{p1v, p3v, p3v}, pagesVals{}}, 350 {[]interface{}{p1, p4, p2, p3}, []interface{}{}, []interface{}{}}, 351 {[]interface{}{}, []interface{}{p1v, p3v, p3v}, []interface{}{}}, 352 } { 353 354 errMsg := fmt.Sprintf("[%d]", test) 355 356 result, err := ns.Intersect(test.l1, test.l2) 357 358 if b, ok := test.expect.(bool); ok && !b { 359 require.Error(t, err, errMsg) 360 continue 361 } 362 363 assert.NoError(t, err, errMsg) 364 if !reflect.DeepEqual(result, test.expect) { 365 t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect) 366 } 367 } 368 } 369 370 func TestIsSet(t *testing.T) { 371 t.Parallel() 372 373 ns := newTestNs() 374 375 for i, test := range []struct { 376 a interface{} 377 key interface{} 378 expect bool 379 isErr bool 380 errStr string 381 }{ 382 {[]interface{}{1, 2, 3, 5}, 2, true, false, ""}, 383 {[]interface{}{1, 2, 3, 5}, 22, false, false, ""}, 384 385 {map[string]interface{}{"a": 1, "b": 2}, "b", true, false, ""}, 386 {map[string]interface{}{"a": 1, "b": 2}, "bc", false, false, ""}, 387 388 {time.Now(), "Day", false, false, ""}, 389 {nil, "nil", false, false, ""}, 390 } { 391 errMsg := fmt.Sprintf("[%d] %v", i, test) 392 393 result, err := ns.IsSet(test.a, test.key) 394 if test.isErr { 395 assert.EqualError(t, err, test.errStr, errMsg) 396 continue 397 } 398 399 assert.NoError(t, err, errMsg) 400 assert.Equal(t, test.expect, result, errMsg) 401 } 402 } 403 404 func TestLast(t *testing.T) { 405 t.Parallel() 406 407 ns := New(&deps.Deps{}) 408 409 for i, test := range []struct { 410 limit interface{} 411 seq interface{} 412 expect interface{} 413 }{ 414 {int(2), []string{"a", "b", "c"}, []string{"b", "c"}}, 415 {int32(3), []string{"a", "b"}, []string{"a", "b"}}, 416 {int64(2), []int{100, 200, 300}, []int{200, 300}}, 417 {100, []int{100, 200}, []int{100, 200}}, 418 {"1", []int{100, 200, 300}, []int{300}}, 419 // errors 420 {int64(-1), []int{100, 200, 300}, false}, 421 {"noint", []int{100, 200, 300}, false}, 422 {1, nil, false}, 423 {nil, []int{100}, false}, 424 {1, t, false}, 425 {1, (*string)(nil), false}, 426 } { 427 errMsg := fmt.Sprintf("[%d] %v", i, test) 428 429 result, err := ns.Last(test.limit, test.seq) 430 431 if b, ok := test.expect.(bool); ok && !b { 432 require.Error(t, err, errMsg) 433 continue 434 } 435 436 require.NoError(t, err, errMsg) 437 assert.Equal(t, test.expect, result, errMsg) 438 } 439 } 440 441 func TestQuerify(t *testing.T) { 442 t.Parallel() 443 444 ns := New(&deps.Deps{}) 445 446 for i, test := range []struct { 447 params []interface{} 448 expect interface{} 449 }{ 450 {[]interface{}{"a", "b"}, "a=b"}, 451 {[]interface{}{"a", "b", "c", "d", "f", " &"}, `a=b&c=d&f=+%26`}, 452 // errors 453 {[]interface{}{5, "b"}, false}, 454 {[]interface{}{"a", "b", "c"}, false}, 455 } { 456 errMsg := fmt.Sprintf("[%d] %v", i, test.params) 457 458 result, err := ns.Querify(test.params...) 459 460 if b, ok := test.expect.(bool); ok && !b { 461 require.Error(t, err, errMsg) 462 continue 463 } 464 465 require.NoError(t, err, errMsg) 466 assert.Equal(t, test.expect, result, errMsg) 467 } 468 } 469 470 func TestSeq(t *testing.T) { 471 t.Parallel() 472 473 ns := New(&deps.Deps{}) 474 475 for i, test := range []struct { 476 args []interface{} 477 expect interface{} 478 }{ 479 {[]interface{}{-2, 5}, []int{-2, -1, 0, 1, 2, 3, 4, 5}}, 480 {[]interface{}{1, 2, 4}, []int{1, 3}}, 481 {[]interface{}{1}, []int{1}}, 482 {[]interface{}{3}, []int{1, 2, 3}}, 483 {[]interface{}{3.2}, []int{1, 2, 3}}, 484 {[]interface{}{0}, []int{}}, 485 {[]interface{}{-1}, []int{-1}}, 486 {[]interface{}{-3}, []int{-1, -2, -3}}, 487 {[]interface{}{3, -2}, []int{3, 2, 1, 0, -1, -2}}, 488 {[]interface{}{6, -2, 2}, []int{6, 4, 2}}, 489 // errors 490 {[]interface{}{1, 0, 2}, false}, 491 {[]interface{}{1, -1, 2}, false}, 492 {[]interface{}{2, 1, 1}, false}, 493 {[]interface{}{2, 1, 1, 1}, false}, 494 {[]interface{}{2001}, false}, 495 {[]interface{}{}, false}, 496 {[]interface{}{0, -1000000}, false}, 497 {[]interface{}{tstNoStringer{}}, false}, 498 {nil, false}, 499 } { 500 errMsg := fmt.Sprintf("[%d] %v", i, test) 501 502 result, err := ns.Seq(test.args...) 503 504 if b, ok := test.expect.(bool); ok && !b { 505 require.Error(t, err, errMsg) 506 continue 507 } 508 509 require.NoError(t, err, errMsg) 510 assert.Equal(t, test.expect, result, errMsg) 511 } 512 } 513 514 func TestShuffle(t *testing.T) { 515 t.Parallel() 516 517 ns := New(&deps.Deps{}) 518 519 for i, test := range []struct { 520 seq interface{} 521 success bool 522 }{ 523 {[]string{"a", "b", "c", "d"}, true}, 524 {[]int{100, 200, 300}, true}, 525 {[]int{100, 200, 300}, true}, 526 {[]int{100, 200}, true}, 527 {[]string{"a", "b"}, true}, 528 {[]int{100, 200, 300}, true}, 529 {[]int{100, 200, 300}, true}, 530 {[]int{100}, true}, 531 // errors 532 {nil, false}, 533 {t, false}, 534 {(*string)(nil), false}, 535 } { 536 errMsg := fmt.Sprintf("[%d] %v", i, test) 537 538 result, err := ns.Shuffle(test.seq) 539 540 if !test.success { 541 require.Error(t, err, errMsg) 542 continue 543 } 544 545 require.NoError(t, err, errMsg) 546 547 resultv := reflect.ValueOf(result) 548 seqv := reflect.ValueOf(test.seq) 549 550 assert.Equal(t, resultv.Len(), seqv.Len(), errMsg) 551 } 552 } 553 554 func TestShuffleRandomising(t *testing.T) { 555 t.Parallel() 556 557 ns := New(&deps.Deps{}) 558 559 // Note that this test can fail with false negative result if the shuffle 560 // of the sequence happens to be the same as the original sequence. However 561 // the propability of the event is 10^-158 which is negligible. 562 seqLen := 100 563 rand.Seed(time.Now().UTC().UnixNano()) 564 565 for _, test := range []struct { 566 seq []int 567 }{ 568 {rand.Perm(seqLen)}, 569 } { 570 result, err := ns.Shuffle(test.seq) 571 resultv := reflect.ValueOf(result) 572 573 require.NoError(t, err) 574 575 allSame := true 576 for i, v := range test.seq { 577 allSame = allSame && (resultv.Index(i).Interface() == v) 578 } 579 580 assert.False(t, allSame, "Expected sequence to be shuffled but was in the same order") 581 } 582 } 583 584 func TestSlice(t *testing.T) { 585 t.Parallel() 586 587 ns := New(&deps.Deps{}) 588 589 for i, test := range []struct { 590 args []interface{} 591 }{ 592 {[]interface{}{"a", "b"}}, 593 // errors 594 {[]interface{}{5, "b"}}, 595 {[]interface{}{tstNoStringer{}}}, 596 } { 597 errMsg := fmt.Sprintf("[%d] %v", i, test.args) 598 599 result := ns.Slice(test.args...) 600 601 assert.Equal(t, test.args, result, errMsg) 602 } 603 } 604 605 func TestUnion(t *testing.T) { 606 t.Parallel() 607 608 ns := New(&deps.Deps{}) 609 610 var ( 611 p1 = &page{"A"} 612 p2 = &page{"B"} 613 // p3 = &page{"C"} 614 p4 = &page{"D"} 615 616 p1v = page{"A"} 617 //p2v = page{"B"} 618 p3v = page{"C"} 619 //p4v = page{"D"} 620 ) 621 622 for i, test := range []struct { 623 l1 interface{} 624 l2 interface{} 625 expect interface{} 626 isErr bool 627 }{ 628 {nil, nil, []interface{}{}, false}, 629 {nil, []string{"a", "b"}, []string{"a", "b"}, false}, 630 {[]string{"a", "b"}, nil, []string{"a", "b"}, false}, 631 632 // []A ∪ []B 633 {[]string{"1", "2"}, []int{3}, []string{}, false}, 634 {[]int{1, 2}, []string{"1", "2"}, []int{}, false}, 635 636 // []T ∪ []T 637 {[]string{"a", "b", "c", "c"}, []string{"a", "b", "b"}, []string{"a", "b", "c"}, false}, 638 {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b", "c"}, false}, 639 {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{"a", "b", "c", "d", "e"}, false}, 640 {[]string{}, []string{}, []string{}, false}, 641 {[]int{1, 2, 3}, []int{3, 4, 5}, []int{1, 2, 3, 4, 5}, false}, 642 {[]int{1, 2, 3}, []int{1, 2, 3}, []int{1, 2, 3}, false}, 643 {[]int{1, 2, 4}, []int{2, 4}, []int{1, 2, 4}, false}, 644 {[]int{2, 4}, []int{1, 2, 4}, []int{2, 4, 1}, false}, 645 {[]int{1, 2, 4}, []int{3, 6}, []int{1, 2, 4, 3, 6}, false}, 646 {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false}, 647 {[]interface{}{"a", "b", "c", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b", "c"}, false}, 648 649 // []T ∪ []interface{} 650 {[]string{"1", "2"}, []interface{}{"9"}, []string{"1", "2", "9"}, false}, 651 {[]int{2, 4}, []interface{}{1, 2, 4}, []int{2, 4, 1}, false}, 652 {[]int8{2, 4}, []interface{}{int8(1), int8(2), int8(4)}, []int8{2, 4, 1}, false}, 653 {[]int8{2, 4}, []interface{}{1, 2, 4}, []int8{2, 4, 1}, false}, 654 {[]int16{2, 4}, []interface{}{1, 2, 4}, []int16{2, 4, 1}, false}, 655 {[]int32{2, 4}, []interface{}{1, 2, 4}, []int32{2, 4, 1}, false}, 656 {[]int64{2, 4}, []interface{}{1, 2, 4}, []int64{2, 4, 1}, false}, 657 658 {[]float64{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false}, 659 {[]float32{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float32{2.2, 4.4, 1.1}, false}, 660 661 // []interface{} ∪ []T 662 {[]interface{}{"a", "b", "c", "c"}, []string{"a", "b", "d"}, []interface{}{"a", "b", "c", "d"}, false}, 663 {[]interface{}{}, []string{}, []interface{}{}, false}, 664 {[]interface{}{1, 2}, []int{2, 3}, []interface{}{1, 2, 3}, false}, 665 {[]interface{}{1, 2}, []int8{2, 3}, []interface{}{1, 2, 3}, false}, // 28 666 {[]interface{}{uint(1), uint(2)}, []uint{2, 3}, []interface{}{uint(1), uint(2), uint(3)}, false}, 667 {[]interface{}{1.1, 2.2}, []float64{2.2, 3.3}, []interface{}{1.1, 2.2, 3.3}, false}, 668 669 // Structs 670 {pagesPtr{p1, p4}, pagesPtr{p4, p2, p2}, pagesPtr{p1, p4, p2}, false}, 671 {pagesVals{p1v}, pagesVals{p3v, p3v}, pagesVals{p1v, p3v}, false}, 672 {[]interface{}{p1, p4}, []interface{}{p4, p2, p2}, []interface{}{p1, p4, p2}, false}, 673 {[]interface{}{p1v}, []interface{}{p3v, p3v}, []interface{}{p1v, p3v}, false}, 674 // #3686 675 {[]interface{}{p1v}, []interface{}{}, []interface{}{p1v}, false}, 676 {[]interface{}{}, []interface{}{p1v}, []interface{}{p1v}, false}, 677 {pagesPtr{p1}, pagesPtr{}, pagesPtr{p1}, false}, 678 {pagesVals{p1v}, pagesVals{}, pagesVals{p1v}, false}, 679 {pagesPtr{}, pagesPtr{p1}, pagesPtr{p1}, false}, 680 {pagesVals{}, pagesVals{p1v}, pagesVals{p1v}, false}, 681 682 // errors 683 {"not array or slice", []string{"a"}, false, true}, 684 {[]string{"a"}, "not array or slice", false, true}, 685 } { 686 687 errMsg := fmt.Sprintf("[%d] %v", i, test) 688 689 result, err := ns.Union(test.l1, test.l2) 690 if test.isErr { 691 assert.Error(t, err, errMsg) 692 continue 693 } 694 695 assert.NoError(t, err, errMsg) 696 if !reflect.DeepEqual(result, test.expect) { 697 t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect) 698 } 699 } 700 } 701 702 func TestUniq(t *testing.T) { 703 t.Parallel() 704 705 ns := New(&deps.Deps{}) 706 for i, test := range []struct { 707 l interface{} 708 expect interface{} 709 isErr bool 710 }{ 711 {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, false}, 712 {[]string{"a", "b", "c", "c"}, []string{"a", "b", "c"}, false}, 713 {[]string{"a", "b", "b", "c"}, []string{"a", "b", "c"}, false}, 714 {[]string{"a", "b", "c", "b"}, []string{"a", "b", "c"}, false}, 715 {[]int{1, 2, 3}, []int{1, 2, 3}, false}, 716 {[]int{1, 2, 3, 3}, []int{1, 2, 3}, false}, 717 {[]int{1, 2, 2, 3}, []int{1, 2, 3}, false}, 718 {[]int{1, 2, 3, 2}, []int{1, 2, 3}, false}, 719 {[4]int{1, 2, 3, 2}, []int{1, 2, 3}, false}, 720 {nil, make([]interface{}, 0), false}, 721 // should-errors 722 {1, 1, true}, 723 {"foo", "fo", true}, 724 } { 725 errMsg := fmt.Sprintf("[%d] %v", i, test) 726 727 result, err := ns.Uniq(test.l) 728 if test.isErr { 729 assert.Error(t, err, errMsg) 730 continue 731 } 732 733 assert.NoError(t, err, errMsg) 734 assert.Equal(t, test.expect, result, errMsg) 735 } 736 } 737 738 func (x *TstX) TstRp() string { 739 return "r" + x.A 740 } 741 742 func (x TstX) TstRv() string { 743 return "r" + x.B 744 } 745 746 func (x TstX) unexportedMethod() string { 747 return x.unexported 748 } 749 750 func (x TstX) MethodWithArg(s string) string { 751 return s 752 } 753 754 func (x TstX) MethodReturnNothing() {} 755 756 func (x TstX) MethodReturnErrorOnly() error { 757 return errors.New("some error occurred") 758 } 759 760 func (x TstX) MethodReturnTwoValues() (string, string) { 761 return "foo", "bar" 762 } 763 764 func (x TstX) MethodReturnValueWithError() (string, error) { 765 return "", errors.New("some error occurred") 766 } 767 768 func (x TstX) String() string { 769 return fmt.Sprintf("A: %s, B: %s", x.A, x.B) 770 } 771 772 type TstX struct { 773 A, B string 774 unexported string 775 } 776 777 func newDeps(cfg config.Provider) *deps.Deps { 778 l := langs.NewLanguage("en", cfg) 779 l.Set("i18nDir", "i18n") 780 cs, err := helpers.NewContentSpec(l) 781 if err != nil { 782 panic(err) 783 } 784 return &deps.Deps{ 785 Cfg: cfg, 786 Fs: hugofs.NewMem(l), 787 ContentSpec: cs, 788 Log: jww.NewNotepad(jww.LevelError, jww.LevelError, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime), 789 } 790 } 791 792 func newTestNs() *Namespace { 793 v := viper.New() 794 v.Set("contentDir", "content") 795 return New(newDeps(v)) 796 }