blob: c82216fc978debc7b89f94fd5a5fd4f939c3a7be [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// reflect_invoker_internal_test uses internals of reflect_invoker (and hence is in the rpc package),
// whereas reflect_invoker_test is it the rpc_test package.
package rpc
import (
"errors"
"fmt"
"strings"
"testing"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/vdl"
"v.io/v23/verror"
)
// test tags.
var (
tagAlpha = vdl.StringValue(nil, "alpha")
tagBeta = vdl.StringValue(nil, "beta")
tagGamma = vdl.StringValue(nil, "gamma")
tagDelta = vdl.StringValue(nil, "delta")
tagEpsilon = vdl.StringValue(nil, "epsilon")
)
var errApp = errors.New("app error")
type notags struct{}
func (o *notags) Method1(*context.T, ServerCall) error { return nil }
func (o *notags) Method2(*context.T, ServerCall) (int, error) { return 0, nil }
func (o *notags) Method3(*context.T, ServerCall, int) error { return nil }
func (o *notags) Method4(*context.T, ServerCall, int) (int, error) { return 0, nil }
func (o *notags) Error(*context.T, ServerCall) error { return errApp }
type tags struct{}
func (o *tags) Alpha(*context.T, ServerCall) error { return nil }
func (o *tags) Beta(*context.T, ServerCall) (int, error) { return 0, nil }
func (o *tags) Gamma(*context.T, ServerCall, int) error { return nil }
func (o *tags) Delta(*context.T, ServerCall, int) (int, error) { return 0, nil }
func (o *tags) Epsilon(*context.T, ServerCall, int, string) (int, string, error) { return 0, "", nil }
func (o *tags) Error(*context.T, ServerCall) error { return errApp }
func (o *tags) Describe__() []InterfaceDesc {
return []InterfaceDesc{{
Methods: []MethodDesc{
{Name: "Alpha", Tags: []*vdl.Value{tagAlpha}},
{Name: "Beta", Tags: []*vdl.Value{tagBeta}},
{Name: "Gamma", Tags: []*vdl.Value{tagGamma}},
{Name: "Delta", Tags: []*vdl.Value{tagDelta}},
{Name: "Epsilon", Tags: []*vdl.Value{tagEpsilon}},
},
}}
}
type (
badcall struct{}
noInitCall struct{ ServerCall }
badInit1Call struct{ ServerCall }
badInit2Call struct{ ServerCall }
badInit3Call struct{ ServerCall }
noSendRecvCall struct{ ServerCall }
badSend1Call struct{ ServerCall }
badSend2Call struct{ ServerCall }
badSend3Call struct{ ServerCall }
badRecv1Call struct{ ServerCall }
badRecv2Call struct{ ServerCall }
badRecv3Call struct{ ServerCall }
badoutargs struct{}
badGlobber struct{}
badGlob1 struct{}
badGlob2 struct{}
badGlob3 struct{}
badGlob4 struct{}
badGlob5 struct{}
badGlob6 struct{}
badGlob7 struct{}
badGlobChildren1 struct{}
badGlobChildren2 struct{}
badGlobChildren3 struct{}
badGlobChildren4 struct{}
badGlobChildren5 struct{}
badGlobChildren6 struct{}
)
func (badcall) notExported(*context.T, ServerCall) error { return nil }
func (badcall) NonRPC1() error { return nil }
func (badcall) NonRPC2(int) error { return nil }
func (badcall) NonRPC3(int, string) error { return nil }
func (badcall) NonRPC4(*badcall) error { return nil }
func (badcall) NonRPC5(context.T, *badcall) error { return nil }
func (badcall) NonRPC6(*context.T, *badcall) error { return nil }
func (badcall) NoInit(*context.T, *noInitCall) error { return nil }
func (badcall) BadInit1(*context.T, *badInit1Call) error { return nil }
func (badcall) BadInit2(*context.T, *badInit2Call) error { return nil }
func (badcall) BadInit3(*context.T, *badInit3Call) error { return nil }
func (badcall) NoSendRecv(*context.T, *noSendRecvCall) error { return nil }
func (badcall) BadSend1(*context.T, *badSend1Call) error { return nil }
func (badcall) BadSend2(*context.T, *badSend2Call) error { return nil }
func (badcall) BadSend3(*context.T, *badSend3Call) error { return nil }
func (badcall) BadRecv1(*context.T, *badRecv1Call) error { return nil }
func (badcall) BadRecv2(*context.T, *badRecv2Call) error { return nil }
func (badcall) BadRecv3(*context.T, *badRecv3Call) error { return nil }
func (*badInit1Call) Init() {}
func (*badInit2Call) Init(int) {}
func (*badInit3Call) Init(StreamServerCall, int) {}
func (*noSendRecvCall) Init(StreamServerCall) {}
func (*badSend1Call) Init(StreamServerCall) {}
func (*badSend1Call) SendStream() {}
func (*badSend2Call) Init(StreamServerCall) {}
func (*badSend2Call) SendStream() interface {
Send() error
} {
return nil
}
func (*badSend3Call) Init(StreamServerCall) {}
func (*badSend3Call) SendStream() interface {
Send(int)
} {
return nil
}
func (*badRecv1Call) Init(StreamServerCall) {}
func (*badRecv1Call) RecvStream() {}
func (*badRecv2Call) Init(StreamServerCall) {}
func (*badRecv2Call) RecvStream() interface {
Advance() bool
Value() int
} {
return nil
}
func (*badRecv3Call) Init(StreamServerCall) {}
func (*badRecv3Call) RecvStream() interface {
Advance()
Value() int
Error() error
} {
return nil
}
func (badoutargs) NoFinalError1(*context.T, ServerCall) {}
func (badoutargs) NoFinalError2(*context.T, ServerCall) string { return "" }
func (badoutargs) NoFinalError3(*context.T, ServerCall) (bool, string) { return false, "" }
func (badoutargs) NoFinalError4(*context.T, ServerCall) (error, string) { return nil, "" }
func (badGlobber) Globber() {}
func (badGlob1) Glob__() {}
func (badGlob2) Glob__(*context.T) {}
func (badGlob3) Glob__(*context.T, ServerCall) {}
func (badGlob4) Glob__(*context.T, ServerCall, string) {}
func (badGlob5) Glob__(*context.T, ServerCall, string) <-chan naming.GlobReply { return nil }
func (badGlob6) Glob__(*context.T, ServerCall, string) error { return nil }
func (badGlob7) Glob__() (<-chan naming.GlobReply, error) { return nil, nil }
func (badGlobChildren1) GlobChildren__() {}
func (badGlobChildren2) GlobChildren__(*context.T) {}
func (badGlobChildren3) GlobChildren__(*context.T, ServerCall) {}
func (badGlobChildren4) GlobChildren__(*context.T, ServerCall) <-chan string { return nil }
func (badGlobChildren5) GlobChildren__(*context.T, ServerCall) error { return nil }
func (badGlobChildren6) GlobChildren__() (<-chan string, error) { return nil, nil }
const (
badInit = `Init must have signature`
badSend = `SendStream must have signature`
badRecv = `RecvStream must have signature`
)
func TestTypeCheckMethods(t *testing.T) {
type testcase struct {
obj interface{}
want map[string]string
}
tests := []testcase{
{struct{}{}, nil},
{&notags{}, map[string]string{
"Method1": "",
"Method2": "",
"Method3": "",
"Method4": "",
"Error": "",
}},
{&tags{}, map[string]string{
"Alpha": "",
"Beta": "",
"Gamma": "",
"Delta": "",
"Epsilon": "",
"Error": "",
"Describe__": verror.New(verror.ErrInternal, nil, verror.New(errReservedMethod, nil)).Error(),
}},
{badcall{}, map[string]string{
"notExported": verror.New(verror.ErrBadArg, nil, verror.New(errMethodNotExported, nil)).Error(),
"NonRPC1": verror.New(errNonRPCMethod, nil).Error(),
"NonRPC2": verror.New(errNonRPCMethod, nil).Error(),
"NonRPC3": verror.New(errNonRPCMethod, nil).Error(),
"NonRPC4": verror.New(errNonRPCMethod, nil).Error(),
"NonRPC5": verror.New(errNonRPCMethod, nil).Error(),
"NonRPC6": verror.New(errNonRPCMethod, nil).Error(),
"NoInit": "must have Init method",
"BadInit1": badInit,
"BadInit2": badInit,
"BadInit3": badInit,
"NoSendRecv": "must have at least one of RecvStream or SendStream",
"BadSend1": badSend,
"BadSend2": badSend,
"BadSend3": badSend,
"BadRecv1": badRecv,
"BadRecv2": badRecv,
"BadRecv3": badRecv,
}},
{badoutargs{}, map[string]string{
"NoFinalError1": verror.New(verror.ErrAborted, nil, verror.New(errNoFinalErrorOutArg, nil)).Error(),
"NoFinalError2": verror.New(verror.ErrAborted, nil, verror.New(errNoFinalErrorOutArg, nil)).Error(),
"NoFinalError3": verror.New(verror.ErrAborted, nil, verror.New(errNoFinalErrorOutArg, nil)).Error(),
"NoFinalError4": verror.New(verror.ErrAborted, nil, verror.New(errNoFinalErrorOutArg, nil)).Error(),
}},
{badGlobber{}, map[string]string{
"Globber": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobber, nil)).Error(),
}},
{badGlob1{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob2{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob3{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob4{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob5{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob6{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlob7{}, map[string]string{
"Glob__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlob, nil)).Error(),
}},
{badGlobChildren1{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
{badGlobChildren2{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
{badGlobChildren3{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
{badGlobChildren4{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
{badGlobChildren5{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
{badGlobChildren6{}, map[string]string{
"GlobChildren__": verror.New(verror.ErrAborted, nil, verror.New(errBadGlobChildren, nil)).Error(),
}},
}
for _, test := range tests {
typecheck := TypeCheckMethods(test.obj)
if got, want := typecheck, test.want; (got == nil) != (want == nil) {
t.Errorf("TypeCheckMethods(%T) got %v, want %v", test.obj, got, want)
}
if got, want := len(typecheck), len(test.want); got != want {
t.Errorf("TypeCheckMethods(%T) got len %d, want %d (got %q, want %q)", test.obj, got, want, typecheck, test.want)
}
for wantKey, wantVal := range test.want {
gotVal, ok := typecheck[wantKey]
if !ok {
t.Errorf("TypeCheckMethods(%T) got %v, want key %q", test.obj, typecheck, wantKey)
}
if wantVal == "" && gotVal != nil {
t.Errorf("TypeCheckMethods(%T) got method %q %q, want %q", test.obj, wantKey, gotVal, wantVal)
}
if got, want := fmt.Sprint(gotVal), wantVal; !strings.Contains(got, want) {
t.Errorf("TypeCheckMethods(%T) got method %q %q, want substr %q", test.obj, wantKey, got, want)
}
}
}
}