ctx.ch, err = ctx.conn.NewAPIChannel()
Expect(err).ShouldNot(HaveOccurred())
- ctx.ch.SetReplyTimeout(time.Millisecond)
-
return ctx
}
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{}
ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{
SwIfIndex: uint32(i),
DevName: []byte("dev-name-test"),
- })
+ }, true)
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true)
reqCtx := ctx.ch.SendMultiRequest(&tap.SwInterfaceTapDump{})
cnt := 0
for i := 1; i <= 10; i++ {
ctx.mockVpp.MockReply(&memif.MemifDetails{
SwIfIndex: uint32(i),
- })
+ }, true)
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true)
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
err := ctx.ch.CheckMessageCompatibility(&interfaces.SwInterfaceSetFlags{})
Expect(err).ShouldNot(HaveOccurred())
}
-
func TestSetReplyTimeout(t *testing.T) {
ctx := setupTest(t)
defer ctx.teardownTest()
+ ctx.ch.SetReplyTimeout(time.Millisecond)
+
// first one request should work
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, false)
err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
Expect(err).ShouldNot(HaveOccurred())
ctx := setupTest(t)
defer ctx.teardownTest()
+ ctx.ch.SetReplyTimeout(time.Millisecond)
+
for i := 1; i <= 3; i++ {
ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{
SwIfIndex: uint32(i),
InterfaceName: []byte("if-name-test"),
- })
+ }, true)
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{}, true)
cnt := 0
sendMultiRequest := func() error {
// mock reply
for i := 1; i <= 3; i++ {
- ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{
+ ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{
SwIfIndex: uint32(i),
InterfaceName: []byte("if-name-test"),
- })
+ }, true, 1)
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true, 1)
for i := 1; i <= 3; i++ {
- ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{
+ ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{
SwIfIndex: uint32(i),
InterfaceName: []byte("if-name-test"),
- })
+ }, true, 2)
}
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true,2)
cnt := 0
- sendMultiRequest := func() error {
+ var sendMultiRequest = func() error {
reqCtx := ctx.ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
for {
msg := &interfaces.SwInterfaceDetails{}
Expect(cnt).To(BeEquivalentTo(6))
}
+
+func TestReceiveReplyAfterTimeout(t *testing.T) {
+ ctx := setupTest(t)
+ defer ctx.teardownTest()
+
+ ctx.ch.SetReplyTimeout(time.Millisecond)
+
+ // first one request should work
+ ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, false,1)
+ err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
+ Expect(err).ShouldNot(HaveOccurred())
+
+ err = ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
+ 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)
+
+ req := &tap.TapConnect{
+ TapName: []byte("test-tap-name"),
+ UseRandomMac: 1,
+ }
+ reply := &tap.TapConnectReply{}
+
+ // should succeed
+ err = ctx.ch.SendRequest(req).ReceiveReply(reply)
+ Expect(err).ShouldNot(HaveOccurred())
+}
+
+func TestReceiveReplyAfterTimeoutMultiRequest(t *testing.T) {
+ /*
+ TODO: fix mock adapter
+ This test will fail because mock adapter will stop sending replies
+ when it encounters control_ping_reply from multi request,
+ thus never sending reply for next request
+ */
+ t.Skip()
+
+ ctx := setupTest(t)
+ defer ctx.teardownTest()
+
+ ctx.ch.SetReplyTimeout(time.Millisecond * 100)
+
+ // first one request should work
+ ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, false, 1)
+ err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
+ Expect(err).ShouldNot(HaveOccurred())
+
+ cnt := 0
+ var sendMultiRequest = func() error {
+ reqCtx := ctx.ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
+ for {
+ msg := &interfaces.SwInterfaceDetails{}
+ stop, err := reqCtx.ReceiveReply(msg)
+ if stop {
+ break // break out of the loop
+ }
+ if err != nil {
+ return err
+ }
+ cnt++
+ }
+ return nil
+ }
+
+ err = sendMultiRequest()
+ Expect(err).Should(HaveOccurred())
+ Expect(err.Error()).To(ContainSubstring("timeout"))
+ Expect(cnt).To(BeEquivalentTo(0))
+
+ // simulating late replies
+ for i := 1; i <= 3; i++ {
+ ctx.mockVpp.MockReplyWithSeqNum(&interfaces.SwInterfaceDetails{
+ SwIfIndex: uint32(i),
+ InterfaceName: []byte("if-name-test"),
+ }, true, 2)
+ }
+ ctx.mockVpp.MockReplyWithSeqNum(&vpe.ControlPingReply{}, true, 2)
+
+ // normal reply for next request
+ ctx.mockVpp.MockReplyWithSeqNum(&tap.TapConnectReply{}, false, 3)
+
+ req := &tap.TapConnect{
+ TapName: []byte("test-tap-name"),
+ UseRandomMac: 1,
+ }
+ reply := &tap.TapConnectReply{}
+
+ // should succeed
+ err = ctx.ch.SendRequest(req).ReceiveReply(reply)
+ Expect(err).ShouldNot(HaveOccurred())
+}
+
+func TestInvalidMessageID(t *testing.T) {
+ ctx := setupTest(t)
+ defer ctx.teardownTest()
+
+ // first one request should work
+ ctx.mockVpp.MockReply(&vpe.ShowVersionReply{}, false)
+ 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)
+ err = ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
+ Expect(err).Should(HaveOccurred())
+ Expect(err.Error()).To(ContainSubstring("invalid message ID"))
+}