summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adapter/mock/mock_adapter.go121
-rw-r--r--api/api.go16
-rw-r--r--api/api_test.go113
-rw-r--r--core/core_test.go94
4 files changed, 222 insertions, 122 deletions
diff --git a/adapter/mock/mock_adapter.go b/adapter/mock/mock_adapter.go
index ae4caf0..959fd86 100644
--- a/adapter/mock/mock_adapter.go
+++ b/adapter/mock/mock_adapter.go
@@ -67,11 +67,19 @@ type MessageDTO struct {
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.
@@ -253,37 +261,32 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error {
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
@@ -313,24 +316,56 @@ func (a *VppAdapter) WaitReady() error {
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
}
diff --git a/api/api.go b/api/api.go
index 3c2c7ec..34e17c1 100644
--- a/api/api.go
+++ b/api/api.go
@@ -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"))
diff --git a/core/core_test.go b/core/core_test.go
index 981ff19..e4fbf63 100644
--- a/core/core_test.go
+++ b/core/core_test.go
@@ -62,7 +62,7 @@ func TestSimpleRequest(t *testing.T) {
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{}
@@ -85,10 +85,12 @@ func TestMultiRequest(t *testing.T) {
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}
@@ -133,7 +135,7 @@ func TestNotifications(t *testing.T) {
ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{
SwIfIndex: 3,
AdminUpDown: 1,
- }, false)
+ })
ctx.mockVpp.SendMsg(0, []byte{0})
// receive the notification
@@ -204,7 +206,7 @@ func TestFullBuffer(t *testing.T) {
// 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{}}
}
@@ -285,7 +287,7 @@ func TestSimpleRequestsWithSequenceNumbers(t *testing.T) {
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))
}
@@ -302,10 +304,12 @@ func TestMultiRequestsWithSequenceNumbers(t *testing.T) {
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{})
@@ -336,7 +340,10 @@ func TestSimpleRequestWithTimeout(t *testing.T) {
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{}
@@ -347,11 +354,19 @@ func TestSimpleRequestWithTimeout(t *testing.T) {
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)
@@ -375,7 +390,10 @@ func TestSimpleRequestsWithMissingReply(t *testing.T) {
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)
@@ -401,18 +419,42 @@ func TestMultiRequestsWithErrors(t *testing.T) {
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{})
@@ -454,12 +496,12 @@ func TestRequestsOrdering(t *testing.T) {
// 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)
@@ -484,11 +526,9 @@ func TestCycleOverSetOfSequenceNumbers(t *testing.T) {
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)
}
@@ -496,7 +536,7 @@ func TestCycleOverSetOfSequenceNumbers(t *testing.T) {
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
+}