defer ctx.teardownTest()
// mock reply
+ msgs := []api.Message{}
for i := 1; i <= 10; i++ {
- byteName := []byte("dev-name-test")
- ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{
+ msgs = append(msgs, &tap.SwInterfaceTapDetails{
SwIfIndex: uint32(i),
- DevName: byteName,
+ DevName: []byte("dev-name-test"),
})
}
+ ctx.mockVpp.MockReply(msgs...)
ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
reqCtx := ctx.ch.SendMultiRequest(&tap.SwInterfaceTapDump{})
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),
})
}
+ ctx.mockVpp.MockReply(msgs...)
ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
reqCtx := ctx.ch.SendMultiRequest(&memif.MemifDump{})
err := ctx.ch.CheckMessageCompatibility(&interfaces.SwInterfaceSetFlags{})
Expect(err).ShouldNot(HaveOccurred())
}
-
func TestSetReplyTimeout(t *testing.T) {
ctx := setupTest(t)
defer ctx.teardownTest()
Expect(err.Error()).To(ContainSubstring("timeout"))
}
+func TestSetReplyTimeoutMultiRequest(t *testing.T) {
+ ctx := setupTest(t)
+ defer ctx.teardownTest()
+
+ ctx.ch.SetReplyTimeout(time.Millisecond)
+
+ msgs := []api.Message{}
+ for i := 1; i <= 3; i++ {
+ msgs = append(msgs, &interfaces.SwInterfaceDetails{
+ SwIfIndex: uint32(i),
+ InterfaceName: []byte("if-name-test"),
+ })
+ }
+ ctx.mockVpp.MockReply(msgs...)
+ ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+
+ cnt := 0
+ 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
+ }
+
+ // first one request should work
+ err := sendMultiRequest()
+ Expect(err).ShouldNot(HaveOccurred())
+
+ // no other reply ready - expect timeout
+ err = sendMultiRequest()
+ Expect(err).Should(HaveOccurred())
+ Expect(err.Error()).To(ContainSubstring("timeout"))
+
+ Expect(cnt).To(BeEquivalentTo(3))
+}
+
func TestReceiveReplyNegative(t *testing.T) {
ctx := setupTest(t)
defer ctx.teardownTest()
Expect(err).Should(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("invalid request context"))
}
+
+func TestMultiRequestDouble(t *testing.T) {
+ ctx := setupTest(t)
+ defer ctx.teardownTest()
+
+ // mock reply
+ msgs := []mock.MsgWithContext{}
+ for i := 1; i <= 3; i++ {
+ msgs = append(msgs, mock.MsgWithContext{
+ Msg: &interfaces.SwInterfaceDetails{
+ SwIfIndex: uint32(i),
+ InterfaceName: []byte("if-name-test"),
+ },
+ Multipart: true,
+ SeqNum: 1,
+ })
+ }
+ msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 1})
+
+ for i := 1; i <= 3; i++ {
+ msgs = append(msgs,
+ mock.MsgWithContext{
+ Msg: &interfaces.SwInterfaceDetails{
+ SwIfIndex: uint32(i),
+ InterfaceName: []byte("if-name-test"),
+ },
+ Multipart: true,
+ SeqNum: 2,
+ })
+ }
+ msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 2})
+
+ ctx.mockVpp.MockReplyWithContext(msgs...)
+
+ 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).ShouldNot(HaveOccurred())
+
+ err = sendMultiRequest()
+ Expect(err).ShouldNot(HaveOccurred())
+
+ 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.MockReplyWithContext(mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, SeqNum: 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"))
+
+ 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"),
+ 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.MockReplyWithContext(mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, SeqNum: 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
+ msgs := []mock.MsgWithContext{}
+ for i := 1; i <= 3; i++ {
+ msgs = append(msgs, mock.MsgWithContext{
+ Msg: &interfaces.SwInterfaceDetails{
+ SwIfIndex: uint32(i),
+ InterfaceName: []byte("if-name-test"),
+ },
+ Multipart: true,
+ SeqNum: 2,
+ })
+ }
+ msgs = append(msgs, mock.MsgWithContext{Msg: &vpe.ControlPingReply{}, Multipart: true, SeqNum: 2})
+ ctx.mockVpp.MockReplyWithContext(msgs...)
+
+ // normal reply for next request
+ ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{Msg: &tap.TapConnectReply{}, SeqNum: 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{})
+ 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{})
+ err = ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
+ Expect(err).Should(HaveOccurred())
+ Expect(err.Error()).To(ContainSubstring("invalid message ID"))
+}