func TestSentineForget(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	abundle := newChannelBundle()
	bbundle := newChannelBundle()
	cbundle := newChannelBundle()
	dbundle := newChannelBundle()
	s := loop.GoSentinel("sentinel-forget")
	lA := loop.Go(makeSimpleLF(abundle), "loop", "a")
	lB := loop.Go(makeSimpleLF(bbundle), "loop", "b")
	lC := loop.Go(makeSimpleLF(cbundle), "loop", "c")
	lD := loop.Go(makeSimpleLF(dbundle), "loop", "d")
	assert.Wait(abundle.startedc, true, timeout)
	assert.Wait(bbundle.startedc, true, timeout)
	assert.Wait(cbundle.startedc, true, timeout)
	assert.Wait(dbundle.startedc, true, timeout)
	s.Observe(lA, lB, lC, lD)
	s.Forget(lB, lC)
	assert.Nil(s.Stop())
	assert.Wait(abundle.donec, true, timeout)
	assert.Wait(dbundle.donec, true, timeout)
	status, _ := s.Error()
	assert.Equal(loop.Stopped, status)
}
TestSentinelForget tests the forgetting of loops
by a sentinel.
package loop_test
import (
	"errors"
	"testing"
	"time"
	"github.com/tideland/golib/audit"
	"github.com/tideland/golib/logger"
	"github.com/tideland/golib/loop"
)
var timeout time.Duration = 5 * time.Second
func TestSimpleStop(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bundle := newChannelBundle()
	l := loop.Go(makeSimpleLF(bundle), "simple-stop")
	assert.Wait(bundle.startedc, true, timeout)
	assert.Nil(l.Stop(), "no error after simple stop")
	assert.Wait(bundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(loop.Stopped, status, "loop is stopped")
}
func TestLogging(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	tl := logger.NewTestLogger()
	ol := logger.SetLogger(tl)
	defer logger.SetLogger(ol)
	bundle := newChannelBundle()
	l := loop.Go(makeSimpleLF(bundle), "logger")
	assert.Wait(bundle.startedc, true, timeout)
	assert.Nil(l.Stop(), "no error after simple stop")
	assert.Wait(bundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(loop.Stopped, status, "loop is stopped")
	assert.Length(tl, 2)
	tl.Reset()
	bundle = newChannelBundle()
	l = loop.Go(makeSimpleLF(bundle))
	assert.Wait(bundle.startedc, true, timeout)
	assert.Nil(l.Stop(), "no error after simple stop")
	assert.Wait(bundle.donec, true, timeout)
	status, _ = l.Error()
	assert.Equal(loop.Stopped, status, "loop is stopped")
	assert.Length(tl, 0)
	tl.Reset()
}
func TestSimpleRestart(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bundle := newChannelBundle()
	l := loop.Go(makeSimpleLF(bundle), "simple-restart")
	assert.Wait(bundle.startedc, true, timeout)
	assert.ErrorMatch(l.Restart(), ".*cannot restart unstopped.*")
	status, _ := l.Error()
	assert.Equal(loop.Running, status)
	assert.Nil(l.Stop())
	assert.Wait(bundle.donec, true, timeout)
	status, _ = l.Error()
	assert.Equal(loop.Stopped, status)
	assert.Nil(l.Restart())
	assert.Wait(bundle.startedc, true, timeout)
	status, _ = l.Error()
	assert.Equal(loop.Running, status)
	assert.Nil(l.Stop())
	assert.Wait(bundle.donec, true, timeout)
}
func TestSimpleKill(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bundle := newChannelBundle()
	l := loop.Go(makeSimpleLF(bundle), "simple-kill")
	assert.Wait(bundle.startedc, true, timeout)
	l.Kill(errors.New("ouch"))
	assert.ErrorMatch(l.Stop(), "ouch")
	assert.Wait(bundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(status, loop.Stopped)
}
func TestError(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bundle := newChannelBundle()
	l := loop.Go(makeErrorLF(bundle), "error")
	assert.Wait(bundle.startedc, true, timeout)
	bundle.errorc <- true
	assert.ErrorMatch(l.Stop(), "internal loop error")
	assert.Wait(bundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(status, loop.Stopped)
}
func TestDeferredError(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	bundle := newChannelBundle()
	l := loop.Go(makeDeferredErrorLF(bundle), "deferred-error")
	assert.Wait(bundle.startedc, true, timeout)
	assert.ErrorMatch(l.Stop(), "deferred error")
	assert.Wait(bundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(status, loop.Stopped)
}
func TestStopRecoverings(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	lbundle := newChannelBundle()
	rbundle := newChannelBundle()
	l := loop.GoRecoverable(makeRecoverPanicLF(lbundle), makeIgnorePanicsRF(rbundle), "stop-recoverings")
	assert.Wait(lbundle.startedc, true, timeout)
	lbundle.errorc <- true
	assert.Nil(l.Stop())
	assert.Wait(rbundle.donec, "recovered", timeout)
	status, _ := l.Error()
	assert.Equal(loop.Stopped, status, "loop is stopped")
}
func TestEndRecoverings(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	lbundle := newChannelBundle()
	rbundle := newChannelBundle()
	l := loop.GoRecoverable(makeRecoverNoErrorLF(lbundle), makeIgnorePanicsRF(rbundle), "end-recoverings")
	assert.Wait(lbundle.startedc, true, timeout)
	lbundle.stopc <- true
	assert.Wait(lbundle.donec, true, timeout)
	status, _ := l.Error()
	assert.Equal(status, loop.Stopped)
}
func TestRecoveringsPanic(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	lbundle := newChannelBundle()
	rbundle := newChannelBundle()
	l := loop.GoRecoverable(makeRecoverPanicLF(lbundle), makeCheckCountRF(rbundle), "recoverings-panic")
	go func() {
		for i := 0; i < 10; i++ {
			<-lbundle.startedc
			lbundle.errorc <- true
			<-rbundle.startedc
		}
	}()
	assert.Wait(rbundle.donec, 5, timeout)
	assert.ErrorMatch(l.Stop(), "too many panics")
	status, _ := l.Error()
	assert.Equal(status, loop.Stopped)
}
func TestRecoveringsError(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	lbundle := newChannelBundle()
	rbundle := newChannelBundle()
	l := loop.GoRecoverable(makeRecoverErrorLF(lbundle), makeCatchErrorRF(rbundle), "recoverings-error")
	assert.Wait(lbundle.startedc, true, timeout)
	lbundle.errorc <- true
	assert.ErrorMatch(l.Stop(), "error")
	assert.Wait(rbundle.donec, "error", timeout)
	status, _ := l.Error()
	assert.Equal(loop.Stopped, status, "loop is stopped")
}
func TestDescription(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	abundle := newChannelBundle()
	bbundle := newChannelBundle()
	s := loop.GoSentinel("one")
	lA := loop.Go(makeSimpleLF(abundle), "two", "three", "four")
	lB := loop.Go(makeSimpleLF(bbundle))
	assert.Wait(abundle.startedc, true, timeout)
	assert.Wait(bbundle.startedc, true, timeout)
	s.Observe(lA, lB)
	assert.Equal(s.String(), "one")
	assert.Equal(lA.String(), "two::three::four")
	assert.Nil(s.Stop())
}
func TestSimpleSentinel(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	abundle := newChannelBundle()
	bbundle := newChannelBundle()
	cbundle := newChannelBundle()
	s := loop.GoSentinel("simple-sentinel")
	lA := loop.Go(makeSimpleLF(abundle), "loop", "a")
	lB := loop.Go(makeSimpleLF(bbundle), "loop", "b")
	lC := loop.Go(makeSimpleLF(cbundle), "loop", "c")
	assert.Wait(abundle.startedc, true, timeout)
	assert.Wait(bbundle.startedc, true, timeout)
	assert.Wait(cbundle.startedc, true, timeout)
	s.Observe(lA, lB, lC)
	assert.Nil(s.Stop())
	assert.Wait(abundle.donec, true, timeout)
	assert.Wait(bbundle.donec, true, timeout)
	assert.Wait(cbundle.donec, true, timeout)
	status, _ := s.Error()
	assert.Equal(status, loop.Stopped)
}
func TestSentinelStoppingLoop(t *testing.T) {
	assert := audit.NewTestingAssertion(t, true)
	abundle := newChannelBundle()
	bbundle := newChannelBundle()
	cbundle := newChannelBundle()
	s := loop.GoSentinel("sentinel-stopping-loop")
	lA := loop.Go(makeSimpleLF(abundle), "loop", "a")
	lB := loop.Go(makeSimpleLF(bbundle), "loop", "b")
	lC := loop.Go(makeSimpleLF(cbundle), "loop", "c")
	assert.Wait(abundle.startedc, true, timeout)
	assert.Wait(bbundle.startedc, true, timeout)
	assert.Wait(cbundle.startedc, true, timeout)
	s.Observe(lA, lB, lC)
	assert.Nil(lB.Stop())
	assert.Wait(bbundle.donec, true, timeout)
	assert.Nil(s.Stop())
	assert.Wait(abundle.donec, true, timeout)
	assert.Wait(cbundle.donec, true, timeout)
	status, _ := s.Error()
	assert.Equal(status, loop.Stopped)
}