blob: 67494662e95933b5229bd01b82bf3dedb2dd786c [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 test
import (
"fmt"
"reflect"
"strings"
"sync"
"testing"
"time"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/security"
"v.io/v23/uniqueid"
"v.io/v23/vdl"
"v.io/v23/verror"
"v.io/x/ref/lib/security/bcrypter"
"v.io/x/ref/test/testutil"
)
var errMethod = verror.New(verror.ErrAborted, nil)
var fakeTimeCaveat = security.CaveatDescriptor{
Id: uniqueid.Id{0x18, 0xba, 0x6f, 0x84, 0xd5, 0xec, 0xdb, 0x9b, 0xf2, 0x32, 0x19, 0x5b, 0x53, 0x92, 0x80, 0x0},
ParamType: vdl.TypeOf(int64(0)),
}
func init() {
security.RegisterCaveatValidator(fakeTimeCaveat, func(_ *context.T, _ security.Call, t int64) error {
if now := clock.Now(); now > t {
return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, t)
}
return nil
})
}
var clock = new(fakeClock)
type fakeClock struct {
sync.Mutex
time int64
}
func (c *fakeClock) Now() int64 {
c.Lock()
defer c.Unlock()
return c.time
}
func (c *fakeClock) Advance(steps uint) {
c.Lock()
c.time += int64(steps)
c.Unlock()
}
// singleBlessingStore implements security.BlessingStore. It is a
// BlessingStore that marks the last blessing that was set on it as
// shareable with any peer. It does not care about the public key that
// blessing being set is bound to.
type singleBlessingStore struct {
pk security.PublicKey
b security.Blessings
def security.Blessings
}
func (s *singleBlessingStore) Set(b security.Blessings, _ security.BlessingPattern) (security.Blessings, error) {
s.b = b
return security.Blessings{}, nil
}
func (s *singleBlessingStore) ForPeer(...string) security.Blessings {
return s.b
}
func (s *singleBlessingStore) SetDefault(b security.Blessings) error {
s.def = b
return nil
}
func (s *singleBlessingStore) Default() (security.Blessings, <-chan struct{}) {
return s.def, nil
}
func (s *singleBlessingStore) PublicKey() security.PublicKey {
return s.pk // This may be inconsistent with s.b & s.def, by design, for tests.
}
func (*singleBlessingStore) DebugString() string {
return ""
}
func (*singleBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
return nil
}
func (*singleBlessingStore) CacheDischarge(security.Discharge, security.Caveat, security.DischargeImpetus) {
return
}
func (*singleBlessingStore) ClearDischarges(...security.Discharge) {
return
}
func (*singleBlessingStore) Discharge(security.Caveat, security.DischargeImpetus) (security.Discharge, time.Time) {
return security.Discharge{}, time.Time{}
}
func extractKey(t *testing.T, rootCtx *context.T, root *bcrypter.Root, blessing string) *bcrypter.PrivateKey {
key, err := root.Extract(rootCtx, blessing)
if err != nil {
t.Fatal(err)
}
return key
}
func withPrincipal(t *testing.T, ctx *context.T, name string, caveats ...security.Caveat) *context.T {
idp := testutil.IDProviderFromPrincipal(v23.GetPrincipal(ctx))
p := testutil.NewPrincipal()
if err := idp.Bless(p, name, caveats...); err != nil {
t.Fatal(err)
}
ctx, err := v23.WithPrincipal(ctx, p)
if err != nil {
t.Fatal(err)
}
return ctx
}
func bless(t *testing.T, pctx, whoctx *context.T, extension string, cavs ...security.Caveat) security.Blessings {
idp := testutil.IDProviderFromPrincipal(v23.GetPrincipal(pctx))
b, err := idp.NewBlessings(v23.GetPrincipal(whoctx), extension, cavs...)
if err != nil {
t.Fatal(err)
}
return b
}
func mkCaveat(cav security.Caveat, err error) security.Caveat {
if err != nil {
panic(err)
}
return cav
}
func mkThirdPartyCaveat(discharger security.PublicKey, location string, c security.Caveat) security.Caveat {
tpc, err := security.NewPublicKeyCaveat(discharger, location, security.ThirdPartyRequirements{}, c)
if err != nil {
panic(err)
}
return tpc
}
func matchesErrorPattern(err error, id verror.IDAction, pattern string) bool {
if len(pattern) > 0 && err != nil && strings.Index(err.Error(), pattern) < 0 {
return false
}
if err == nil && id.ID == "" {
return true
}
return verror.ErrorID(err) == id.ID
}
func waitForNames(t *testing.T, ctx *context.T, exist bool, names ...string) {
for _, n := range names {
for {
me, err := v23.GetNamespace(ctx).Resolve(ctx, n)
if err == nil && exist && len(me.Names()) > 0 {
break
}
if (err != nil && !exist) || (err == nil && len(me.Names()) == 0) {
break
}
ctx.Infof("Still waiting for %v, %v: %#v, %v", exist, n, me, err)
time.Sleep(10 * time.Millisecond)
}
}
}
func makeResultPtrs(ins []interface{}) []interface{} {
outs := make([]interface{}, len(ins))
for ix, in := range ins {
typ := reflect.TypeOf(in)
if typ == nil {
// Nil indicates interface{}.
var empty interface{}
typ = reflect.ValueOf(&empty).Elem().Type()
}
outs[ix] = reflect.New(typ).Interface()
}
return outs
}
func checkResultPtrs(t *testing.T, name string, gotptrs, want []interface{}) {
for ix, res := range gotptrs {
got := reflect.ValueOf(res).Elem().Interface()
want := want[ix]
switch g := got.(type) {
case verror.E:
w, ok := want.(verror.E)
// don't use reflect deep equal on verror's since they contain
// a list of stack PCs which will be different.
if !ok {
t.Errorf("%s result %d got type %T, want %T", name, ix, g, w)
}
if verror.ErrorID(g) != w.ID {
t.Errorf("%s result %d got %v, want %v", name, ix, g, w)
}
default:
if !reflect.DeepEqual(got, want) {
t.Errorf("%s result %d got %v, want %v", name, ix, got, want)
}
}
}
}