Skip to content
Snippets Groups Projects
Commit e083ddcb authored by Manuel Kieweg's avatar Manuel Kieweg
Browse files

Merge branch 'unified-storage-architecture' into 'develop'

Unified Storage Architecture

See merge request cocsn/gosdn!104
parents cdc3702e db0d0c0a
No related branches found
No related tags found
2 merge requests!104Unified Storage Architecture,!90Develop
Pipeline #65848 failed
// Code generated by mockery v2.6.0. DO NOT EDIT.
package mocks
import (
mock "github.com/stretchr/testify/mock"
uuid "github.com/google/uuid"
)
// PrincipalNetworkDomain is an autogenerated mock type for the PrincipalNetworkDomain type
type PrincipalNetworkDomain struct {
mock.Mock
}
// AddDevice provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) AddDevice(_a0 interface{}) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// AddSbi provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) AddSbi(_a0 interface{}) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(interface{}) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// ContainsDevice provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) ContainsDevice(_a0 uuid.UUID) bool {
ret := _m.Called(_a0)
var r0 bool
if rf, ok := ret.Get(0).(func(uuid.UUID) bool); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// Destroy provides a mock function with given fields:
func (_m *PrincipalNetworkDomain) Destroy() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// GetDescription provides a mock function with given fields:
func (_m *PrincipalNetworkDomain) GetDescription() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// GetName provides a mock function with given fields:
func (_m *PrincipalNetworkDomain) GetName() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// GetSBIs provides a mock function with given fields:
func (_m *PrincipalNetworkDomain) GetSBIs() interface{} {
ret := _m.Called()
var r0 interface{}
if rf, ok := ret.Get(0).(func() interface{}); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(interface{})
}
}
return r0
}
// Id provides a mock function with given fields:
func (_m *PrincipalNetworkDomain) Id() uuid.UUID {
ret := _m.Called()
var r0 uuid.UUID
if rf, ok := ret.Get(0).(func() uuid.UUID); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(uuid.UUID)
}
}
return r0
}
// MarshalDevice provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) MarshalDevice(_a0 uuid.UUID) (string, error) {
ret := _m.Called(_a0)
var r0 string
if rf, ok := ret.Get(0).(func(uuid.UUID) string); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok {
r1 = rf(_a0)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// RemoveDevice provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) RemoveDevice(_a0 uuid.UUID) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// RemoveSbi provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) RemoveSbi(_a0 uuid.UUID) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// Request provides a mock function with given fields: _a0, _a1
func (_m *PrincipalNetworkDomain) Request(_a0 uuid.UUID, _a1 string) error {
ret := _m.Called(_a0, _a1)
var r0 error
if rf, ok := ret.Get(0).(func(uuid.UUID, string) error); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Error(0)
}
return r0
}
// RequestAll provides a mock function with given fields: _a0
func (_m *PrincipalNetworkDomain) RequestAll(_a0 string) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
......@@ -6,6 +6,8 @@ import (
gnmi "github.com/openconfig/gnmi/proto/gnmi"
mock "github.com/stretchr/testify/mock"
uuid "github.com/google/uuid"
yang "github.com/openconfig/goyang/pkg/yang"
ytypes "github.com/openconfig/ygot/ytypes"
......@@ -16,6 +18,22 @@ type SouthboundInterface struct {
mock.Mock
}
// Id provides a mock function with given fields:
func (_m *SouthboundInterface) Id() uuid.UUID {
ret := _m.Called()
var r0 uuid.UUID
if rf, ok := ret.Get(0).(func() uuid.UUID); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(uuid.UUID)
}
}
return r0
}
// SbiIdentifier provides a mock function with given fields:
func (_m *SouthboundInterface) SbiIdentifier() string {
ret := _m.Called()
......
// Code generated by mockery v2.6.0. DO NOT EDIT.
package mocks
import (
mock "github.com/stretchr/testify/mock"
uuid "github.com/google/uuid"
)
// Storable is an autogenerated mock type for the Storable type
type Storable struct {
mock.Mock
}
// Id provides a mock function with given fields:
func (_m *Storable) Id() uuid.UUID {
ret := _m.Called()
var r0 uuid.UUID
if rf, ok := ret.Get(0).(func() uuid.UUID); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(uuid.UUID)
}
}
return r0
}
......@@ -39,7 +39,6 @@ type server struct {
pb.UnimplementedGrpcCliServer
core *Core
logConnections []*logConnection
devices map[uuid.UUID]Device
}
var srv *server
......@@ -142,21 +141,45 @@ func getCLIGoing(core *Core) {
// the core
func (s *server) CreatePND(ctx context.Context, in *pb.CreatePNDRequest) (*pb.CreatePNDReply, error) {
log.Info("Received: Create a PND with the name", in.GetName())
sbi := s.core.southboundInterfaces[in.GetSbi()]
sbi, err := s.core.sbic.get(uuid.New())
if err != nil {
return nil, err
}
id := uuid.New()
s.core.principalNetworkDomains[id] = NewPND(in.GetName(), in.GetDescription(), sbi)
pnd, err := NewPNDwithId(in.GetName(), in.GetDescription(), id, sbi.(SouthboundInterface))
if err != nil {
log.Error(err)
return &pb.CreatePNDReply{Message: err.Error()}, err
}
if err := s.core.pndc.add(pnd); err != nil {
return nil, err
}
return &pb.CreatePNDReply{Message: "Created new PND: " + id.String()}, nil
}
// deprecated
// Subject to change, using discontinued full device access
// GetAllPNDs is a request to get all currently registered PNDs and returns a slim
// variant of PNDs and their respective devices
func (s *server) GetAllPNDs(ctx context.Context, in *emptypb.Empty) (*pb.AllPNDsReply, error) {
log.Info("Received: Get all PNDs")
var pnds []*pb.PND
for uuidPND, pnd := range s.core.principalNetworkDomains {
for _, uuidPND := range s.core.pndc.UUIDs() {
pnd, err := s.core.pndc.get(uuidPND)
if err != nil {
log.Error(err)
continue
}
var devices []*pb.Device
for uuidDevice, device := range pnd.(*pndImplementation).devices {
for uuidDevice, d := range pnd.(*pndImplementation).devices.store {
device, ok := d.(*Device)
if !ok {
log.Error(&ErrInvalidTypeAssertion{
v: d,
t: "Device",
})
}
tmpDevice := pb.Device{
Uuid: uuidDevice.String(),
Address: device.Config.Address,
......@@ -164,11 +187,16 @@ func (s *server) GetAllPNDs(ctx context.Context, in *emptypb.Empty) (*pb.AllPNDs
Password: device.Config.Password}
devices = append(devices, &tmpDevice)
}
sbi, err := s.core.sbic.get(pnd.GetSBIs().(*sbiStore).UUIDs()[0])
if err != nil {
log.Error(err)
continue
}
tmpPND := pb.PND{
Uuid: uuidPND.String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
Sbi: pnd.GetSBIs()["default"].SbiIdentifier(),
Sbi: sbi.SbiIdentifier(),
Devices: devices,
}
pnds = append(pnds, &tmpPND)
......@@ -179,7 +207,12 @@ func (s *server) GetAllPNDs(ctx context.Context, in *emptypb.Empty) (*pb.AllPNDs
// GetAllSBINames returns all registered SBIs from core.
func (s *server) GetAllSBINames(ctx context.Context, in *emptypb.Empty) (*pb.AllSBINamesReply, error) {
var sbiNames []string
for _, s := range s.core.southboundInterfaces {
for _, uuidDevice := range s.core.sbic.UUIDs() {
s, err := s.core.sbic.get(uuidDevice)
if err != nil {
log.Error(err)
continue
}
sbiNames = append(sbiNames, s.SbiIdentifier())
}
return &pb.AllSBINamesReply{SbiNames: sbiNames}, nil
......@@ -193,12 +226,18 @@ func (s *server) AddDevice(ctx context.Context, in *pb.AddDeviceRequest) (*pb.Ad
if err != nil {
return &pb.AddDeviceReply{Message: err.Error()}, err
}
pnd, exists := s.core.principalNetworkDomains[uuidPND]
if exists != true {
log.Info(err)
pnd, err := s.core.pndc.get(uuidPND)
if err != nil {
log.Error(err)
return &pb.AddDeviceReply{Message: err.Error()}, err
}
// TODO: Add notion of default SBI to PND or solve differently
uuidSbi := pnd.GetSBIs().(*sbiStore).UUIDs()[0]
sbi, err := s.core.sbic.get(uuidSbi)
if err != nil {
log.Error(err)
return &pb.AddDeviceReply{Message: err.Error()}, err
}
sbi := s.core.principalNetworkDomains[uuidPND].GetSBIs()["default"]
//TODO: could the transport and the related config be created in device?
transport := &Gnmi{SetNode: sbi.SetNode()}
......@@ -215,7 +254,7 @@ func (s *server) AddDevice(ctx context.Context, in *pb.AddDeviceRequest) (*pb.Ad
err = pnd.AddDevice(newDevice)
if err != nil {
log.Info(err)
log.Error(err)
return &pb.AddDeviceReply{Message: err.Error()}, err
}
......@@ -235,8 +274,8 @@ func (s *server) HandleDeviceGetRequest(ctx context.Context, in *pb.DeviceGetReq
log.Info(err)
return &pb.DeviceGetReply{Message: err.Error()}, err
}
pnd, exists := s.core.principalNetworkDomains[uuidPND]
if exists != true {
pnd, err := s.core.pndc.get(uuidPND)
if err != nil {
err := errors.New("Couldnt find PND: UUID is wrong")
log.Info(err)
return &pb.DeviceGetReply{Message: err.Error()}, err
......
package nucleus
// ClientConfig contains SBI ciena
// ClientConfig contains SBI client
// configuration parameters
// Deprecated in favor of spf viper
type ClientConfig struct {
......
......@@ -4,33 +4,28 @@ import (
"os"
"code.fbi.h-da.de/cocsn/gosdn/database"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
// Core is the representation of the controllers core
type Core struct {
// deprecated, use sbiStore instead
southboundInterfaces map[string]SouthboundInterface
// deprecated, use pndStore instead
principalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
// deprecated
database database.Database
pndStore pndStorage
sbiStore sbiStorage
pndc pndStore
sbic sbiStore
IsRunning chan bool
}
//Initialize does start-up housekeeping like reading controller config files
func (c *Core) Initialize(IsRunningChannel chan bool) error {
c.sbiStore = sbiStorage{}
c.pndStore = pndStorage{}
// TODO: Just for compatability remove once deprecated code is cleaned up
c.southboundInterfaces = c.sbiStore
c.principalNetworkDomains = c.pndStore
c.sbic = sbiStore{
store{},
}
c.pndc = pndStore{
store{},
}
// Set config defaults
viper.SetDefault("socket", "localhost:55055")
......@@ -61,10 +56,10 @@ func (c *Core) AttachDatabase() {
// CreateSouthboundInterfaces initializes the controller with its supported SBIs
func (c *Core) CreateSouthboundInterfaces() error {
if err := c.sbiStore.add(&AristaOC{}); err != nil {
if err := c.sbic.add(&AristaOC{}); err != nil {
return err
}
if err := c.sbiStore.add(&OpenConfig{}); err != nil {
if err := c.sbic.add(&OpenConfig{}); err != nil {
return err
}
return nil
......
package nucleus
import (
"code.fbi.h-da.de/cocsn/gosdn/database"
"github.com/google/uuid"
"testing"
)
func TestCore_CreateSouthboundInterfaces(t *testing.T) {
type fields struct {
southboundInterfaces map[string]SouthboundInterface
principalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
database database.Database
IsRunning chan bool
}
tests := []struct {
name string
fields fields
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_ = &Core{
southboundInterfaces: tt.fields.southboundInterfaces,
principalNetworkDomains: tt.fields.principalNetworkDomains,
database: tt.fields.database,
IsRunning: tt.fields.IsRunning,
}
})
}
}
func TestCore_Initialize(t *testing.T) {
type fields struct {
southboundInterfaces map[string]SouthboundInterface
principalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
database database.Database
IsRunning chan bool
}
type args struct {
IsRunningChannel chan bool
}
tests := []struct {
name string
fields fields
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_ = &Core{
southboundInterfaces: tt.fields.southboundInterfaces,
principalNetworkDomains: tt.fields.principalNetworkDomains,
database: tt.fields.database,
IsRunning: tt.fields.IsRunning,
}
})
}
}
func TestCore_Shutdown(t *testing.T) {
type fields struct {
southboundInterfaces map[string]SouthboundInterface
principalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
database database.Database
IsRunning chan bool
}
tests := []struct {
name string
fields fields
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_ = &Core{
southboundInterfaces: tt.fields.southboundInterfaces,
principalNetworkDomains: tt.fields.principalNetworkDomains,
database: tt.fields.database,
IsRunning: tt.fields.IsRunning,
}
})
}
}
......@@ -35,6 +35,10 @@ func NewDevice(sbi SouthboundInterface, addr, username, password string,
}
}
func (d *Device) Id() uuid.UUID {
return d.Config.Uuid
}
type DeviceConfig struct {
Uuid uuid.UUID
Address string
......
......@@ -24,3 +24,12 @@ type ErrAlreadyExists struct {
func (e *ErrAlreadyExists) Error() string {
return fmt.Sprintf("%v already exists", e.item)
}
type ErrInvalidTypeAssertion struct {
v interface{}
t interface{}
}
func (e ErrInvalidTypeAssertion) Error() string {
return fmt.Sprintf("%v does not implement %v", e.v, e.t)
}
......@@ -19,9 +19,11 @@ import (
)
// TestMain bootstraps all tests. Humongous beast
// TODO: Move somewhere more sensible
func TestMain(m *testing.M) {
testSetupGnmi()
testSetupPnd()
testSetupStore()
os.Exit(m.Run())
}
......
......@@ -11,9 +11,9 @@ import (
// interface for PND implementations
type PrincipalNetworkDomain interface {
Destroy() error
AddSbi(SouthboundInterface) error
RemoveSbi(string) error
AddDevice(*Device) error
AddSbi(interface{}) error
RemoveSbi(uuid.UUID) error
AddDevice(interface{}) error
RemoveDevice(uuid.UUID) error
Request(uuid.UUID, string) error
RequestAll(string) error
......@@ -21,28 +21,48 @@ type PrincipalNetworkDomain interface {
GetDescription() string
MarshalDevice(uuid.UUID) (string, error)
ContainsDevice(uuid.UUID) bool
GetSBIs() map[string]SouthboundInterface
GetSBIs() interface{}
Id() uuid.UUID
}
type pndImplementation struct {
name string
description string
sbi map[string]SouthboundInterface
devices map[uuid.UUID]*Device
sbic sbiStore
devices deviceStore
id uuid.UUID
}
// NewPND creates a Principle Network Domain
func NewPND(name, description string, sbi SouthboundInterface) PrincipalNetworkDomain {
sbic := make(map[string]SouthboundInterface)
sbic["default"] = sbi
devices := make(map[uuid.UUID]*Device)
return &pndImplementation{
func NewPND(name, description string, sbi SouthboundInterface) (PrincipalNetworkDomain, error) {
pnd := &pndImplementation{
name: name,
description: description,
sbi: sbic,
devices: devices,
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
}
if err := pnd.sbic.add(sbi); err != nil {
return nil, &ErrAlreadyExists{item: sbi}
}
return pnd, nil
}
func NewPNDwithId(name, description string, id uuid.UUID, sbi SouthboundInterface) (PrincipalNetworkDomain, error) {
pnd := &pndImplementation{
name: name,
description: description,
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
id: id,
}
if err := pnd.sbic.add(sbi); err != nil {
return nil, &ErrAlreadyExists{item: sbi}
}
return pnd, nil
}
func (pnd *pndImplementation) Id() uuid.UUID {
return pnd.id
}
// GetName returns the name of the PND
......@@ -51,9 +71,8 @@ func (pnd *pndImplementation) GetName() string {
}
// ContainsDevice checks if the given device uuid is registered for this PND
func (pnd *pndImplementation) ContainsDevice(uuid uuid.UUID) bool {
_, exists := pnd.devices[uuid]
return exists
func (pnd *pndImplementation) ContainsDevice(id uuid.UUID) bool {
return pnd.devices.exists(id)
}
// GetDescription returns the current description of the PND
......@@ -62,8 +81,8 @@ func (pnd *pndImplementation) GetDescription() string {
}
// GetSBIs returns the registered SBIs
func (pnd *pndImplementation) GetSBIs() map[string]SouthboundInterface {
return pnd.sbi
func (pnd *pndImplementation) GetSBIs() interface{} {
return &pnd.sbic
}
// Destroy destroys the PND
......@@ -72,21 +91,35 @@ func (pnd *pndImplementation) Destroy() error {
}
// AddSbi adds a SBI to the PND which will be supported
func (pnd *pndImplementation) AddSbi(sbi SouthboundInterface) error {
return pnd.addSbi(sbi)
func (pnd *pndImplementation) AddSbi(sbi interface{}) error {
s, ok := sbi.(SouthboundInterface)
if !ok {
return &ErrInvalidTypeAssertion{
v: sbi,
t: "Device",
}
}
return pnd.addSbi(s)
}
// AddSbi removes a SBI from the PND
// TODO: this should to recursivly through
// devices and remove the devices using
// this SBI
func (pnd *pndImplementation) RemoveSbi(sbiIdentifier string) error {
return pnd.removeSbi(sbiIdentifier)
func (pnd *pndImplementation) RemoveSbi(id uuid.UUID) error {
return pnd.removeSbi(id)
}
//AddDevice adds a new device to the PND
func (pnd *pndImplementation) AddDevice(device *Device) error {
return pnd.addDevice(device)
func (pnd *pndImplementation) AddDevice(device interface{}) error {
d, ok := device.(*Device)
if !ok {
return &ErrInvalidTypeAssertion{
v: device,
t: "Device",
}
}
return pnd.addDevice(d)
}
// RemoveDevice removes a device from the PND
......@@ -101,31 +134,23 @@ func destroy() error {
}
func (pnd *pndImplementation) addSbi(sbi SouthboundInterface) error {
pnd.sbi[sbi.SbiIdentifier()] = sbi
return nil
return pnd.sbic.add(sbi)
}
func (pnd *pndImplementation) removeSbi(sbiIdentifier string) error {
delete(pnd.sbi, sbiIdentifier)
return nil
func (pnd *pndImplementation) removeSbi(id uuid.UUID) error {
return pnd.sbic.delete(id)
}
func (pnd *pndImplementation) addDevice(device *Device) error {
pnd.devices[device.Config.Uuid] = device
return nil
return pnd.devices.add(device)
}
func (pnd *pndImplementation) getDevice(uuid uuid.UUID) (*Device, error) {
d, ok := pnd.devices[uuid]
if !ok {
return nil, &ErrNotFound{id: uuid}
}
return d, nil
func (pnd *pndImplementation) getDevice(id uuid.UUID) (*Device, error) {
return pnd.devices.get(id)
}
func (pnd *pndImplementation) removeDevice(uuid uuid.UUID) error {
delete(pnd.devices, uuid)
return nil
func (pnd *pndImplementation) removeDevice(id uuid.UUID) error {
return pnd.devices.delete(id)
}
func (pnd *pndImplementation) MarshalDevice(uuid uuid.UUID) (string, error) {
......@@ -161,38 +186,10 @@ func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error {
//RequestAll sends a request for all registered devices
func (pnd *pndImplementation) RequestAll(path string) error {
for k := range pnd.devices {
for _, k := range pnd.devices.UUIDs() {
if err := pnd.Request(k, path); err != nil {
return err
}
}
return nil
}
type pndStorage map[uuid.UUID]PrincipalNetworkDomain
func (p pndStorage) exists(id uuid.UUID) bool {
_, ok := p[id]
return ok
}
func (p pndStorage) add(pnd PrincipalNetworkDomain) error {
// TODO: Implement duplicate detection. Changes PrincipalNetworkDomain API
p[uuid.New()] = pnd
return nil
}
func (p pndStorage) Sbi(id uuid.UUID) (PrincipalNetworkDomain, error) {
if !p.exists(id) {
return nil, &ErrNotFound{id: id}
}
return p[id], nil
}
func (p pndStorage) delete(id uuid.UUID) error {
if !p.exists(id) {
return &ErrNotFound{id: id}
}
delete(p, id)
return nil
}
......@@ -22,6 +22,16 @@ func testSetupPnd() {
if err != nil {
log.Fatal(err)
}
defaultSbiId, err = uuid.Parse("b70c8425-68c7-4d4b-bb5e-5586572bd64b")
if err != nil {
log.Fatal(err)
}
defaultPndId, err = uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
if err != nil {
log.Fatal(err)
}
}
func mockDevice() Device {
......@@ -38,49 +48,114 @@ func mockDevice() Device {
}
}
func freshPnd() pndImplementation {
func newPnd() pndImplementation {
return pndImplementation{
name: "default",
description: "default test pnd",
sbi: map[string]SouthboundInterface{"default": &OpenConfig{}},
devices: map[uuid.UUID]*Device{},
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
}
}
func newPndWithId() pndImplementation {
return pndImplementation{
name: "default",
description: "default test pnd",
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
id: defaultPndId,
}
}
var did uuid.UUID
var mdid uuid.UUID
var defaultSbiId uuid.UUID
var defaultPndId uuid.UUID
func TestNewPND(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
if err := pnd.addSbi(&OpenConfig{id: defaultSbiId}); err != nil {
t.Error(err)
}
type args struct {
name string
description string
sbi SouthboundInterface
}
tests := []struct {
name string
args args
want PrincipalNetworkDomain
name string
args args
want PrincipalNetworkDomain
wantErr bool
}{
{
name: "default",
args: args{
name: "default",
description: "default test pnd",
sbi: &OpenConfig{},
sbi: &OpenConfig{id: defaultSbiId},
},
want: &pnd,
want: &pnd,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewPND(tt.args.name, tt.args.description, tt.args.sbi); !reflect.DeepEqual(got, tt.want) {
got, err := NewPND(tt.args.name, tt.args.description, tt.args.sbi)
if (err != nil) != tt.wantErr {
t.Errorf("NewPND() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewPND() = %v, want %v", got, tt.want)
}
})
}
}
func TestNewPNDwithId(t *testing.T) {
pnd := newPndWithId()
if err := pnd.addSbi(&OpenConfig{id: defaultSbiId}); err != nil {
t.Error(err)
}
type args struct {
name string
description string
id uuid.UUID
sbi SouthboundInterface
}
tests := []struct {
name string
args args
want PrincipalNetworkDomain
wantErr bool
}{
{
name: "default",
args: args{
name: "default",
description: "default test pnd",
id: defaultPndId,
sbi: &OpenConfig{id: defaultSbiId},
},
want: &pnd,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewPNDwithId(tt.args.name, tt.args.description, tt.args.id, tt.args.sbi)
if (err != nil) != tt.wantErr {
t.Errorf("NewPNDwithId() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewPNDwithId() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_destroy(t *testing.T) {
tests := []struct {
name string
......@@ -118,16 +193,18 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
if err := pnd.AddDevice(tt.args.device); (err != nil) != tt.wantErr {
t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
}
_, ok := pnd.devices[did]
_, ok := pnd.devices.store[did]
if !ok {
t.Errorf("AddDevice() Device %v not in device store %v",
tt.args.device, pnd.devices)
}
delete(pnd.devices, did)
if err := pnd.devices.delete(did); err != nil {
t.Error(err)
}
})
}
}
......@@ -141,20 +218,30 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
args args
wantErr bool
}{
{name: "default", args: args{sbi: &OpenConfig{}}, wantErr: false},
{
name: "default",
args: args{
sbi: &OpenConfig{
id: defaultSbiId,
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
if err := pnd.AddSbi(tt.args.sbi); (err != nil) != tt.wantErr {
t.Errorf("AddSbi() error = %v, wantErr %v", err, tt.wantErr)
}
_, ok := pnd.GetSBIs()[tt.args.sbi.SbiIdentifier()]
_, ok := pnd.sbic.store[defaultSbiId]
if !ok {
t.Errorf("AddSbi() SBI %v not in device store %v",
tt.args.sbi, pnd.GetSBIs())
}
delete(pnd.sbi, tt.args.sbi.SbiIdentifier())
if err := pnd.sbic.delete(defaultSbiId); err != nil {
t.Error(err)
}
})
}
}
......@@ -177,15 +264,25 @@ func Test_pndImplementation_ContainsDevice(t *testing.T) {
uuid: uuid.New(),
device: &Device{Config: DeviceConfig{Uuid: did}},
}, want: false},
{name: "fails empty", args: args{
uuid: uuid.New(),
device: &Device{Config: DeviceConfig{Uuid: did}},
}, want: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd.devices[did] = tt.args.device
pnd := newPnd()
if tt.name != "fails empty" {
if err := pnd.devices.add(tt.args.device); err != nil {
t.Error(err)
}
}
if got := pnd.ContainsDevice(tt.args.uuid); got != tt.want {
t.Errorf("ContainsDevice() = %v, want %v", got, tt.want)
}
delete(pnd.devices, did)
if err := pnd.devices.delete(did); err != nil && tt.name != "fails empty" {
t.Error(err)
}
})
}
}
......@@ -194,8 +291,8 @@ func Test_pndImplementation_Destroy(t *testing.T) {
type fields struct {
name string
description string
sbi map[string]SouthboundInterface
devices map[uuid.UUID]*Device
sbi sbiStore
devices deviceStore
}
tests := []struct {
name string
......@@ -209,7 +306,7 @@ func Test_pndImplementation_Destroy(t *testing.T) {
pnd := &pndImplementation{
name: tt.fields.name,
description: tt.fields.description,
sbi: tt.fields.sbi,
sbic: tt.fields.sbi,
devices: tt.fields.devices,
}
if err := pnd.Destroy(); (err != nil) != tt.wantErr {
......@@ -228,7 +325,7 @@ func Test_pndImplementation_GetDescription(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
if got := pnd.GetDescription(); got != tt.want {
t.Errorf("GetDescription() = %v, want %v", got, tt.want)
}
......@@ -245,7 +342,7 @@ func Test_pndImplementation_GetName(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
if got := pnd.GetName(); got != tt.want {
t.Errorf("GetName() = %v, want %v", got, tt.want)
}
......@@ -254,12 +351,12 @@ func Test_pndImplementation_GetName(t *testing.T) {
}
func Test_pndImplementation_GetSBIs(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
tests := []struct {
name string
want map[string]SouthboundInterface
want *sbiStore
}{
{name: "default", want: pnd.sbi},
{name: "default", want: &pnd.sbic},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......@@ -284,7 +381,7 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
pnd := newPnd()
d := &Device{
GoStruct: &openconfig.Device{},
SBI: nil,
......@@ -296,7 +393,9 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) {
},
Transport: nil,
}
_ = pnd.addDevice(d)
if err := pnd.addDevice(d); err != nil {
t.Error(err)
}
got, err := pnd.MarshalDevice(tt.args.uuid)
if (err != nil) != tt.wantErr {
t.Errorf("MarshalDevice() error = %v, wantErr %v", err, tt.wantErr)
......@@ -305,7 +404,9 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) {
if got != tt.want {
t.Errorf("MarshalDevice() got = %v, want %v", got, tt.want)
}
delete(pnd.devices, did)
if err := pnd.devices.delete(did); err != nil {
t.Error(err)
}
})
}
}
......@@ -320,18 +421,23 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
wantErr bool
}{
{name: "default", args: args{uuid: did}, wantErr: false},
{name: "fails", args: args{uuid: uuid.New()}, wantErr: true},
{name: "fails empty", args: args{uuid: did}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
d := &Device{Config: DeviceConfig{Uuid: did}}
_ = pnd.addDevice(d)
pnd := newPnd()
if tt.name != "fails empty" {
d := &Device{Config: DeviceConfig{Uuid: did}}
if err := pnd.addDevice(d); err != nil {
t.Error(err)
}
}
if err := pnd.RemoveDevice(tt.args.uuid); (err != nil) != tt.wantErr {
t.Errorf("RemoveDevice() error = %v, wantErr %v", err, tt.wantErr)
}
_, ok := pnd.devices[did]
if ok {
t.Errorf("RemoveDevice() device %v still in device store %v", d, pnd.devices)
if pnd.devices.exists(did) && tt.name == "default" {
t.Errorf("RemoveDevice() device still in device store %v", pnd.devices)
}
})
}
......@@ -339,25 +445,36 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
func Test_pndImplementation_RemoveSbi(t *testing.T) {
type args struct {
sbiIdentifier string
id uuid.UUID
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "default", args: args{sbiIdentifier: "openconfig"}, wantErr: false},
{name: "default", args: args{id: defaultSbiId}, wantErr: false},
{name: "fails", args: args{id: uuid.New()}, wantErr: true},
{name: "fails empty", args: args{id: defaultSbiId}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pnd := freshPnd()
_ = pnd.addSbi(&OpenConfig{})
if err := pnd.RemoveSbi(tt.args.sbiIdentifier); (err != nil) != tt.wantErr {
pnd := &pndImplementation{
name: "test-remove-sbi",
description: "test-remove-sbi",
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
id: defaultPndId,
}
if tt.name != "fails empty" {
if err := pnd.addSbi(&OpenConfig{id: defaultSbiId}); err != nil {
t.Error(err)
}
}
if err := pnd.RemoveSbi(tt.args.id); (err != nil) != tt.wantErr {
t.Errorf("RemoveSbi() error = %v, wantErr %v", err, tt.wantErr)
}
sbi, ok := pnd.sbi[tt.args.sbiIdentifier]
if ok {
t.Errorf("RemoveDevice() SBI %v still in SBI store %v", sbi, pnd.sbi)
if pnd.sbic.exists(tt.args.id) {
t.Errorf("RemoveDevice() SBI still in SBI store %v", pnd.sbic)
}
})
}
......@@ -396,7 +513,7 @@ func Test_pndImplementation_Request(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deviceWithMockTransport := mockDevice()
pnd := freshPnd()
pnd := newPnd()
tr := deviceWithMockTransport.Transport.(*mocks.Transport)
tr.On("Get", mockContext, mock.Anything).Return(mock.Anything, tt.args.rErr)
tr.On("ProcessResponse", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.rErr)
......@@ -404,7 +521,9 @@ func Test_pndImplementation_Request(t *testing.T) {
if err := pnd.Request(tt.args.uuid, tt.args.path); (err != nil) != tt.wantErr {
t.Errorf("Request() error = %v, wantErr %v", err, tt.wantErr)
}
delete(pnd.devices, mdid)
if err := pnd.devices.delete(mdid); err != nil {
t.Error(err)
}
})
}
}
......@@ -442,7 +561,7 @@ func Test_pndImplementation_RequestAll(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deviceWithMockTransport := mockDevice()
pnd := freshPnd()
pnd := newPnd()
tr := deviceWithMockTransport.Transport.(*mocks.Transport)
tr.On("Get", mockContext, mock.Anything).Return(mock.Anything, tt.args.rErr)
tr.On("ProcessResponse", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.rErr)
......@@ -450,7 +569,9 @@ func Test_pndImplementation_RequestAll(t *testing.T) {
if err := pnd.RequestAll(tt.args.path); (err != nil) != tt.wantErr {
t.Errorf("RequestAll() error = %v, wantErr %v", err, tt.wantErr)
}
delete(pnd.devices, mdid)
if err := pnd.devices.delete(mdid); err != nil {
t.Error(err)
}
})
}
}
......@@ -4,6 +4,7 @@ import (
"code.fbi.h-da.de/cocsn/yang-models/generated/arista"
"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
log "github.com/golang/glog"
"github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/ytypes"
......@@ -20,6 +21,7 @@ type SouthboundInterface interface {
// Needed for type assertion.
SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
Schema() *ytypes.Schema
Id() uuid.UUID
}
type Tapi struct {
......@@ -33,6 +35,7 @@ type OpenConfig struct {
transport Transport
schema *ytypes.Schema
id uuid.UUID
}
// SbiIdentifier returns the string representation of
......@@ -62,6 +65,10 @@ func (oc *OpenConfig) SetNode() func(schema *yang.Entry, root interface{}, path
}
}
func (oc *OpenConfig) Id() uuid.UUID {
return oc.id
}
// deprecated
// Use for prototyping only.
// Use OpenConfig instead
......@@ -70,6 +77,11 @@ type AristaOC struct {
transport Transport
schema *ytypes.Schema
id uuid.UUID
}
func (oc *AristaOC) Id() uuid.UUID {
return oc.id
}
func (oc *AristaOC) SbiIdentifier() string {
......@@ -95,33 +107,3 @@ func (oc *AristaOC) SetNode() func(schema *yang.Entry, root interface{}, path *g
return nil
}
}
type sbiStorage map[string]SouthboundInterface
func (s sbiStorage) exists(name string) bool {
_, ok := s[name]
return ok
}
func (s sbiStorage) add(sbi SouthboundInterface) error {
if s.exists(sbi.SbiIdentifier()) {
return &ErrAlreadyExists{item: sbi}
}
s[sbi.SbiIdentifier()] = sbi
return nil
}
func (s sbiStorage) Sbi(name string) (SouthboundInterface, error) {
if !s.exists(name) {
return nil, &ErrNotFound{id: name}
}
return s[name], nil
}
func (s sbiStorage) delete(name string) error {
if !s.exists(name) {
return &ErrNotFound{id: name}
}
delete(s, name)
return nil
}
package nucleus
import (
"github.com/google/uuid"
)
type Storable interface {
Id() uuid.UUID
}
type store map[uuid.UUID]Storable
func (s store) exists(id uuid.UUID) bool {
_, ok := s[id]
return ok
}
func (s store) add(item Storable) error {
if s.exists(item.Id()) {
return &ErrAlreadyExists{item: item}
}
s[item.Id()] = item
return nil
}
func (s store) get(id uuid.UUID) (Storable, error) {
if !s.exists(id) {
return nil, &ErrNotFound{id: id}
}
return s[id], nil
}
func (s store) delete(id uuid.UUID) error {
if !s.exists(id) {
return &ErrNotFound{id: id}
}
delete(s, id)
return nil
}
func (s store) UUIDs() []uuid.UUID {
keys := make([]uuid.UUID, len(s))
i := 0
for k := range s {
keys[i] = k
i++
}
return keys
}
type sbiStore struct {
store
}
func (s sbiStore) get(id uuid.UUID) (SouthboundInterface, error) {
item, err := s.store.get(id)
if err != nil {
return nil, err
}
sbi, ok := item.(SouthboundInterface)
if !ok {
return nil, &ErrInvalidTypeAssertion{
v: sbi,
t: "SouthboundInterface",
}
}
return sbi, nil
}
type pndStore struct {
store
}
func (s pndStore) get(id uuid.UUID) (PrincipalNetworkDomain, error) {
item, err := s.store.get(id)
if err != nil {
return nil, err
}
pnd, ok := item.(PrincipalNetworkDomain)
if !ok {
return nil, &ErrInvalidTypeAssertion{
v: pnd,
t: "PrincipalNetworkDomain",
}
}
return pnd, nil
}
type deviceStore struct {
store
}
func (s deviceStore) get(id uuid.UUID) (*Device, error) {
item, err := s.store.get(id)
if err != nil {
return nil, err
}
device, ok := item.(*Device)
if !ok {
return nil, &ErrInvalidTypeAssertion{
v: device,
t: "Device",
}
}
return device, nil
}
package nucleus
import (
"code.fbi.h-da.de/cocsn/gosdn/mocks"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"reflect"
"testing"
)
func testSetupStore() {
var err error
iid, err = uuid.Parse("8495a8ac-a1e8-418e-b787-10f5878b2690")
altIid, err = uuid.Parse("edc5de93-2d15-4586-b2a7-fb1bc770986b")
if err != nil {
log.Fatal(err)
}
}
var iid uuid.UUID
var altIid uuid.UUID
func Test_store_add(t *testing.T) {
type args struct {
item Storable
}
tests := []struct {
name string
s store
args args
wantErr bool
}{
{
name: "default",
s: store{},
args: args{
item: &mocks.Storable{},
},
},
{
name: "already exists",
s: store{
iid: &mocks.Storable{},
},
args: args{
item: &mocks.Storable{},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.args.item.(*mocks.Storable).On("Id").Return(iid)
switch tt.name {
case "already exixts":
_ = tt.s.add(tt.args.item)
default:
}
if err := tt.s.add(tt.args.item); (err != nil) != tt.wantErr {
t.Errorf("add() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func Test_store_delete(t *testing.T) {
type args struct {
id uuid.UUID
}
tests := []struct {
name string
s store
args args
wantErr bool
}{
{
name: "default",
s: store{
iid: &mocks.Storable{},
},
args: args{id: iid},
wantErr: false,
},
{
name: "not found empty",
s: store{},
args: args{id: iid},
wantErr: true,
},
{
name: "not found",
s: store{
iid: &mocks.Storable{},
},
args: args{id: altIid},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.s.delete(tt.args.id); (err != nil) != tt.wantErr {
t.Errorf("delete() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.name == "default" {
item, ok := tt.s[iid]
if ok {
t.Errorf("delete() item %v still in store %v", item, tt.s)
}
}
})
}
}
func Test_store_exists(t *testing.T) {
type args struct {
id uuid.UUID
}
tests := []struct {
name string
s store
args args
want bool
}{
{
name: "default",
s: store{
iid: &mocks.Storable{},
},
args: args{id: iid},
want: true,
},
{
name: "not found empty",
s: store{},
args: args{id: iid},
want: false,
},
{
name: "not found",
s: store{
iid: &mocks.Storable{},
},
args: args{id: altIid},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.s.exists(tt.args.id); got != tt.want {
t.Errorf("exists() = %v, want %v", got, tt.want)
}
})
}
}
func Test_store_get(t *testing.T) {
type args struct {
id uuid.UUID
}
tests := []struct {
name string
s store
args args
want Storable
wantErr bool
}{
{
name: "exists",
s: store{
iid: &mocks.Storable{},
},
args: args{id: iid},
want: &mocks.Storable{},
wantErr: false,
},
{
name: "not found",
s: store{
iid: &mocks.Storable{},
},
args: args{id: altIid},
want: nil,
wantErr: true,
},
{
name: "not found empty",
s: store{},
args: args{id: iid},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.s.get(tt.args.id)
if (err != nil) != tt.wantErr {
t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("get() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_store_UUIDs(t *testing.T) {
tests := []struct {
name string
s store
want []uuid.UUID
}{
{
name: "default",
s: store{
iid: &mocks.Storable{},
altIid: &mocks.Storable{},
},
want: []uuid.UUID{iid, altIid},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.s.UUIDs(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("UUIDs() = %v, want %v", got, tt.want)
}
})
}
}
func Test_sbiStore_get(t *testing.T) {
type fields struct {
store store
}
type args struct {
id uuid.UUID
}
tests := []struct {
name string
fields fields
args args
want SouthboundInterface
wantErr bool
}{
{
name: "exists",
fields: fields{
store: store{
defaultSbiId: &OpenConfig{id: defaultSbiId},
},
},
args: args{id: defaultSbiId},
want: &OpenConfig{id: defaultSbiId},
wantErr: false,
},
{
name: "fails",
fields: fields{
store: store{
defaultSbiId: &OpenConfig{id: defaultSbiId},
},
},
args: args{id: iid},
wantErr: true,
},
{
name: "fails empty",
fields: fields{
store: store{},
},
args: args{id: defaultSbiId},
wantErr: true,
},
{
name: "fails wrong type",
fields: fields{
store: store{
did: &Device{
Config: DeviceConfig{
Uuid: did,
},
},
},
},
args: args{id: did},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := sbiStore{
store: tt.fields.store,
}
got, err := s.get(tt.args.id)
if (err != nil) != tt.wantErr {
t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("get() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_pndStore_get(t *testing.T) {
type fields struct {
store store
}
type args struct {
id uuid.UUID
}
tests := []struct {
name string
fields fields
args args
want PrincipalNetworkDomain
wantErr bool
}{
{
name: "exists",
fields: fields{
store: store{
defaultPndId: &pndImplementation{id: defaultPndId},
},
},
args: args{id: defaultPndId},
want: &pndImplementation{id: defaultPndId},
wantErr: false,
},
{
name: "fails",
fields: fields{
store: store{
defaultPndId: &pndImplementation{id: defaultPndId},
},
},
args: args{id: iid},
wantErr: true,
},
{
name: "fails empty",
fields: fields{
store: store{},
},
args: args{id: defaultPndId},
wantErr: true,
},
{
name: "fails wrong type",
fields: fields{
store: store{
did: &Device{
Config: DeviceConfig{
Uuid: did,
},
},
},
},
args: args{id: defaultPndId},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := pndStore{
store: tt.fields.store,
}
got, err := s.get(tt.args.id)
if (err != nil) != tt.wantErr {
t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("get() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_deviceStore_get(t *testing.T) {
type fields struct {
store store
}
type args struct {
id uuid.UUID
}
tests := []struct {
name string
fields fields
args args
want *Device
wantErr bool
}{
{
name: "exists",
fields: fields{
store: store{
defaultPndId: &Device{Config: DeviceConfig{Uuid: did}}}},
args: args{id: defaultPndId},
want: &Device{
Config: DeviceConfig{
Uuid: did,
},
},
wantErr: false,
},
{
name: "fails",
fields: fields{
store: store{
defaultPndId: &Device{Config: DeviceConfig{Uuid: did}}}},
args: args{id: iid},
wantErr: true,
},
{
name: "fails empty",
fields: fields{
store: store{},
},
args: args{id: defaultPndId},
wantErr: true,
},
{
name: "fails wrong type",
fields: fields{
store: store{
defaultPndId: &pndImplementation{id: defaultPndId}}},
args: args{id: defaultPndId},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := deviceStore{
store: tt.fields.store,
}
got, err := s.get(tt.args.id)
if (err != nil) != tt.wantErr {
t.Errorf("get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("get() got = %v, want %v", got, tt.want)
}
})
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment