package acp_test import ( "testing" "time" "github.com/datawire/dlib/dtime" "github.com/emissary-ingress/emissary/v3/pkg/acp" ) type diagdMetadata struct { t *testing.T ft *dtime.FakeTime dw *acp.DiagdWatcher } func (m *diagdMetadata) check(seq int, clock int, alive bool, ready bool) { if m.ft.TimeSinceBoot() != time.Duration(clock)*time.Second { m.t.Errorf("%d: fakeTime.TimeSinceBoot should be %ds, not %v", seq, clock, m.ft.TimeSinceBoot()) } if m.dw.IsAlive() != alive { m.t.Errorf("%d: DiagdWatcher.IsAlive %t, wanted %t", seq, m.dw.IsAlive(), alive) } if m.dw.IsReady() != ready { m.t.Errorf("%d: DiagdWatcher.IsReady %t, wanted %t", seq, m.dw.IsReady(), ready) } } func (m *diagdMetadata) stepSec(step int) { m.ft.StepSec(step) } func newDiagdMetadata(t *testing.T) *diagdMetadata { ft := dtime.NewFakeTime() dw := acp.NewDiagdWatcher() dw.SetFetchTime(ft.Now) if dw == nil { t.Error("New DiagdWatcher is nil?") } bootGraceLength := dw.GraceEnd.Sub(ft.BootTime()) tenMinutes := time.Minute * 10 if bootGraceLength != tenMinutes { t.Errorf("GraceEnd is %v after bootTime, not %v", bootGraceLength, tenMinutes) } return &diagdMetadata{t: t, ft: ft, dw: dw} } func TestDiagdHappyPath(t *testing.T) { m := newDiagdMetadata(t) m.check(0, 0, true, false) // Advance the clock 10s. m.stepSec(10) m.check(1, 10, true, false) // Send a snapshot. We should still be alive but not ready. m.dw.NoteSnapshotSent() m.check(2, 10, true, false) // Advance another 30s. m.stepSec(30) // Mark the snapshot processed. We should now be ready. m.dw.NoteSnapshotProcessed() m.check(3, 40, true, true) } func TestDiagdVerySlowlySent(t *testing.T) { m := newDiagdMetadata(t) m.check(0, 0, true, false) // Don't send a snapshot, but advance the clock into the boot grace period. // We should still be alive. m.stepSec(300) m.check(1, 300, true, false) // Advance the clock to just before the end of the boot grace period. // We should still be alive. m.stepSec(299) m.check(1, 599, true, false) // Advance the clock to just past the end of the boot grace period. // We should no longer be alive. m.stepSec(1) m.check(2, 600, false, false) // Send a snapshot. We should stay dead. m.stepSec(1) m.dw.NoteSnapshotSent() m.check(3, 601, false, false) // Not very useful, but if we mark the snapshot processed, we should snap // to alive and ready. m.stepSec(1) m.dw.NoteSnapshotProcessed() m.check(2, 602, true, true) } func TestDiagdNeverProcessed(t *testing.T) { m := newDiagdMetadata(t) m.check(0, 0, true, false) // Advance the clock 10s. m.stepSec(10) m.check(1, 10, true, false) // Send a snapshot. We should still be alive but not ready. m.dw.NoteSnapshotSent() m.check(2, 10, true, false) // Advance another 9m (540s). m.stepSec(540) m.check(3, 550, true, false) // Advance the clock another minute. We're now past the ten-minute grace period. m.stepSec(60) m.check(4, 610, false, false) } func TestDiagdSlowlyProcessed(t *testing.T) { m := newDiagdMetadata(t) m.check(0, 0, true, false) // Advance the clock 10s. m.stepSec(10) m.check(1, 10, true, false) // Send a snapshot. We should still be alive but not ready. m.dw.NoteSnapshotSent() m.check(2, 10, true, false) // Mark the snapshot processed after another 10s. This should take // us to alive and ready. m.stepSec(10) m.dw.NoteSnapshotProcessed() m.check(3, 20, true, true) // Send another snapshot after 40s (to take us to an even minute). // Still alive and ready. m.stepSec(40) m.dw.NoteSnapshotSent() m.check(4, 60, true, true) // Don't process that snapshot. 9m59s after sending, we should // still be alive and ready. m.stepSec(599) m.check(5, 659, true, true) // At 10m after sending, we should become not alive and not ready. m.stepSec(1) m.check(6, 660, false, false) }