diff --git a/controller/topology/nodes/nodeService_test.go b/controller/topology/nodes/nodeService_test.go index 2472d8564c6d8159ea70f917c4bac01b9c99d0c3..e9b76b8634babdbbb44942ab55eecda17837e009 100644 --- a/controller/topology/nodes/nodeService_test.go +++ b/controller/topology/nodes/nodeService_test.go @@ -148,7 +148,7 @@ func TestNodeService_Update(t *testing.T) { { name: "should update an existing node", fields: fields{ - store: store.NewGenericStore[Node](), + store: getTestStoreWithNodes(t, []Node{getTestNode()}), }, args: args{ node: getTestNode(), @@ -194,7 +194,7 @@ func TestNodeService_Delete(t *testing.T) { { name: "should delete an existing node", fields: fields{ - store: store.NewGenericStore[Node](), + store: getTestStoreWithNodes(t, []Node{getTestNode()}), }, args: args{ node: getTestNode(), @@ -209,7 +209,7 @@ func TestNodeService_Delete(t *testing.T) { args: args{ node: getTestNode(), }, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -295,7 +295,7 @@ func TestNodeService_GetAll(t *testing.T) { wantErr bool }{ { - name: "should fail if a node does not exists", + name: "should get all stored nodes", fields: fields{ store: getTestStoreWithNodes(t, []Node{getTestNode()}), }, diff --git a/controller/topology/ports/portService_test.go b/controller/topology/ports/portService_test.go index bc73c2b0c971413ce14caf1280a21291a94237f3..37dc354579e4a3425b791317a0eff7918333d25c 100644 --- a/controller/topology/ports/portService_test.go +++ b/controller/topology/ports/portService_test.go @@ -148,7 +148,7 @@ func TestPortService_Update(t *testing.T) { { name: "should update an existing port", fields: fields{ - store: store.NewGenericStore[Port](), + store: getTestStoreWithPorts(t, []Port{getTestPort()}), }, args: args{ port: getTestPort(), @@ -194,7 +194,7 @@ func TestPortService_Delete(t *testing.T) { { name: "should delete an existing port", fields: fields{ - store: store.NewGenericStore[Port](), + store: getTestStoreWithPorts(t, []Port{getTestPort()}), }, args: args{ port: getTestPort(), @@ -209,7 +209,7 @@ func TestPortService_Delete(t *testing.T) { args: args{ port: getTestPort(), }, - wantErr: false, + wantErr: true, }, } for _, tt := range tests { @@ -295,7 +295,7 @@ func TestPortService_GetAll(t *testing.T) { wantErr bool }{ { - name: "should fail if a port does not exists", + name: "should get all stored ports", fields: fields{ store: getTestStoreWithPorts(t, []Port{getTestPort()}), }, diff --git a/controller/topology/store/genericStore.go b/controller/topology/store/genericStore.go index 9d02d1764e8f3819401cdd2525bab43b42314084..6860cb187339cbe919eadace9a1751bf3d1c9c26 100644 --- a/controller/topology/store/genericStore.go +++ b/controller/topology/store/genericStore.go @@ -25,7 +25,7 @@ func NewGenericStore[T storableConstraint]() *GenericStore[T] { func (t *GenericStore[T]) Add(item T) error { _, ok := t.Store[item.GetID()] if ok { - return errors.New("item not found") + return errors.New("item already exists") } t.Store[item.GetID()] = item @@ -35,7 +35,7 @@ func (t *GenericStore[T]) Add(item T) error { func (t *GenericStore[T]) Update(item T) error { _, ok := t.Store[item.GetID()] - if ok { + if !ok { return errors.New("item not found") } @@ -46,7 +46,7 @@ func (t *GenericStore[T]) Update(item T) error { func (t *GenericStore[T]) Delete(item T) error { _, ok := t.Store[item.GetID()] - if ok { + if !ok { return errors.New("item not found") } diff --git a/controller/topology/topologyService.go b/controller/topology/topologyService.go index 4defe312bde10bceb11af394f7c6694fba803d44..a08649426ff6d85ce79fb802de5df5d1d5a51ad3 100644 --- a/controller/topology/topologyService.go +++ b/controller/topology/topologyService.go @@ -1,12 +1,16 @@ package topology -import "code.fbi.h-da.de/danet/gosdn/controller/topology/links" +import ( + "code.fbi.h-da.de/danet/gosdn/controller/topology/links" + "code.fbi.h-da.de/danet/gosdn/controller/topology/store" +) // Service defines an interface for a Service type Service interface { AddLink(links.Link) error UpdateLink(links.Link) error DeleteLink(links.Link) error + Get(store.Query) (links.Link, error) GetAll() ([]links.Link, error) } @@ -60,3 +64,13 @@ func (t *service) GetAll() ([]links.Link, error) { } return topo, nil } + +// GetAll returns the current topology +func (t *service) Get(query store.Query) (links.Link, error) { + link, err := t.store.Get(query) + if err != nil { + return link, err + } + + return link, nil +} diff --git a/controller/topology/topologyService_test.go b/controller/topology/topologyService_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f49a035cc2007229a803a489f66217b015f714a0 --- /dev/null +++ b/controller/topology/topologyService_test.go @@ -0,0 +1,327 @@ +package topology + +import ( + "reflect" + "testing" + + "code.fbi.h-da.de/danet/gosdn/controller/topology/links" + "code.fbi.h-da.de/danet/gosdn/controller/topology/nodes" + "code.fbi.h-da.de/danet/gosdn/controller/topology/ports" + "code.fbi.h-da.de/danet/gosdn/controller/topology/store" + "github.com/google/uuid" +) + +func getTestNode() nodes.Node { + return nodes.Node{ + ID: uuid.MustParse("44fb4aa4-c53c-4cf9-a081-5aabc61c7610"), + Name: "Test-Node", + } +} + +func getTestPort() ports.Port { + return ports.Port{ + ID: uuid.MustParse("1fa479e7-d393-4d45-822d-485cc1f05fce"), + Name: "Test-Port", + } +} + +func getTestLink() links.Link { + return links.Link{ + ID: uuid.MustParse("5eb474f1-428e-4503-ba68-dcf9bef53467"), + Name: "Test-Link", + SourceNode: getTestNode(), + TargetNode: nodes.Node{ + ID: uuid.MustParse("44fb4aa4-c53c-4cf9-a081-5aabc61c7612"), + Name: "Test-Node", + }, + SourcePort: getTestPort(), + TargetPort: ports.Port{ + ID: uuid.MustParse("1fa479e7-d393-4d45-822d-485cc1f05fc2"), + Name: "Test-Port", + }, + } +} + +func getEmptyLink() links.Link { + return links.Link{} +} + +func getTestStoreWithLinks(t *testing.T, nodes []links.Link) Store { + store := store.NewGenericStore[links.Link]() + + 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 TestNewTopologyService(t *testing.T) { + type args struct { + store Store + } + tests := []struct { + name string + args args + want Service + }{ + { + name: "should create a new topology service", + args: args{ + store: getTestStoreWithLinks(t, []links.Link{}), + }, + want: NewTopologyService(getTestStoreWithLinks(t, []links.Link{})), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewTopologyService(tt.args.store); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewNodeService() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTopologyService_AddLink(t *testing.T) { + type fields struct { + store Store + } + type args struct { + link links.Link + } + tests := []struct { + name string + fields fields + args args + want links.Link + wantErr bool + }{ + { + name: "should add a link to the store", + fields: fields{ + store: store.NewGenericStore[links.Link](), + }, + args: args{ + link: getTestLink(), + }, + want: getTestLink(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &service{ + store: tt.fields.store, + } + err := p.AddLink(tt.args.link) + if (err != nil) != tt.wantErr { + t.Errorf("service.AddLink() error = %v, wantErr %v", err, tt.wantErr) + return + } + + got, err := p.Get(store.Query{ID: tt.args.link.ID}) + if (err != nil) != tt.wantErr { + t.Errorf("service.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("service.Get() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTopologyService_Update(t *testing.T) { + type fields struct { + store Store + } + type args struct { + link links.Link + } + tests := []struct { + name string + fields fields + args args + want links.Link + wantErr bool + }{ + { + name: "should update an existing link", + fields: fields{ + store: getTestStoreWithLinks(t, []links.Link{getTestLink()}), + }, + args: args{ + link: getTestLink(), + }, + want: getTestLink(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &service{ + store: tt.fields.store, + } + err := p.UpdateLink(tt.args.link) + if (err != nil) != tt.wantErr { + t.Errorf("service.Update() error = %v, wantErr %v", err, tt.wantErr) + return + } + + got, err := p.Get(store.Query{ID: tt.args.link.ID}) + if (err != nil) != tt.wantErr { + t.Errorf("service.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("service.Get() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNodeService_Delete(t *testing.T) { + type fields struct { + store Store + } + type args struct { + link links.Link + } + tests := []struct { + name string + fields fields + args args + want links.Link + wantErr bool + }{ + { + name: "should delete an existing link", + fields: fields{ + store: getTestStoreWithLinks(t, []links.Link{getTestLink()}), + }, + args: args{ + link: getTestLink(), + }, + wantErr: false, + }, + { + name: "should fail if a node does not exists", + fields: fields{ + store: store.NewGenericStore[links.Link](), + }, + args: args{ + link: getTestLink(), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &service{ + store: tt.fields.store, + } + if err := p.DeleteLink(tt.args.link); (err != nil) != tt.wantErr { + t.Errorf("service.Delete() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestTopologyService_Get(t *testing.T) { + type fields struct { + store Store + } + type args struct { + query store.Query + } + tests := []struct { + name string + fields fields + args args + want links.Link + wantErr bool + }{ + { + name: "should error if link with uuid is not in store", + fields: fields{ + store: getTestStoreWithLinks(t, []links.Link{}), + }, + args: args{ + query: store.Query{ + ID: getTestLink().ID, + Name: getTestLink().Name, + }, + }, + want: getEmptyLink(), + wantErr: true, + }, + { + name: "should return link that is in the store", + fields: fields{ + store: getTestStoreWithLinks(t, []links.Link{getTestLink()}), + }, + args: args{ + query: store.Query{ + ID: getTestLink().ID, + Name: getTestLink().Name, + }, + }, + want: getTestLink(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &service{ + store: tt.fields.store, + } + got, err := p.Get(tt.args.query) + if (err != nil) != tt.wantErr { + t.Errorf("service.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("service.Get() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestTopologyService_GetAll(t *testing.T) { + type fields struct { + store Store + } + tests := []struct { + name string + fields fields + want []links.Link + wantErr bool + }{ + { + name: "should get all stored links", + fields: fields{ + store: getTestStoreWithLinks(t, []links.Link{getTestLink()}), + }, + want: []links.Link{getTestLink()}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &service{ + store: tt.fields.store, + } + got, err := p.GetAll() + if (err != nil) != tt.wantErr { + t.Errorf("service.GetAll() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("service.GetAll() = %v, want %v", got, tt.want) + } + }) + } +}