1 // Copyright (c) 2017 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
20 "git.fd.io/govpp.git/adapter/mock"
21 "git.fd.io/govpp.git/api"
22 "git.fd.io/govpp.git/core/bin_api/vpe"
23 "git.fd.io/govpp.git/examples/bin_api/interfaces"
25 . "github.com/onsi/gomega"
29 mockVpp *mock.VppAdapter
34 func setupTest(t *testing.T) *testCtx {
38 ctx.mockVpp = &mock.VppAdapter{}
41 ctx.conn, err = Connect(ctx.mockVpp)
42 Expect(err).ShouldNot(HaveOccurred())
44 ctx.ch, err = ctx.conn.NewAPIChannel()
45 Expect(err).ShouldNot(HaveOccurred())
50 func (ctx *testCtx) teardownTest() {
55 func TestSimpleRequest(t *testing.T) {
57 defer ctx.teardownTest()
59 ctx.mockVpp.MockReply(&vpe.ControlPingReply{Retval: -5})
61 req := &vpe.ControlPing{}
62 reply := &vpe.ControlPingReply{}
64 // send the request and receive a reply
65 ctx.ch.ReqChan <- &api.VppRequest{Message: req}
66 vppReply := <-ctx.ch.ReplyChan
68 Expect(vppReply).ShouldNot(BeNil())
69 Expect(vppReply.Error).ShouldNot(HaveOccurred())
72 err := ctx.ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
73 Expect(err).ShouldNot(HaveOccurred())
75 Expect(reply.Retval).To(BeEquivalentTo(-5))
78 func TestMultiRequest(t *testing.T) {
80 defer ctx.teardownTest()
82 for m := 0; m < 10; m++ {
83 ctx.mockVpp.MockReply(&interfaces.SwInterfaceDetails{})
85 ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
87 // send multipart request
88 ctx.ch.ReqChan <- &api.VppRequest{Message: &interfaces.SwInterfaceDump{}, Multipart: true}
93 vppReply := <-ctx.ch.ReplyChan
94 if vppReply.LastReplyReceived {
95 break // break out of the loop
97 Expect(vppReply.Error).ShouldNot(HaveOccurred())
100 reply := &interfaces.SwInterfaceDetails{}
101 err := ctx.ch.MsgDecoder.DecodeMsg(vppReply.Data, reply)
102 Expect(err).ShouldNot(HaveOccurred())
106 Expect(cnt).To(BeEquivalentTo(10))
109 func TestNotifications(t *testing.T) {
111 defer ctx.teardownTest()
113 // subscribe for notification
114 notifChan := make(chan api.Message, 1)
115 subscription := &api.NotifSubscription{
116 NotifChan: notifChan,
117 MsgFactory: interfaces.NewSwInterfaceSetFlags,
119 ctx.ch.NotifSubsChan <- &api.NotifSubscribeRequest{
120 Subscription: subscription,
123 err := <-ctx.ch.NotifSubsReplyChan
124 Expect(err).ShouldNot(HaveOccurred())
126 // mock the notification and force its delivery
127 ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{
131 ctx.mockVpp.SendMsg(0, []byte{0})
133 // receive the notification
134 notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
136 Expect(notif.SwIfIndex).To(BeEquivalentTo(3))
138 // unsubscribe notification
139 ctx.ch.NotifSubsChan <- &api.NotifSubscribeRequest{
140 Subscription: subscription,
143 err = <-ctx.ch.NotifSubsReplyChan
144 Expect(err).ShouldNot(HaveOccurred())
147 func TestNilConnection(t *testing.T) {
151 ch, err := conn.NewAPIChannel()
152 Expect(ch).Should(BeNil())
153 Expect(err).Should(HaveOccurred())
154 Expect(err.Error()).To(ContainSubstring("nil"))
156 ch, err = conn.NewAPIChannelBuffered(1, 1)
157 Expect(ch).Should(BeNil())
158 Expect(err).Should(HaveOccurred())
159 Expect(err.Error()).To(ContainSubstring("nil"))
162 func TestDoubleConnection(t *testing.T) {
164 defer ctx.teardownTest()
166 conn, err := Connect(ctx.mockVpp)
167 Expect(err).Should(HaveOccurred())
168 Expect(err.Error()).To(ContainSubstring("only one connection per process"))
169 Expect(conn).Should(BeNil())
172 func TestAsyncConnection(t *testing.T) {
174 defer ctx.teardownTest()
176 ctx.conn.Disconnect()
177 conn, ch, err := AsyncConnect(ctx.mockVpp)
180 Expect(err).ShouldNot(HaveOccurred())
181 Expect(conn).ShouldNot(BeNil())
184 Expect(ev.State).Should(BeEquivalentTo(Connected))
187 func TestFullBuffer(t *testing.T) {
189 defer ctx.teardownTest()
191 // close the default API channel
194 // create a new channel with limited buffer sizes
196 ctx.ch, err = ctx.conn.NewAPIChannelBuffered(10, 1)
197 Expect(err).ShouldNot(HaveOccurred())
199 // send multiple requests, only one reply should be read
200 for i := 0; i < 20; i++ {
201 ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
202 ctx.ch.ReqChan <- &api.VppRequest{Message: &vpe.ControlPing{}}
205 vppReply := <-ctx.ch.ReplyChan
206 Expect(vppReply).ShouldNot(BeNil())
210 case vppReply = <-ctx.ch.ReplyChan:
211 received = true // this should not happen
213 received = false // no reply to be received
215 Expect(received).Should(BeFalse(), "A reply has been recieved, should had been ignored.")
218 func TestCodec(t *testing.T) {
224 data, err := codec.EncodeMsg(&vpe.CreateLoopback{MacAddress: []byte{1, 2, 3, 4, 5, 6}}, 11)
225 Expect(err).ShouldNot(HaveOccurred())
226 Expect(data).ShouldNot(BeEmpty())
228 msg1 := &vpe.CreateLoopback{}
229 err = codec.DecodeMsg(data, msg1)
230 Expect(err).ShouldNot(HaveOccurred())
231 Expect(msg1.MacAddress).To(BeEquivalentTo([]byte{1, 2, 3, 4, 5, 6}))
234 data, err = codec.EncodeMsg(&vpe.ControlPingReply{Retval: 55}, 22)
235 Expect(err).ShouldNot(HaveOccurred())
236 Expect(data).ShouldNot(BeEmpty())
238 msg2 := &vpe.ControlPingReply{}
239 err = codec.DecodeMsg(data, msg2)
240 Expect(err).ShouldNot(HaveOccurred())
241 Expect(msg2.Retval).To(BeEquivalentTo(55))
244 data, err = codec.EncodeMsg(&vpe.VnetIP4FibCounters{VrfID: 77}, 33)
245 Expect(err).ShouldNot(HaveOccurred())
246 Expect(data).ShouldNot(BeEmpty())
248 msg3 := &vpe.VnetIP4FibCounters{}
249 err = codec.DecodeMsg(data, msg3)
250 Expect(err).ShouldNot(HaveOccurred())
251 Expect(msg3.VrfID).To(BeEquivalentTo(77))
254 func TestCodecNegative(t *testing.T) {
259 // nil message for encoding
260 data, err := codec.EncodeMsg(nil, 15)
261 Expect(err).Should(HaveOccurred())
262 Expect(err.Error()).To(ContainSubstring("nil message"))
263 Expect(data).Should(BeNil())
265 // nil message for decoding
266 err = codec.DecodeMsg(data, nil)
267 Expect(err).Should(HaveOccurred())
268 Expect(err.Error()).To(ContainSubstring("nil message"))
270 // nil data for decoding
271 err = codec.DecodeMsg(nil, &vpe.ControlPingReply{})
272 Expect(err).Should(HaveOccurred())
273 Expect(err.Error()).To(ContainSubstring("EOF"))