Add support for string types
[govpp.git] / adapter / mock / mock_adapter.go
index a5cb62d..9783651 100644 (file)
@@ -25,7 +25,6 @@ import (
        "git.fd.io/govpp.git/adapter"
        "git.fd.io/govpp.git/adapter/mock/binapi"
        "git.fd.io/govpp.git/api"
-
        "git.fd.io/govpp.git/codec"
        "github.com/lunixbochs/struc"
 )
@@ -33,24 +32,24 @@ import (
 type replyMode int
 
 const (
-       _                replyMode = 0
-       useRepliesQueue            = 1 // use replies in the queue
-       useReplyHandlers           = 2 // use reply handler
+       _                replyMode = iota
+       useRepliesQueue            // use replies in the queue
+       useReplyHandlers           // use reply handler
 )
 
-// VppAdapter represents a mock VPP adapter that can be used for unit/integration testing instead of the vppapiclient adapter.
+// VppAPI represents a mock VPP adapter that can be used for unit/integration testing instead of the vppapiclient adapter.
 type VppAdapter struct {
-       callback func(context uint32, msgId uint16, data []byte)
+       callback adapter.MsgCallback
 
+       msgIDSeq     uint16
+       access       sync.RWMutex
        msgNameToIds map[string]uint16
        msgIDsToName map[uint16]string
-       msgIDSeq     uint16
        binAPITypes  map[string]reflect.Type
-       access       sync.RWMutex
 
+       repliesLock   sync.Mutex     // mutex for the queue
        replies       []reply        // FIFO queue of messages
        replyHandlers []ReplyHandler // callbacks that are able to calculate mock responses
-       repliesLock   sync.Mutex     // mutex for the queue
        mode          replyMode      // mode in which the mock operates
 }
 
@@ -91,8 +90,15 @@ const (
 )
 
 // NewVppAdapter returns a new mock adapter.
-func NewVppAdapter() adapter.VppAdapter {
-       return &VppAdapter{}
+func NewVppAdapter() *VppAdapter {
+       a := &VppAdapter{
+               msgIDSeq:     1000,
+               msgIDsToName: make(map[uint16]string),
+               msgNameToIds: make(map[string]uint16),
+               binAPITypes:  make(map[string]reflect.Type),
+       }
+       a.registerBinAPITypes()
+       return a
 }
 
 // Connect emulates connecting the process to VPP.
@@ -101,8 +107,8 @@ func (a *VppAdapter) Connect() error {
 }
 
 // Disconnect emulates disconnecting the process from VPP.
-func (a *VppAdapter) Disconnect() {
-       // no op
+func (a *VppAdapter) Disconnect() error {
+       return nil
 }
 
 // GetMsgNameByID returns message name for specified message ID.
@@ -120,21 +126,16 @@ func (a *VppAdapter) GetMsgNameByID(msgID uint16) (string, bool) {
 
        a.access.Lock()
        defer a.access.Unlock()
-       a.initMaps()
        msgName, found := a.msgIDsToName[msgID]
 
        return msgName, found
 }
 
-// RegisterBinAPITypes registers binary API message types in the mock adapter.
-func (a *VppAdapter) RegisterBinAPITypes(binAPITypes map[string]reflect.Type) {
+func (a *VppAdapter) registerBinAPITypes() {
        a.access.Lock()
        defer a.access.Unlock()
-       a.initMaps()
-       for _, v := range binAPITypes {
-               if msg, ok := reflect.New(v).Interface().(api.Message); ok {
-                       a.binAPITypes[msg.GetMessageName()] = v
-               }
+       for _, msg := range api.GetAllMessages() {
+               a.binAPITypes[msg.GetMessageName()] = reflect.TypeOf(msg).Elem()
        }
 }
 
@@ -178,8 +179,16 @@ func (a *VppAdapter) ReplyBytes(request MessageDTO, reply api.Message) ([]byte,
        log.Println("ReplyBytes ", replyMsgID, " ", reply.GetMessageName(), " clientId: ", request.ClientID)
 
        buf := new(bytes.Buffer)
-       struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: replyMsgID, Context: request.ClientID})
-       struc.Pack(buf, reply)
+       err = struc.Pack(buf, &codec.VppReplyHeader{
+               VlMsgID: replyMsgID,
+               Context: request.ClientID,
+       })
+       if err != nil {
+               return nil, err
+       }
+       if err = struc.Pack(buf, reply); err != nil {
+               return nil, err
+       }
 
        return buf.Bytes(), nil
 }
@@ -199,7 +208,6 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) {
 
        a.access.Lock()
        defer a.access.Unlock()
-       a.initMaps()
 
        msgID, found := a.msgNameToIds[msgName]
        if found {
@@ -211,29 +219,13 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) {
        a.msgNameToIds[msgName] = msgID
        a.msgIDsToName[msgID] = msgName
 
-       log.Println("VPP GetMessageId ", msgID, " name:", msgName, " crc:", msgCrc)
-
        return msgID, nil
 }
 
-// initMaps initializes internal maps (if not already initialized).
-func (a *VppAdapter) initMaps() {
-       if a.msgIDsToName == nil {
-               a.msgIDsToName = map[uint16]string{}
-               a.msgNameToIds = map[string]uint16{}
-               a.msgIDSeq = 1000
-       }
-
-       if a.binAPITypes == nil {
-               a.binAPITypes = map[string]reflect.Type{}
-       }
-}
-
 // SendMsg emulates sending a binary-encoded message to VPP.
 func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error {
        switch a.mode {
        case useReplyHandlers:
-               a.initMaps()
                for i := len(a.replyHandlers) - 1; i >= 0; i-- {
                        replyHandler := a.replyHandlers[i]
 
@@ -252,11 +244,12 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error {
                                Data:     data,
                        })
                        if finished {
-                               a.callback(clientID, msgID, reply)
+                               a.callback(msgID, reply)
                                return nil
                        }
                }
                fallthrough
+
        case useRepliesQueue:
                a.repliesLock.Lock()
                defer a.repliesLock.Unlock()
@@ -274,15 +267,15 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error {
                                }
                                if msg.Msg.GetMessageType() == api.ReplyMessage {
                                        struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: context})
-                               } else if msg.Msg.GetMessageType() == api.EventMessage {
-                                       struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID, Context: context})
                                } else if msg.Msg.GetMessageType() == api.RequestMessage {
                                        struc.Pack(buf, &codec.VppRequestHeader{VlMsgID: msgID, Context: context})
+                               } else if msg.Msg.GetMessageType() == api.EventMessage {
+                                       struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID})
                                } else {
                                        struc.Pack(buf, &codec.VppOtherHeader{VlMsgID: msgID})
                                }
                                struc.Pack(buf, msg.Msg)
-                               a.callback(context, msgID, buf.Bytes())
+                               a.callback(msgID, buf.Bytes())
                        }
 
                        a.replies = a.replies[1:]
@@ -301,13 +294,13 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error {
                msgID := uint16(defaultReplyMsgID)
                struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: clientID})
                struc.Pack(buf, &defaultReply{})
-               a.callback(clientID, msgID, buf.Bytes())
+               a.callback(msgID, buf.Bytes())
        }
        return nil
 }
 
 // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from the mock.
-func (a *VppAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) {
+func (a *VppAdapter) SetMsgCallback(cb adapter.MsgCallback) {
        a.callback = cb
 }