diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/api.go | 16 | ||||
-rw-r--r-- | api/api_test.go | 113 |
2 files changed, 77 insertions, 52 deletions
@@ -87,7 +87,7 @@ type MessageIdentifier interface { // methods provided inside of this package. Do not use the same channel from multiple goroutines concurrently, // otherwise the responses could mix! Use multiple channels instead. type Channel struct { - ID uint16 // channel ID + ID uint16 // channel ID ReqChan chan *VppRequest // channel for sending the requests to VPP, closing this channel releases all resources in the ChannelProvider ReplyChan chan *VppReply // channel where VPP replies are delivered to @@ -134,13 +134,13 @@ type NotifSubscription struct { // RequestCtx is a context of a ongoing request (simple one - only one response is expected). type RequestCtx struct { - ch *Channel + ch *Channel seqNum uint16 } // MultiRequestCtx is a context of a ongoing multipart request (multiple responses are expected). type MultiRequestCtx struct { - ch *Channel + ch *Channel seqNum uint16 } @@ -151,7 +151,7 @@ const defaultReplyTimeout = time.Second * 1 // default timeout for replies from // Use ChannelProvider to get an API channel ready for communication with VPP. func NewChannelInternal(id uint16) *Channel { return &Channel{ - ID: id, + ID: id, replyTimeout: defaultReplyTimeout, } } @@ -175,7 +175,7 @@ func (ch *Channel) SendRequest(msg Message) *RequestCtx { ch.lastSeqNum++ ch.ReqChan <- &VppRequest{ Message: msg, - SeqNum: ch.lastSeqNum, + SeqNum: ch.lastSeqNum, } return &RequestCtx{ch: ch, seqNum: ch.lastSeqNum} } @@ -266,7 +266,7 @@ func (ch *Channel) processReply(reply *VppReply, expSeqNum uint16, msg Message) ignore = true return } - if cmpSeqNums == 1 { + if cmpSeqNums == 1 { ch.delayedReply = reply err = fmt.Errorf("missing binary API reply with sequence number: %d", expSeqNum) return @@ -298,8 +298,8 @@ func (ch *Channel) processReply(reply *VppReply, expSeqNum uint16, msg Message) msgNameCrc = nameCrc } - err = fmt.Errorf("received invalid message ID (seq-num=%d), expected %d (%s), but got %d (%s) " + - "(check if multiple goroutines are not sharing single GoVPP channel)", + err = fmt.Errorf("received invalid message ID (seq-num=%d), expected %d (%s), but got %d (%s) "+ + "(check if multiple goroutines are not sharing single GoVPP channel)", reply.SeqNum, expMsgID, msg.GetMessageName(), reply.MessageID, msgNameCrc) return } diff --git a/api/api_test.go b/api/api_test.go index a83b1cc..7cbd9f0 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -64,7 +64,7 @@ func TestRequestReplyTapConnect(t *testing.T) { ctx.mockVpp.MockReply(&tap.TapConnectReply{ Retval: 10, SwIfIndex: 1, - }, false) + }) request := &tap.TapConnect{ TapName: []byte("test-tap-name"), UseRandomMac: 1, @@ -84,7 +84,7 @@ func TestRequestReplyTapModify(t *testing.T) { ctx.mockVpp.MockReply(&tap.TapModifyReply{ Retval: 15, SwIfIndex: 2, - }, false) + }) request := &tap.TapModify{ TapName: []byte("test-tap-modify"), UseRandomMac: 1, @@ -104,7 +104,7 @@ func TestRequestReplyTapDelete(t *testing.T) { ctx.mockVpp.MockReply(&tap.TapDeleteReply{ Retval: 20, - }, false) + }) request := &tap.TapDelete{ SwIfIndex: 3, } @@ -123,7 +123,7 @@ func TestRequestReplySwInterfaceTapDump(t *testing.T) { ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{ SwIfIndex: 25, DevName: byteName, - }, false) + }) request := &tap.SwInterfaceTapDump{} reply := &tap.SwInterfaceTapDetails{} @@ -140,7 +140,7 @@ func TestRequestReplyMemifCreate(t *testing.T) { ctx.mockVpp.MockReply(&memif.MemifCreateReply{ Retval: 22, SwIfIndex: 4, - }, false) + }) request := &memif.MemifCreate{ Role: 10, ID: 12, @@ -161,7 +161,7 @@ func TestRequestReplyMemifDelete(t *testing.T) { ctx.mockVpp.MockReply(&memif.MemifDeleteReply{ Retval: 24, - }, false) + }) request := &memif.MemifDelete{ SwIfIndex: 15, } @@ -180,7 +180,7 @@ func TestRequestReplyMemifDetails(t *testing.T) { SwIfIndex: 25, IfName: []byte("memif-name"), Role: 0, - }, false) + }) request := &memif.MemifDump{} reply := &memif.MemifDetails{} @@ -196,13 +196,15 @@ func TestMultiRequestReplySwInterfaceTapDump(t *testing.T) { defer ctx.teardownTest() // mock reply + msgs := []api.Message{} for i := 1; i <= 10; i++ { - ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{ + msgs = append(msgs, &tap.SwInterfaceTapDetails{ SwIfIndex: uint32(i), DevName: []byte("dev-name-test"), - }, true) + }) } - ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true) + ctx.mockVpp.MockReply(msgs...) + ctx.mockVpp.MockReply(&vpe.ControlPingReply{}) reqCtx := ctx.ch.SendMultiRequest(&tap.SwInterfaceTapDump{}) cnt := 0 @@ -223,12 +225,14 @@ func TestMultiRequestReplySwInterfaceMemifDump(t *testing.T) { defer ctx.teardownTest() // mock reply + msgs := []api.Message{} for i := 1; i <= 10; i++ { - ctx.mockVpp.MockReply(&memif.MemifDetails{ + msgs = append(msgs, &memif.MemifDetails{ SwIfIndex: uint32(i), - }, true) + }) } - ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true) + ctx.mockVpp.MockReply(msgs...) + ctx.mockVpp.MockReply(&vpe.ControlPingReply{}) reqCtx := ctx.ch.SendMultiRequest(&memif.MemifDump{}) cnt := 0 @@ -257,7 +261,7 @@ func TestNotifications(t *testing.T) { ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{ SwIfIndex: 3, AdminUpDown: 1, - }, false) + }) ctx.mockVpp.SendMsg(0, []byte("")) // receive the notification @@ -292,7 +296,7 @@ func TestNotificationEvent(t *testing.T) { ctx.mockVpp.MockReply(&interfaces.SwInterfaceEvent{ SwIfIndex: 2, LinkUpDown: 1, - }, false) + }) ctx.mockVpp.SendMsg(0, []byte("")) // receive the notification @@ -328,7 +332,7 @@ func TestSetReplyTimeout(t *testing.T) { ctx.ch.SetReplyTimeout(time.Millisecond) // first one request should work - ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, false) + ctx.mockVpp.MockReply(&vpe.ControlPingReply{}) err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{}) Expect(err).ShouldNot(HaveOccurred()) @@ -344,13 +348,15 @@ func TestSetReplyTimeoutMultiRequest(t *testing.T) { ctx.ch.SetReplyTimeout(time.Millisecond) + msgs := []api.Message{} for i := 1; i <= 3; i++ { - ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{ + msgs = append(msgs, &interfaces.SwInterfaceDetails{ SwIfIndex: uint32(i), InterfaceName: []byte("if-name-test"), - }, true) + }) } - ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true) + ctx.mockVpp.MockReply(msgs...) + ctx.mockVpp.MockReply(&vpe.ControlPingReply{}) cnt := 0 sendMultiRequest := func() error { @@ -409,20 +415,33 @@ func TestMultiRequestDouble(t *testing.T) { defer ctx.teardownTest() // mock reply + msgs := []mock.MsgWithContext{} for i := 1; i <= 3; i++ { - ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{ - SwIfIndex: uint32(i), - InterfaceName: []byte("if-name-test"), - }, true, 1) + msgs = append(msgs, mock.MsgWithContext{ + Msg: &interfaces.SwInterfaceDetails{ + SwIfIndex: uint32(i), + InterfaceName: []byte("if-name-test"), + }, + Multipart: true, + SeqNum: 1, + }) } - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true, 1) + msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 1}) + for i := 1; i <= 3; i++ { - ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{ - SwIfIndex: uint32(i), - InterfaceName: []byte("if-name-test"), - }, true, 2) + msgs = append(msgs, + mock.MsgWithContext{ + Msg: &interfaces.SwInterfaceDetails{ + SwIfIndex: uint32(i), + InterfaceName: []byte("if-name-test"), + }, + Multipart: true, + SeqNum: 2, + }) } - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true,2) + msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 2}) + + ctx.mockVpp.MockReplyWithContext(msgs...) cnt := 0 var sendMultiRequest = func() error { @@ -457,7 +476,7 @@ func TestReceiveReplyAfterTimeout(t *testing.T) { ctx.ch.SetReplyTimeout(time.Millisecond) // first one request should work - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, false,1) + ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, SeqNum: 1}) err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{}) Expect(err).ShouldNot(HaveOccurred()) @@ -465,11 +484,11 @@ func TestReceiveReplyAfterTimeout(t *testing.T) { Expect(err).Should(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("timeout")) - // simulating late reply - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, false,2) - - // normal reply for next request - ctx.mockVpp.MockReplyWithSeqNum(&tap.TapConnectReply{}, false,3) + ctx.mockVpp.MockReplyWithContext( + // simulating late reply + mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, SeqNum: 2}, + // normal reply for next request + mock.MsgWithContext{Msg: &tap.TapConnectReply{}, SeqNum: 3}) req := &tap.TapConnect{ TapName: []byte("test-tap-name"), @@ -497,7 +516,7 @@ func TestReceiveReplyAfterTimeoutMultiRequest(t *testing.T) { ctx.ch.SetReplyTimeout(time.Millisecond * 100) // first one request should work - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, false, 1) + ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, SeqNum: 1}) err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{}) Expect(err).ShouldNot(HaveOccurred()) @@ -524,16 +543,22 @@ func TestReceiveReplyAfterTimeoutMultiRequest(t *testing.T) { Expect(cnt).To(BeEquivalentTo(0)) // simulating late replies + msgs := []mock.MsgWithContext{} for i := 1; i <= 3; i++ { - ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{ - SwIfIndex: uint32(i), - InterfaceName: []byte("if-name-test"), - }, true, 2) + msgs = append(msgs, mock.MsgWithContext{ + Msg: &interfaces.SwInterfaceDetails{ + SwIfIndex: uint32(i), + InterfaceName: []byte("if-name-test"), + }, + Multipart: true, + SeqNum: 2, + }) } - ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true, 2) + msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 2}) + ctx.mockVpp.MockReplyWithContext(msgs...) // normal reply for next request - ctx.mockVpp.MockReplyWithSeqNum(&tap.TapConnectReply{}, false, 3) + ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{Msg: &tap.TapConnectReply{}, SeqNum: 3}) req := &tap.TapConnect{ TapName: []byte("test-tap-name"), @@ -551,12 +576,12 @@ func TestInvalidMessageID(t *testing.T) { defer ctx.teardownTest() // first one request should work - ctx.mockVpp.MockReply(&vpe.ShowVersionReply{}, false) + ctx.mockVpp.MockReply(&vpe.ShowVersionReply{}) err := ctx.ch.SendRequest(&vpe.ShowVersion{}).ReceiveReply(&vpe.ShowVersionReply{}) Expect(err).ShouldNot(HaveOccurred()) // second should fail with error invalid message ID - ctx.mockVpp.MockReply(&vpe.ShowVersionReply{}, false) + ctx.mockVpp.MockReply(&vpe.ShowVersionReply{}) err = ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{}) Expect(err).Should(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("invalid message ID")) |