Newer
Older
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"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
log "github.com/sirupsen/logrus"
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)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
}
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{},
},
}
}
func TestGnmi_SetIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
type fields struct {
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{
name: "destination unreachable",
fields: fields{
opt: &tpb.TransportOption{
Address: "203.0.113.10:6030",
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{}},
args: args{
ctx: context.Background(),
params: []string{"/system/config/hostname", "ceos3000"},
name: "valid update",
fields: fields{opt: opt},
args: args{
{
name: "invalid update",
fields: fields{opt: opt},
args: args{
ctx: context.Background(),
params: 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))
t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
return
if (err != nil) != tt.wantErr {
t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestGnmi_GetIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
paths := []string{
"/interfaces/interface",
"system/config/hostname",
}
type fields struct {
}
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],
},
want: gnmiMessages["../proto/resp-interfaces-arista-ceos"],
wantErr: false,
},
{
name: "destination unreachable",
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
}
if reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
t.Errorf("Get() got = %v, want %v", got, tt.want)
}
})
}
}
func TestGnmi_SubscribeIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
}
type args struct {
ctx context.Context
opts *gnmi.SubscribeOptions
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{
name: "default",
fields: fields{
Address: testAddress,
Username: testUsername,
Password: testPassword,
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",
}),
},
},
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",
}),
},
},
wantErr: true,
},
{
name: "destination unreachable",
fields: fields{
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) {
g, err := nucleus.NewTransport(tt.fields.opt, nucleus.NewSBI(spb.Type_OPENCONFIG))
ctx := context.WithValue(context.Background(), types.CtxKeyOpts, tt.args.opts) //nolint
ctx, cancel := context.WithCancel(ctx)
go func() {
subErr := g.Subscribe(ctx)
if (subErr != nil) != wantErr {
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)
})
}
}
func TestGnmi_CapabilitiesIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
type fields struct {
}
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()},
want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedModels,
wantErr: false,
},
{
name: "supported encodings",
fields: fields{opt: opt},
args: args{ctx: context.Background()},
want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedEncodings,
wantErr: false,
},
{
name: "gnmi version",
fields: fields{opt: opt},
args: args{ctx: context.Background()},
want: gnmiMessages["../proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).GNMIVersion,
wantErr: false,
},
{
name: "destination unreachable",
fields: fields{opt: &tpb.TransportOption{
Address: "203.0.113.10:6030",
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{}},
},
},
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))
if err != nil {
t.Error(err)
return
}
g, ok := tr.(*nucleus.Gnmi)
if !ok {
t.Error(&errors.ErrInvalidTypeAssertion{})
}
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":
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
})