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 }