github.com/uber/kraken@v0.1.4/lib/torrent/scheduler/announcer/announcer_test.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package announcer 15 16 import ( 17 "errors" 18 "testing" 19 "time" 20 21 "github.com/uber/kraken/core" 22 "github.com/uber/kraken/mocks/tracker/announceclient" 23 "github.com/uber/kraken/tracker/announceclient" 24 "go.uber.org/zap" 25 26 "github.com/andres-erbsen/clock" 27 "github.com/golang/mock/gomock" 28 "github.com/stretchr/testify/require" 29 ) 30 31 // How long to wait for the Ticker goroutine to fire / not fire. Fairly large 32 // to prevent flakey tests. 33 const _tickerTimeout = time.Second 34 35 type mockEvents struct { 36 tick chan struct{} 37 } 38 39 func newMockEvents() *mockEvents { 40 return &mockEvents{make(chan struct{}, 1)} 41 } 42 43 func (e *mockEvents) AnnounceTick() { e.tick <- struct{}{} } 44 45 func (e *mockEvents) expectTick(t *testing.T) { 46 select { 47 case <-e.tick: 48 case <-time.After(_tickerTimeout): 49 require.FailNow(t, "Tick timed out") 50 } 51 } 52 53 func (e *mockEvents) expectNoTick(t *testing.T) { 54 select { 55 case <-e.tick: 56 require.FailNow(t, "Unexpected tick") 57 case <-time.After(_tickerTimeout): 58 } 59 } 60 61 type announcerMocks struct { 62 client *mockannounceclient.MockClient 63 events *mockEvents 64 clk *clock.Mock 65 } 66 67 func newAnnouncerMocks(t *testing.T) (*announcerMocks, func()) { 68 ctrl := gomock.NewController(t) 69 return &announcerMocks{ 70 client: mockannounceclient.NewMockClient(ctrl), 71 events: newMockEvents(), 72 clk: clock.NewMock(), 73 }, ctrl.Finish 74 } 75 76 func (m *announcerMocks) newAnnouncer(config Config) *Announcer { 77 return New(config, m.client, m.events, m.clk, zap.NewNop().Sugar()) 78 } 79 80 func TestAnnouncerAnnounceUpdatesInterval(t *testing.T) { 81 require := require.New(t) 82 83 mocks, cleanup := newAnnouncerMocks(t) 84 defer cleanup() 85 86 config := Config{DefaultInterval: 5 * time.Second} 87 88 announcer := mocks.newAnnouncer(config) 89 90 go announcer.Ticker(nil) 91 92 mocks.clk.Add(config.DefaultInterval) 93 mocks.events.expectTick(t) 94 95 d := core.DigestFixture() 96 hash := core.InfoHashFixture() 97 interval := 10 * time.Second 98 peers := []*core.PeerInfo{core.PeerInfoFixture()} 99 100 mocks.client.EXPECT().Announce(d, hash, false, announceclient.V1).Return(peers, interval, nil) 101 102 result, err := announcer.Announce(d, hash, false) 103 require.NoError(err) 104 require.Equal(peers, result) 105 106 mocks.clk.Add(config.DefaultInterval) 107 mocks.events.expectTick(t) 108 109 // Timer should have been reset to new interval now. 110 111 mocks.clk.Add(config.DefaultInterval) 112 mocks.events.expectNoTick(t) 113 114 mocks.clk.Add(interval - config.DefaultInterval) 115 mocks.events.expectTick(t) 116 } 117 118 func TestAnnouncerAnnounceErr(t *testing.T) { 119 require := require.New(t) 120 121 mocks, cleanup := newAnnouncerMocks(t) 122 defer cleanup() 123 124 announcer := mocks.newAnnouncer(Config{}) 125 126 go announcer.Ticker(nil) 127 128 d := core.DigestFixture() 129 hash := core.InfoHashFixture() 130 err := errors.New("some error") 131 132 mocks.client.EXPECT().Announce(d, hash, false, announceclient.V1).Return(nil, time.Duration(0), err) 133 134 _, aErr := announcer.Announce(d, hash, false) 135 require.Equal(err, aErr) 136 }