github.com/network-quality/goresponsiveness@v0.0.0-20240129151524-343954285090/series/series_test.go (about) 1 /* 2 * This file is part of Go Responsiveness. 3 * 4 * Go Responsiveness is free software: you can redistribute it and/or modify it under 5 * the terms of the GNU General Public License as published by the Free Software Foundation, 6 * either version 2 of the License, or (at your option) any later version. 7 * Go Responsiveness is distributed in the hope that it will be useful, but WITHOUT ANY 8 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 9 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along 12 * with Go Responsiveness. If not, see <https://www.gnu.org/licenses/>. 13 */ 14 package series 15 16 import ( 17 "reflect" 18 "sync" 19 "testing" 20 "time" 21 22 RPMTesting "github.com/network-quality/goresponsiveness/testing" 23 "github.com/network-quality/goresponsiveness/utilities" 24 ) 25 26 func TestNextIndex(t *testing.T) { 27 wsi := newWindowSeriesWindowOnlyImpl[int, int](4) 28 29 // Calling internal functions must be done with the lock held! 30 wsi.lock.Lock() 31 defer wsi.lock.Unlock() 32 33 idx := wsi.nextIndex(wsi.latestIndex) 34 if idx != 1 { 35 t.Fatalf("nextIndex is wrong (1)") 36 } 37 wsi.latestIndex = idx 38 39 idx = wsi.nextIndex(wsi.latestIndex) 40 if idx != 2 { 41 t.Fatalf("nextIndex is wrong (2)") 42 } 43 wsi.latestIndex = idx 44 45 idx = wsi.nextIndex(wsi.latestIndex) 46 if idx != 3 { 47 t.Fatalf("nextIndex is wrong (3)") 48 } 49 wsi.latestIndex = idx 50 51 idx = wsi.nextIndex(wsi.latestIndex) 52 if idx != 0 { 53 t.Fatalf("nextIndex is wrong (0)") 54 } 55 wsi.latestIndex = idx 56 57 idx = wsi.nextIndex(wsi.latestIndex) 58 if idx != 1 { 59 t.Fatalf("nextIndex is wrong (1)") 60 } 61 wsi.latestIndex = idx 62 } 63 64 func TestNextIndexUnlocked(t *testing.T) { 65 wsi := newWindowSeriesWindowOnlyImpl[int, int](4) 66 67 panicingTest := func() { 68 wsi.nextIndex(wsi.latestIndex) 69 } 70 71 if !RPMTesting.DidPanic(panicingTest) { 72 t.Fatalf("Expected a call to nextIndex (without the lock held) to panic but it did not") 73 } 74 } 75 76 func TestSimpleWindowComplete(t *testing.T) { 77 wsi := newWindowSeriesWindowOnlyImpl[int, int](4) 78 if wsi.Complete() { 79 t.Fatalf("Window should not be complete.") 80 } 81 wsfImpl := newWindowSeriesForeverImpl[int, int]() 82 wsfImpl.Reserve(1) 83 if wsfImpl.Complete() { 84 t.Fatalf("Window should not be complete.") 85 } 86 } 87 88 func TestSimpleReserve(t *testing.T) { 89 wswoImpl := newWindowSeriesWindowOnlyImpl[int, int](4) 90 result := wswoImpl.Reserve(0) 91 if result != nil { 92 t.Fatalf("Reserving 1 should be a-ok!") 93 } 94 wsfImpl := newWindowSeriesForeverImpl[int, int]() 95 result = wsfImpl.Reserve(0) 96 if result != nil { 97 t.Fatalf("Reserving 1 should be a-ok!") 98 } 99 } 100 101 func Test_ForeverValues(test *testing.T) { 102 series := newWindowSeriesForeverImpl[float64, int]() 103 shouldMatch := make([]utilities.Optional[float64], 0) 104 previous := float64(1.0) 105 for i := range utilities.Iota(1, 81) { 106 previous *= 1.059 107 series.Reserve(i) 108 series.Fill(i, float64(previous)) 109 shouldMatch = append(shouldMatch, utilities.Some[float64](previous)) 110 } 111 112 if !reflect.DeepEqual(shouldMatch, series.GetValues()) { 113 test.Fatalf("Values() on infinite mathematical series does not work.") 114 } 115 } 116 117 func Test_WindowOnly_no_values_getvalues(test *testing.T) { 118 expectedLen := 5 119 series := newWindowSeriesWindowOnlyImpl[float64, int](5) 120 result := series.GetValues() 121 allZeros := true 122 for _, v := range result { 123 if utilities.IsSome(v) { 124 allZeros = false 125 break 126 } 127 } 128 if len(result) != expectedLen { 129 test.Fatalf("GetValues of empty window-only series returned list with incorrect size.") 130 } 131 if !allZeros { 132 test.Fatalf("GetValues of empty window-only series returned list with some values.") 133 } 134 } 135 136 func Test_WindowOnlySequentialIncreasesAlwaysLessThan(test *testing.T) { 137 series := newWindowSeriesWindowOnlyImpl[float64, int](10) 138 previous := float64(1.0) 139 for i := range utilities.Iota(1, 11) { 140 previous *= 1.5 141 series.Reserve(i) 142 series.Fill(i, float64(previous)) 143 } 144 if complete, islt, maxSeqIncrease := AllSequentialIncreasesLessThan[float64, int](series, 145 100); !complete || maxSeqIncrease != 50.0 || !islt { 146 test.Fatalf( 147 "(Window Only) Sequential increases are not always less than 100 (%v, %v, %f ).", 148 complete, islt, maxSeqIncrease, 149 ) 150 } 151 } 152 153 func Test_WindowOnlyTooFewInstantsSequentialIncreasesLessThanAlwaysFalse(test *testing.T) { 154 series := newWindowSeriesWindowOnlyImpl[float64, int](500) 155 series.Reserve(1) 156 series.Fill(1, 0.0) 157 if complete, islt, _ := AllSequentialIncreasesLessThan[float64, int](series, 0.0); complete || islt { 158 test.Fatalf( 159 "(Window Only) 0 elements in a series should always yield false when asking if sequential increases are less than a value.", 160 ) 161 } 162 } 163 164 func Test_Forever_Complete(test *testing.T) { 165 series := newWindowSeriesForeverImpl[int, int]() 166 series.Reserve(1) 167 series.Fill(1, 10) 168 if !series.Complete() { 169 test.Fatalf("(infinite) Series with one element and a window size of 1 is not complete.") 170 } 171 } 172 173 func Test_Forever_CompleteN(test *testing.T) { 174 series := newWindowSeriesWindowOnlyImpl[float64, int](10) 175 previous := float64(1.0) 176 for i := range utilities.Iota(1, 11) { 177 previous *= 1.5 178 series.Reserve(i) 179 series.Fill(i, float64(previous)) 180 } 181 if !series.Complete() { 182 test.Fatalf("(infinite) Series with one element and a window size of 2 is complete.") 183 } 184 } 185 186 func Test_Forever_degenerate_percentile_too_high(test *testing.T) { 187 series := newWindowSeriesForeverImpl[int, int]() 188 if complete, result := Percentile[int, int](series, 101); !complete || result != 0.0 { 189 test.Fatalf("(infinite) Series percentile of 101 failed.") 190 } 191 } 192 193 func Test_Forever_degenerate_percentile_too_low(test *testing.T) { 194 series := newWindowSeriesForeverImpl[int, int]() 195 if complete, result := Percentile[int, int](series, 0); !complete || result != 0.0 { 196 test.Fatalf("(infinite) Series percentile of -1 failed.") 197 } 198 } 199 200 func Test_Forever_degenerate_percentile_no_values(test *testing.T) { 201 series := newWindowSeriesForeverImpl[int, int]() 202 if complete, p := Percentile[int, int](series, 50); !complete || p != 0 { 203 test.Fatalf("empty series percentile of 50 failed.") 204 } 205 } 206 207 /////////// 208 209 func Test_Forever90_percentile(test *testing.T) { 210 var expected int = 10 211 series := newWindowSeriesForeverImpl[int, int]() 212 series.Reserve(1) 213 series.Reserve(2) 214 series.Reserve(3) 215 series.Reserve(4) 216 series.Reserve(5) 217 series.Reserve(6) 218 series.Reserve(7) 219 series.Reserve(8) 220 series.Reserve(9) 221 series.Reserve(10) 222 223 series.Fill(10, 10) 224 series.Fill(9, 9) 225 series.Fill(8, 8) 226 series.Fill(7, 7) 227 series.Fill(6, 6) 228 series.Fill(5, 5) 229 series.Fill(4, 4) 230 series.Fill(3, 3) 231 series.Fill(2, 2) 232 series.Fill(1, 1) 233 234 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 235 test.Fatalf( 236 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 237 } 238 } 239 240 func Test_Forever90_WindowOnly_percentile(test *testing.T) { 241 var expected int = 10 242 series := newWindowSeriesForeverImpl[int, int]() 243 series.Reserve(1) 244 series.Reserve(2) 245 series.Reserve(3) 246 series.Reserve(4) 247 series.Reserve(5) 248 series.Reserve(6) 249 series.Reserve(7) 250 series.Reserve(8) 251 series.Reserve(9) 252 series.Reserve(10) 253 254 series.Fill(10, 10) 255 series.Fill(9, 9) 256 series.Fill(8, 8) 257 series.Fill(7, 7) 258 series.Fill(6, 6) 259 series.Fill(5, 5) 260 series.Fill(4, 4) 261 series.Fill(3, 3) 262 series.Fill(2, 2) 263 series.Fill(1, 1) 264 265 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 266 test.Fatalf( 267 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 268 } 269 } 270 271 func Test_Forever90_percentile_reversed(test *testing.T) { 272 var expected int = 10 273 series := newWindowSeriesForeverImpl[int, int]() 274 series.Reserve(1) 275 series.Reserve(2) 276 series.Reserve(3) 277 series.Reserve(4) 278 series.Reserve(5) 279 series.Reserve(6) 280 series.Reserve(7) 281 series.Reserve(8) 282 series.Reserve(9) 283 series.Reserve(10) 284 285 series.Fill(10, 1) 286 series.Fill(9, 2) 287 series.Fill(8, 3) 288 series.Fill(7, 4) 289 series.Fill(6, 5) 290 series.Fill(5, 6) 291 series.Fill(4, 7) 292 series.Fill(3, 8) 293 series.Fill(2, 9) 294 series.Fill(1, 10) 295 296 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 297 test.Fatalf( 298 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 299 } 300 } 301 302 func Test_Forever50_percentile_jumbled(test *testing.T) { 303 var expected int64 = 15 304 series := newWindowSeriesForeverImpl[int64, int]() 305 306 series.Reserve(1) 307 series.Reserve(2) 308 series.Reserve(3) 309 series.Reserve(4) 310 series.Reserve(5) 311 series.Reserve(6) 312 series.Reserve(7) 313 series.Reserve(8) 314 series.Reserve(9) 315 series.Reserve(10) 316 317 series.Fill(1, 7) 318 series.Fill(2, 2) 319 series.Fill(3, 15) 320 series.Fill(4, 27) 321 series.Fill(5, 5) 322 series.Fill(6, 52) 323 series.Fill(7, 18) 324 series.Fill(8, 23) 325 series.Fill(9, 11) 326 series.Fill(10, 12) 327 328 if complete, result := Percentile[int64, int](series, 50); !complete || result != expected { 329 test.Fatalf( 330 "Series 50 percentile of a jumble of numbers failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 331 } 332 } 333 334 func Test_Forever90_partial_percentile(test *testing.T) { 335 var expected int = 10 336 series := newWindowSeriesForeverImpl[int, int]() 337 series.Reserve(1) 338 series.Reserve(2) 339 series.Reserve(3) 340 series.Reserve(4) 341 series.Reserve(5) 342 series.Reserve(6) 343 series.Reserve(7) 344 series.Reserve(8) 345 series.Reserve(9) 346 series.Reserve(10) 347 348 series.Fill(10, 10) 349 series.Fill(9, 9) 350 series.Fill(8, 8) 351 series.Fill(7, 7) 352 series.Fill(6, 6) 353 series.Fill(5, 5) 354 series.Fill(4, 4) 355 series.Fill(3, 3) 356 series.Fill(2, 2) 357 series.Fill(1, 1) 358 359 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 360 test.Fatalf( 361 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 362 } 363 } 364 365 func Test_Forever90_partial_percentile_reversed(test *testing.T) { 366 var expected int = 10 367 series := newWindowSeriesForeverImpl[int, int]() 368 series.Reserve(1) 369 series.Reserve(2) 370 series.Reserve(3) 371 series.Reserve(4) 372 series.Reserve(5) 373 series.Reserve(6) 374 series.Reserve(7) 375 series.Reserve(8) 376 series.Reserve(9) 377 series.Reserve(10) 378 379 series.Fill(10, 1) 380 series.Fill(9, 2) 381 series.Fill(8, 3) 382 series.Fill(7, 4) 383 series.Fill(6, 5) 384 series.Fill(5, 6) 385 series.Fill(4, 7) 386 series.Fill(3, 8) 387 series.Fill(2, 9) 388 series.Fill(1, 10) 389 390 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 391 test.Fatalf( 392 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 393 } 394 } 395 396 func Test_Forever50_partial_percentile_jumbled(test *testing.T) { 397 var expected int64 = 15 398 series := newWindowSeriesForeverImpl[int64, int]() 399 400 series.Reserve(1) 401 series.Reserve(2) 402 series.Reserve(3) 403 series.Reserve(4) 404 series.Reserve(5) 405 series.Reserve(6) 406 series.Reserve(7) 407 series.Reserve(8) 408 series.Reserve(9) 409 series.Reserve(10) 410 411 series.Fill(1, 7) 412 series.Fill(2, 2) 413 series.Fill(3, 15) 414 series.Fill(4, 27) 415 series.Fill(5, 5) 416 series.Fill(6, 52) 417 series.Fill(7, 18) 418 series.Fill(8, 23) 419 series.Fill(9, 11) 420 series.Fill(10, 12) 421 422 if complete, result := Percentile[int64, int](series, 50); !complete || result != expected { 423 test.Fatalf( 424 "Series 50 percentile of a jumble of numbers failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 425 } 426 } 427 428 /////////////////////// 429 430 func Test_WindowOnlySequentialIncreasesAlwaysLessThanWithWraparound(test *testing.T) { 431 series := newWindowSeriesWindowOnlyImpl[float64, int](20) 432 previous := float64(1.0) 433 for i := range utilities.Iota(1, 21) { 434 previous *= 1.15 435 series.Reserve(i) 436 series.Fill(1, float64(previous)) 437 } 438 439 // All those measurements should be ejected by the following 440 // loop! 441 for i := range utilities.Iota(1, 21) { 442 previous *= 1.10 443 series.Reserve(i + 20) 444 series.Fill(i+20, float64(previous)) 445 } 446 447 if complete, islt, maxSeqIncrease := AllSequentialIncreasesLessThan[float64, int](series, 448 11.0); !complete || !islt || !utilities.ApproximatelyEqual(maxSeqIncrease, 10, 0.1) { 449 test.Fatalf( 450 "Sequential increases are not always less than 11.0 in wraparound situation (%f v 11.0).", 451 maxSeqIncrease, 452 ) 453 } 454 } 455 456 func Test_WindowOnlySequentialIncreasesAlwaysLessThanWithWraparoundInverse(test *testing.T) { 457 series := newWindowSeriesWindowOnlyImpl[float64, int](20) 458 previous := float64(1.0) 459 i := 0 460 for i = range utilities.Iota(1, 21) { 461 previous *= 1.15 462 series.Reserve(i) 463 series.Fill(i, float64(previous)) 464 } 465 466 // *Not* all those measurements should be ejected by the following 467 // loop! 468 for j := range utilities.Iota(1, 16) { 469 previous *= 1.10 470 series.Reserve(i + j) 471 series.Fill(i+j, float64(previous)) 472 } 473 474 if complete, islt, maxSeqIncrease := AllSequentialIncreasesLessThan[float64, int](series, 11.0); complete == false || islt { 475 test.Fatalf( 476 "Sequential increases are (unexpectedly) always less than 11.0 in wraparound situation: %f v 11.0.", 477 maxSeqIncrease, 478 ) 479 } 480 } 481 482 func Test_WindowOnlyStandardDeviationIncompleteCalculation(test *testing.T) { 483 expected := 2.93 484 series := newWindowSeriesWindowOnlyImpl[float64, int](6) 485 // 5.7, 1.0, 8.6, 7.4, 2.2 486 series.Reserve(1) 487 series.Reserve(2) 488 series.Reserve(3) 489 series.Reserve(4) 490 series.Reserve(5) 491 492 series.Fill(1, 5.7) 493 series.Fill(2, 1.0) 494 series.Fill(3, 8.6) 495 series.Fill(4, 7.4) 496 series.Fill(5, 2.2) 497 498 if complete, sd := SeriesStandardDeviation[float64, int](series); complete != false || 499 !utilities.ApproximatelyEqual(sd, expected, 0.01) { 500 test.Fatalf("Standard deviation max calculation failed: Expected: %v; Actual: %v.", expected, sd) 501 } else { 502 test.Logf("Standard deviation calculation result: %v", sd) 503 } 504 } 505 506 func Test_WindowOnlyStandardDeviationCalculation(test *testing.T) { 507 expected := 2.93 508 series := newWindowSeriesWindowOnlyImpl[float64, int](5) 509 // 5.7, 1.0, 8.6, 7.4, 2.2 510 series.Reserve(1) 511 series.Reserve(2) 512 series.Reserve(3) 513 series.Reserve(4) 514 series.Reserve(5) 515 series.Reserve(6) 516 series.Reserve(7) 517 series.Reserve(8) 518 series.Reserve(9) 519 series.Reserve(10) 520 series.Reserve(11) 521 series.Reserve(12) 522 series.Reserve(13) 523 524 series.Fill(1, 5.7) 525 series.Fill(2, 5.7) 526 series.Fill(3, 5.7) 527 series.Fill(4, 5.7) 528 series.Fill(5, 5.7) 529 series.Fill(6, 5.7) 530 series.Fill(7, 5.7) 531 series.Fill(8, 5.7) 532 series.Fill(9, 5.7) 533 series.Fill(10, 1.0) 534 series.Fill(11, 8.6) 535 series.Fill(12, 7.4) 536 series.Fill(13, 2.2) 537 538 if complete, sd := SeriesStandardDeviation[float64, int](series); complete != true || 539 !utilities.ApproximatelyEqual(sd, expected, 0.01) { 540 test.Fatalf("Standard deviation max calculation failed: Expected: %v; Actual: %v.", expected, sd) 541 } 542 } 543 544 func Test_WindowOnlyStandardDeviationCalculation2(test *testing.T) { 545 expected := 1.41 546 series := newWindowSeriesWindowOnlyImpl[float64, int](5) 547 548 series.Reserve(1) 549 series.Reserve(2) 550 series.Reserve(3) 551 series.Reserve(4) 552 series.Reserve(5) 553 554 series.Fill(1, 8) 555 series.Fill(2, 9) 556 series.Fill(3, 10) 557 series.Fill(4, 11) 558 series.Fill(5, 12) 559 560 if _, sd := SeriesStandardDeviation[float64, int](series); !utilities.ApproximatelyEqual(sd, expected, 0.01) { 561 test.Fatalf("Standard deviation max calculation failed: Expected: %v; Actual: %v.", expected, sd) 562 } else { 563 test.Logf("Standard deviation calculation result: %v", sd) 564 } 565 } 566 567 func Test_WindowOnlyRotatingValues(test *testing.T) { 568 series := newWindowSeriesWindowOnlyImpl[int, int](5) 569 570 series.Reserve(1) 571 series.Reserve(2) 572 series.Reserve(3) 573 series.Reserve(4) 574 series.Reserve(5) 575 576 series.Reserve(6) 577 series.Reserve(7) 578 579 series.Fill(1, 1) 580 series.Fill(2, 2) 581 series.Fill(3, 3) 582 series.Fill(4, 4) 583 series.Fill(5, 5) 584 585 series.Fill(6, 6) 586 series.Fill(7, 7) 587 588 actual := utilities.Fmap(series.GetValues(), func(i utilities.Optional[int]) int { 589 return utilities.GetSome[int](i) 590 }) 591 if !reflect.DeepEqual([]int{7, 6, 5, 4, 3}, actual) { 592 test.Fatalf("Adding values does not properly erase earlier values.") 593 } 594 } 595 596 func Test_WindowOnly_degenerate_percentile_too_high(test *testing.T) { 597 series := newWindowSeriesWindowOnlyImpl[int, int](21) 598 if complete, p := Percentile[int, int](series, 101); complete != false || p != 0 { 599 test.Fatalf("Series percentile of 101 failed.") 600 } 601 } 602 603 func Test_WindowOnly_degenerate_percentile_too_low(test *testing.T) { 604 series := newWindowSeriesWindowOnlyImpl[int, int](21) 605 if complete, p := Percentile[int, int](series, 0); complete != false || p != 0 { 606 test.Fatalf("Series percentile of -1 failed.") 607 } 608 } 609 610 func Test_WindowOnly_degenerate_percentile_no_values(test *testing.T) { 611 series := newWindowSeriesWindowOnlyImpl[int, int](0) 612 if complete, p := Percentile[int, int](series, 50); !complete || p != 0 { 613 test.Fatalf("empty series percentile of 50 failed.") 614 } 615 } 616 617 func Test_WindowOnly90_percentile(test *testing.T) { 618 var expected int = 10 619 series := newWindowSeriesWindowOnlyImpl[int, int](10) 620 series.Reserve(1) 621 series.Reserve(2) 622 series.Reserve(3) 623 series.Reserve(4) 624 series.Reserve(5) 625 series.Reserve(6) 626 series.Reserve(7) 627 series.Reserve(8) 628 series.Reserve(9) 629 series.Reserve(10) 630 631 series.Fill(10, 10) 632 series.Fill(9, 9) 633 series.Fill(8, 8) 634 series.Fill(7, 7) 635 series.Fill(6, 6) 636 series.Fill(5, 5) 637 series.Fill(4, 4) 638 series.Fill(3, 3) 639 series.Fill(2, 2) 640 series.Fill(1, 1) 641 642 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 643 test.Fatalf( 644 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 645 } 646 } 647 648 func Test_WindowOnly90_percentile_reversed(test *testing.T) { 649 var expected int = 10 650 series := newWindowSeriesWindowOnlyImpl[int, int](10) 651 series.Reserve(1) 652 series.Reserve(2) 653 series.Reserve(3) 654 series.Reserve(4) 655 series.Reserve(5) 656 series.Reserve(6) 657 series.Reserve(7) 658 series.Reserve(8) 659 series.Reserve(9) 660 series.Reserve(10) 661 662 series.Fill(10, 1) 663 series.Fill(9, 2) 664 series.Fill(8, 3) 665 series.Fill(7, 4) 666 series.Fill(6, 5) 667 series.Fill(5, 6) 668 series.Fill(4, 7) 669 series.Fill(3, 8) 670 series.Fill(2, 9) 671 series.Fill(1, 10) 672 673 if complete, result := Percentile[int, int](series, 90); !complete || result != expected { 674 test.Fatalf( 675 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 676 } 677 } 678 679 func Test_WindowOnly50_percentile_jumbled(test *testing.T) { 680 var expected int64 = 15 681 series := newWindowSeriesWindowOnlyImpl[int64, int](10) 682 683 series.Reserve(1) 684 series.Reserve(2) 685 series.Reserve(3) 686 series.Reserve(4) 687 series.Reserve(5) 688 series.Reserve(6) 689 series.Reserve(7) 690 series.Reserve(8) 691 series.Reserve(9) 692 series.Reserve(10) 693 694 series.Fill(1, 7) 695 series.Fill(2, 2) 696 series.Fill(3, 15) 697 series.Fill(4, 27) 698 series.Fill(5, 5) 699 series.Fill(6, 52) 700 series.Fill(7, 18) 701 series.Fill(8, 23) 702 series.Fill(9, 11) 703 series.Fill(10, 12) 704 705 if complete, result := Percentile[int64, int](series, 50); !complete || result != expected { 706 test.Fatalf( 707 "Series 50 percentile of a jumble of numbers failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 708 } 709 } 710 711 func Test_WindowOnly90_partial_percentile(test *testing.T) { 712 var expected int = 10 713 series := newWindowSeriesWindowOnlyImpl[int, int](20) 714 series.Reserve(1) 715 series.Reserve(2) 716 series.Reserve(3) 717 series.Reserve(4) 718 series.Reserve(5) 719 series.Reserve(6) 720 series.Reserve(7) 721 series.Reserve(8) 722 series.Reserve(9) 723 series.Reserve(10) 724 725 series.Fill(10, 10) 726 series.Fill(9, 9) 727 series.Fill(8, 8) 728 series.Fill(7, 7) 729 series.Fill(6, 6) 730 series.Fill(5, 5) 731 series.Fill(4, 4) 732 series.Fill(3, 3) 733 series.Fill(2, 2) 734 series.Fill(1, 1) 735 736 if complete, result := Percentile[int, int](series, 90); complete != false || result != expected { 737 test.Fatalf( 738 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 739 } 740 } 741 742 func Test_WindowOnly90_partial_percentile_reversed(test *testing.T) { 743 var expected int = 10 744 series := newWindowSeriesWindowOnlyImpl[int, int](20) 745 series.Reserve(1) 746 series.Reserve(2) 747 series.Reserve(3) 748 series.Reserve(4) 749 series.Reserve(5) 750 series.Reserve(6) 751 series.Reserve(7) 752 series.Reserve(8) 753 series.Reserve(9) 754 series.Reserve(10) 755 756 series.Fill(10, 1) 757 series.Fill(9, 2) 758 series.Fill(8, 3) 759 series.Fill(7, 4) 760 series.Fill(6, 5) 761 series.Fill(5, 6) 762 series.Fill(4, 7) 763 series.Fill(3, 8) 764 series.Fill(2, 9) 765 series.Fill(1, 10) 766 767 if complete, result := Percentile[int, int](series, 90); complete != false || result != expected { 768 test.Fatalf( 769 "Series 90th percentile of 0 ... 10 failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 770 } 771 } 772 773 func Test_WindowOnly50_partial_percentile_jumbled(test *testing.T) { 774 var expected int64 = 15 775 series := newWindowSeriesWindowOnlyImpl[int64, int](20) 776 777 series.Reserve(1) 778 series.Reserve(2) 779 series.Reserve(3) 780 series.Reserve(4) 781 series.Reserve(5) 782 series.Reserve(6) 783 series.Reserve(7) 784 series.Reserve(8) 785 series.Reserve(9) 786 series.Reserve(10) 787 788 series.Fill(1, 7) 789 series.Fill(2, 2) 790 series.Fill(3, 15) 791 series.Fill(4, 27) 792 series.Fill(5, 5) 793 series.Fill(6, 52) 794 series.Fill(7, 18) 795 series.Fill(8, 23) 796 series.Fill(9, 11) 797 series.Fill(10, 12) 798 799 if complete, result := Percentile[int64, int](series, 50); complete != false || result != expected { 800 test.Fatalf( 801 "Series 50 percentile of a jumble of numbers failed: (Complete: %v) Expected %v got %v.", complete, expected, result) 802 } 803 } 804 805 /* 806 807 func Test_WindowOnlyDoubleSidedTrimmedMean_jumbled(test *testing.T) { 808 expected := 8 809 series := newWindowSeriesWindowOnlyImpl[int64, int](10) 810 series.AddElement(7) 811 series.AddElement(2) 812 series.AddElement(15) 813 series.AddElement(27) 814 series.AddElement(5) 815 series.AddElement(5) 816 series.AddElement(52) 817 series.AddElement(18) 818 series.AddElement(23) 819 series.AddElement(11) 820 series.AddElement(12) 821 822 trimmed := series.DoubleSidedTrim(10) 823 824 if trimmed.Len() != expected { 825 test.Fatalf( 826 "WindowOnly series is not of the proper size. Expected %v and got %v", 827 expected, 828 trimmed.Len(), 829 ) 830 } 831 832 prev := int64(0) 833 for _, v := range trimmed.Values() { 834 if !(prev <= v) { 835 test.Fatalf("Not sorted: %v is not less than or equal to %v\n", prev, v) 836 } 837 prev = v 838 } 839 } 840 841 func Test_WindowOnlyAverage(test *testing.T) { 842 expected := 1.0082230220488836e+08 843 series := newWindowSeriesWindowOnlyImpl[float64, int](4) 844 series.AddElement(9.94747772516195e+07) 845 series.AddElement(9.991286984703423e+07) 846 series.AddElement(1.0285437111086299e+08) 847 series.AddElement(1.0104719061003672e+08) 848 if average := series.CalculateAverage(); !utilities.ApproximatelyEqual(average, 0.01, expected) { 849 test.Fatalf( 850 "Expected: %v; Actual: %v.", average, expected, 851 ) 852 } 853 } 854 */ 855 856 func Test_ForeverStandardDeviationIncompleteCalculation(test *testing.T) { 857 foreverExpected := 2.90 858 series := newWindowSeriesForeverImpl[float64, int]() 859 series.Reserve(1) 860 series.Reserve(2) 861 series.Reserve(3) 862 series.Reserve(4) 863 series.Reserve(5) 864 series.Reserve(6) 865 866 series.Fill(1, 5.7) 867 series.Fill(2, 1.0) 868 series.Fill(3, 8.6) 869 series.Fill(4, 7.4) 870 series.Fill(5, 2.2) 871 series.Fill(6, 8.0) 872 873 if complete, sd := SeriesStandardDeviation[float64, int](series); !complete || 874 !utilities.ApproximatelyEqual(sd, foreverExpected, 0.01) { 875 test.Fatalf("Standard deviation max calculation failed: Expected: %v; Actual: %v.", foreverExpected, sd) 876 } 877 } 878 879 func Test_ForeverStandardDeviationCalculation2(test *testing.T) { 880 expected := 1.41 881 series := newWindowSeriesForeverImpl[float64, int]() 882 883 series.Reserve(1) 884 series.Reserve(2) 885 series.Reserve(3) 886 series.Reserve(4) 887 series.Reserve(5) 888 889 series.Fill(1, 8) 890 series.Fill(2, 9) 891 series.Fill(3, 10) 892 series.Fill(4, 11) 893 series.Fill(5, 12) 894 895 if _, sd := SeriesStandardDeviation[float64, int](series); !utilities.ApproximatelyEqual(sd, expected, 0.01) { 896 test.Fatalf("Standard deviation(series) max calculation(series) failed: Expected: %v; Actual: %v.", expected, sd) 897 } 898 } 899 900 func Test_ForeverLocking(test *testing.T) { 901 series := newWindowSeriesForeverImpl[float64, int]() 902 testFail := false 903 904 series.Reserve(1) 905 series.Reserve(2) 906 907 series.Fill(1, 8) 908 series.Fill(2, 9) 909 910 wg := sync.WaitGroup{} 911 912 counter := 0 913 914 wg.Add(2) 915 go func() { 916 series.ForEach(func(b int, d *utilities.Optional[float64]) { 917 // All of these ++s should be done under a single lock of the lock and, therefore, 918 // the ForEach below should not start until both buckets are ForEach'd over! 919 counter++ 920 // Make this a long wait so we know that there is no chance for a race and that 921 // we are really testing what we mean to test! 922 time.Sleep(time.Second * 5) 923 }) 924 wg.Done() 925 }() 926 927 time.Sleep(1 * time.Second) 928 929 go func() { 930 series.ForEach(func(b int, d *utilities.Optional[float64]) { 931 if counter != 2 { 932 testFail = true 933 } 934 }) 935 wg.Done() 936 }() 937 938 wg.Wait() 939 940 if testFail { 941 test.Fatalf("Mutual exclusion checks did not properly lock out parallel ForEach operations.") 942 } 943 } 944 945 func Test_ForeverGetBucketBounds(test *testing.T) { 946 series := newWindowSeriesForeverImpl[float64, int]() 947 948 series.Reserve(1) 949 series.Reserve(2) 950 series.Reserve(3) 951 series.Reserve(4) 952 series.Reserve(5) 953 954 series.Fill(1, 8) 955 series.Fill(2, 9) 956 series.Fill(3, 10) 957 series.Fill(4, 11) 958 series.Fill(5, 12) 959 960 lower, upper := series.GetBucketBounds() 961 if lower != 1 || upper != 5 { 962 test.Fatalf("expected a lower of 1 and upper of 5; got %v and %v, respectively!\n", lower, upper) 963 } 964 } 965 966 func Test_WindowGetBucketBounds(test *testing.T) { 967 series := newWindowSeriesWindowOnlyImpl[float64, int](3) 968 969 series.Reserve(1) 970 series.Reserve(2) 971 series.Reserve(3) 972 series.Reserve(4) 973 series.Reserve(5) 974 975 series.Fill(3, 10) 976 series.Fill(4, 11) 977 series.Fill(5, 12) 978 979 lower, upper := series.GetBucketBounds() 980 if lower != 3 || upper != 5 { 981 test.Fatalf("expected a lower of 3 and upper of 5; got %v and %v, respectively!\n", lower, upper) 982 } 983 } 984 985 func Test_ForeverBucketBoundsEmpty(test *testing.T) { 986 series := newWindowSeriesForeverImpl[float64, int]() 987 988 lower, upper := series.GetBucketBounds() 989 if lower != 0 || upper != 0 { 990 test.Fatalf("expected a lower of 0 and upper of 0; got %v and %v, respectively!\n", lower, upper) 991 } 992 } 993 994 func Test_ForeverTrimmingBucketBounds(test *testing.T) { 995 series := newWindowSeriesForeverImpl[float64, int]() 996 997 series.Reserve(1) 998 series.Reserve(2) 999 series.Reserve(3) 1000 series.Reserve(4) 1001 series.Reserve(5) 1002 1003 series.Fill(1, 8) 1004 series.Fill(2, 9) 1005 series.Fill(3, 10) 1006 series.Fill(4, 11) 1007 series.Fill(5, 12) 1008 1009 series.SetTrimmingBucketBounds(3, 5) 1010 1011 trimmedValues := series.GetValues() 1012 if len(trimmedValues) != 3 { 1013 test.Fatalf("Expected that the list would have 3 elements but it only had %v!\n", len(trimmedValues)) 1014 } 1015 if utilities.GetSome(trimmedValues[0]) != 10 || utilities.GetSome(trimmedValues[1]) != 11 || 1016 utilities.GetSome(trimmedValues[2]) != 12 { 1017 test.Fatalf("Expected values are not the actual values.\n") 1018 } 1019 } 1020 1021 func Test_WindowTrimmingBucketBounds(test *testing.T) { 1022 series := newWindowSeriesWindowOnlyImpl[float64, int](5) 1023 1024 series.Reserve(1) 1025 series.Reserve(2) 1026 series.Reserve(3) 1027 series.Reserve(4) 1028 series.Reserve(5) 1029 1030 series.Fill(1, 8) 1031 series.Fill(2, 9) 1032 series.Fill(3, 10) 1033 series.Fill(4, 11) 1034 series.Fill(5, 12) 1035 1036 series.SetTrimmingBucketBounds(3, 5) 1037 1038 trimmedValues := series.GetValues() 1039 if len(trimmedValues) != 3 { 1040 test.Fatalf("Expected that the list would have 3 elements but it only had %v!\n", len(trimmedValues)) 1041 } 1042 if utilities.GetSome(trimmedValues[0]) != 12 || utilities.GetSome(trimmedValues[1]) != 11 || 1043 utilities.GetSome(trimmedValues[2]) != 10 { 1044 test.Fatalf("Expected values are not the actual values.\n") 1045 } 1046 } 1047 1048 func Test_ForeverBoundedAppend(test *testing.T) { 1049 appending_series := NewWindowSeries[float64, int](Forever, 0) 1050 baseSeries := NewWindowSeries[float64, int](Forever, 0) 1051 1052 baseSeries.Reserve(1) 1053 baseSeries.Fill(1, 1) 1054 baseSeries.Reserve(2) 1055 baseSeries.Fill(2, 2) 1056 baseSeries.Reserve(3) 1057 baseSeries.Fill(3, 3) 1058 1059 appending_series.Reserve(4) 1060 appending_series.Reserve(5) 1061 appending_series.Reserve(6) 1062 appending_series.Reserve(7) 1063 appending_series.Reserve(8) 1064 1065 appending_series.Fill(4, 8) 1066 appending_series.Fill(5, 9) 1067 appending_series.Fill(6, 10) 1068 appending_series.Fill(7, 11) 1069 appending_series.Fill(8, 12) 1070 1071 appending_series.SetTrimmingBucketBounds(6, 8) 1072 1073 baseSeries.BoundedAppend(&appending_series) 1074 1075 if len(baseSeries.GetValues()) != 6 { 1076 test.Fatalf("The base series should have 6 values, but it actually has %v (bounded test)", len(baseSeries.GetValues())) 1077 } 1078 1079 baseSeriesValues := baseSeries.GetValues() 1080 if utilities.GetSome(baseSeriesValues[0]) != 1 || 1081 utilities.GetSome(baseSeriesValues[1]) != 2 || 1082 utilities.GetSome(baseSeriesValues[2]) != 3 || 1083 utilities.GetSome(baseSeriesValues[3]) != 10 || 1084 utilities.GetSome(baseSeriesValues[4]) != 11 || 1085 utilities.GetSome(baseSeriesValues[5]) != 12 { 1086 test.Fatalf("The values that should be in a series with bounded append are not there.") 1087 } 1088 baseSeries = NewWindowSeries[float64, int](Forever, 0) 1089 baseSeries.Append(&appending_series) 1090 if len(baseSeries.GetValues()) != 5 { 1091 test.Fatalf("The base series should have 5 values, but it actually has %v (unbounded test)", len(baseSeries.GetValues())) 1092 } 1093 } 1094 1095 func Test_ForeverExtractBounded(test *testing.T) { 1096 series := NewWindowSeries[float64, int](Forever, 0) 1097 1098 series.Reserve(1) 1099 series.Reserve(2) 1100 series.Reserve(3) 1101 series.Reserve(4) 1102 series.Reserve(5) 1103 1104 series.Fill(1, 8) 1105 series.Fill(2, 9) 1106 series.Fill(3, 10) 1107 series.Fill(4, 11) 1108 series.Fill(5, 12) 1109 1110 extracted := series.ExtractBoundedSeries() 1111 1112 if len(extracted.GetValues()) != 5 { 1113 test.Fatalf("Expected the extracted list to have 5 values but it really has %v", len(extracted.GetValues())) 1114 } 1115 1116 series.SetTrimmingBucketBounds(3, 5) 1117 extracted = series.ExtractBoundedSeries() 1118 if len(extracted.GetValues()) != 3 { 1119 test.Fatalf("Expected the extracted list to have 3 values but it really has %v", len(extracted.GetValues())) 1120 } 1121 }