blob: 0e6615bff597763407e9a517a94065832f9c3bc2 [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.
package server
import (
"fmt"
"reflect"
"testing"
"v.io/v23/context"
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/v23/vdl"
"v.io/v23/vdlroot/signature"
"v.io/v23/verror"
"v.io/x/ref/services/wspr/internal/lib"
"v.io/x/ref/services/wspr/internal/lib/testwriter"
)
type mockFlowFactory struct {
writer testwriter.Writer
}
func (m *mockFlowFactory) createFlow() *Flow {
return &Flow{ID: 0, Writer: &m.writer}
}
func (*mockFlowFactory) cleanupFlow(int32) {}
type mockInvoker struct {
handle int32
sig []signature.Interface
hasGlobber bool
}
func (m mockInvoker) Prepare(string, int) ([]interface{}, []*vdl.Value, error) {
return nil, nil, nil
}
func (mockInvoker) Invoke(*context.T, rpc.StreamServerCall, string, []interface{}) ([]interface{}, error) {
return nil, nil
}
func (mockInvoker) Globber() *rpc.GlobState {
return nil
}
func (m mockInvoker) Signature(ctx *context.T, call rpc.ServerCall) ([]signature.Interface, error) {
return m.sig, nil
}
func (m mockInvoker) MethodSignature(ctx *context.T, call rpc.ServerCall, methodName string) (signature.Method, error) {
method, found := m.sig[0].FindMethod(methodName)
if !found {
return signature.Method{}, fmt.Errorf("Method %q not found", methodName)
}
return method, nil
}
type mockInvokerFactory struct{}
func (mockInvokerFactory) createInvoker(handle int32, sig []signature.Interface, hasGlobber bool) (rpc.Invoker, error) {
return &mockInvoker{handle: handle, sig: sig, hasGlobber: hasGlobber}, nil
}
type mockAuthorizer struct {
handle int32
hasAuthorizer bool
}
func (mockAuthorizer) Authorize(*context.T, security.Call) error { return nil }
type mockAuthorizerFactory struct{}
func (mockAuthorizerFactory) createAuthorizer(handle int32, hasAuthorizer bool) (security.Authorizer, error) {
return mockAuthorizer{handle: handle, hasAuthorizer: hasAuthorizer}, nil
}
func TestSuccessfulLookup(t *testing.T) {
flowFactory := &mockFlowFactory{}
d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{})
expectedSig := []signature.Interface{
{Name: "AName"},
}
go func() {
if err := flowFactory.writer.WaitForMessage(1); err != nil {
t.Errorf("failed to get dispatch request %v", err)
t.Fail()
}
reply := LookupReply{
Handle: 1,
HasAuthorizer: false,
Signature: expectedSig,
}
d.handleLookupResponse(0, lib.HexVomEncodeOrDie(reply, nil))
}()
invoker, auth, err := d.Lookup("a/b")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig}
if !reflect.DeepEqual(invoker, expectedInvoker) {
t.Errorf("wrong invoker returned, expected: %#v, got :%#v", expectedInvoker, invoker)
}
expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: false}
if !reflect.DeepEqual(auth, expectedAuth) {
t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
}
expectedResponses := []lib.Response{
{
Type: lib.ResponseDispatcherLookup,
Message: map[string]interface{}{
"serverId": 0.0,
"suffix": "a/b",
},
},
}
if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil, nil); err != nil {
t.Error(err)
}
}
func TestSuccessfulLookupWithAuthorizer(t *testing.T) {
flowFactory := &mockFlowFactory{}
d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{})
expectedSig := []signature.Interface{
{Name: "AName"},
}
go func() {
if err := flowFactory.writer.WaitForMessage(1); err != nil {
t.Errorf("failed to get dispatch request %v", err)
t.Fail()
}
reply := LookupReply{
Handle: 1,
HasAuthorizer: true,
Signature: expectedSig,
}
d.handleLookupResponse(0, lib.HexVomEncodeOrDie(reply, nil))
}()
invoker, auth, err := d.Lookup("a/b")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig}
if !reflect.DeepEqual(invoker, expectedInvoker) {
t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
}
expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: true}
if !reflect.DeepEqual(auth, expectedAuth) {
t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
}
expectedResponses := []lib.Response{
{
Type: lib.ResponseDispatcherLookup,
Message: map[string]interface{}{
"serverId": 0.0,
"suffix": "a/b",
},
},
}
if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil, nil); err != nil {
t.Error(err)
}
}
func TestFailedLookup(t *testing.T) {
flowFactory := &mockFlowFactory{}
d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{})
go func() {
if err := flowFactory.writer.WaitForMessage(1); err != nil {
t.Errorf("failed to get dispatch request %v", err)
t.Fail()
}
reply := LookupReply{
Err: verror.New(verror.ErrNoExist, nil),
}
d.handleLookupResponse(0, lib.HexVomEncodeOrDie(reply, nil))
}()
_, _, err := d.Lookup("a/b")
if err == nil {
t.Error("expected error, but got none")
}
expectedResponses := []lib.Response{
{
Type: lib.ResponseDispatcherLookup,
Message: map[string]interface{}{
"serverId": 0.0,
"suffix": "a/b",
},
},
}
if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil, nil); err != nil {
t.Error(err)
}
}