func TestPeer(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() type testStruct struct { msg string pid PeerIdentifier agent transport.Agent appliedFunc func(*Peer) expectedIdentifier string expectedHostPort string expectedStatus transport.PeerStatus expectedAgent transport.Agent } tests := []testStruct{ func() (s testStruct) { s.msg = "create" s.pid = PeerIdentifier("localhost:12345") s.agent = transporttest.NewMockAgent(mockCtrl) s.appliedFunc = func(p *Peer) {} s.expectedIdentifier = "localhost:12345" s.expectedHostPort = "localhost:12345" s.expectedAgent = s.agent s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 0, ConnectionStatus: transport.PeerUnavailable, } return }(), func() (s testStruct) { s.msg = "start request" agent := transporttest.NewMockAgent(mockCtrl) agent.EXPECT().NotifyStatusChanged(gomock.Any()).Times(1) s.agent = agent s.appliedFunc = func(p *Peer) { p.StartRequest() } s.expectedAgent = s.agent s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 1, ConnectionStatus: transport.PeerUnavailable, } return }(), func() (s testStruct) { s.msg = "start request stop request" agent := transporttest.NewMockAgent(mockCtrl) agent.EXPECT().NotifyStatusChanged(gomock.Any()).Times(2) s.agent = agent s.appliedFunc = func(p *Peer) { done := p.StartRequest() done() } s.expectedAgent = s.agent s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 0, ConnectionStatus: transport.PeerUnavailable, } return }(), func() (s testStruct) { s.msg = "start 5 stop 2" agent := transporttest.NewMockAgent(mockCtrl) agent.EXPECT().NotifyStatusChanged(gomock.Any()).Times(7) s.agent = agent s.appliedFunc = func(p *Peer) { done1 := p.StartRequest() p.StartRequest() p.StartRequest() done2 := p.StartRequest() done1() p.StartRequest() done2() } s.expectedAgent = s.agent s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 3, ConnectionStatus: transport.PeerUnavailable, } return }(), func() (s testStruct) { s.msg = "start 5 stop 5" agent := transporttest.NewMockAgent(mockCtrl) agent.EXPECT().NotifyStatusChanged(gomock.Any()).Times(10) s.agent = agent s.appliedFunc = func(p *Peer) { for i := 0; i < 5; i++ { done := p.StartRequest() defer done() } } s.expectedAgent = s.agent s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 0, ConnectionStatus: transport.PeerUnavailable, } return }(), func() (s testStruct) { s.msg = "set status" s.appliedFunc = func(p *Peer) { p.SetStatus(transport.PeerAvailable) } s.expectedStatus = transport.PeerStatus{ PendingRequestCount: 0, ConnectionStatus: transport.PeerAvailable, } return }(), } for _, tt := range tests { if tt.pid == PeerIdentifier("") { tt.pid = PeerIdentifier("localhost:12345") tt.expectedIdentifier = "localhost:12345" tt.expectedHostPort = "localhost:12345" } if tt.agent == nil { tt.agent = transporttest.NewMockAgent(mockCtrl) tt.expectedAgent = tt.agent } peer := NewPeer(tt.pid, tt.agent) tt.appliedFunc(peer) assert.Equal(t, tt.expectedIdentifier, peer.Identifier(), tt.msg) assert.Equal(t, tt.expectedHostPort, peer.HostPort(), tt.msg) assert.Equal(t, tt.expectedAgent, peer.Agent(), tt.msg) assert.Equal(t, tt.expectedStatus, peer.Status(), tt.msg) } }
func TestSingle(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() type expectedChooseResult struct { peer transport.Peer err error } type testStruct struct { msg string pid transport.PeerIdentifier agent *transporttest.MockAgent appliedFunc func(*single) error expectedPeerID transport.PeerIdentifier expectedPeer transport.Peer expectedAgent transport.Agent expectedStarted bool expectedErr error expectedChooseResults []expectedChooseResult } tests := []testStruct{ func() (s testStruct) { s.msg = "setup" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.appliedFunc = func(pl *single) error { return nil } s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = false return }(), func() (s testStruct) { s.msg = "stop before start" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.appliedFunc = func(pl *single) error { return pl.Stop() } s.expectedErr = errors.ErrPeerListNotStarted("single") s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = false return }(), func() (s testStruct) { s.msg = "choose before start" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.appliedFunc = func(pl *single) error { return nil } s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = false s.expectedChooseResults = []expectedChooseResult{{ peer: nil, err: errors.ErrPeerListNotStarted("single"), }} return }(), func() (s testStruct) { s.msg = "start and choose" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.expectedPeer = transporttest.NewMockPeer(mockCtrl) s.agent.EXPECT().RetainPeer(s.pid, gomock.Any()).Return(s.expectedPeer, nil) s.appliedFunc = func(pl *single) error { return pl.Start() } s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = true s.expectedChooseResults = []expectedChooseResult{{ peer: s.expectedPeer, err: nil, }} return }(), func() (s testStruct) { s.msg = "start with agent error" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.expectedErr = fmt.Errorf("test error") s.agent.EXPECT().RetainPeer(s.pid, gomock.Any()).Return(nil, s.expectedErr) s.appliedFunc = func(pl *single) error { return pl.Start() } s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = false return }(), func() (s testStruct) { s.msg = "start twice" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.expectedPeer = transporttest.NewMockPeer(mockCtrl) s.agent.EXPECT().RetainPeer(s.pid, gomock.Any()).Return(s.expectedPeer, nil) s.appliedFunc = func(pl *single) error { pl.Start() return pl.Start() } s.expectedErr = errors.ErrPeerListAlreadyStarted("single") s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = true return }(), func() (s testStruct) { s.msg = "start stop" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) peer := transporttest.NewMockPeer(mockCtrl) s.agent.EXPECT().RetainPeer(s.pid, gomock.Any()).Return(peer, nil) s.agent.EXPECT().ReleasePeer(s.pid, gomock.Any()).Return(nil) s.appliedFunc = func(pl *single) error { err := pl.Start() if err != nil { return err } return pl.Stop() } s.expectedErr = nil s.expectedPeerID = s.pid s.expectedPeer = nil s.expectedAgent = s.agent s.expectedStarted = false return }(), func() (s testStruct) { s.msg = "start stop release failure" s.pid = transporttest.NewMockPeerIdentifier(mockCtrl) s.agent = transporttest.NewMockAgent(mockCtrl) s.expectedPeer = transporttest.NewMockPeer(mockCtrl) s.agent.EXPECT().RetainPeer(s.pid, gomock.Any()).Return(s.expectedPeer, nil) s.expectedErr = errors.ErrAgentHasNoReferenceToPeer{} s.agent.EXPECT().ReleasePeer(s.pid, gomock.Any()).Return(s.expectedErr) s.appliedFunc = func(pl *single) error { err := pl.Start() if err != nil { return err } return pl.Stop() } s.expectedPeerID = s.pid s.expectedAgent = s.agent s.expectedStarted = false return }(), } for _, tt := range tests { pl := NewSingle(tt.pid, tt.agent).(*single) err := tt.appliedFunc(pl) assert.Equal(t, tt.expectedErr, err, tt.msg) assert.Equal(t, tt.expectedAgent, pl.agent, tt.msg) assert.Equal(t, tt.expectedPeerID, pl.initialPeerID, tt.msg) assert.Equal(t, tt.expectedPeer, pl.peer, tt.msg) assert.Equal(t, tt.expectedStarted, pl.started, tt.msg) for _, expectedResult := range tt.expectedChooseResults { peer, err := pl.ChoosePeer(context.Background(), &transport.Request{}) assert.Equal(t, expectedResult.peer, peer, tt.msg) assert.True(t, expectedResult.peer == peer, tt.msg) assert.Equal(t, expectedResult.err, err, tt.msg) } } }