github.com/hairyhenderson/templater@v3.5.0+incompatible/funcs/math_test.go (about)

     1  package funcs
     2  
     3  import (
     4  	"fmt"
     5  	gmath "math"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestAdd(t *testing.T) {
    12  	m := MathNS()
    13  	assert.Equal(t, int64(12), m.Add(1, 1, 2, 3, 5))
    14  	assert.Equal(t, int64(2), m.Add(1, 1))
    15  	assert.Equal(t, int64(1), m.Add(1))
    16  	assert.Equal(t, int64(0), m.Add(-5, 5))
    17  	assert.InDelta(t, float64(5.1), m.Add(4.9, "0.2"), 0.000000001)
    18  }
    19  
    20  func TestMul(t *testing.T) {
    21  	m := MathNS()
    22  	assert.Equal(t, int64(30), m.Mul(1, 1, 2, 3, 5))
    23  	assert.Equal(t, int64(1), m.Mul(1, 1))
    24  	assert.Equal(t, int64(1), m.Mul(1))
    25  	assert.Equal(t, int64(-25), m.Mul("-5", 5))
    26  	assert.Equal(t, int64(28), m.Mul(14, "2"))
    27  	assert.Equal(t, float64(0.5), m.Mul("-1", -0.5))
    28  }
    29  
    30  func TestSub(t *testing.T) {
    31  	m := MathNS()
    32  	assert.Equal(t, int64(0), m.Sub(1, 1))
    33  	assert.Equal(t, int64(-10), m.Sub(-5, 5))
    34  	assert.Equal(t, int64(-41), m.Sub(true, "42"))
    35  	assert.InDelta(t, -5.3, m.Sub(10, 15.3), 0.000000000000001)
    36  }
    37  
    38  func mustDiv(a, b interface{}) interface{} {
    39  	m := MathNS()
    40  	r, err := m.Div(a, b)
    41  	if err != nil {
    42  		return -1
    43  	}
    44  	return r
    45  }
    46  
    47  func TestDiv(t *testing.T) {
    48  	m := MathNS()
    49  	_, err := m.Div(1, 0)
    50  	assert.Error(t, err)
    51  	assert.Equal(t, 1., mustDiv(1, 1))
    52  	assert.Equal(t, -1., mustDiv(-5, 5))
    53  	assert.Equal(t, 1./42, mustDiv(true, "42"))
    54  	assert.InDelta(t, 0.5, mustDiv(1, 2), 1e-12)
    55  }
    56  
    57  func TestRem(t *testing.T) {
    58  	m := MathNS()
    59  	assert.Equal(t, int64(0), m.Rem(1, 1))
    60  	assert.Equal(t, int64(2), m.Rem(5, 3.0))
    61  }
    62  
    63  func TestPow(t *testing.T) {
    64  	m := MathNS()
    65  	assert.Equal(t, int64(4), m.Pow(2, "2"))
    66  	assert.Equal(t, 2.25, m.Pow(1.5, 2))
    67  }
    68  
    69  func mustSeq(n ...interface{}) []int64 {
    70  	m := MathNS()
    71  	s, err := m.Seq(n...)
    72  	if err != nil {
    73  		panic(err)
    74  	}
    75  	return s
    76  }
    77  func TestSeq(t *testing.T) {
    78  	m := MathNS()
    79  	assert.EqualValues(t, []int64{0, 1, 2, 3}, mustSeq(0, 3))
    80  	assert.EqualValues(t, []int64{1, 0}, mustSeq(0))
    81  	assert.EqualValues(t, []int64{0, 2, 4}, mustSeq(0, 4, 2))
    82  	assert.EqualValues(t, []int64{0, 2, 4}, mustSeq(0, 5, 2))
    83  	assert.EqualValues(t, []int64{0}, mustSeq(0, 5, 8))
    84  	_, err := m.Seq()
    85  	assert.Error(t, err)
    86  }
    87  
    88  func TestIsIntFloatNum(t *testing.T) {
    89  	tests := []struct {
    90  		in      interface{}
    91  		isInt   bool
    92  		isFloat bool
    93  	}{
    94  		{0, true, false},
    95  		{1, true, false},
    96  		{-1, true, false},
    97  		{uint(42), true, false},
    98  		{uint8(255), true, false},
    99  		{uint16(42), true, false},
   100  		{uint32(42), true, false},
   101  		{uint64(42), true, false},
   102  		{int(42), true, false},
   103  		{int8(127), true, false},
   104  		{int16(42), true, false},
   105  		{int32(42), true, false},
   106  		{int64(42), true, false},
   107  		{float32(18.3), false, true},
   108  		{float64(18.3), false, true},
   109  		{1.5, false, true},
   110  		{-18.6, false, true},
   111  		{"42", true, false},
   112  		{"052", true, false},
   113  		{"0xff", true, false},
   114  		{"-42", true, false},
   115  		{"-0", true, false},
   116  		{"3.14", false, true},
   117  		{"-3.14", false, true},
   118  		{"0.00", false, true},
   119  		{"NaN", false, true},
   120  		{"-Inf", false, true},
   121  		{"+Inf", false, true},
   122  		{"", false, false},
   123  		{"foo", false, false},
   124  		{nil, false, false},
   125  		{true, false, false},
   126  	}
   127  	m := MathNS()
   128  	for _, tt := range tests {
   129  		t.Run(fmt.Sprintf("%T(%#v)", tt.in, tt.in), func(t *testing.T) {
   130  			assert.Equal(t, tt.isInt, m.IsInt(tt.in))
   131  			assert.Equal(t, tt.isFloat, m.IsFloat(tt.in))
   132  			assert.Equal(t, tt.isInt || tt.isFloat, m.IsNum(tt.in))
   133  		})
   134  	}
   135  }
   136  
   137  func BenchmarkIsFloat(b *testing.B) {
   138  	data := []interface{}{
   139  		0, 1, -1, uint(42), uint8(255), uint16(42), uint32(42), uint64(42), int(42), int8(127), int16(42), int32(42), int64(42), float32(18.3), float64(18.3), 1.5, -18.6, "42", "052", "0xff", "-42", "-0", "3.14", "-3.14", "0.00", "NaN", "-Inf", "+Inf", "", "foo", nil, true,
   140  	}
   141  	m := MathNS()
   142  	for _, n := range data {
   143  		b.Run(fmt.Sprintf("%T(%v)", n, n), func(b *testing.B) {
   144  			for i := 0; i < b.N; i++ {
   145  				m.IsFloat(n)
   146  			}
   147  		})
   148  	}
   149  }
   150  
   151  func TestMax(t *testing.T) {
   152  	m := MathNS()
   153  	data := []struct {
   154  		n        []interface{}
   155  		expected interface{}
   156  	}{
   157  		{[]interface{}{nil}, int64(0)},
   158  		{[]interface{}{0}, int64(0)},
   159  		{[]interface{}{"not a number"}, int64(0)},
   160  		{[]interface{}{1}, int64(1)},
   161  		{[]interface{}{-1}, int64(-1)},
   162  		{[]interface{}{-1, 0, 1}, int64(1)},
   163  		{[]interface{}{3.14, 3, 3.9}, 3.9},
   164  		{[]interface{}{"14", "0xff", -5}, int64(255)},
   165  	}
   166  	for _, d := range data {
   167  		t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) {
   168  			var actual interface{}
   169  			if len(d.n) == 1 {
   170  				actual, _ = m.Max(d.n[0])
   171  			} else {
   172  				actual, _ = m.Max(d.n[0], d.n[1:]...)
   173  			}
   174  			assert.Equal(t, d.expected, actual)
   175  		})
   176  	}
   177  }
   178  
   179  func TestMin(t *testing.T) {
   180  	m := MathNS()
   181  	data := []struct {
   182  		n        []interface{}
   183  		expected interface{}
   184  	}{
   185  		{[]interface{}{nil}, int64(0)},
   186  		{[]interface{}{0}, int64(0)},
   187  		{[]interface{}{"not a number"}, int64(0)},
   188  		{[]interface{}{1}, int64(1)},
   189  		{[]interface{}{-1}, int64(-1)},
   190  		{[]interface{}{-1, 0, 1}, int64(-1)},
   191  		{[]interface{}{3.14, 3, 3.9}, 3.},
   192  		{[]interface{}{"14", "0xff", -5}, int64(-5)},
   193  	}
   194  	for _, d := range data {
   195  		t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) {
   196  			var actual interface{}
   197  			if len(d.n) == 1 {
   198  				actual, _ = m.Min(d.n[0])
   199  			} else {
   200  				actual, _ = m.Min(d.n[0], d.n[1:]...)
   201  			}
   202  			assert.Equal(t, d.expected, actual)
   203  		})
   204  	}
   205  }
   206  
   207  func TestContainsFloat(t *testing.T) {
   208  	m := MathNS()
   209  	data := []struct {
   210  		n        []interface{}
   211  		expected bool
   212  	}{
   213  		{[]interface{}{nil}, false},
   214  		{[]interface{}{0}, false},
   215  		{[]interface{}{"not a number"}, false},
   216  		{[]interface{}{1}, false},
   217  		{[]interface{}{-1}, false},
   218  		{[]interface{}{-1, 0, 1}, false},
   219  		{[]interface{}{3.14, 3, 3.9}, true},
   220  		{[]interface{}{"14", "0xff", -5}, false},
   221  		{[]interface{}{"14.8", "0xff", -5}, true},
   222  		{[]interface{}{"-Inf", 2}, true},
   223  		{[]interface{}{"NaN"}, true},
   224  	}
   225  	for _, d := range data {
   226  		t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) {
   227  			if d.expected {
   228  				assert.True(t, m.containsFloat(d.n...))
   229  			} else {
   230  				assert.False(t, m.containsFloat(d.n...))
   231  			}
   232  		})
   233  	}
   234  }
   235  
   236  func TestCeil(t *testing.T) {
   237  	m := MathNS()
   238  	data := []struct {
   239  		n interface{}
   240  		a float64
   241  	}{
   242  		{"", 0.},
   243  		{nil, 0.},
   244  		{"Inf", gmath.Inf(1)},
   245  		{0, 0.},
   246  		{4.99, 5.},
   247  		{42.1, 43},
   248  		{-1.9, -1},
   249  	}
   250  	for _, d := range data {
   251  		t.Run(fmt.Sprintf("%v==%v", d.n, d.a), func(t *testing.T) {
   252  			assert.InDelta(t, d.a, m.Ceil(d.n), 1e-12)
   253  		})
   254  	}
   255  }
   256  
   257  func TestFloor(t *testing.T) {
   258  	m := MathNS()
   259  	data := []struct {
   260  		n interface{}
   261  		a float64
   262  	}{
   263  		{"", 0.},
   264  		{nil, 0.},
   265  		{"Inf", gmath.Inf(1)},
   266  		{0, 0.},
   267  		{4.99, 4.},
   268  		{42.1, 42},
   269  		{-1.9, -2.},
   270  	}
   271  	for _, d := range data {
   272  		t.Run(fmt.Sprintf("%v==%v", d.n, d.a), func(t *testing.T) {
   273  			assert.InDelta(t, d.a, m.Floor(d.n), 1e-12)
   274  		})
   275  	}
   276  }
   277  
   278  func TestRound(t *testing.T) {
   279  	m := MathNS()
   280  	data := []struct {
   281  		n interface{}
   282  		a float64
   283  	}{
   284  		{"", 0.},
   285  		{nil, 0.},
   286  		{"Inf", gmath.Inf(1)},
   287  		{0, 0.},
   288  		{4.99, 5},
   289  		{42.1, 42},
   290  		{-1.9, -2.},
   291  		{3.5, 4},
   292  		{-3.5, -4},
   293  		{4.5, 5},
   294  		{-4.5, -5},
   295  	}
   296  	for _, d := range data {
   297  		t.Run(fmt.Sprintf("%v==%v", d.n, d.a), func(t *testing.T) {
   298  			assert.InDelta(t, d.a, m.Round(d.n), 1e-12)
   299  		})
   300  	}
   301  }
   302  
   303  func TestAbs(t *testing.T) {
   304  	m := MathNS()
   305  	data := []struct {
   306  		n interface{}
   307  		a interface{}
   308  	}{
   309  		{"", 0.},
   310  		{nil, 0.},
   311  		{"-Inf", gmath.Inf(1)},
   312  		{0, int64(0)},
   313  		{0., 0.},
   314  		{gmath.Copysign(0, -1), 0.},
   315  		{3.14, 3.14},
   316  		{-1.9, 1.9},
   317  		{2, int64(2)},
   318  		{-2, int64(2)},
   319  	}
   320  	for _, d := range data {
   321  		t.Run(fmt.Sprintf("%#v==%v", d.n, d.a), func(t *testing.T) {
   322  			assert.Equal(t, d.a, m.Abs(d.n))
   323  		})
   324  	}
   325  }