Skip to content
Snippets Groups Projects
pnd_test.go 11.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package server
    
    import (
    	"context"
    	"os"
    	"reflect"
    	"testing"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    
    	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/networkdomain"
    
    	"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"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
    
    	"github.com/golang/protobuf/proto"
    	"github.com/google/go-cmp/cmp"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	log "github.com/sirupsen/logrus"
    	"github.com/stretchr/testify/mock"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"google.golang.org/grpc/credentials/insecure"
    
    	cpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    )
    
    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"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    var pndUUID uuid.UUID
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    var pendingChangeUUID uuid.UUID
    var committedChangeUUID uuid.UUID
    var deviceUUID uuid.UUID
    
    var mockPnd *mocks.NetworkDomain
    var mockDevice device.Device
    
    func callback(id uuid.UUID, ch chan device.Details) {
    
    	// Need for pnd creation, but not needed for this test case.
    }
    
    func getMockPND() networkdomain.NetworkDomain {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	conn, err := grpc.Dial("orchestrator", grpc.WithTransportCredentials(insecure.NewCredentials()))
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	csbiClient := cpb.NewCsbiServiceClient(conn)
    
    
    	newPnd, _ := nucleus.NewPND(
    		"test",
    		"test",
    		pndUUID,
    		csbiClient,
    		callback,
    	)
    
    	return newPnd
    }
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    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)
    	}
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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)
    	}
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	mockDevice = &nucleus.CommonDevice{
    
    Andre Sterba's avatar
    Andre Sterba committed
    		Model: &openconfig.Device{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			System: &openconfig.OpenconfigSystem_System{
    				Config: &openconfig.OpenconfigSystem_System_Config{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		UUID: deviceUUID,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    
    	sbi, err := nucleus.NewSBI(spb.Type_TYPE_OPENCONFIG, sbiUUID)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Fatal(err)
    	}
    	mockDevice.(*nucleus.CommonDevice).SetSBI(sbi)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	mockDevice.(*nucleus.CommonDevice).SetTransport(&mocks.Transport{})
    	mockDevice.(*nucleus.CommonDevice).SetName(hostname)
    
    	sbiStore = nucleus.NewSbiStore(pndUUID)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err := sbiStore.Add(mockDevice.SBI()); err != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		log.Fatal(err)
    	}
    
    
    	mockChange := &mocks.Change{}
    	mockChange.On("Age").Return(time.Hour)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	mockChange.On("State").Return(ppb.ChangeState_CHANGE_STATE_INCONSISTENT)
    
    	mockPnd = &mocks.NetworkDomain{}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	mockPnd.On("ID").Return(pndUUID)
    	mockPnd.On("GetName").Return("test")
    	mockPnd.On("GetDescription").Return("test")
    	mockPnd.On("GetSBIs").Return(sbiStore)
    
    	mockPnd.On("GetSBI").Return(mockDevice.SBI(), nil)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		log.Fatal(err)
    	}
    
    
    	userc = rbac.NewUserStore()
    	rolec = rbac.NewRoleStore()
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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.
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func Test_pnd_Get(t *testing.T) {
    	type args struct {
    		ctx     context.Context
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		request *pb.GetPndRequest
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	tests := []struct {
    		name    string
    		args    args
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		want    *pb.GetPndResponse
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		wantErr bool
    	}{
    		{
    			name: "get pnd",
    			args: args{
    				ctx: context.Background(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    				request: &pb.GetPndRequest{
    					Pid: []string{
    						pndID},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				},
    			},
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			want: &pb.GetPndResponse{
    				Pnd: []*ppb.PrincipalNetworkDomain{
    					{Id: pndID,
    						Name:        "test",
    						Description: "test"},
    				},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			p := core{
    				UnimplementedCoreServiceServer: pb.UnimplementedCoreServiceServer{},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			resp, err := p.GetPnd(tt.args.ctx, tt.args.request)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			got := resp.GetPnd()
    
    			if !reflect.DeepEqual(got, tt.want.Pnd) {
    				t.Errorf("Get() got = %v, want %v", got, tt.want.Pnd)
    
    	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{
    
    					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{
    
    					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{
    
    					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)
    				}
    			}
    		})
    	}
    }
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func Test_pnd_Set(t *testing.T) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	// 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)
    	// 			}
    	// 		}
    	// 	})
    	// }
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }