diff options
Diffstat (limited to 'series/series_test.go')
| -rw-r--r-- | series/series_test.go | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/series/series_test.go b/series/series_test.go index 3ed752d..54ddfcc 100644 --- a/series/series_test.go +++ b/series/series_test.go @@ -15,14 +15,21 @@ package series import ( "reflect" + "sync" "testing" + "time" + RPMTesting "github.com/network-quality/goresponsiveness/testing" "github.com/network-quality/goresponsiveness/utilities" ) func TestNextIndex(t *testing.T) { wsi := newWindowSeriesWindowOnlyImpl[int, int](4) + // Calling internal functions must be done with the lock held! + wsi.lock.Lock() + defer wsi.lock.Unlock() + idx := wsi.nextIndex(wsi.latestIndex) if idx != 1 { t.Fatalf("nextIndex is wrong (1)") @@ -54,6 +61,18 @@ func TestNextIndex(t *testing.T) { wsi.latestIndex = idx } +func TestNextIndexUnlocked(t *testing.T) { + wsi := newWindowSeriesWindowOnlyImpl[int, int](4) + + panicingTest := func() { + wsi.nextIndex(wsi.latestIndex) + } + + if !RPMTesting.DidPanic(panicingTest) { + t.Fatalf("Expected a call to nextIndex (without the lock held) to panic but it did not") + } +} + func TestSimpleWindowComplete(t *testing.T) { wsi := newWindowSeriesWindowOnlyImpl[int, int](4) if wsi.Complete() { @@ -877,3 +896,48 @@ func Test_ForeverStandardDeviationCalculation2(test *testing.T) { test.Fatalf("Standard deviation(series) max calculation(series) failed: Expected: %v; Actual: %v.", expected, sd) } } + +func Test_ForeverLocking(test *testing.T) { + series := newWindowSeriesForeverImpl[float64, int]() + testFail := false + + series.Reserve(1) + series.Reserve(2) + + series.Fill(1, 8) + series.Fill(2, 9) + + wg := sync.WaitGroup{} + + counter := 0 + + wg.Add(2) + go func() { + series.ForEach(func(b int, d *utilities.Optional[float64]) { + // All of these ++s should be done under a single lock of the lock and, therefore, + // the ForEach below should not start until both buckets are ForEach'd over! + counter++ + // Make this a long wait so we know that there is no chance for a race and that + // we are really testing what we mean to test! + time.Sleep(time.Second * 5) + }) + wg.Done() + }() + + time.Sleep(1 * time.Second) + + go func() { + series.ForEach(func(b int, d *utilities.Optional[float64]) { + if counter != 2 { + testFail = true + } + }) + wg.Done() + }() + + wg.Wait() + + if testFail { + test.Fatalf("Mutual exclusion checks did not properly lock out parallel ForEach operations.") + } +} |
