import (
"testing"
+ "time"
- "git.fd.io/govpp.git/adapter/mock"
- "git.fd.io/govpp.git/api"
- "git.fd.io/govpp.git/codec"
- "git.fd.io/govpp.git/core"
- "git.fd.io/govpp.git/examples/bin_api/interfaces"
- "git.fd.io/govpp.git/examples/bin_api/vpe"
. "github.com/onsi/gomega"
+
+ "go.fd.io/govpp/adapter/mock"
+ "go.fd.io/govpp/api"
+ "go.fd.io/govpp/binapi/ethernet_types"
+ interfaces "go.fd.io/govpp/binapi/interface"
+ "go.fd.io/govpp/binapi/interface_types"
+ memclnt "go.fd.io/govpp/binapi/memclnt"
+ "go.fd.io/govpp/codec"
+ "go.fd.io/govpp/core"
)
type testCtx struct {
Expect(ev.State).Should(BeEquivalentTo(core.Connected))
}
+func TestAsyncConnectionProcessesVppTimeout(t *testing.T) {
+ ctx := setupTest(t, false)
+ defer ctx.teardownTest()
+
+ ctx.conn.Disconnect()
+ conn, statusChan, err := core.AsyncConnect(ctx.mockVpp, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval)
+ ctx.conn = conn
+
+ Expect(err).ShouldNot(HaveOccurred())
+ Expect(conn).ShouldNot(BeNil())
+
+ ev := <-statusChan
+ Expect(ev.State).Should(BeEquivalentTo(core.Connected))
+
+ // make control ping reply fail so that connection.healthCheckLoop()
+ // initiates reconnection.
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{
+ Retval: -1,
+ })
+ time.Sleep(time.Duration(1+core.HealthCheckThreshold) * (core.HealthCheckInterval + 2*core.HealthCheckReplyTimeout))
+}
+
func TestCodec(t *testing.T) {
RegisterTestingT(t)
- msgCodec := &codec.MsgCodec{}
+ var msgCodec = codec.DefaultCodec
// request
- data, err := msgCodec.EncodeMsg(&interfaces.CreateLoopback{MacAddress: []byte{1, 2, 3, 4, 5, 6}}, 11)
+ data, err := msgCodec.EncodeMsg(&interfaces.CreateLoopback{MacAddress: ethernet_types.MacAddress{1, 2, 3, 4, 5, 6}}, 11)
Expect(err).ShouldNot(HaveOccurred())
Expect(data).ShouldNot(BeEmpty())
msg1 := &interfaces.CreateLoopback{}
err = msgCodec.DecodeMsg(data, msg1)
Expect(err).ShouldNot(HaveOccurred())
- Expect(msg1.MacAddress).To(BeEquivalentTo([]byte{1, 2, 3, 4, 5, 6}))
+ Expect(msg1.MacAddress).To(BeEquivalentTo(ethernet_types.MacAddress{1, 2, 3, 4, 5, 6}))
// reply
- data, err = msgCodec.EncodeMsg(&vpe.ControlPingReply{Retval: 55}, 22)
+ data, err = msgCodec.EncodeMsg(&memclnt.ControlPingReply{Retval: 55}, 22)
Expect(err).ShouldNot(HaveOccurred())
Expect(data).ShouldNot(BeEmpty())
- msg2 := &vpe.ControlPingReply{}
+ msg2 := &memclnt.ControlPingReply{}
err = msgCodec.DecodeMsg(data, msg2)
Expect(err).ShouldNot(HaveOccurred())
Expect(msg2.Retval).To(BeEquivalentTo(55))
func TestCodecNegative(t *testing.T) {
RegisterTestingT(t)
- msgCodec := &codec.MsgCodec{}
+ var msgCodec = codec.DefaultCodec
// nil message for encoding
data, err := msgCodec.EncodeMsg(nil, 15)
Expect(err.Error()).To(ContainSubstring("nil message"))
// nil data for decoding
- err = msgCodec.DecodeMsg(nil, &vpe.ControlPingReply{})
+ err = msgCodec.DecodeMsg(nil, &memclnt.ControlPingReply{})
Expect(err).Should(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("EOF"))
+ Expect(err.Error()).To(ContainSubstring("panic"))
}
func TestSimpleRequestsWithSequenceNumbers(t *testing.T) {
var reqCtx []api.RequestCtx
for i := 0; i < 10; i++ {
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
- req := &vpe.ControlPing{}
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{})
+ req := &memclnt.ControlPing{}
reqCtx = append(reqCtx, ctx.ch.SendRequest(req))
}
for i := 0; i < 10; i++ {
- reply := &vpe.ControlPingReply{}
+ reply := &memclnt.ControlPingReply{}
err := reqCtx[i].ReceiveReply(reply)
Expect(err).ShouldNot(HaveOccurred())
}
var msgs []api.Message
for i := 0; i < 10; i++ {
- msgs = append(msgs, &interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)})
+ msgs = append(msgs, &interfaces.SwInterfaceDetails{SwIfIndex: interface_types.InterfaceIndex(i)})
}
ctx.mockVpp.MockReply(msgs...)
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{})
// send multipart request
reqCtx := ctx.ch.SendMultiRequest(&interfaces.SwInterfaceDump{})
// reply for a previous timeouted requests to be ignored
ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{
- Msg: &vpe.ControlPingReply{},
+ Msg: &memclnt.ControlPingReply{},
SeqNum: 0,
})
// send reply later
- req1 := &vpe.ControlPing{}
+ req1 := &memclnt.ControlPing{}
reqCtx1 := ctx.ch.SendRequest(req1)
- reply := &vpe.ControlPingReply{}
+ reply := &memclnt.ControlPingReply{}
err := reqCtx1.ReceiveReply(reply)
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(HavePrefix("no reply received within the timeout period"))
ctx.mockVpp.MockReplyWithContext(
// reply for the previous request
mock.MsgWithContext{
- Msg: &vpe.ControlPingReply{},
+ Msg: &memclnt.ControlPingReply{},
SeqNum: 1,
},
// reply for the next request
mock.MsgWithContext{
- Msg: &vpe.ControlPingReply{},
+ Msg: &memclnt.ControlPingReply{},
SeqNum: 2,
})
// next request
- req2 := &vpe.ControlPing{}
+ req2 := &memclnt.ControlPing{}
reqCtx2 := ctx.ch.SendRequest(req2)
// second request should ignore the first reply and return the second one
- reply = &vpe.ControlPingReply{}
+ reply = &memclnt.ControlPingReply{}
err = reqCtx2.ReceiveReply(reply)
Expect(err).To(BeNil())
}
defer ctx.teardownTest()
// request without reply
- req1 := &vpe.ControlPing{}
+ req1 := &memclnt.ControlPing{}
reqCtx1 := ctx.ch.SendRequest(req1)
// another request without reply
- req2 := &vpe.ControlPing{}
+ req2 := &memclnt.ControlPing{}
reqCtx2 := ctx.ch.SendRequest(req2)
// third request with reply
ctx.mockVpp.MockReplyWithContext(mock.MsgWithContext{
- Msg: &vpe.ControlPingReply{},
+ Msg: &memclnt.ControlPingReply{},
SeqNum: 3,
})
- req3 := &vpe.ControlPing{}
+ req3 := &memclnt.ControlPing{}
reqCtx3 := ctx.ch.SendRequest(req3)
// the first two should fail, but not consume reply for the 3rd
- reply := &vpe.ControlPingReply{}
+ reply := &memclnt.ControlPingReply{}
err := reqCtx1.ReceiveReply(reply)
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(Equal("missing binary API reply with sequence number: 1"))
- reply = &vpe.ControlPingReply{}
+ reply = &memclnt.ControlPingReply{}
err = reqCtx2.ReceiveReply(reply)
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(Equal("missing binary API reply with sequence number: 2"))
// the second request should succeed
- reply = &vpe.ControlPingReply{}
+ reply = &memclnt.ControlPingReply{}
err = reqCtx3.ReceiveReply(reply)
Expect(err).To(BeNil())
}
// replies for a previous timeouted requests to be ignored
msgs := []mock.MsgWithContext{
- {Msg: &vpe.ControlPingReply{}, SeqNum: 0xffff - 1},
- {Msg: &vpe.ControlPingReply{}, SeqNum: 0xffff},
- {Msg: &vpe.ControlPingReply{}, SeqNum: 0},
+ {Msg: &memclnt.ControlPingReply{}, SeqNum: 0xffff - 1},
+ {Msg: &memclnt.ControlPingReply{}, SeqNum: 0xffff},
+ {Msg: &memclnt.ControlPingReply{}, SeqNum: 0},
}
for i := 0; i < 10; i++ {
msgs = append(msgs, mock.MsgWithContext{
- Msg: &interfaces.SwInterfaceDetails{SwIfIndex: uint32(i)},
+ Msg: &interfaces.SwInterfaceDetails{SwIfIndex: interface_types.InterfaceIndex(i)},
SeqNum: 1,
Multipart: true,
})
// reply for a next request
msgs = append(msgs, mock.MsgWithContext{
- Msg: &vpe.ControlPingReply{},
+ Msg: &memclnt.ControlPingReply{},
SeqNum: 2,
})
Expect(err.Error()).To(Equal("missing binary API reply with sequence number: 1"))
// reply for the second request has not been consumed
- reqCtx2 := ctx.ch.SendRequest(&vpe.ControlPing{})
- reply2 := &vpe.ControlPingReply{}
+ reqCtx2 := ctx.ch.SendRequest(&memclnt.ControlPing{})
+ reply2 := &memclnt.ControlPingReply{}
err = reqCtx2.ReceiveReply(reply2)
Expect(err).To(BeNil())
}
// some replies will get thrown away
// first request
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
- req1 := &vpe.ControlPing{}
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{})
+ req1 := &memclnt.ControlPing{}
reqCtx1 := ctx.ch.SendRequest(req1)
// second request
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
- req2 := &vpe.ControlPing{}
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{})
+ req2 := &memclnt.ControlPing{}
reqCtx2 := ctx.ch.SendRequest(req2)
// if reply for the second request is read first, the reply for the first
// request gets thrown away.
- reply2 := &vpe.ControlPingReply{}
+ reply2 := &memclnt.ControlPingReply{}
err := reqCtx2.ReceiveReply(reply2)
Expect(err).To(BeNil())
// first request has already been considered closed
- reply1 := &vpe.ControlPingReply{}
+ reply1 := &memclnt.ControlPingReply{}
err = reqCtx1.ReceiveReply(reply1)
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(HavePrefix("no reply received within the timeout period"))
for i := 0; i < numIters+30; i++ {
if i < numIters {
- ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
- req := &vpe.ControlPing{}
+ ctx.mockVpp.MockReply(&memclnt.ControlPingReply{})
+ req := &memclnt.ControlPing{}
reqCtx[i] = ctx.ch.SendRequest(req)
}
if i > 30 {
- reply := &vpe.ControlPingReply{}
+ reply := &memclnt.ControlPingReply{}
err := reqCtx[i-30].ReceiveReply(reply)
Expect(err).ShouldNot(HaveOccurred())
}