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  }