Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pnd_test.go 8.38 KiB
package server

import (
	"context"
	"os"
	"reflect"
	"testing"
	"time"

	pb "code.fbi.h-da.de/danet/api/go/gosdn/core"
	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
	spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
	"code.fbi.h-da.de/danet/api/go/gosdn/transport"
	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
	"code.fbi.h-da.de/danet/gosdn/mocks"
	"code.fbi.h-da.de/danet/gosdn/nucleus"
	"code.fbi.h-da.de/danet/gosdn/store"
	"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
	"github.com/google/uuid"
	log "github.com/sirupsen/logrus"
	"github.com/stretchr/testify/mock"
	"google.golang.org/grpc"

	cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi"
)

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 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 *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 {
	sbi, err := nucleus.NewSBI(spb.Type(1), sbiUUID)
	if err != nil {
		log.Fatal(err)
	}

	conn, err := grpc.Dial("orchestrator", grpc.WithInsecure())
	if err != nil {
		log.Fatal(err)
	}

	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{},
			},
			Type: spb.Type_TYPE_OPENCONFIG,
		}, sbiUUID)

	return newPnd
}

func TestMain(m *testing.M) {
	removeExistingStores()

	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{
		GoStruct: &openconfig.Device{
			System: &openconfig.OpenconfigSystem_System{
				Config: &openconfig.OpenconfigSystem_System_Config{
					Hostname: &hostname,
				},
			},
		},
		UUID: deviceUUID,
	}
	sbi, err := nucleus.NewSBI(spb.Type_TYPE_OPENCONFIG)
	if err != nil {
		log.Fatal(err)
	}
	mockDevice.(*nucleus.CommonDevice).SetSBI(sbi)
	mockDevice.(*nucleus.CommonDevice).SetTransport(&mocks.Transport{})
	mockDevice.(*nucleus.CommonDevice).SetName(hostname)
	sbiStore = store.NewSbiStore()
	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("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)

	newPnd := getMockPND()

	pndc = store.NewPndStore()
	if err := pndc.Add(newPnd); err != nil {
		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.
func Test_pnd_Get(t *testing.T) {
	removeExistingStores()

	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: []string{
						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_Set(t *testing.T) {
	removeExistingStores()

	// 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)
	// 			}
	// 		}
	// 	})
	// }
}