package slots import ( "testing" "time" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" ) var _ Ticker = (*SlotTicker)(nil) func TestSlotTicker(t *testing.T) { ticker := &SlotTicker{ c: make(chan primitives.Slot), done: make(chan struct{}), } defer ticker.Done() var sinceDuration time.Duration since := func(time.Time) time.Duration { return sinceDuration } var untilDuration time.Duration until := func(time.Time) time.Duration { return untilDuration } var tick chan time.Time after := func(time.Duration) <-chan time.Time { return tick } genesisTime := time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC) secondsPerSlot := uint64(8) // Test when the ticker starts immediately after genesis time. sinceDuration = 1 * time.Second untilDuration = 7 * time.Second // Make this a buffered channel to prevent a deadlock since // the other goroutine calls a function in this goroutine. tick = make(chan time.Time, 2) ticker.start(genesisTime, secondsPerSlot, since, until, after) // Tick once. tick <- time.Now() slot := <-ticker.C() if slot != 0 { t.Fatalf("Expected %d, got %d", 0, slot) } // Tick twice. tick <- time.Now() slot = <-ticker.C() if slot != 1 { t.Fatalf("Expected %d, got %d", 1, slot) } // Tick thrice. tick <- time.Now() slot = <-ticker.C() if slot != 2 { t.Fatalf("Expected %d, got %d", 2, slot) } } func TestSlotTickerGenesis(t *testing.T) { ticker := &SlotTicker{ c: make(chan primitives.Slot), done: make(chan struct{}), } defer ticker.Done() var sinceDuration time.Duration since := func(time.Time) time.Duration { return sinceDuration } var untilDuration time.Duration until := func(time.Time) time.Duration { return untilDuration } var tick chan time.Time after := func(time.Duration) <-chan time.Time { return tick } genesisTime := time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC) secondsPerSlot := uint64(8) // Test when the ticker starts before genesis time. sinceDuration = -1 * time.Second untilDuration = 1 * time.Second // Make this a buffered channel to prevent a deadlock since // the other goroutine calls a function in this goroutine. tick = make(chan time.Time, 2) ticker.start(genesisTime, secondsPerSlot, since, until, after) // Tick once. tick <- time.Now() slot := <-ticker.C() if slot != 0 { t.Fatalf("Expected %d, got %d", 0, slot) } // Tick twice. tick <- time.Now() slot = <-ticker.C() if slot != 1 { t.Fatalf("Expected %d, got %d", 1, slot) } } func TestGetSlotTickerWithOffset_OK(t *testing.T) { genesisTime := time.Now() secondsPerSlot := uint64(4) offset := time.Duration(secondsPerSlot/2) * time.Second offsetTicker := NewSlotTickerWithOffset(genesisTime, offset, secondsPerSlot) normalTicker := NewSlotTicker(genesisTime, secondsPerSlot) firstTicked := 0 for { select { case <-offsetTicker.C(): if firstTicked != 1 { t.Fatal("Expected other ticker to tick first") } return case <-normalTicker.C(): if firstTicked != 0 { t.Fatal("Expected normal ticker to tick first") } firstTicked = 1 } } }