Data []byte
}
+// reply for one request (can be multipart, contain replies to previously timeouted requests, etc.)
type reply struct {
- msg api.Message
- multipart bool
- hasSeqNum bool
- seqNum uint16
+ msgs []MsgWithContext
+}
+
+// MsgWithContext encapsulates reply message with possibly sequence number and is-multipart flag.
+type MsgWithContext struct {
+ Msg api.Message
+ SeqNum uint16
+ Multipart bool
+
+ /* set by mock adapter */
+ hasCtx bool
}
// ReplyHandler is a type that allows to extend the behaviour of VPP mock.
a.repliesLock.Lock()
defer a.repliesLock.Unlock()
- // pop all replies from queue
- withSeqNums := false
- for i, reply := range a.replies {
- if i > 0 && reply.msg.GetMessageName() == "control_ping_reply" && !withSeqNums {
- // hack - do not send control_ping_reply immediately, leave it for the the next callback
- a.replies = a.replies[i:]
- return nil
- }
- msgID, _ := a.GetMsgID(reply.msg.GetMessageName(), reply.msg.GetCrcString())
- buf := new(bytes.Buffer)
- context := clientID
- context = setMultipart(context, reply.multipart)
- if reply.hasSeqNum {
- withSeqNums = true
- context = setSeqNum(context, reply.seqNum)
- }
- if reply.msg.GetMessageType() == api.ReplyMessage {
- struc.Pack(buf, &core.VppReplyHeader{VlMsgID: msgID, Context: context})
- } else if reply.msg.GetMessageType() == api.EventMessage {
- struc.Pack(buf, &core.VppEventHeader{VlMsgID: msgID, Context: context})
- } else if reply.msg.GetMessageType() == api.RequestMessage {
- struc.Pack(buf, &core.VppRequestHeader{VlMsgID: msgID, Context: context})
- } else {
- struc.Pack(buf, &core.VppOtherHeader{VlMsgID: msgID})
- }
- struc.Pack(buf, reply.msg)
- a.callback(context, msgID, buf.Bytes())
- }
+ // pop the first reply
if len(a.replies) > 0 {
- a.replies = []reply{}
- if len(a.replyHandlers) > 0 {
+ reply := a.replies[0]
+ for _, msg := range reply.msgs {
+ msgID, _ := a.GetMsgID(msg.Msg.GetMessageName(), msg.Msg.GetCrcString())
+ buf := new(bytes.Buffer)
+ context := clientID
+ if msg.hasCtx {
+ context = setMultipart(context, msg.Multipart)
+ context = setSeqNum(context, msg.SeqNum)
+ }
+ if msg.Msg.GetMessageType() == api.ReplyMessage {
+ struc.Pack(buf, &core.VppReplyHeader{VlMsgID: msgID, Context: context})
+ } else if msg.Msg.GetMessageType() == api.EventMessage {
+ struc.Pack(buf, &core.VppEventHeader{VlMsgID: msgID, Context: context})
+ } else if msg.Msg.GetMessageType() == api.RequestMessage {
+ struc.Pack(buf, &core.VppRequestHeader{VlMsgID: msgID, Context: context})
+ } else {
+ struc.Pack(buf, &core.VppOtherHeader{VlMsgID: msgID})
+ }
+ struc.Pack(buf, msg.Msg)
+ a.callback(context, msgID, buf.Bytes())
+ }
+
+ a.replies = a.replies[1:]
+ if len(a.replies) == 0 && len(a.replyHandlers) > 0 {
// Switch back to handlers once the queue is empty to revert back
// the fallthrough effect.
a.mode = useReplyHandlers
return nil
}
-// MockReply stores a message to be returned when the next request comes. It is a FIFO queue - multiple replies
-// can be pushed into it, the first one will be popped when some request comes.
-// Using of this method automatically switches the mock into th useRepliesQueue mode.
-func (a *VppAdapter) MockReply(replyMsg api.Message, isMultipart bool) {
+// MockReply stores a message or a list of multipart messages to be returned when
+// the next request comes. It is a FIFO queue - multiple replies can be pushed into it,
+// the first message or the first set of multi-part messages will be popped when
+// some request comes.
+// Using of this method automatically switches the mock into the useRepliesQueue mode.
+//
+// Note: multipart requests are implemented using two requests actually - the multipart
+// request itself followed by control ping used to tell which multipart message
+// is the last one. A mock reply to a multipart request has to thus consist of
+// exactly two calls of this method.
+// For example:
+//
+// mockVpp.MockReply( // push multipart messages all at once
+// &interfaces.SwInterfaceDetails{SwIfIndex:1},
+// &interfaces.SwInterfaceDetails{SwIfIndex:2},
+// &interfaces.SwInterfaceDetails{SwIfIndex:3},
+// )
+// mockVpp.MockReply(&vpe.ControlPingReply{})
+//
+// Even if the multipart request has no replies, MockReply has to be called twice:
+//
+// mockVpp.MockReply() // zero multipart messages
+// mockVpp.MockReply(&vpe.ControlPingReply{})
+func (a *VppAdapter) MockReply(msgs ...api.Message) {
a.repliesLock.Lock()
defer a.repliesLock.Unlock()
- a.replies = append(a.replies, reply{msg: replyMsg, multipart: isMultipart, hasSeqNum: false})
+ r := reply{}
+ for _, msg := range msgs {
+ r.msgs = append(r.msgs, MsgWithContext{Msg: msg, hasCtx: false})
+ }
+ a.replies = append(a.replies, r)
a.mode = useRepliesQueue
}
-// MockReplyWithSeqNum queues next reply like MockReply() does, except that the
-// sequence number can be customized and not necessarily match with the request.
-func (a *VppAdapter) MockReplyWithSeqNum(replyMsg api.Message, isMultipart bool, sequenceNum uint16) {
+// MockReplyWithContext queues next reply like MockReply() does, except that the
+// sequence number and multipart flag (= context minus channel ID) can be customized
+// and not necessarily match with the request.
+// The purpose of this function is to test handling of sequence numbers and as such
+// it is not really meant to be used outside the govpp UTs.
+func (a *VppAdapter) MockReplyWithContext(msgs ...MsgWithContext) {
a.repliesLock.Lock()
defer a.repliesLock.Unlock()
- a.replies = append(a.replies, reply{msg: replyMsg, multipart: isMultipart, hasSeqNum: true, seqNum: sequenceNum})
+ r := reply{}
+ for _, msg := range msgs {
+ r.msgs = append(r.msgs,
+ MsgWithContext{Msg: msg.Msg, SeqNum: msg.SeqNum, Multipart: msg.Multipart, hasCtx: true})
+ }
+ a.replies = append(a.replies, r)
a.mode = useRepliesQueue
}
// 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
// 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
}
// 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,
}
}
ch.lastSeqNum++
ch.ReqChan <- &VppRequest{
Message: msg,
- SeqNum: ch.lastSeqNum,
+ SeqNum: ch.lastSeqNum,
}
return &RequestCtx{ch: ch, seqNum: ch.lastSeqNum}
}
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
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
}
ctx.mockVpp.MockReply(&tap.TapConnectReply{
Retval: 10,
SwIfIndex: 1,
- }, false)
+ })
request := &tap.TapConnect{
TapName: []byte("test-tap-name"),
UseRandomMac: 1,
ctx.mockVpp.MockReply(&tap.TapModifyReply{
Retval: 15,
SwIfIndex: 2,
- }, false)
+ })
request := &tap.TapModify{
TapName: []byte("test-tap-modify"),
UseRandomMac: 1,
ctx.mockVpp.MockReply(&tap.TapDeleteReply{
Retval: 20,
- }, false)
+ })
request := &tap.TapDelete{
SwIfIndex: 3,
}
ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{
SwIfIndex: 25,
DevName: byteName,
- }, false)
+ })
request := &tap.SwInterfaceTapDump{}
reply := &tap.SwInterfaceTapDetails{}
ctx.mockVpp.MockReply(&memif.MemifCreateReply{
Retval: 22,
SwIfIndex: 4,
- }, false)
+ })
request := &memif.MemifCreate{
Role: 10,
ID: 12,
ctx.mockVpp.MockReply(&memif.MemifDeleteReply{
Retval: 24,
- }, false)
+ })
request := &memif.MemifDelete{
SwIfIndex: 15,
}
SwIfIndex: 25,
IfName: []byte("memif-name"),
Role: 0,
- }, false)
+ })
request := &memif.MemifDump{}
reply := &memif.MemifDetails{}
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
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
ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{
SwIfIndex: 3,
AdminUpDown: 1,
- }, false)
+ })
ctx.mockVpp.SendMsg(0, []byte(""))
// receive the notification
ctx.mockVpp.MockReply(&interfaces.SwInterfaceEvent{
SwIfIndex: 2,
LinkUpDown: 1,
- }, false)
+ })
ctx.mockVpp.SendMsg(0, []byte(""))
// receive the notification
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())
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 {
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 {
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())
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"),
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())
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"),
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"))
ctx := setupTest(t, false)
defer ctx.teardownTest()
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: -5}, false)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: -5})
req := &vpe.ControlPing{}
reply := &vpe.ControlPingReply{}
ctx := setupTest(t, false)
defer ctx.teardownTest()
+ msgs := []api.Message{}
for m := 0; m < 10; m++ {
- ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{}, true)
+ msgs = append(msgs, &interfaces.SwInterfaceDetails{})
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true)
+ ctx.mockVpp.MockReply(msgs...)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
// send multipart request
ctx.ch.ReqChan <- &api.VppRequest{Message: &interfaces.SwInterfaceDump{}, Multipart: true}
ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{
SwIfIndex: 3,
AdminUpDown: 1,
- }, false)
+ })
ctx.mockVpp.SendMsg(0, []byte{0})
// receive the notification
// send multiple requests, only one reply should be read
for i := 0; i < 20; i++ {
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, false)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
ctx.ch.ReqChan <- &api.VppRequest{Message: &vpe.ControlPing{}}
}
var reqCtx []*api.RequestCtx
for i := 0; i < 10; i++ {
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: int32(i)}, false)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: int32(i)})
req := &vpe.ControlPing{}
reqCtx = append(reqCtx, ctx.ch.SendRequest(req))
}
ctx := setupTest(t, false)
defer ctx.teardownTest()
+ msgs := []api.Message{}
for i := 0; i < 10; i++ {
- ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)}, true)
+ msgs = append(msgs, &interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)})
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true)
+ ctx.mockVpp.MockReply(msgs...)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
// send multipart request
reqCtx := ctx.ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
defer ctx.teardownTest()
// reply for a previous timeouted requests to be ignored
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 1}, false,0)
+ ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 1},
+ SeqNum: 0,
+ })
// send reply later
req1 := &vpe.ControlPing{}
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(HavePrefix("no reply received within the timeout period"))
- // reply for the previous request
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 1}, false,1)
+ ctx.mockVpp.MockReplyWithContext(
+ // reply for the previous request
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 1},
+ SeqNum: 1,
+ },
+ // reply for the next request
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 2},
+ SeqNum: 2,
+ })
// next request
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: 2}, false)
req2 := &vpe.ControlPing{}
reqCtx2 := ctx.ch.SendRequest(req2)
reqCtx2 := ctx.ch.SendRequest(req2)
// third request with reply
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 3}, false, 3)
+ ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 3},
+ SeqNum: 3,
+ })
req3 := &vpe.ControlPing{}
reqCtx3 := ctx.ch.SendRequest(req3)
ctx := setupTest(t, false)
defer ctx.teardownTest()
- // reply for a previous timeouted requests to be ignored
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 1}, false,0xffff - 1)
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 1}, false,0xffff)
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 1}, false,0)
+ // replies for a previous timeouted requests to be ignored
+ msgs := []mock.MsgWithContext{}
+ msgs = append(msgs,
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 1},
+ SeqNum: 0xffff - 1,
+ },
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 1},
+ SeqNum: 0xffff,
+ },
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 1},
+ SeqNum: 0,
+ })
for i := 0; i < 10; i++ {
- ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)}, true)
+ msgs = append(msgs,
+ mock.MsgWithContext{
+ Msg: &interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)},
+ SeqNum: 1,
+ Multipart: true,
+ })
}
// missing finalizing control ping
// reply for a next request
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: 2}, false,2)
+ msgs = append(msgs,
+ mock.MsgWithContext{
+ Msg: &vpe.ControlPingReply{Retval: 2},
+ SeqNum: 2,
+ Multipart: false,
+ })
+
+ // queue replies
+ ctx.mockVpp.MockReplyWithContext(msgs...)
// send multipart request
reqCtx := ctx.ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
// some replies will get thrown away
// first request
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: 1}, false)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: 1})
req1 := &vpe.ControlPing{}
reqCtx1 := ctx.ch.SendRequest(req1)
// second request
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: 2}, false)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: 2})
req2 := &vpe.ControlPing{}
reqCtx2 := ctx.ch.SendRequest(req2)
numIters := 0xffff + 100
reqCtx := make(map[int]*api.RequestCtx)
- var seqNum uint16 = 0
- for i := 0; i < numIters + 30 /* receiver is 30 reqs behind */; i++ {
- seqNum++
+ for i := 0; i < numIters+30; /* receiver is 30 reqs behind */ i++ {
if i < numIters {
- ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{Retval: int32(i)}, false, seqNum)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: int32(i)})
req := &vpe.ControlPing{}
reqCtx[i] = ctx.ch.SendRequest(req)
}
reply := &vpe.ControlPingReply{}
err := reqCtx[i-30].ReceiveReply(reply)
Expect(err).ShouldNot(HaveOccurred())
- Expect(reply.Retval).To(BeEquivalentTo(i-30))
+ Expect(reply.Retval).To(BeEquivalentTo(i - 30))
}
}
-}
\ No newline at end of file
+}