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.
22 "git.fd.io/govpp.git/adapter/mock"
23 "git.fd.io/govpp.git/api"
24 "git.fd.io/govpp.git/core"
25 "git.fd.io/govpp.git/core/bin_api/vpe"
26 "git.fd.io/govpp.git/examples/bin_api/interfaces"
27 "git.fd.io/govpp.git/examples/bin_api/memif"
28 "git.fd.io/govpp.git/examples/bin_api/tap"
30 . "github.com/onsi/gomega"
34 mockVpp *mock.VppAdapter
39 func setupTest(t *testing.T) *testCtx {
43 ctx.mockVpp = &mock.VppAdapter{}
44 govpp.SetAdapter(ctx.mockVpp)
47 ctx.conn, err = govpp.Connect()
48 Expect(err).ShouldNot(HaveOccurred())
50 ctx.ch, err = ctx.conn.NewAPIChannel()
51 Expect(err).ShouldNot(HaveOccurred())
56 func (ctx *testCtx) teardownTest() {
61 func TestRequestReplyTapConnect(t *testing.T) {
63 defer ctx.teardownTest()
65 ctx.mockVpp.MockReply(&tap.TapConnectReply{
69 request := &tap.TapConnect{
70 TapName: []byte("test-tap-name"),
73 reply := &tap.TapConnectReply{}
75 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
76 Expect(err).ShouldNot(HaveOccurred())
77 Expect(reply.Retval).To(BeEquivalentTo(10), "Incorrect retval value for TapConnectReply")
78 Expect(reply.SwIfIndex).To(BeEquivalentTo(1), "Incorrect SwIfIndex value for TapConnectReply")
81 func TestRequestReplyTapModify(t *testing.T) {
83 defer ctx.teardownTest()
85 ctx.mockVpp.MockReply(&tap.TapModifyReply{
89 request := &tap.TapModify{
90 TapName: []byte("test-tap-modify"),
94 reply := &tap.TapModifyReply{}
96 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
97 Expect(err).ShouldNot(HaveOccurred())
98 Expect(reply.Retval).To(BeEquivalentTo(15), "Incorrect retval value for TapModifyReply")
99 Expect(reply.SwIfIndex).To(BeEquivalentTo(2), "Incorrect SwIfIndex value for TapModifyReply")
102 func TestRequestReplyTapDelete(t *testing.T) {
104 defer ctx.teardownTest()
106 ctx.mockVpp.MockReply(&tap.TapDeleteReply{
109 request := &tap.TapDelete{
112 reply := &tap.TapDeleteReply{}
114 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
115 Expect(err).ShouldNot(HaveOccurred())
116 Expect(reply.Retval).To(BeEquivalentTo(20), "Incorrect retval value for TapDeleteReply")
119 func TestRequestReplySwInterfaceTapDump(t *testing.T) {
121 defer ctx.teardownTest()
123 byteName := []byte("dev-name-test")
124 ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{
128 request := &tap.SwInterfaceTapDump{}
129 reply := &tap.SwInterfaceTapDetails{}
131 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
132 Expect(err).ShouldNot(HaveOccurred())
133 Expect(reply.SwIfIndex).To(BeEquivalentTo(25), "Incorrect SwIfIndex value for SwInterfaceTapDetails")
134 Expect(reply.DevName).ToNot(BeNil(), "Incorrect DevName value for SwInterfaceTapDetails")
137 func TestRequestReplyMemifCreate(t *testing.T) {
139 defer ctx.teardownTest()
141 ctx.mockVpp.MockReply(&memif.MemifCreateReply{
145 request := &memif.MemifCreate{
151 reply := &memif.MemifCreateReply{}
153 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
154 Expect(err).ShouldNot(HaveOccurred())
155 Expect(reply.Retval).To(BeEquivalentTo(22), "Incorrect Retval value for MemifCreate")
156 Expect(reply.SwIfIndex).To(BeEquivalentTo(4), "Incorrect SwIfIndex value for MemifCreate")
159 func TestRequestReplyMemifDelete(t *testing.T) {
161 defer ctx.teardownTest()
163 ctx.mockVpp.MockReply(&memif.MemifDeleteReply{
166 request := &memif.MemifDelete{
169 reply := &memif.MemifDeleteReply{}
171 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
172 Expect(err).ShouldNot(HaveOccurred())
173 Expect(reply.Retval).To(BeEquivalentTo(24), "Incorrect Retval value for MemifDelete")
176 func TestRequestReplyMemifDetails(t *testing.T) {
178 defer ctx.teardownTest()
180 ctx.mockVpp.MockReply(&memif.MemifDetails{
182 IfName: []byte("memif-name"),
185 request := &memif.MemifDump{}
186 reply := &memif.MemifDetails{}
188 err := ctx.ch.SendRequest(request).ReceiveReply(reply)
189 Expect(err).ShouldNot(HaveOccurred())
190 Expect(reply.SwIfIndex).To(BeEquivalentTo(25), "Incorrect SwIfIndex value for MemifDetails")
191 Expect(reply.IfName).ToNot(BeEmpty(), "MemifDetails IfName is empty byte array")
192 Expect(reply.Role).To(BeEquivalentTo(0), "Incorrect Role value for MemifDetails")
195 func TestMultiRequestReplySwInterfaceTapDump(t *testing.T) {
197 defer ctx.teardownTest()
200 for i := 1; i <= 10; i++ {
201 byteName := []byte("dev-name-test")
202 ctx.mockVpp.MockReply(&tap.SwInterfaceTapDetails{
203 SwIfIndex: uint32(i),
207 ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
209 reqCtx := ctx.ch.SendMultiRequest(&tap.SwInterfaceTapDump{})
212 msg := &tap.SwInterfaceTapDetails{}
213 stop, err := reqCtx.ReceiveReply(msg)
215 break // break out of the loop
217 Expect(err).ShouldNot(HaveOccurred())
220 Expect(cnt).To(BeEquivalentTo(10))
223 func TestMultiRequestReplySwInterfaceMemifDump(t *testing.T) {
225 defer ctx.teardownTest()
228 for i := 1; i <= 10; i++ {
229 ctx.mockVpp.MockReply(&memif.MemifDetails{
230 SwIfIndex: uint32(i),
233 ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
235 reqCtx := ctx.ch.SendMultiRequest(&memif.MemifDump{})
238 msg := &memif.MemifDetails{}
239 stop, err := reqCtx.ReceiveReply(msg)
241 break // break out of the loop
243 Expect(err).ShouldNot(HaveOccurred())
246 Expect(cnt).To(BeEquivalentTo(10))
249 func TestNotifications(t *testing.T) {
251 defer ctx.teardownTest()
253 // subscribe for notification
254 notifChan := make(chan api.Message, 1)
255 subs, err := ctx.ch.SubscribeNotification(notifChan, interfaces.NewSwInterfaceSetFlags)
256 Expect(err).ShouldNot(HaveOccurred())
258 // mock the notification and force its delivery
259 ctx.mockVpp.MockReply(&interfaces.SwInterfaceSetFlags{
263 ctx.mockVpp.SendMsg(0, []byte(""))
265 // receive the notification
266 notif := (<-notifChan).(*interfaces.SwInterfaceSetFlags)
268 // verify the received notifications
269 Expect(notif).ShouldNot(BeNil())
270 Expect(notif.SwIfIndex).To(BeEquivalentTo(3), "Incorrect SwIfIndex value for SwInterfaceSetFlags")
271 Expect(notif.AdminUpDown).To(BeEquivalentTo(1), "Incorrect AdminUpDown value for SwInterfaceSetFlags")
273 ctx.ch.UnsubscribeNotification(subs)
276 func TestCheckMessageCompatibility(t *testing.T) {
278 defer ctx.teardownTest()
280 err := ctx.ch.CheckMessageCompatibility(&interfaces.SwInterfaceSetFlags{})
281 Expect(err).ShouldNot(HaveOccurred())
284 func TestSetReplyTimeout(t *testing.T) {
286 defer ctx.teardownTest()
288 ctx.ch.SetReplyTimeout(time.Millisecond)
290 // first one request should work
291 ctx.mockVpp.MockReply(&vpe.ControlPingReply{})
292 err := ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
293 Expect(err).ShouldNot(HaveOccurred())
295 // no other reply ready - expect timeout
296 err = ctx.ch.SendRequest(&vpe.ControlPing{}).ReceiveReply(&vpe.ControlPingReply{})
297 Expect(err).Should(HaveOccurred())
298 Expect(err.Error()).To(ContainSubstring("timeout"))
301 func TestReceiveReplyNegative(t *testing.T) {
303 defer ctx.teardownTest()
306 reqCtx1 := &api.RequestCtx{}
307 err := reqCtx1.ReceiveReply(&vpe.ControlPingReply{})
308 Expect(err).Should(HaveOccurred())
309 Expect(err.Error()).To(ContainSubstring("invalid request context"))
312 reqCtx2 := &api.MultiRequestCtx{}
313 _, err = reqCtx2.ReceiveReply(&vpe.ControlPingReply{})
314 Expect(err).Should(HaveOccurred())
315 Expect(err.Error()).To(ContainSubstring("invalid request context"))
318 reqCtx3 := &api.RequestCtx{}
319 err = reqCtx3.ReceiveReply(nil)
320 Expect(err).Should(HaveOccurred())
321 Expect(err.Error()).To(ContainSubstring("invalid request context"))