hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

compare_test.go (10607B)

    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 compare
   15 
   16 import (
   17 	"path"
   18 	"reflect"
   19 	"runtime"
   20 	"testing"
   21 	"time"
   22 
   23 	"github.com/gohugoio/hugo/htesting/hqt"
   24 
   25 	qt "github.com/frankban/quicktest"
   26 	"github.com/gohugoio/hugo/common/hugo"
   27 	"github.com/spf13/cast"
   28 )
   29 
   30 type T struct {
   31 	NonEmptyInterfaceNil      I
   32 	NonEmptyInterfaceTypedNil I
   33 }
   34 
   35 type I interface {
   36 	Foo() string
   37 }
   38 
   39 func (t *T) Foo() string {
   40 	return "foo"
   41 }
   42 
   43 var testT = &T{
   44 	NonEmptyInterfaceTypedNil: (*T)(nil),
   45 }
   46 
   47 type (
   48 	tstEqerType1 string
   49 	tstEqerType2 string
   50 )
   51 
   52 func (t tstEqerType2) Eq(other any) bool {
   53 	return cast.ToString(t) == cast.ToString(other)
   54 }
   55 
   56 func (t tstEqerType2) String() string {
   57 	return string(t)
   58 }
   59 
   60 func (t tstEqerType1) Eq(other any) bool {
   61 	return cast.ToString(t) == cast.ToString(other)
   62 }
   63 
   64 func (t tstEqerType1) String() string {
   65 	return string(t)
   66 }
   67 
   68 type stringType string
   69 
   70 type tstCompareType int
   71 
   72 const (
   73 	tstEq tstCompareType = iota
   74 	tstNe
   75 	tstGt
   76 	tstGe
   77 	tstLt
   78 	tstLe
   79 )
   80 
   81 func tstIsEq(tp tstCompareType) bool { return tp == tstEq || tp == tstGe || tp == tstLe }
   82 func tstIsGt(tp tstCompareType) bool { return tp == tstGt || tp == tstGe }
   83 func tstIsLt(tp tstCompareType) bool { return tp == tstLt || tp == tstLe }
   84 
   85 func TestDefaultFunc(t *testing.T) {
   86 	t.Parallel()
   87 	c := qt.New(t)
   88 
   89 	then := time.Now()
   90 	now := time.Now()
   91 	ns := New(time.UTC, false)
   92 
   93 	for i, test := range []struct {
   94 		dflt   any
   95 		given  any
   96 		expect any
   97 	}{
   98 		{true, false, false},
   99 		{"5", 0, "5"},
  100 
  101 		{"test1", "set", "set"},
  102 		{"test2", "", "test2"},
  103 		{"test3", nil, "test3"},
  104 
  105 		{[2]int{10, 20}, [2]int{1, 2}, [2]int{1, 2}},
  106 		{[2]int{10, 20}, [0]int{}, [2]int{10, 20}},
  107 		{[2]int{100, 200}, nil, [2]int{100, 200}},
  108 
  109 		{[]string{"one"}, []string{"uno"}, []string{"uno"}},
  110 		{[]string{"two"}, []string{}, []string{"two"}},
  111 		{[]string{"three"}, nil, []string{"three"}},
  112 
  113 		{map[string]int{"one": 1}, map[string]int{"uno": 1}, map[string]int{"uno": 1}},
  114 		{map[string]int{"one": 1}, map[string]int{}, map[string]int{"one": 1}},
  115 		{map[string]int{"two": 2}, nil, map[string]int{"two": 2}},
  116 
  117 		{10, 1, 1},
  118 		{10, 0, 10},
  119 		{20, nil, 20},
  120 
  121 		{float32(10), float32(1), float32(1)},
  122 		{float32(10), 0, float32(10)},
  123 		{float32(20), nil, float32(20)},
  124 
  125 		{complex(2, -2), complex(1, -1), complex(1, -1)},
  126 		{complex(2, -2), complex(0, 0), complex(2, -2)},
  127 		{complex(3, -3), nil, complex(3, -3)},
  128 
  129 		{struct{ f string }{f: "one"}, struct{}{}, struct{}{}},
  130 		{struct{ f string }{f: "two"}, nil, struct{ f string }{f: "two"}},
  131 
  132 		{then, now, now},
  133 		{then, time.Time{}, then},
  134 	} {
  135 
  136 		eq := qt.CmpEquals(hqt.DeepAllowUnexported(test.dflt))
  137 
  138 		errMsg := qt.Commentf("[%d] %v", i, test)
  139 
  140 		result, err := ns.Default(test.dflt, test.given)
  141 
  142 		c.Assert(err, qt.IsNil, errMsg)
  143 		c.Assert(result, eq, test.expect, errMsg)
  144 	}
  145 }
  146 
  147 func TestCompare(t *testing.T) {
  148 	t.Parallel()
  149 
  150 	n := New(time.UTC, false)
  151 
  152 	twoEq := func(a, b any) bool {
  153 		return n.Eq(a, b)
  154 	}
  155 
  156 	twoGt := func(a, b any) bool {
  157 		return n.Gt(a, b)
  158 	}
  159 
  160 	twoLt := func(a, b any) bool {
  161 		return n.Lt(a, b)
  162 	}
  163 
  164 	twoGe := func(a, b any) bool {
  165 		return n.Ge(a, b)
  166 	}
  167 
  168 	twoLe := func(a, b any) bool {
  169 		return n.Le(a, b)
  170 	}
  171 
  172 	twoNe := func(a, b any) bool {
  173 		return n.Ne(a, b)
  174 	}
  175 
  176 	for _, test := range []struct {
  177 		tstCompareType
  178 		funcUnderTest func(a, b any) bool
  179 	}{
  180 		{tstGt, twoGt},
  181 		{tstLt, twoLt},
  182 		{tstGe, twoGe},
  183 		{tstLe, twoLe},
  184 		{tstEq, twoEq},
  185 		{tstNe, twoNe},
  186 	} {
  187 		doTestCompare(t, test.tstCompareType, test.funcUnderTest)
  188 	}
  189 }
  190 
  191 func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b any) bool) {
  192 	for i, test := range []struct {
  193 		left            any
  194 		right           any
  195 		expectIndicator int
  196 	}{
  197 		{5, 8, -1},
  198 		{8, 5, 1},
  199 		{5, 5, 0},
  200 		{int(5), int64(5), 0},
  201 		{int32(5), int(5), 0},
  202 		{int16(4), int(5), -1},
  203 		{uint(15), uint64(15), 0},
  204 		{-2, 1, -1},
  205 		{2, -5, 1},
  206 		{0.0, 1.23, -1},
  207 		{1.1, 1.1, 0},
  208 		{float32(1.0), float64(1.0), 0},
  209 		{1.23, 0.0, 1},
  210 		{"5", "5", 0},
  211 		{"8", "5", 1},
  212 		{"5", "0001", 1},
  213 		{[]int{100, 99}, []int{1, 2, 3, 4}, -1},
  214 		{cast.ToTime("2015-11-20"), cast.ToTime("2015-11-20"), 0},
  215 		{cast.ToTime("2015-11-19"), cast.ToTime("2015-11-20"), -1},
  216 		{cast.ToTime("2015-11-20"), cast.ToTime("2015-11-19"), 1},
  217 		{"a", "a", 0},
  218 		{"a", "b", -1},
  219 		{"b", "a", 1},
  220 		{tstEqerType1("a"), tstEqerType1("a"), 0},
  221 		{tstEqerType1("a"), tstEqerType2("a"), 0},
  222 		{tstEqerType2("a"), tstEqerType1("a"), 0},
  223 		{tstEqerType2("a"), tstEqerType1("b"), -1},
  224 		{hugo.MustParseVersion("0.32.1").Version(), hugo.MustParseVersion("0.32").Version(), 1},
  225 		{hugo.MustParseVersion("0.35").Version(), hugo.MustParseVersion("0.32").Version(), 1},
  226 		{hugo.MustParseVersion("0.36").Version(), hugo.MustParseVersion("0.36").Version(), 0},
  227 		{hugo.MustParseVersion("0.32").Version(), hugo.MustParseVersion("0.36").Version(), -1},
  228 		{hugo.MustParseVersion("0.32").Version(), "0.36", -1},
  229 		{"0.36", hugo.MustParseVersion("0.32").Version(), 1},
  230 		{"0.36", hugo.MustParseVersion("0.36").Version(), 0},
  231 		{"0.37", hugo.MustParseVersion("0.37-DEV").Version(), 1},
  232 		{"0.37-DEV", hugo.MustParseVersion("0.37").Version(), -1},
  233 		{"0.36", hugo.MustParseVersion("0.37-DEV").Version(), -1},
  234 		{"0.37-DEV", hugo.MustParseVersion("0.37-DEV").Version(), 0},
  235 		// https://github.com/gohugoio/hugo/issues/5905
  236 		{nil, nil, 0},
  237 		{testT.NonEmptyInterfaceNil, nil, 0},
  238 		{testT.NonEmptyInterfaceTypedNil, nil, 0},
  239 	} {
  240 
  241 		result := funcUnderTest(test.left, test.right)
  242 		success := false
  243 
  244 		if test.expectIndicator == 0 {
  245 			if tstIsEq(tp) {
  246 				success = result
  247 			} else {
  248 				success = !result
  249 			}
  250 		}
  251 
  252 		if test.expectIndicator < 0 {
  253 			success = result && (tstIsLt(tp) || tp == tstNe)
  254 			success = success || (!result && !tstIsLt(tp))
  255 		}
  256 
  257 		if test.expectIndicator > 0 {
  258 			success = result && (tstIsGt(tp) || tp == tstNe)
  259 			success = success || (!result && (!tstIsGt(tp) || tp != tstNe))
  260 		}
  261 
  262 		if !success {
  263 			t.Fatalf("[%d][%s] %v compared to %v: %t", i, path.Base(runtime.FuncForPC(reflect.ValueOf(funcUnderTest).Pointer()).Name()), test.left, test.right, result)
  264 		}
  265 	}
  266 }
  267 
  268 func TestEqualExtend(t *testing.T) {
  269 	t.Parallel()
  270 	c := qt.New(t)
  271 
  272 	ns := New(time.UTC, false)
  273 
  274 	for _, test := range []struct {
  275 		first  any
  276 		others []any
  277 		expect bool
  278 	}{
  279 		{1, []any{1, 2}, true},
  280 		{1, []any{2, 1}, true},
  281 		{1, []any{2, 3}, false},
  282 		{tstEqerType1("a"), []any{tstEqerType1("a"), tstEqerType1("b")}, true},
  283 		{tstEqerType1("a"), []any{tstEqerType1("b"), tstEqerType1("a")}, true},
  284 		{tstEqerType1("a"), []any{tstEqerType1("b"), tstEqerType1("c")}, false},
  285 	} {
  286 
  287 		result := ns.Eq(test.first, test.others...)
  288 
  289 		c.Assert(result, qt.Equals, test.expect)
  290 	}
  291 }
  292 
  293 func TestNotEqualExtend(t *testing.T) {
  294 	t.Parallel()
  295 	c := qt.New(t)
  296 
  297 	ns := New(time.UTC, false)
  298 
  299 	for _, test := range []struct {
  300 		first  any
  301 		others []any
  302 		expect bool
  303 	}{
  304 		{1, []any{2, 3}, true},
  305 		{1, []any{2, 1}, false},
  306 		{1, []any{1, 2}, false},
  307 	} {
  308 		result := ns.Ne(test.first, test.others...)
  309 		c.Assert(result, qt.Equals, test.expect)
  310 	}
  311 }
  312 
  313 func TestGreaterEqualExtend(t *testing.T) {
  314 	t.Parallel()
  315 	c := qt.New(t)
  316 
  317 	ns := New(time.UTC, false)
  318 
  319 	for _, test := range []struct {
  320 		first  any
  321 		others []any
  322 		expect bool
  323 	}{
  324 		{5, []any{2, 3}, true},
  325 		{5, []any{5, 5}, true},
  326 		{3, []any{4, 2}, false},
  327 		{3, []any{2, 4}, false},
  328 	} {
  329 		result := ns.Ge(test.first, test.others...)
  330 		c.Assert(result, qt.Equals, test.expect)
  331 	}
  332 }
  333 
  334 func TestGreaterThanExtend(t *testing.T) {
  335 	t.Parallel()
  336 	c := qt.New(t)
  337 
  338 	ns := New(time.UTC, false)
  339 
  340 	for _, test := range []struct {
  341 		first  any
  342 		others []any
  343 		expect bool
  344 	}{
  345 		{5, []any{2, 3}, true},
  346 		{5, []any{5, 4}, false},
  347 		{3, []any{4, 2}, false},
  348 	} {
  349 		result := ns.Gt(test.first, test.others...)
  350 		c.Assert(result, qt.Equals, test.expect)
  351 	}
  352 }
  353 
  354 func TestLessEqualExtend(t *testing.T) {
  355 	t.Parallel()
  356 	c := qt.New(t)
  357 
  358 	ns := New(time.UTC, false)
  359 
  360 	for _, test := range []struct {
  361 		first  any
  362 		others []any
  363 		expect bool
  364 	}{
  365 		{1, []any{2, 3}, true},
  366 		{1, []any{1, 2}, true},
  367 		{2, []any{1, 2}, false},
  368 		{3, []any{2, 4}, false},
  369 	} {
  370 		result := ns.Le(test.first, test.others...)
  371 		c.Assert(result, qt.Equals, test.expect)
  372 	}
  373 }
  374 
  375 func TestLessThanExtend(t *testing.T) {
  376 	t.Parallel()
  377 	c := qt.New(t)
  378 
  379 	ns := New(time.UTC, false)
  380 
  381 	for _, test := range []struct {
  382 		first  any
  383 		others []any
  384 		expect bool
  385 	}{
  386 		{1, []any{2, 3}, true},
  387 		{1, []any{1, 2}, false},
  388 		{2, []any{1, 2}, false},
  389 		{3, []any{2, 4}, false},
  390 	} {
  391 		result := ns.Lt(test.first, test.others...)
  392 		c.Assert(result, qt.Equals, test.expect)
  393 	}
  394 }
  395 
  396 func TestCase(t *testing.T) {
  397 	c := qt.New(t)
  398 	n := New(time.UTC, false)
  399 
  400 	c.Assert(n.Eq("az", "az"), qt.Equals, true)
  401 	c.Assert(n.Eq("az", stringType("az")), qt.Equals, true)
  402 }
  403 
  404 func TestStringType(t *testing.T) {
  405 	c := qt.New(t)
  406 	n := New(time.UTC, true)
  407 
  408 	c.Assert(n.Lt("az", "Za"), qt.Equals, true)
  409 	c.Assert(n.Gt("ab", "Ab"), qt.Equals, true)
  410 }
  411 
  412 func TestTimeUnix(t *testing.T) {
  413 	t.Parallel()
  414 	n := New(time.UTC, false)
  415 	var sec int64 = 1234567890
  416 	tv := reflect.ValueOf(time.Unix(sec, 0))
  417 	i := 1
  418 
  419 	res := n.toTimeUnix(tv)
  420 	if sec != res {
  421 		t.Errorf("[%d] timeUnix got %v but expected %v", i, res, sec)
  422 	}
  423 
  424 	i++
  425 	func(t *testing.T) {
  426 		defer func() {
  427 			if err := recover(); err == nil {
  428 				t.Errorf("[%d] timeUnix didn't return an expected error", i)
  429 			}
  430 		}()
  431 		iv := reflect.ValueOf(sec)
  432 		n.toTimeUnix(iv)
  433 	}(t)
  434 }
  435 
  436 func TestConditional(t *testing.T) {
  437 	c := qt.New(t)
  438 	n := New(time.UTC, false)
  439 	a, b := "a", "b"
  440 
  441 	c.Assert(n.Conditional(true, a, b), qt.Equals, a)
  442 	c.Assert(n.Conditional(false, a, b), qt.Equals, b)
  443 }
  444 
  445 // Issue 9462
  446 func TestComparisonArgCount(t *testing.T) {
  447 	t.Parallel()
  448 	c := qt.New(t)
  449 
  450 	ns := New(time.UTC, false)
  451 
  452 	panicMsg := "missing arguments for comparison"
  453 
  454 	c.Assert(func() { ns.Eq(1) }, qt.PanicMatches, panicMsg)
  455 	c.Assert(func() { ns.Ge(1) }, qt.PanicMatches, panicMsg)
  456 	c.Assert(func() { ns.Gt(1) }, qt.PanicMatches, panicMsg)
  457 	c.Assert(func() { ns.Le(1) }, qt.PanicMatches, panicMsg)
  458 	c.Assert(func() { ns.Lt(1) }, qt.PanicMatches, panicMsg)
  459 	c.Assert(func() { ns.Ne(1) }, qt.PanicMatches, panicMsg)
  460 }