math_test.go (8264B)
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 }