-
Fabian Seidl authoredFabian Seidl authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pnd_test.go 10.61 KiB
package server
import (
"context"
"os"
"reflect"
"testing"
"time"
pb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core"
ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
"code.fbi.h-da.de/danet/gosdn/controller/mocks"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
"code.fbi.h-da.de/danet/gosdn/controller/rbac"
"code.fbi.h-da.de/danet/gosdn/models/generated/openconfig"
"github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
"github.com/openconfig/gnmi/proto/gnmi"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/mock"
)
const pndID = "2043519e-46d1-4963-9a8e-d99007e104b8"
const pendingChangeID = "0992d600-f7d4-4906-9559-409b04d59a5f"
const committedChangeID = "804787d6-e5a8-4dba-a1e6-e73f96b0119e"
const sbiID = "f6fd4b35-f039-4111-9156-5e4501bb8a5a"
const ondID = "7e0ed8cc-ebf5-46fa-9794-741494914883"
var hostname = "manfred"
var domainname = "uwe"
var pndUUID uuid.UUID
var sbiUUID uuid.UUID
var pendingChangeUUID uuid.UUID
var committedChangeUUID uuid.UUID
var deviceUUID uuid.UUID
var mockPnd *mocks.NetworkDomain
var mockDevice device.Device
var sbiStore southbound.Store
func TestMain(m *testing.M) {
log.SetReportCaller(true)
var err error
pndUUID, err = uuid.Parse(pndID)
if err != nil {
log.Fatal(err)
}
sbiUUID, err = uuid.Parse(sbiID)
if err != nil {
log.Fatal(err)
}
pendingChangeUUID, err = uuid.Parse(pendingChangeID)
if err != nil {
log.Fatal(err)
}
committedChangeUUID, err = uuid.Parse(committedChangeID)
if err != nil {
log.Fatal(err)
}
deviceUUID, err = uuid.Parse(ondID)
if err != nil {
log.Fatal(err)
}
mockDevice = &nucleus.CommonDevice{
Model: &openconfig.Device{
System: &openconfig.OpenconfigSystem_System{
Config: &openconfig.OpenconfigSystem_System_Config{
Hostname: &hostname,
DomainName: &domainname,
},
},
},
UUID: deviceUUID,
}
sbi, err := nucleus.NewSBI(spb.Type_TYPE_OPENCONFIG, sbiUUID)
if err != nil {
log.Fatal(err)
}
mockDevice.(*nucleus.CommonDevice).SetSBI(sbi)
mockDevice.(*nucleus.CommonDevice).SetTransport(&mocks.Transport{})
mockDevice.(*nucleus.CommonDevice).SetName(hostname)
sbiStore = nucleus.NewSbiStore(pndUUID)
if err := sbiStore.Add(mockDevice.SBI()); err != nil {
log.Fatal(err)
}
mockChange := &mocks.Change{}
mockChange.On("Age").Return(time.Hour)
mockChange.On("State").Return(ppb.ChangeState_CHANGE_STATE_INCONSISTENT)
mockPnd = &mocks.NetworkDomain{}
mockPnd.On("ID").Return(pndUUID)
mockPnd.On("GetName").Return("test")
mockPnd.On("GetDescription").Return("test")
mockPnd.On("GetSBIs").Return(sbiStore)
mockPnd.On("GetSBI", mock.Anything).Return(mockDevice.SBI(), nil)
mockPnd.On("Devices").Return([]uuid.UUID{deviceUUID})
mockPnd.On("PendingChanges").Return([]uuid.UUID{pendingChangeUUID})
mockPnd.On("CommittedChanges").Return([]uuid.UUID{committedChangeUUID})
mockPnd.On("GetChange", mock.Anything).Return(mockChange, nil)
mockPnd.On("AddDevice", mock.Anything, mock.Anything, mock.Anything).Return(nil)
mockPnd.On("GetDevice", mock.Anything).Return(mockDevice, nil)
mockPnd.On("Commit", mock.Anything).Return(nil)
mockPnd.On("Confirm", mock.Anything).Return(nil)
mockPnd.On("ChangeOND", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(uuid.Nil, nil)
mockPnd.On("Request", mock.Anything, mock.Anything).Return(nil, nil)
pndc = nucleus.NewMemoryPndStore()
if err := pndc.Add(mockPnd); err != nil {
log.Fatal(err)
}
// everyting auth related
userc = rbac.NewUserService(rbac.NewMemoryUserStore())
rolec = rbac.NewRoleService(rbac.NewMemoryRoleStore())
err = clearAndCreateAuthTestSetup()
if err != nil {
log.Fatal(err)
}
jwt = rbac.NewJWTManager("", 1*time.Minute)
os.Exit(m.Run())
}
// TODO: We should re-add all tests for changes.
// As of now this is not possible as we can't use the mock pnd, as it can't be serialized because of
// cyclic use of mock in it.
func Test_pnd_Get(t *testing.T) {
type args struct {
ctx context.Context
request *pb.GetPndRequest
}
tests := []struct {
name string
args args
want *pb.GetPndResponse
wantErr bool
}{
{
name: "get pnd",
args: args{
ctx: context.Background(),
request: &pb.GetPndRequest{
Pid: pndID,
},
},
want: &pb.GetPndResponse{
Pnd: &ppb.PrincipalNetworkDomain{
Id: pndID,
Name: "test",
Description: "test"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := core{
UnimplementedCoreServiceServer: pb.UnimplementedCoreServiceServer{},
}
resp, err := p.GetPnd(tt.args.ctx, tt.args.request)
if (err != nil) != tt.wantErr {
t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
return
}
got := resp.GetPnd()
if !reflect.DeepEqual(got, tt.want.Pnd) {
t.Errorf("Get() got = %v, want %v", got, tt.want.Pnd)
}
})
}
}
func Test_pnd_GetPath(t *testing.T) {
opts := cmp.Options{
cmpopts.SortSlices(
func(x, y *gnmi.Update) bool {
return x.GetVal().String() < y.GetVal().String()
},
),
cmp.Comparer(proto.Equal),
}
type args struct {
ctx context.Context
request *ppb.GetPathRequest
}
tests := []struct {
name string
args args
want []*gnmi.Notification
wantErr bool
}{
{
name: "get path: system/config/hostname",
args: args{
ctx: context.Background(),
request: &ppb.GetPathRequest{
Timestamp: time.Now().UnixNano(),
Did: mockDevice.ID().String(),
Path: "system/config/hostname",
Pid: mockPnd.ID().String(),
},
},
want: []*gnmi.Notification{
{
Update: []*gnmi.Update{
{
Path: &gnmi.Path{Element: []string{"hostname"}},
Val: &gnmi.TypedValue{
Value: &gnmi.TypedValue_StringVal{
StringVal: "manfred",
},
},
},
}},
},
wantErr: false,
},
{
name: "get path: system",
args: args{
ctx: context.Background(),
request: &ppb.GetPathRequest{
Timestamp: time.Now().UnixNano(),
Did: mockDevice.ID().String(),
Path: "system",
Pid: mockPnd.ID().String(),
},
},
want: []*gnmi.Notification{
{
Update: []*gnmi.Update{
{
Path: &gnmi.Path{Element: []string{"config", "domain-name"}},
Val: &gnmi.TypedValue{
Value: &gnmi.TypedValue_StringVal{
StringVal: "uwe",
},
},
},
{
Path: &gnmi.Path{Element: []string{"config", "hostname"}},
Val: &gnmi.TypedValue{
Value: &gnmi.TypedValue_StringVal{
StringVal: "manfred",
},
},
},
}},
},
wantErr: false,
},
{
name: "get path: this/path/is/not/valid",
args: args{
ctx: context.Background(),
request: &ppb.GetPathRequest{
Timestamp: time.Now().UnixNano(),
Did: mockDevice.ID().String(),
Path: "this/path/is/not/valid",
Pid: mockPnd.ID().String(),
},
},
want: []*gnmi.Notification{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := pndServer{
UnimplementedPndServiceServer: ppb.UnimplementedPndServiceServer{},
}
resp, err := s.GetPath(tt.args.ctx, tt.args.request)
if (err != nil) != tt.wantErr {
t.Errorf("GetPath() error = %v, wantErr %v", err, tt.wantErr)
return
}
got := resp.GetDevice()
for i, n := range got {
if diff := cmp.Diff(n.GetUpdate(), tt.want[i].GetUpdate(), opts...); diff != "" {
t.Errorf("GetPath() diff in the received notification %d: \n%s", i+1, diff)
}
}
})
}
}
func Test_pnd_Set(t *testing.T) {
// type args struct {
// ctx context.Context
// request *ppb.SetRequest
// }
// tests := []struct {
// name string
// args args
// want ppb.SetResponseStatus
// wantErr bool
// }{
// {
// name: "set ond",
// args: args{
// ctx: context.Background(),
// request: &ppb.SetRequest{
// Ond: []*ppb.SetOnd{
// {
// Sbi: &spb.SouthboundInterface{
// Id: sbiID,
// Type: spb.Type_TYPE_OPENCONFIG,
// },
// DeviceName: hostname,
// TransportOption: &transport.TransportOption{
// Address: "test",
// Username: "test",
// Password: "test",
// TransportOption: &transport.TransportOption_GnmiTransportOption{
// GnmiTransportOption: &transport.GnmiTransportOption{},
// },
// },
// },
// },
// Pid: pndID,
// },
// },
// want: ppb.SetResponse_OK,
// },
// // {
// // name: "set change",
// // args: args{
// // ctx: context.Background(),
// // request: &ppb.SetRequest{
// // Pid: pndID,
// // Change: []*ppb.SetChange{
// // {
// // Cuid: pendingChangeID,
// // Op: ppb.SetChange_COMMIT,
// // },
// // {
// // Cuid: committedChangeID,
// // Op: ppb.SetChange_CONFIRM,
// // },
// // },
// // },
// // },
// // want: ppb.SetResponse_OK,
// // },
// // {
// // name: "change request",
// // args: args{
// // ctx: context.Background(),
// // request: &ppb.SetRequest{
// // Pid: pndID,
// // ChangeRequest: []*ppb.ChangeRequest{
// // {
// // Id: ondID,
// // Path: "/system/config/hostname",
// // Value: "herbert",
// // ApiOp: ppb.ApiOperation_UPDATE,
// // },
// // {
// // Id: ondID,
// // Path: "/system/config/hostname",
// // Value: "fridolin",
// // ApiOp: ppb.ApiOperation_REPLACE,
// // },
// // {
// // Id: ondID,
// // Path: "/system/config/hostname",
// // ApiOp: ppb.ApiOperation_DELETE,
// // },
// // },
// // },
// // },
// // want: ppb.SetResponse_OK,
// // },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// p := pndServer{
// UnimplementedPndServiceServer: ppb.UnimplementedPndServiceServer{},
// }
// resp, err := p.Set(tt.args.ctx, tt.args.request)
// if (err != nil) != tt.wantErr {
// t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
// return
// }
// got := resp.Status
// if !reflect.DeepEqual(got, tt.want) {
// t.Errorf("Set() got = %v, want %v", got, tt.want)
// }
// for _, r := range resp.Responses {
// got = r.Status
// if !reflect.DeepEqual(got, tt.want) {
// t.Errorf("Set() got = %v, want %v", got, tt.want)
// }
// }
// })
// }
}