Skip to content
Snippets Groups Projects
pnd_test.go 11.6 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/api/go/gosdn/transport"
    	"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/mocks"
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
    	"code.fbi.h-da.de/danet/gosdn/controller/store"
    
    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
    
    var sbiStore *store.SbiStore
    
    func callback(id uuid.UUID, ch chan store.DeviceDetails) {
    	// Need for pnd creation, but not needed for this test case.
    }
    
    func removeExistingStores() {
    	os.RemoveAll("stores/")
    }
    
    func getMockPND() networkdomain.NetworkDomain {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	sbi, err := nucleus.NewSBI(spb.Type(1), sbiUUID)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    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,
    		sbi,
    		csbiClient,
    		callback,
    	)
    
    	newPnd.AddDeviceFromStore(
    		"test",
    		deviceUUID,
    		&transport.TransportOption{
    			Address:  "test",
    			Username: "test",
    			Password: "test",
    			TransportOption: &transport.TransportOption_GnmiTransportOption{
    				GnmiTransportOption: &transport.GnmiTransportOption{},
    			},
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			Type: spb.Type_TYPE_OPENCONFIG,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func TestMain(m *testing.M) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		GoStruct: &openconfig.Device{
    			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 = store.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("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)
    
    	pndc = store.NewPndStore()
    
    	//if err := pndc.Add(newPnd); err != nil {
    	//	log.Fatal(err)
    	//}
    
    	if err := pndc.Add(mockPnd); err != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		log.Fatal(err)
    	}
    
    	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) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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)
    
    func Test_pnd_GetPath(t *testing.T) {
    	removeExistingStores()
    
    
    	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
    }