diff --git a/revid/senders_test.go b/revid/senders_test.go index a6d1d298..291f2c1b 100644 --- a/revid/senders_test.go +++ b/revid/senders_test.go @@ -31,6 +31,7 @@ package revid import ( "errors" "fmt" + "sync" "testing" "time" @@ -355,19 +356,26 @@ func TestMultiSenderNotActiveNoRetry(t *testing.T) { newDummyLoadSender(false), newDummyLoadSender(false), } + + // This will allow us to simulate a change in running state of + // multiSender's 'owner'. active := true activeFunc := func() bool { return active } + ms, err := newMultiSender(senders, false, activeFunc) if err != nil { t.Fatalf("Unexpected error: %v", err) } + // We will perform two writes. We expect the second write not to be complete, + // i.e. the senders should not send anything on this write. ms.Write([]byte{0x00}) active = false ms.Write([]byte{0x01}) + // Check that the senders only sent data once. for _, dest := range ms.senders { if len(dest.(*dummyLoadSender).buf) != 1 { t.Errorf("length of sender buf is not 1 as expected") @@ -375,5 +383,60 @@ func TestMultiSenderNotActiveNoRetry(t *testing.T) { } } +// TestMultiSenderNotActiveRetry checks that we correctly returns from a call to +// multiSender.Write when the active callback func return false during repeated +// send retries. +func TestMultiSenderNotActiveRetry(t *testing.T) { + senders := []loadSender{ + newDummyLoadSender(false), + } + + // Active will simulate the running state of the multiSender's 'owner'. + active := true + + // We will run the ms.Write as routine so we need some sync. + var mu sync.Mutex + + // After the write is running as a routine we will call this to change the + // running state of the 'owner'. + setActive := func(b bool) { + mu.Lock() + defer mu.Unlock() + active = b + } + + // Once we use setActive to change the state of the fake owner, this will + // return false and we expect the ms.Write method to return from the continous + // send retry state. + activeFunc := func() bool { + mu.Lock() + defer mu.Unlock() + return active + } + + ms, err := newMultiSender(senders, false, activeFunc) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // We run this in background so that we can change running state during the + // the write. We then expect done to be true after some period of time. + done := false + go func() { + ms.Write([]byte{0x00}) + done = true + }() + + // Wait for half a second and then change the active state. + time.Sleep(500 * time.Millisecond) + setActive(false) + + // Wait half a second for the routine to return and check that done is true. + time.Sleep(500 * time.Millisecond) + if !done { + t.Fatal("multiSender.Write did not return as expected with active=false") + } +} + // TODO: test that send retry works // TODO: test that send fail works with no retry