Skip to content
Snippets Groups Projects
Commit 4ca6a4ef authored by André Sterba's avatar André Sterba
Browse files

Refactor topology to enable testing and add nodeService tests

parent 1e1532da
Branches
Tags
5 merge requests!376Add additional example application hostname-checker,!349Northbound refactoring to implement NIB concept for devices,!343Add basic application framework and example application to show interaction between events an NBI,!339Create basic venv-manager for use with arista,!324Provide prototype implementation for topology handling
Pipeline #104641 failed
package nodes package nodes
import ( import (
"code.fbi.h-da.de/danet/gosdn/controller/store" "code.fbi.h-da.de/danet/gosdn/controller/topology/store"
"github.com/google/uuid" "github.com/google/uuid"
) )
......
package nodes
import (
"reflect"
"testing"
"code.fbi.h-da.de/danet/gosdn/controller/topology/store"
"github.com/google/uuid"
)
func getTestNode() Node {
return Node{
ID: uuid.MustParse("44fb4aa4-c53c-4cf9-a081-5aabc61c7610"),
Name: "Test-Node",
}
}
func getEmptyNode() Node {
return Node{
ID: uuid.Nil,
Name: "",
}
}
func getTestStoreWithNodes(t *testing.T, nodes []Node) Store {
store := store.NewGenericStore[Node]()
for _, node := range nodes {
err := store.Add(node)
if err != nil {
t.Fatalf("failed to prepare test store while adding node: %v", err)
}
}
return store
}
func TestNewNodeService(t *testing.T) {
type args struct {
store Store
}
tests := []struct {
name string
args args
want Service
}{
{
name: "should create a new node service",
args: args{
store: getTestStoreWithNodes(t, []Node{}),
},
want: NewNodeService(getTestStoreWithNodes(t, []Node{})),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewNodeService(tt.args.store); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewNodeService() = %v, want %v", got, tt.want)
}
})
}
}
func TestNodeService_EnsureExists(t *testing.T) {
type fields struct {
store Store
}
type args struct {
node Node
}
tests := []struct {
name string
fields fields
args args
want Node
wantErr bool
}{
// {
// name: "should add not existing node",
// fields: fields{
// store: store.NewGenericStore[Node](),
// },
// args: args{
// node: Node{
// ID: uuid.Nil,
// Name: "Test-Node",
// },
// },
// want: Node{
// Name: "Test-Node",
// },
// wantErr: false,
// },
{
name: "should error if node with uuid is not in store",
fields: fields{
store: store.NewGenericStore[Node](),
},
args: args{
node: getTestNode(),
},
want: getEmptyNode(),
wantErr: true,
},
{
name: "should return node that is in the store",
fields: fields{
store: getTestStoreWithNodes(t, []Node{getTestNode()}),
},
args: args{
node: getTestNode(),
},
want: getTestNode(),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &NodeService{
store: tt.fields.store,
}
got, err := p.EnsureExists(tt.args.node)
if (err != nil) != tt.wantErr {
t.Errorf("NodeService.EnsureExists() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NodeService.EnsureExists() = %v, want %v", got, tt.want)
}
})
}
}
func TestNodeService_Update(t *testing.T) {
type fields struct {
store Store
}
type args struct {
node Node
}
tests := []struct {
name string
fields fields
args args
want Node
wantErr bool
}{
{
name: "should update an existing node",
fields: fields{
store: store.NewGenericStore[Node](),
},
args: args{
node: getTestNode(),
},
want: getTestNode(),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &NodeService{
store: tt.fields.store,
}
if err := p.Update(tt.args.node); (err != nil) != tt.wantErr {
t.Errorf("NodeService.Update() error = %v, wantErr %v", err, tt.wantErr)
}
updatedNode, err := p.Get(store.Query(tt.args.node))
if err != nil {
t.Errorf("NodeService.Get() failed %v", err)
}
if !reflect.DeepEqual(updatedNode, tt.want) {
t.Errorf("Got updated node = %v, want %v", updatedNode, tt.want)
}
})
}
}
func TestNodeService_Delete(t *testing.T) {
type fields struct {
store Store
}
type args struct {
node Node
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{
name: "should delete an existing node",
fields: fields{
store: store.NewGenericStore[Node](),
},
args: args{
node: getTestNode(),
},
wantErr: false,
},
{
name: "should fail if a node does not exists",
fields: fields{
store: store.NewGenericStore[Node](),
},
args: args{
node: getTestNode(),
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &NodeService{
store: tt.fields.store,
}
if err := p.Delete(tt.args.node); (err != nil) != tt.wantErr {
t.Errorf("NodeService.Delete() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestNodeService_Get(t *testing.T) {
type fields struct {
store Store
}
type args struct {
query store.Query
}
tests := []struct {
name string
fields fields
args args
want Node
wantErr bool
}{
{
name: "should error if node with uuid is not in store",
fields: fields{
store: store.NewGenericStore[Node](),
},
args: args{
query: store.Query{
ID: getTestNode().ID,
Name: getTestNode().Name,
},
},
want: getEmptyNode(),
wantErr: true,
},
{
name: "should return node that is in the store",
fields: fields{
store: getTestStoreWithNodes(t, []Node{getTestNode()}),
},
args: args{
query: store.Query{
ID: getTestNode().ID,
Name: getTestNode().Name,
},
},
want: getTestNode(),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &NodeService{
store: tt.fields.store,
}
got, err := p.Get(tt.args.query)
if (err != nil) != tt.wantErr {
t.Errorf("NodeService.Get() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NodeService.Get() = %v, want %v", got, tt.want)
}
})
}
}
func TestNodeService_GetAll(t *testing.T) {
type fields struct {
store Store
}
tests := []struct {
name string
fields fields
want []Node
wantErr bool
}{
{
name: "should fail if a node does not exists",
fields: fields{
store: getTestStoreWithNodes(t, []Node{getTestNode()}),
},
want: []Node{getTestNode()},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &NodeService{
store: tt.fields.store,
}
got, err := p.GetAll()
if (err != nil) != tt.wantErr {
t.Errorf("NodeService.GetAll() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NodeService.GetAll() = %v, want %v", got, tt.want)
}
})
}
}
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/database" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/database"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
"code.fbi.h-da.de/danet/gosdn/controller/store" "code.fbi.h-da.de/danet/gosdn/controller/topology/store"
"github.com/google/uuid" "github.com/google/uuid"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
......
package topology package store
import ( import (
"errors" "errors"
"code.fbi.h-da.de/danet/gosdn/controller/store"
"github.com/google/uuid" "github.com/google/uuid"
) )
...@@ -17,8 +16,8 @@ type GenericStore[T storableConstraint] struct { ...@@ -17,8 +16,8 @@ type GenericStore[T storableConstraint] struct {
} }
// NewGenericStore returns a specific in-memory store for a type T. // NewGenericStore returns a specific in-memory store for a type T.
func NewGenericStore[T storableConstraint]() GenericStore[T] { func NewGenericStore[T storableConstraint]() *GenericStore[T] {
return GenericStore[T]{ return &GenericStore[T]{
Store: make(map[uuid.UUID]T), Store: make(map[uuid.UUID]T),
} }
} }
...@@ -37,7 +36,7 @@ func (t *GenericStore[T]) Add(item T) error { ...@@ -37,7 +36,7 @@ func (t *GenericStore[T]) Add(item T) error {
func (t *GenericStore[T]) Update(item T) error { func (t *GenericStore[T]) Update(item T) error {
_, ok := t.Store[item.GetID()] _, ok := t.Store[item.GetID()]
if ok { if ok {
return nil return errors.New("item not found")
} }
t.Store[item.GetID()] = item t.Store[item.GetID()] = item
...@@ -46,12 +45,17 @@ func (t *GenericStore[T]) Update(item T) error { ...@@ -46,12 +45,17 @@ func (t *GenericStore[T]) Update(item T) error {
} }
func (t *GenericStore[T]) Delete(item T) error { func (t *GenericStore[T]) Delete(item T) error {
_, ok := t.Store[item.GetID()]
if ok {
return errors.New("item not found")
}
delete(t.Store, item.GetID()) delete(t.Store, item.GetID())
return nil return nil
} }
func (t *GenericStore[T]) Get(query store.Query) (T, error) { func (t *GenericStore[T]) Get(query Query) (T, error) {
// First search for direct hit on UUID. // First search for direct hit on UUID.
item, ok := t.Store[query.ID] item, ok := t.Store[query.ID]
if !ok { if !ok {
......
package store
import "github.com/google/uuid"
type Query struct {
ID uuid.UUID
Name string
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment