func (mds *MockDataSync) ResyncEvent(keyPrefix ...string) (event *controller.DBResync, resyncCount int) {
	mds.resyncCount++
	event = controller.NewDBResync()
	for key, data := range mds.data {
		if data.val == nil {
			continue
		}
		resource := mds.getResourceByKey(key)
		event.KubeState[resource][key] = data.val
	}
	return event, mds.resyncCount
}
ResyncEvent returns the same data as Resync(), but formatted as DBResync event
from the controller.
package datasync
import (
	"strings"
	"golang.org/x/net/context"
	"github.com/golang/protobuf/proto"
	"go.ligato.io/cn-infra/v2/datasync"
	"github.com/contiv/vpp/dbresources"
	controller "github.com/contiv/vpp/plugins/controller/api"
)
type MockDataSync struct {
	resyncCount int
	data        map[string]*ProtoData
	anyError    error
}
type ProtoData struct {
	val proto.Message
	rev int64
}
type MockKeyVal struct {
	key string
	val proto.Message
	rev int64
}
type MockChangeEvent struct {
	mds *MockDataSync
	wr  *MockProtoWatchResp
}
type MockProtoWatchResp struct {
	eventType datasync.Op
	MockKeyVal
	prevVal proto.Message
}
type MockResyncEvent struct {
	mds         *MockDataSync
	data        map[string]*ProtoData
	keyPrefixes []string
}
type MockKeyValIterator struct {
	mre    *MockResyncEvent
	keys   []string
	cursor int
}
func NewMockDataSync() *MockDataSync {
	return &MockDataSync{
		data: make(map[string]*ProtoData),
	}
}
func (mds *MockDataSync) RestartResyncCount() {
	mds.resyncCount = 0
}
func (mds *MockDataSync) Put(key string, value proto.Message) datasync.ChangeEvent {
	newVal, prevVal, rev := mds.put(key, value)
	return &MockChangeEvent{
		mds: mds,
		wr: &MockProtoWatchResp{
			eventType: datasync.Put,
			MockKeyVal: MockKeyVal{
				key: key,
				val: newVal,
				rev: rev,
			},
			prevVal: prevVal,
		},
	}
}
func (mds *MockDataSync) put(key string, value proto.Message) (newVal, prevVal proto.Message, rev int64) {
	if value == nil {
		panic("Put nil value")
	}
	if _, modify := mds.data[key]; modify {
		prevVal = mds.data[key].val
		mds.data[key].val = value
		mds.data[key].rev++
	} else {
		mds.data[key] = &ProtoData{
			val: value,
			rev: 0,
		}
	}
	return value, prevVal, mds.data[key].rev
}
func (mds *MockDataSync) PutEvent(key string, value proto.Message) (event *controller.KubeStateChange) {
	newVal, prevVal, _ := mds.put(key, value)
	return &controller.KubeStateChange{
		Key:       key,
		Resource:  mds.getResourceByKey(key),
		PrevValue: prevVal,
		NewValue:  newVal,
	}
}
func (mds *MockDataSync) getResourceByKey(key string) string {
	for _, resource := range dbresources.GetDBResources() {
		if strings.HasPrefix(key, resource.KeyPrefix) {
			return resource.Keyword
		}
	}
	return ""
}
func (mds *MockDataSync) Delete(key string) datasync.ChangeEvent {
	prevVal, rev := mds.del(key)
	if prevVal == nil {
		return nil
	}
	return &MockChangeEvent{
		mds: mds,
		wr: &MockProtoWatchResp{
			eventType: datasync.Delete,
			MockKeyVal: MockKeyVal{
				key: key,
				rev: rev,
				val: nil,
			},
			prevVal: prevVal,
		},
	}
}
func (mds *MockDataSync) del(key string) (prevVal proto.Message, rev int64) {
	if _, found := mds.data[key]; !found {
		return nil, 0
	}
	mds.data[key].rev++
	prevVal = mds.data[key].val
	mds.data[key].val = nil
	return prevVal, mds.data[key].rev
}
func (mds *MockDataSync) DeleteEvent(key string) (event *controller.KubeStateChange) {
	prevVal, _ := mds.del(key)
	if prevVal == nil {
		return nil
	}
	return &controller.KubeStateChange{
		Key:       key,
		Resource:  mds.getResourceByKey(key),
		PrevValue: prevVal,
		NewValue:  nil,
	}
}
func (mds *MockDataSync) Resync(keyPrefix ...string) datasync.ResyncEvent {
	mds.resyncCount++
	mre := &MockResyncEvent{
		keyPrefixes: keyPrefix,
		data:        make(map[string]*ProtoData),
	}
	for key, data := range mds.data {
		if data.val == nil {
			continue
		}
		mre.data[key] = &ProtoData{
			val: proto.Clone(data.val),
			rev: data.rev,
		}
	}
	return mre
}