Skip to content
Snippets Groups Projects
nucleusIntegration_test.go 10.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • package integration
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    import (
    	"context"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"reflect"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"testing"
    	"time"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    	spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound"
    	tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport"
    
    	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
    	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
    
    	"code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/cocsn/gosdn/nucleus/types"
    
    	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	gpb "github.com/openconfig/gnmi/proto/gnmi"
    
    	log "github.com/sirupsen/logrus"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pb "google.golang.org/protobuf/proto"
    
    const unreachable = "203.0.113.10:6030"
    const testPath = "/system/config/hostname"
    
    
    var testAddress = "141.100.70.170:6030"
    
    var testUsername = "admin"
    var testPassword = "arista"
    var opt *tpb.TransportOption
    
    var gnmiMessages map[string]pb.Message
    
    func TestMain(m *testing.M) {
    	testSetupIntegration()
    	os.Exit(m.Run())
    }
    
    func testSetupIntegration() {
    	if os.Getenv("GOSDN_LOG") == "nolog" {
    		log.SetLevel(log.PanicLevel)
    	}
    
    
    	addr := os.Getenv("GOSDN_TEST_ENDPOINT")
    	if addr != "" {
    		testAddress = addr
    		log.Infof("GOSDN_TEST_ENDPOINT set to %v", testAddress)
    
    	}
    	u := os.Getenv("GOSDN_TEST_USER")
    	if u != "" {
    		testUsername = u
    		log.Infof("GOSDN_TEST_USER set to %v", testUsername)
    	}
    	p := os.Getenv("GOSDN_TEST_PASSWORD")
    	if p != "" {
    		testPassword = p
    		log.Infof("GOSDN_TEST_PASSWORD set to %v", testPassword)
    	}
    
    	gnmiMessages = map[string]pb.Message{
    		"../proto/cap-resp-arista-ceos":                  &gpb.CapabilityResponse{},
    		"../proto/req-full-node":                         &gpb.GetRequest{},
    		"../proto/req-full-node-arista-ceos":             &gpb.GetRequest{},
    		"../proto/req-interfaces-arista-ceos":            &gpb.GetRequest{},
    		"../proto/req-interfaces-interface-arista-ceos":  &gpb.GetRequest{},
    		"../proto/req-interfaces-wildcard":               &gpb.GetRequest{},
    		"../proto/resp-full-node":                        &gpb.GetResponse{},
    		"../proto/resp-full-node-arista-ceos":            &gpb.GetResponse{},
    		"../proto/resp-interfaces-arista-ceos":           &gpb.GetResponse{},
    		"../proto/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{},
    		"../proto/resp-interfaces-wildcard":              &gpb.GetResponse{},
    		"../proto/resp-set-system-config-hostname":       &gpb.SetResponse{},
    	}
    	for k, v := range gnmiMessages {
    		if err := proto.Read(k, v); err != nil {
    			log.Fatalf("error parsing %v: %v", k, err)
    		}
    	}
    
    	opt = &tpb.TransportOption{
    		Address:  testAddress,
    		Username: testUsername,
    		Password: testPassword,
    		TransportOption: &tpb.TransportOption_GnmiTransportOption{
    			GnmiTransportOption: &tpb.GnmiTransportOption{},
    		},
    	}
    }
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func TestGnmi_SetIntegration(t *testing.T) {
    	if testing.Short() {
    		t.Skip("skipping integration test")
    	}
    	type fields struct {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		opt *tpb.TransportOption
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	type args struct {
    		ctx    context.Context
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		params []string
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		wantErr bool
    	}{
    		{
    			name: "destination unreachable",
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			fields: fields{
    				opt: &tpb.TransportOption{
    					Address: "203.0.113.10:6030",
    
    					TransportOption: &tpb.TransportOption_GnmiTransportOption{
    						GnmiTransportOption: &tpb.GnmiTransportOption{}},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    
    			args: args{
    				ctx:    context.Background(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				params: []string{"/system/config/hostname", "ceos3000"},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    			wantErr: true,
    		},
    		{
    
    			name:   "valid update",
    			fields: fields{opt: opt},
    			args: args{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				ctx:    context.Background(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				params: []string{"/system/config/hostname", "ceos3000"},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			wantErr: false,
    		},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		{
    			name:   "invalid update",
    			fields: fields{opt: opt},
    			args: args{
    				ctx:    context.Background(),
    				params: nil,
    			},
    			wantErr: true,
    		},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			g, err := nucleus.NewTransport(tt.fields.opt, nucleus.NewSBI(spb.Type_OPENCONFIG))
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if err != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
    				return
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			err = g.Set(tt.args.ctx, tt.args.params)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    		})
    	}
    }
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func TestGnmi_GetIntegration(t *testing.T) {
    	if testing.Short() {
    		t.Skip("skipping integration test")
    	}
    
    
    	paths := []string{
    		"/interfaces/interface",
    		"system/config/hostname",
    	}
    	type fields struct {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		opt *tpb.TransportOption
    
    	}
    	type args struct {
    		ctx    context.Context
    		params []string
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    interface{}
    		wantErr bool
    	}{
    		{
    			name:   "default",
    			fields: fields{opt: opt},
    			args: args{
    				ctx:    context.Background(),
    				params: paths[:1],
    			},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			want:    gnmiMessages["../proto/resp-interfaces-arista-ceos"],
    
    			wantErr: false,
    		},
    		{
    			name: "destination unreachable",
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			fields: fields{
    				opt: &tpb.TransportOption{
    					Address: "203.0.113.10:6030",
    
    					TransportOption: &tpb.TransportOption_GnmiTransportOption{
    						GnmiTransportOption: &tpb.GnmiTransportOption{}},
    
    				},
    			},
    			args: args{
    				ctx:    context.Background(),
    				params: paths,
    			},
    			want:    nil,
    			wantErr: true,
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			g, err := nucleus.NewTransport(tt.fields.opt, nucleus.NewSBI(spb.Type_OPENCONFIG))
    
    			if err != nil {
    				t.Error(err)
    				return
    			}
    			got, err := g.Get(tt.args.ctx, tt.args.params...)
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
    
    				t.Errorf("Get() got = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    func TestGnmi_SubscribeIntegration(t *testing.T) {
    	if testing.Short() {
    		t.Skip("skipping integration test")
    	}
    
    
    	type fields struct {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		opt *tpb.TransportOption
    
    	}
    	type args struct {
    		ctx  context.Context
    		opts *gnmi.SubscribeOptions
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		wantErr bool
    	}{
    		{
    			name: "default",
    			fields: fields{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				opt: &tpb.TransportOption{
    
    					Address:  testAddress,
    					Username: testUsername,
    					Password: testPassword,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    					Tls:      false,
    					TransportOption: &tpb.TransportOption_GnmiTransportOption{
    						GnmiTransportOption: &tpb.GnmiTransportOption{
    							Compression:     "",
    							GrpcDialOptions: nil,
    							Token:           "",
    							Encoding:        0,
    						},
    					},
    
    				},
    			},
    			args: args{
    				ctx: context.Background(),
    				opts: &gnmi.SubscribeOptions{
    					Mode:              "stream",
    					StreamMode:        "sample",
    					SampleInterval:    uint64(1 * time.Second),
    					HeartbeatInterval: uint64(100 * time.Millisecond),
    					Paths: gnmi.SplitPaths([]string{
    						"/interfaces/interface/name",
    						"/system/config/hostname",
    					}),
    
    					Target: testAddress,
    
    				},
    			},
    			wantErr: false,
    		},
    		{
    			name: "wrong path",
    			fields: fields{
    
    				opt: &tpb.TransportOption{
    					TransportOption: &tpb.TransportOption_GnmiTransportOption{
    						GnmiTransportOption: &tpb.GnmiTransportOption{}},
    				},
    
    			},
    			args: args{
    				opts: &gnmi.SubscribeOptions{
    					Mode:              "stream",
    					StreamMode:        "sample",
    					SampleInterval:    uint64(1 * time.Second),
    					HeartbeatInterval: uint64(100 * time.Millisecond),
    					Paths: gnmi.SplitPaths([]string{
    						"interfaces/interface/name",
    						"ystem/config/hostname",
    					}),
    
    					Target: testAddress,
    
    				},
    			},
    			wantErr: true,
    		},
    		{
    			name: "destination unreachable",
    			fields: fields{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				opt: &tpb.TransportOption{
    					Address: "203.0.113.10:6030",
    
    					TransportOption: &tpb.TransportOption_GnmiTransportOption{
    						GnmiTransportOption: &tpb.GnmiTransportOption{}},
    
    				},
    			},
    			args: args{
    				opts: &gnmi.SubscribeOptions{},
    			},
    			wantErr: false,
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			var wantErr = tt.wantErr
    
    			g, err := nucleus.NewTransport(tt.fields.opt, nucleus.NewSBI(spb.Type_OPENCONFIG))
    
    			if err != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				t.Error(err)
    
    				return
    
    			ctx := context.WithValue(context.Background(), types.CtxKeyOpts, tt.args.opts) //nolint
    
    			ctx, cancel := context.WithCancel(ctx)
    			go func() {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				subErr := g.Subscribe(ctx)
    				if (subErr != nil) != wantErr {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    					if !wantErr && subErr != nil {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    						if subErr.Error() != "rpc error: code = Canceled desc = context canceled" {
    
    							t.Errorf("Subscribe() error = %v, wantErr %v", subErr, tt.wantErr)
    
    						}
    					}
    				}
    			}()
    			time.Sleep(time.Second * 3)
    			cancel()
    			time.Sleep(time.Second * 1)
    		})
    	}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    func TestGnmi_CapabilitiesIntegration(t *testing.T) {
    	if testing.Short() {
    		t.Skip("skipping integration test")
    	}
    	type fields struct {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		opt *tpb.TransportOption
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	type args struct {
    		ctx context.Context
    	}
    	tests := []struct {
    		name    string
    		fields  fields
    		args    args
    		want    interface{}
    		wantErr bool
    	}{
    		{
    			name:    "supported models",
    			fields:  fields{opt: opt},
    			args:    args{ctx: context.Background()},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			want:    gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedModels,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			wantErr: false,
    		},
    		{
    			name:    "supported encodings",
    			fields:  fields{opt: opt},
    			args:    args{ctx: context.Background()},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			want:    gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedEncodings,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			wantErr: false,
    		},
    		{
    			name:    "gnmi version",
    			fields:  fields{opt: opt},
    			args:    args{ctx: context.Background()},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			want:    gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).GNMIVersion,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			wantErr: false,
    		},
    		{
    			name: "destination unreachable",
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			fields: fields{opt: &tpb.TransportOption{
    				Address: "203.0.113.10:6030",
    
    				TransportOption: &tpb.TransportOption_GnmiTransportOption{
    					GnmiTransportOption: &tpb.GnmiTransportOption{}},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    			},
    			args:    args{ctx: context.Background()},
    			want:    nil,
    			wantErr: true,
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    
    			tr, err := nucleus.NewTransport(tt.fields.opt, nucleus.NewSBI(spb.Type_OPENCONFIG))
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if err != nil {
    				t.Error(err)
    				return
    			}
    
    			g, ok := tr.(*nucleus.Gnmi)
    			if !ok {
    				t.Error(&errors.ErrInvalidTypeAssertion{})
    			}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			resp, err := g.Capabilities(tt.args.ctx)
    			if (err != nil) != tt.wantErr {
    				t.Errorf("Capabilities() error = %v, wantErr %v", err, tt.wantErr)
    				return
    			}
    			var got interface{}
    			switch tt.name {
    			case "supported encodings":
    				got = resp.(*gpb.CapabilityResponse).SupportedEncodings
    			case "supported models":
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				t.Skip("test causes false negative")
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				got = resp.(*gpb.CapabilityResponse).SupportedModels
    
    				sort.Slice(got.([]*gpb.ModelData), func(i, j int) bool {
    					return got.([]*gpb.ModelData)[i].Name < got.([]*gpb.ModelData)[j].Name
    				})
    				sort.Slice(tt.want.([]*gpb.ModelData), func(i, j int) bool {
    					return tt.want.([]*gpb.ModelData)[i].Name < tt.want.([]*gpb.ModelData)[j].Name
    				})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			case "gnmi version":
    				got = resp.(*gpb.CapabilityResponse).GNMIVersion
    			default:
    			}
    			if !reflect.DeepEqual(got, tt.want) {
    				t.Errorf("Type() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }