github.com/olliephillips/hugo@v0.42.2/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  	"fmt"
    18  	"math"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  func TestBasicNSArithmetic(t *testing.T) {
    26  	t.Parallel()
    27  
    28  	ns := New()
    29  
    30  	for i, test := range []struct {
    31  		fn     func(a, b interface{}) (interface{}, error)
    32  		a      interface{}
    33  		b      interface{}
    34  		expect interface{}
    35  	}{
    36  		{ns.Add, 4, 2, int64(6)},
    37  		{ns.Add, 1.0, "foo", false},
    38  		{ns.Sub, 4, 2, int64(2)},
    39  		{ns.Sub, 1.0, "foo", false},
    40  		{ns.Mul, 4, 2, int64(8)},
    41  		{ns.Mul, 1.0, "foo", false},
    42  		{ns.Div, 4, 2, int64(2)},
    43  		{ns.Div, 1.0, "foo", false},
    44  	} {
    45  		errMsg := fmt.Sprintf("[%d] %v", i, test)
    46  
    47  		result, err := test.fn(test.a, test.b)
    48  
    49  		if b, ok := test.expect.(bool); ok && !b {
    50  			require.Error(t, err, errMsg)
    51  			continue
    52  		}
    53  
    54  		require.NoError(t, err, errMsg)
    55  		assert.Equal(t, test.expect, result, errMsg)
    56  	}
    57  }
    58  
    59  func TestDoArithmetic(t *testing.T) {
    60  	t.Parallel()
    61  
    62  	for i, test := range []struct {
    63  		a      interface{}
    64  		b      interface{}
    65  		op     rune
    66  		expect interface{}
    67  	}{
    68  		{3, 2, '+', int64(5)},
    69  		{3, 2, '-', int64(1)},
    70  		{3, 2, '*', int64(6)},
    71  		{3, 2, '/', int64(1)},
    72  		{3.0, 2, '+', float64(5)},
    73  		{3.0, 2, '-', float64(1)},
    74  		{3.0, 2, '*', float64(6)},
    75  		{3.0, 2, '/', float64(1.5)},
    76  		{3, 2.0, '+', float64(5)},
    77  		{3, 2.0, '-', float64(1)},
    78  		{3, 2.0, '*', float64(6)},
    79  		{3, 2.0, '/', float64(1.5)},
    80  		{3.0, 2.0, '+', float64(5)},
    81  		{3.0, 2.0, '-', float64(1)},
    82  		{3.0, 2.0, '*', float64(6)},
    83  		{3.0, 2.0, '/', float64(1.5)},
    84  		{uint(3), uint(2), '+', uint64(5)},
    85  		{uint(3), uint(2), '-', uint64(1)},
    86  		{uint(3), uint(2), '*', uint64(6)},
    87  		{uint(3), uint(2), '/', uint64(1)},
    88  		{uint(3), 2, '+', uint64(5)},
    89  		{uint(3), 2, '-', uint64(1)},
    90  		{uint(3), 2, '*', uint64(6)},
    91  		{uint(3), 2, '/', uint64(1)},
    92  		{3, uint(2), '+', uint64(5)},
    93  		{3, uint(2), '-', uint64(1)},
    94  		{3, uint(2), '*', uint64(6)},
    95  		{3, uint(2), '/', uint64(1)},
    96  		{uint(3), -2, '+', int64(1)},
    97  		{uint(3), -2, '-', int64(5)},
    98  		{uint(3), -2, '*', int64(-6)},
    99  		{uint(3), -2, '/', int64(-1)},
   100  		{-3, uint(2), '+', int64(-1)},
   101  		{-3, uint(2), '-', int64(-5)},
   102  		{-3, uint(2), '*', int64(-6)},
   103  		{-3, uint(2), '/', int64(-1)},
   104  		{uint(3), 2.0, '+', float64(5)},
   105  		{uint(3), 2.0, '-', float64(1)},
   106  		{uint(3), 2.0, '*', float64(6)},
   107  		{uint(3), 2.0, '/', float64(1.5)},
   108  		{3.0, uint(2), '+', float64(5)},
   109  		{3.0, uint(2), '-', float64(1)},
   110  		{3.0, uint(2), '*', float64(6)},
   111  		{3.0, uint(2), '/', float64(1.5)},
   112  		{0, 0, '+', 0},
   113  		{0, 0, '-', 0},
   114  		{0, 0, '*', 0},
   115  		{"foo", "bar", '+', "foobar"},
   116  		{3, 0, '/', false},
   117  		{3.0, 0, '/', false},
   118  		{3, 0.0, '/', false},
   119  		{uint(3), uint(0), '/', false},
   120  		{3, uint(0), '/', false},
   121  		{-3, uint(0), '/', false},
   122  		{uint(3), 0, '/', false},
   123  		{3.0, uint(0), '/', false},
   124  		{uint(3), 0.0, '/', false},
   125  		{3, "foo", '+', false},
   126  		{3.0, "foo", '+', false},
   127  		{uint(3), "foo", '+', false},
   128  		{"foo", 3, '+', false},
   129  		{"foo", "bar", '-', false},
   130  		{3, 2, '%', false},
   131  	} {
   132  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   133  
   134  		result, err := DoArithmetic(test.a, test.b, test.op)
   135  
   136  		if b, ok := test.expect.(bool); ok && !b {
   137  			require.Error(t, err, errMsg)
   138  			continue
   139  		}
   140  
   141  		require.NoError(t, err, errMsg)
   142  		assert.Equal(t, test.expect, result, errMsg)
   143  	}
   144  }
   145  
   146  func TestCeil(t *testing.T) {
   147  	t.Parallel()
   148  
   149  	ns := New()
   150  
   151  	for i, test := range []struct {
   152  		x      interface{}
   153  		expect interface{}
   154  	}{
   155  		{0.1, 1.0},
   156  		{0.5, 1.0},
   157  		{1.1, 2.0},
   158  		{1.5, 2.0},
   159  		{-0.1, 0.0},
   160  		{-0.5, 0.0},
   161  		{-1.1, -1.0},
   162  		{-1.5, -1.0},
   163  		{"abc", false},
   164  	} {
   165  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   166  
   167  		result, err := ns.Ceil(test.x)
   168  
   169  		if b, ok := test.expect.(bool); ok && !b {
   170  			require.Error(t, err, errMsg)
   171  			continue
   172  		}
   173  
   174  		require.NoError(t, err, errMsg)
   175  		assert.Equal(t, test.expect, result, errMsg)
   176  	}
   177  }
   178  
   179  func TestFloor(t *testing.T) {
   180  	t.Parallel()
   181  
   182  	ns := New()
   183  
   184  	for i, test := range []struct {
   185  		x      interface{}
   186  		expect interface{}
   187  	}{
   188  		{0.1, 0.0},
   189  		{0.5, 0.0},
   190  		{1.1, 1.0},
   191  		{1.5, 1.0},
   192  		{-0.1, -1.0},
   193  		{-0.5, -1.0},
   194  		{-1.1, -2.0},
   195  		{-1.5, -2.0},
   196  		{"abc", false},
   197  	} {
   198  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   199  
   200  		result, err := ns.Floor(test.x)
   201  
   202  		if b, ok := test.expect.(bool); ok && !b {
   203  			require.Error(t, err, errMsg)
   204  			continue
   205  		}
   206  
   207  		require.NoError(t, err, errMsg)
   208  		assert.Equal(t, test.expect, result, errMsg)
   209  	}
   210  }
   211  
   212  func TestLog(t *testing.T) {
   213  	t.Parallel()
   214  
   215  	ns := New()
   216  
   217  	for i, test := range []struct {
   218  		a      interface{}
   219  		expect interface{}
   220  	}{
   221  		{1, float64(0)},
   222  		{3, float64(1.0986)},
   223  		{0, float64(math.Inf(-1))},
   224  		{1.0, float64(0)},
   225  		{3.1, float64(1.1314)},
   226  		{"abc", false},
   227  	} {
   228  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   229  
   230  		result, err := ns.Log(test.a)
   231  
   232  		if b, ok := test.expect.(bool); ok && !b {
   233  			require.Error(t, err, errMsg)
   234  			continue
   235  		}
   236  
   237  		// we compare only 4 digits behind point if its a real float
   238  		// otherwise we usually get different float values on the last positions
   239  		if result != math.Inf(-1) {
   240  			result = float64(int(result*10000)) / 10000
   241  		}
   242  
   243  		require.NoError(t, err, errMsg)
   244  		assert.Equal(t, test.expect, result, errMsg)
   245  	}
   246  }
   247  
   248  func TestMod(t *testing.T) {
   249  	t.Parallel()
   250  
   251  	ns := New()
   252  
   253  	for i, test := range []struct {
   254  		a      interface{}
   255  		b      interface{}
   256  		expect interface{}
   257  	}{
   258  		{3, 2, int64(1)},
   259  		{3, 1, int64(0)},
   260  		{3, 0, false},
   261  		{0, 3, int64(0)},
   262  		{3.1, 2, int64(1)},
   263  		{3, 2.1, int64(1)},
   264  		{3.1, 2.1, int64(1)},
   265  		{int8(3), int8(2), int64(1)},
   266  		{int16(3), int16(2), int64(1)},
   267  		{int32(3), int32(2), int64(1)},
   268  		{int64(3), int64(2), int64(1)},
   269  		{"3", "2", int64(1)},
   270  		{"3.1", "2", false},
   271  		{"aaa", "0", false},
   272  		{"3", "aaa", false},
   273  	} {
   274  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   275  
   276  		result, err := ns.Mod(test.a, test.b)
   277  
   278  		if b, ok := test.expect.(bool); ok && !b {
   279  			require.Error(t, err, errMsg)
   280  			continue
   281  		}
   282  
   283  		require.NoError(t, err, errMsg)
   284  		assert.Equal(t, test.expect, result, errMsg)
   285  	}
   286  }
   287  
   288  func TestModBool(t *testing.T) {
   289  	t.Parallel()
   290  
   291  	ns := New()
   292  
   293  	for i, test := range []struct {
   294  		a      interface{}
   295  		b      interface{}
   296  		expect interface{}
   297  	}{
   298  		{3, 3, true},
   299  		{3, 2, false},
   300  		{3, 1, true},
   301  		{3, 0, nil},
   302  		{0, 3, true},
   303  		{3.1, 2, false},
   304  		{3, 2.1, false},
   305  		{3.1, 2.1, false},
   306  		{int8(3), int8(3), true},
   307  		{int8(3), int8(2), false},
   308  		{int16(3), int16(3), true},
   309  		{int16(3), int16(2), false},
   310  		{int32(3), int32(3), true},
   311  		{int32(3), int32(2), false},
   312  		{int64(3), int64(3), true},
   313  		{int64(3), int64(2), false},
   314  		{"3", "3", true},
   315  		{"3", "2", false},
   316  		{"3.1", "2", nil},
   317  		{"aaa", "0", nil},
   318  		{"3", "aaa", nil},
   319  	} {
   320  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   321  
   322  		result, err := ns.ModBool(test.a, test.b)
   323  
   324  		if test.expect == nil {
   325  			require.Error(t, err, errMsg)
   326  			continue
   327  		}
   328  
   329  		require.NoError(t, err, errMsg)
   330  		assert.Equal(t, test.expect, result, errMsg)
   331  	}
   332  }
   333  
   334  func TestRound(t *testing.T) {
   335  	t.Parallel()
   336  
   337  	ns := New()
   338  
   339  	for i, test := range []struct {
   340  		x      interface{}
   341  		expect interface{}
   342  	}{
   343  		{0.1, 0.0},
   344  		{0.5, 1.0},
   345  		{1.1, 1.0},
   346  		{1.5, 2.0},
   347  		{-0.1, -0.0},
   348  		{-0.5, -1.0},
   349  		{-1.1, -1.0},
   350  		{-1.5, -2.0},
   351  		{"abc", false},
   352  	} {
   353  		errMsg := fmt.Sprintf("[%d] %v", i, test)
   354  
   355  		result, err := ns.Round(test.x)
   356  
   357  		if b, ok := test.expect.(bool); ok && !b {
   358  			require.Error(t, err, errMsg)
   359  			continue
   360  		}
   361  
   362  		require.NoError(t, err, errMsg)
   363  		assert.Equal(t, test.expect, result, errMsg)
   364  	}
   365  }