Skip to content
Snippets Groups Projects
gnmi_transport_test.go 13.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package nucleus
    
    
    import (
    	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
    
    	"code.fbi.h-da.de/cocsn/gosdn/mocks"
    	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
    
    	"code.fbi.h-da.de/cocsn/gosdn/test"
    
    	"code.fbi.h-da.de/cocsn/yang-models/generated/arista"
    	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
    
    	"context"
    	log "github.com/golang/glog"
    	gpb "github.com/openconfig/gnmi/proto/gnmi"
    	"github.com/openconfig/goyang/pkg/yang"
    	"github.com/openconfig/ygot/ytypes"
    
    	"github.com/stretchr/testify/mock"
    
    	"os"
    	"reflect"
    	"testing"
    )
    
    
    // TestMain bootstraps all tests. Humongous beast
    
    // TODO: Move somewhere more sensible
    
    func TestMain(m *testing.M) {
    	testSetupGnmi()
    
    	testSetupStore()
    
    	os.Exit(m.Run())
    }
    
    // testSetupGnmi bootstraps tests for gnmi transport
    func testSetupGnmi() {
    	// TODO: Set sane defaults
    	gnmiConfig = &gnmi.Config{
    		Username: "test",
    		Password: "test",
    		Addr:     "localhost:13371",
    		Encoding: gpb.Encoding_PROTO,
    	}
    
    	startGnmiTarget = make(chan string)
    	stopGnmiTarget = make(chan bool)
    	go targetRunner()
    }
    
    func targetRunner() {
    	for {
    		addr := <-startGnmiTarget
    
    		if err := test.GnmiTarget(stopGnmiTarget, addr); err != nil {
    
    			log.Fatal(err)
    		}
    	}
    }
    
    
    func mockTransport() Gnmi {
    	return Gnmi{
    		SetNode:  nil,
    		RespChan: make(chan *gpb.SubscribeResponse),
    		config:   gnmiConfig,
    		client:   &mocks.GNMIClient{},
    	}
    }
    
    
    var gnmiConfig *gnmi.Config
    var startGnmiTarget chan string
    var stopGnmiTarget chan bool
    
    var mockContext = mock.MatchedBy(func(ctx context.Context) bool { return true })
    
    
    func TestGnmi_Capabilities(t *testing.T) {
    
    	transport := mockTransport()
    
    	capabilityResponse := &gpb.CapabilityResponse{
    		SupportedModels:    nil,
    		SupportedEncodings: []gpb.Encoding{gpb.Encoding_PROTO, gpb.Encoding_JSON_IETF, gpb.Encoding_JSON},
    		GNMIVersion:        "0.6.0",
    		Extension:          nil,
    	}
    
    	capabilityRequest := &gpb.CapabilityRequest{}
    
    	ctx := context.Background()
    	transport.client.(*mocks.GNMIClient).
    		On("Capabilities", ctx, capabilityRequest).
    		Return(capabilityResponse, nil)
    
    
    	type fields struct {
    
    		transport *Gnmi
    
    	}
    	type args struct {
    
    		runEndpoint bool
    
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    *gpb.CapabilityResponse
    		wantErr bool
    	}{
    		{
    
    			name:   "mock",
    
    			fields: fields{transport: &transport},
    
    			args: args{
    
    				endpoint:    gnmiConfig.Addr,
    
    				runEndpoint: false,
    
    			want:    capabilityResponse,
    			wantErr: false,
    
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			if tt.args.runEndpoint {
    				startGnmiTarget <- tt.args.endpoint
    			}
    
    
    			got, err := tt.fields.transport.Capabilities(context.Background())
    
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Capabilities() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("Get() got = %v, want %v", got, tt.want)
    
    			if tt.args.runEndpoint {
    				stopGnmiTarget <- true
    			}
    
    		})
    	}
    }
    
    func TestGnmi_Close(t *testing.T) {
    	type fields struct {
    		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
    		RespChan chan *gpb.SubscribeResponse
    		config   *gnmi.Config
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		wantErr bool
    	}{
    
    		{name: "dummy", fields: fields{}, wantErr: false},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			g := &Gnmi{
    				SetNode:  tt.fields.SetNode,
    				RespChan: tt.fields.RespChan,
    				config:   tt.fields.config,
    			}
    			if err := g.Close(); (err != nil) != tt.wantErr {
    				t.Errorf("Close() error = %v, wantErr %v", err, tt.wantErr)
    			}
    		})
    	}
    }
    
    func TestGnmi_Get(t *testing.T) {
    
    	transport := mockTransport()
    
    	getRequest := &gpb.GetRequest{
    		Prefix:    nil,
    		Path:      nil,
    		Type:      0,
    		Encoding:  0,
    		UseModels: nil,
    		Extension: nil,
    	}
    
    
    	getResponse := &gpb.GetResponse{
    
    		Notification: nil,
    		Error:        nil,
    		Extension:    nil,
    	}
    
    	transport.client.(*mocks.GNMIClient).
    		On("NewContext", mockContext, mock.Anything).
    		Return(mockContext)
    	transport.client.(*mocks.GNMIClient).
    		On("NewGetRequest", mockContext, mock.Anything, mock.Anything).
    		Return(getRequest, nil)
    	transport.client.(*mocks.GNMIClient).
    		On("Get", mockContext, mock.Anything).
    
    		Return(getResponse, nil)
    
    	type fields struct {
    
    		transport *Gnmi
    
    	}
    	type args struct {
    
    		runEndpoint bool
    
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    interface{}
    		wantErr bool
    	}{
    
    			name:   "uninitialised",
    
    			fields: fields{&Gnmi{}},
    			args: args{
    				params: nil,
    			},
    
    			fields:  fields{transport: &transport},
    
    			args:    args{},
    			want:    getResponse,
    
    			fields: fields{transport: &transport},
    
    			args: args{
    				runEndpoint: true,
    			},
    
    			wantErr: false,
    		},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			if tt.args.runEndpoint {
    				startGnmiTarget <- tt.fields.transport.config.Addr
    			}
    
    			got, err := tt.fields.transport.Get(context.Background(), tt.args.params...)
    
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("Get() got = %v, want %v", got, tt.want)
    			}
    
    			if tt.args.runEndpoint {
    				stopGnmiTarget <- true
    			}
    		})
    
    	}
    }
    
    func TestGnmi_GetConfig(t *testing.T) {
    
    	transport := mockTransport()
    
    	type fields struct {
    
    		transport *Gnmi
    
    	}
    	tests := []struct {
    		name   string
    		fields fields
    		want   *gnmi.Config
    	}{
    
    			fields: fields{transport: &transport},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			if got := tt.fields.transport.GetConfig(); !reflect.DeepEqual(got, tt.want) {
    
    				t.Errorf("GetConfig() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    func TestGnmi_ProcessResponse(t *testing.T) {
    	type fields struct {
    
    		Sbi SouthboundInterface
    
    	}
    	type args struct {
    
    		root interface{}
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		wantErr bool
    	}{
    
    			name:   "Arista Full Node",
    
    			fields: fields{Sbi: &Arista{}},
    
    				path: "../test/resp-full-node",
    
    				root: &arista.Device{},
    			},
    			wantErr: false,
    		},
    		{
    
    			name:   "Arista Interfaces Wildcard",
    
    			fields: fields{Sbi: &Arista{}},
    
    				path: "../test/resp-interfaces-wildcard",
    
    				root: &arista.Device{},
    			},
    			wantErr: false,
    		},
    		{
    
    			name:   "OC Full Node",
    
    			fields: fields{Sbi: &OpenConfig{}},
    			args: args{
    
    				path: "../test/resp-full-node",
    
    				root: &openconfig.Device{},
    			},
    			wantErr: false,
    		},
    		{
    
    			name:   "OC Interfaces Wildcard",
    
    			fields: fields{Sbi: &OpenConfig{}},
    			args: args{
    
    				path: "../test/resp-interfaces-wildcard",
    
    				root: &openconfig.Device{},
    			},
    			wantErr: false,
    		},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			g := &Gnmi{
    
    				SetNode: tt.fields.Sbi.SetNode(),
    
    			s := tt.fields.Sbi.Schema()
    			resp := &gpb.GetResponse{}
    			if err := util.Read(tt.args.path, resp); err != nil {
    				t.Errorf("error reading file %v,", err)
    			}
    			if err := g.ProcessResponse(resp, tt.args.root, s); (err != nil) != tt.wantErr {
    
    				t.Errorf("ProcessResponse() error = %v, wantErr %v", err, tt.wantErr)
    			}
    		})
    	}
    }
    
    func TestGnmi_Set(t *testing.T) {
    	type fields struct {
    
    		transport *Gnmi
    
    	}
    	type args struct {
    
    		runEndpoint bool
    
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    interface{}
    		wantErr bool
    	}{
    
    		{
    			name:   "uninitialised",
    			fields: fields{&Gnmi{}},
    			args: args{
    				params: nil,
    			},
    			want:    nil,
    			wantErr: true,
    		},
    		// TODO: Positive test cases
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			got, err := tt.fields.transport.Set(context.Background(), tt.args.params...)
    
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("Set() got = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    func TestGnmi_SetConfig(t *testing.T) {
    	type fields struct {
    		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
    		RespChan chan *gpb.SubscribeResponse
    		config   *gnmi.Config
    	}
    	type args struct {
    		config *gnmi.Config
    	}
    	tests := []struct {
    		name   string
    		fields fields
    		args   args
    	}{
    		// TODO: Add test cases.
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    		})
    	}
    }
    
    func TestGnmi_Subscribe(t *testing.T) {
    	type fields struct {
    		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
    		RespChan chan *gpb.SubscribeResponse
    		config   *gnmi.Config
    	}
    	type args struct {
    		ctx    context.Context
    		params []string
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		wantErr bool
    	}{
    		// TODO: Add test cases.
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			g := &Gnmi{
    				SetNode:  tt.fields.SetNode,
    				RespChan: tt.fields.RespChan,
    				config:   tt.fields.config,
    			}
    			if err := g.Subscribe(tt.args.ctx, tt.args.params...); (err != nil) != tt.wantErr {
    				t.Errorf("Subscribe() error = %v, wantErr %v", err, tt.wantErr)
    			}
    		})
    	}
    }
    
    func TestGnmi_Type(t *testing.T) {
    	type fields struct {
    		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
    		RespChan chan *gpb.SubscribeResponse
    		config   *gnmi.Config
    	}
    	tests := []struct {
    		name   string
    		fields fields
    		want   string
    	}{
    
    		{name: "dummy", fields: fields{}, want: "gnmi"},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			g := &Gnmi{
    				SetNode:  tt.fields.SetNode,
    				RespChan: tt.fields.RespChan,
    				config:   tt.fields.config,
    			}
    			if got := g.Type(); got != tt.want {
    				t.Errorf("Type() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    func TestGnmi_get(t *testing.T) {
    
    	// TODO: Design integration test for this one
    }
    
    func TestGnmi_getWithRequest(t *testing.T) {
    
    	transport := mockTransport()
    
    	reqFullNode := &gpb.GetRequest{}
    	reqInterfacesWildcard := &gpb.GetRequest{}
    	respFullNode := &gpb.GetResponse{}
    	respInterfacesWildcard := &gpb.GetResponse{}
    	respInterfacesWildcardExp := &gpb.GetResponse{}
    	respFullNodeExp := &gpb.GetResponse{}
    
    	if err := util.Read("../test/req-full-node", reqFullNode); err != nil {
    
    		t.Errorf("error parsing req-full-node: %v", err)
    
    	if err := util.Read("../test/req-interfaces-wildcard", reqInterfacesWildcard); err != nil {
    
    		t.Errorf("error parsing req-interfaces-wildcard: %v", err)
    
    	if err := util.Read("../test/resp-full-node", respFullNode); err != nil {
    
    		t.Errorf("error parsing getFullNode: %v", err)
    
    	if err := util.Read("../test/resp-full-node", respFullNodeExp); err != nil {
    
    		t.Errorf("error parsing getFullNode: %v", err)
    	}
    
    	if err := util.Read("../test/resp-interfaces-wildcard", respInterfacesWildcard); err != nil {
    
    		t.Errorf("error parsing getFullNode: %v", err)
    	}
    
    	if err := util.Read("../test/resp-interfaces-wildcard", respInterfacesWildcardExp); err != nil {
    
    		t.Errorf("error parsing getFullNode: %v", err)
    
    	transport.client.(*mocks.GNMIClient).
    		On("Get", mockContext, reqFullNode).
    		Return(respFullNode, nil)
    
    	transport.client.(*mocks.GNMIClient).
    		On("Get", mockContext, reqInterfacesWildcard).
    		Return(respInterfacesWildcard, nil)
    
    
    	type fields struct {
    
    		transport *Gnmi
    
    	}
    	type args struct {
    
    		request     *gpb.GetRequest
    
    		runEndpoint bool
    
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    interface{}
    		wantErr bool
    	}{
    
    			name:   "getFullNode",
    
    			fields: fields{transport: &transport},
    
    				request: reqFullNode,
    
    			want:    respFullNodeExp,
    
    			name:   "getInterfacesWildcard",
    
    			fields: fields{transport: &transport},
    
    			args: args{
    				request: reqInterfacesWildcard,
    			},
    
    			want:    respInterfacesWildcardExp,
    
    			wantErr: false,
    		},
    
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			got, err := tt.fields.transport.getWithRequest(context.Background(), tt.args.request)
    
    			if (err != nil) != tt.wantErr {
    				t.Errorf("getWithRequest() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("getWithRequest() got = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    func TestGnmi_set(t *testing.T) {
    
    	// Does not test well
    
    }
    
    func TestGnmi_subscribe(t *testing.T) {
    
    	// TODO: Design integration test for this one
    
    }
    
    func Test_extractModelKey(t *testing.T) {
    	type args struct {
    		path *gpb.Path
    	}
    	tests := []struct {
    		name string
    		args args
    		want string
    	}{
    		// TODO: Add test cases.
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			if got := extractModelKey(tt.args.path); got != tt.want {
    				t.Errorf("extractModelKey() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    func Test_gnmiFullPath(t *testing.T) {
    	type args struct {
    		prefix *gpb.Path
    		path   *gpb.Path
    	}
    	tests := []struct {
    		name    string
    		args    args
    		want    *gpb.Path
    		wantErr bool
    	}{
    		// TODO: Add test cases.
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			got, err := gnmiFullPath(tt.args.prefix, tt.args.path)
    			if (err != nil) != tt.wantErr {
    				t.Errorf("gnmiFullPath() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("gnmiFullPath() got = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }