github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/tpl/math/math_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 math
    15  
    16  import (
    17  	"math"
    18  	"testing"
    19  
    20  	qt "github.com/frankban/quicktest"
    21  )
    22  
    23  func TestBasicNSArithmetic(t *testing.T) {
    24  	t.Parallel()
    25  	c := qt.New(t)
    26  
    27  	ns := New()
    28  
    29  	for _, test := range []struct {
    30  		fn     func(a, b any) (any, error)
    31  		a      any
    32  		b      any
    33  		expect any
    34  	}{
    35  		{ns.Add, 4, 2, int64(6)},
    36  		{ns.Add, 1.0, "foo", false},
    37  		{ns.Sub, 4, 2, int64(2)},
    38  		{ns.Sub, 1.0, "foo", false},
    39  		{ns.Mul, 4, 2, int64(8)},
    40  		{ns.Mul, 1.0, "foo", false},
    41  		{ns.Div, 4, 2, int64(2)},
    42  		{ns.Div, 1.0, "foo", false},
    43  	} {
    44  
    45  		result, err := test.fn(test.a, test.b)
    46  
    47  		if b, ok := test.expect.(bool); ok && !b {
    48  			c.Assert(err, qt.Not(qt.IsNil))
    49  			continue
    50  		}
    51  
    52  		c.Assert(err, qt.IsNil)
    53  		c.Assert(result, qt.Equals, test.expect)
    54  	}
    55  }
    56  
    57  func TestCeil(t *testing.T) {
    58  	t.Parallel()
    59  	c := qt.New(t)
    60  	ns := New()
    61  
    62  	for _, test := range []struct {
    63  		x      any
    64  		expect any
    65  	}{
    66  		{0.1, 1.0},
    67  		{0.5, 1.0},
    68  		{1.1, 2.0},
    69  		{1.5, 2.0},
    70  		{-0.1, 0.0},
    71  		{-0.5, 0.0},
    72  		{-1.1, -1.0},
    73  		{-1.5, -1.0},
    74  		{"abc", false},
    75  	} {
    76  
    77  		result, err := ns.Ceil(test.x)
    78  
    79  		if b, ok := test.expect.(bool); ok && !b {
    80  			c.Assert(err, qt.Not(qt.IsNil))
    81  			continue
    82  		}
    83  
    84  		c.Assert(err, qt.IsNil)
    85  		c.Assert(result, qt.Equals, test.expect)
    86  	}
    87  }
    88  
    89  func TestFloor(t *testing.T) {
    90  	t.Parallel()
    91  	c := qt.New(t)
    92  
    93  	ns := New()
    94  
    95  	for _, test := range []struct {
    96  		x      any
    97  		expect any
    98  	}{
    99  		{0.1, 0.0},
   100  		{0.5, 0.0},
   101  		{1.1, 1.0},
   102  		{1.5, 1.0},
   103  		{-0.1, -1.0},
   104  		{-0.5, -1.0},
   105  		{-1.1, -2.0},
   106  		{-1.5, -2.0},
   107  		{"abc", false},
   108  	} {
   109  
   110  		result, err := ns.Floor(test.x)
   111  
   112  		if b, ok := test.expect.(bool); ok && !b {
   113  			c.Assert(err, qt.Not(qt.IsNil))
   114  			continue
   115  		}
   116  
   117  		c.Assert(err, qt.IsNil)
   118  		c.Assert(result, qt.Equals, test.expect)
   119  	}
   120  }
   121  
   122  func TestLog(t *testing.T) {
   123  	t.Parallel()
   124  	c := qt.New(t)
   125  
   126  	ns := New()
   127  
   128  	for _, test := range []struct {
   129  		a      any
   130  		expect any
   131  	}{
   132  		{1, float64(0)},
   133  		{3, float64(1.0986)},
   134  		{0, float64(math.Inf(-1))},
   135  		{1.0, float64(0)},
   136  		{3.1, float64(1.1314)},
   137  		{"abc", false},
   138  	} {
   139  
   140  		result, err := ns.Log(test.a)
   141  
   142  		if b, ok := test.expect.(bool); ok && !b {
   143  			c.Assert(err, qt.Not(qt.IsNil))
   144  			continue
   145  		}
   146  
   147  		// we compare only 4 digits behind point if its a real float
   148  		// otherwise we usually get different float values on the last positions
   149  		if result != math.Inf(-1) {
   150  			result = float64(int(result*10000)) / 10000
   151  		}
   152  
   153  		c.Assert(err, qt.IsNil)
   154  		c.Assert(result, qt.Equals, test.expect)
   155  	}
   156  
   157  	// Separate test for Log(-1) -- returns NaN
   158  	result, err := ns.Log(-1)
   159  	c.Assert(err, qt.IsNil)
   160  	c.Assert(result, qt.Satisfies, math.IsNaN)
   161  }
   162  
   163  func TestSqrt(t *testing.T) {
   164  	t.Parallel()
   165  	c := qt.New(t)
   166  
   167  	ns := New()
   168  
   169  	for _, test := range []struct {
   170  		a      any
   171  		expect any
   172  	}{
   173  		{81, float64(9)},
   174  		{0.25, float64(0.5)},
   175  		{0, float64(0)},
   176  		{"abc", false},
   177  	} {
   178  
   179  		result, err := ns.Sqrt(test.a)
   180  
   181  		if b, ok := test.expect.(bool); ok && !b {
   182  			c.Assert(err, qt.Not(qt.IsNil))
   183  			continue
   184  		}
   185  
   186  		// we compare only 4 digits behind point if its a real float
   187  		// otherwise we usually get different float values on the last positions
   188  		if result != math.Inf(-1) {
   189  			result = float64(int(result*10000)) / 10000
   190  		}
   191  
   192  		c.Assert(err, qt.IsNil)
   193  		c.Assert(result, qt.Equals, test.expect)
   194  	}
   195  
   196  	// Separate test for Sqrt(-1) -- returns NaN
   197  	result, err := ns.Sqrt(-1)
   198  	c.Assert(err, qt.IsNil)
   199  	c.Assert(result, qt.Satisfies, math.IsNaN)
   200  }
   201  
   202  func TestMod(t *testing.T) {
   203  	t.Parallel()
   204  	c := qt.New(t)
   205  
   206  	ns := New()
   207  
   208  	for _, test := range []struct {
   209  		a      any
   210  		b      any
   211  		expect any
   212  	}{
   213  		{3, 2, int64(1)},
   214  		{3, 1, int64(0)},
   215  		{3, 0, false},
   216  		{0, 3, int64(0)},
   217  		{3.1, 2, int64(1)},
   218  		{3, 2.1, int64(1)},
   219  		{3.1, 2.1, int64(1)},
   220  		{int8(3), int8(2), int64(1)},
   221  		{int16(3), int16(2), int64(1)},
   222  		{int32(3), int32(2), int64(1)},
   223  		{int64(3), int64(2), int64(1)},
   224  		{"3", "2", int64(1)},
   225  		{"3.1", "2", false},
   226  		{"aaa", "0", false},
   227  		{"3", "aaa", false},
   228  	} {
   229  
   230  		result, err := ns.Mod(test.a, test.b)
   231  
   232  		if b, ok := test.expect.(bool); ok && !b {
   233  			c.Assert(err, qt.Not(qt.IsNil))
   234  			continue
   235  		}
   236  
   237  		c.Assert(err, qt.IsNil)
   238  		c.Assert(result, qt.Equals, test.expect)
   239  	}
   240  }
   241  
   242  func TestModBool(t *testing.T) {
   243  	t.Parallel()
   244  	c := qt.New(t)
   245  
   246  	ns := New()
   247  
   248  	for _, test := range []struct {
   249  		a      any
   250  		b      any
   251  		expect any
   252  	}{
   253  		{3, 3, true},
   254  		{3, 2, false},
   255  		{3, 1, true},
   256  		{3, 0, nil},
   257  		{0, 3, true},
   258  		{3.1, 2, false},
   259  		{3, 2.1, false},
   260  		{3.1, 2.1, false},
   261  		{int8(3), int8(3), true},
   262  		{int8(3), int8(2), false},
   263  		{int16(3), int16(3), true},
   264  		{int16(3), int16(2), false},
   265  		{int32(3), int32(3), true},
   266  		{int32(3), int32(2), false},
   267  		{int64(3), int64(3), true},
   268  		{int64(3), int64(2), false},
   269  		{"3", "3", true},
   270  		{"3", "2", false},
   271  		{"3.1", "2", nil},
   272  		{"aaa", "0", nil},
   273  		{"3", "aaa", nil},
   274  	} {
   275  
   276  		result, err := ns.ModBool(test.a, test.b)
   277  
   278  		if test.expect == nil {
   279  			c.Assert(err, qt.Not(qt.IsNil))
   280  			continue
   281  		}
   282  
   283  		c.Assert(err, qt.IsNil)
   284  		c.Assert(result, qt.Equals, test.expect)
   285  	}
   286  }
   287  
   288  func TestRound(t *testing.T) {
   289  	t.Parallel()
   290  	c := qt.New(t)
   291  
   292  	ns := New()
   293  
   294  	for _, test := range []struct {
   295  		x      any
   296  		expect any
   297  	}{
   298  		{0.1, 0.0},
   299  		{0.5, 1.0},
   300  		{1.1, 1.0},
   301  		{1.5, 2.0},
   302  		{-0.1, -0.0},
   303  		{-0.5, -1.0},
   304  		{-1.1, -1.0},
   305  		{-1.5, -2.0},
   306  		{"abc", false},
   307  	} {
   308  
   309  		result, err := ns.Round(test.x)
   310  
   311  		if b, ok := test.expect.(bool); ok && !b {
   312  			c.Assert(err, qt.Not(qt.IsNil))
   313  			continue
   314  		}
   315  
   316  		c.Assert(err, qt.IsNil)
   317  		c.Assert(result, qt.Equals, test.expect)
   318  	}
   319  }
   320  
   321  func TestPow(t *testing.T) {
   322  	t.Parallel()
   323  	c := qt.New(t)
   324  
   325  	ns := New()
   326  
   327  	for _, test := range []struct {
   328  		a      any
   329  		b      any
   330  		expect any
   331  	}{
   332  		{0, 0, float64(1)},
   333  		{2, 0, float64(1)},
   334  		{2, 3, float64(8)},
   335  		{-2, 3, float64(-8)},
   336  		{2, -3, float64(0.125)},
   337  		{-2, -3, float64(-0.125)},
   338  		{0.2, 3, float64(0.008)},
   339  		{2, 0.3, float64(1.2311)},
   340  		{0.2, 0.3, float64(0.617)},
   341  		{"aaa", "3", false},
   342  		{"2", "aaa", false},
   343  	} {
   344  
   345  		result, err := ns.Pow(test.a, test.b)
   346  
   347  		if b, ok := test.expect.(bool); ok && !b {
   348  			c.Assert(err, qt.Not(qt.IsNil))
   349  			continue
   350  		}
   351  
   352  		// we compare only 4 digits behind point if its a real float
   353  		// otherwise we usually get different float values on the last positions
   354  		result = float64(int(result*10000)) / 10000
   355  
   356  		c.Assert(err, qt.IsNil)
   357  		c.Assert(result, qt.Equals, test.expect)
   358  	}
   359  }
   360  
   361  func TestMax(t *testing.T) {
   362  	t.Parallel()
   363  	c := qt.New(t)
   364  
   365  	ns := New()
   366  
   367  	for _, test := range []struct {
   368  		a      any
   369  		b      any
   370  		expect any
   371  	}{
   372  		{-1, -1, float64(-1)},
   373  		{-1, 0, float64(0)},
   374  		{-1, 1, float64(1)},
   375  		{0, -1, float64(0)},
   376  		{0, 0, float64(0)},
   377  		{0, 1, float64(1)},
   378  		{1, -1, float64(1)},
   379  		{1, 0, float64(1)},
   380  		{1, 1, float64(1)},
   381  		{1.2, 1.23, float64(1.23)},
   382  		{-1.2, -1.23, float64(-1.2)},
   383  		{0, "a", false},
   384  		{"a", 0, false},
   385  		{"a", "b", false},
   386  	} {
   387  
   388  		result, err := ns.Max(test.a, test.b)
   389  
   390  		if b, ok := test.expect.(bool); ok && !b {
   391  			c.Assert(err, qt.Not(qt.IsNil))
   392  			continue
   393  		}
   394  
   395  		c.Assert(err, qt.IsNil)
   396  		c.Assert(result, qt.Equals, test.expect)
   397  	}
   398  }
   399  
   400  func TestMin(t *testing.T) {
   401  	t.Parallel()
   402  	c := qt.New(t)
   403  
   404  	ns := New()
   405  
   406  	for _, test := range []struct {
   407  		a      any
   408  		b      any
   409  		expect any
   410  	}{
   411  		{-1, -1, float64(-1)},
   412  		{-1, 0, float64(-1)},
   413  		{-1, 1, float64(-1)},
   414  		{0, -1, float64(-1)},
   415  		{0, 0, float64(0)},
   416  		{0, 1, float64(0)},
   417  		{1, -1, float64(-1)},
   418  		{1, 0, float64(0)},
   419  		{1, 1, float64(1)},
   420  		{1.2, 1.23, float64(1.2)},
   421  		{-1.2, -1.23, float64(-1.23)},
   422  		{0, "a", false},
   423  		{"a", 0, false},
   424  		{"a", "b", false},
   425  	} {
   426  
   427  		result, err := ns.Min(test.a, test.b)
   428  
   429  		if b, ok := test.expect.(bool); ok && !b {
   430  			c.Assert(err, qt.Not(qt.IsNil))
   431  			continue
   432  		}
   433  
   434  		c.Assert(err, qt.IsNil)
   435  		c.Assert(result, qt.Equals, test.expect)
   436  	}
   437  }