blob: 7b67b1bcd9e008c5b9b67911237658445287770b [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 rpc
import (
"testing"
"time"
"v.io/v23/security"
"v.io/v23/vdl"
"v.io/x/ref/test/testutil"
)
func TestDischargeClientCache(t *testing.T) {
dcc := &dischargeCache{
cache: make(map[dischargeCacheKey]security.Discharge),
idToKeys: make(map[string][]dischargeCacheKey),
}
var (
discharger = testutil.NewPrincipal("discharger")
expiredCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
argsCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
methodCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
serverCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
dExpired = mkDischarge(discharger.MintDischarge(expiredCav, mkCaveat(security.NewExpiryCaveat(time.Now().Add(-1*time.Minute)))))
dArgs = mkDischarge(discharger.MintDischarge(argsCav, security.UnconstrainedUse()))
dMethod = mkDischarge(discharger.MintDischarge(methodCav, security.UnconstrainedUse()))
dServer = mkDischarge(discharger.MintDischarge(serverCav, security.UnconstrainedUse()))
emptyImp = security.DischargeImpetus{}
argsImp = security.DischargeImpetus{Arguments: []*vdl.Value{&vdl.Value{}}}
methodImp = security.DischargeImpetus{Method: "foo"}
otherMethodImp = security.DischargeImpetus{Method: "bar"}
serverImp = security.DischargeImpetus{Server: []security.BlessingPattern{security.BlessingPattern("fooserver")}}
otherServerImp = security.DischargeImpetus{Server: []security.BlessingPattern{security.BlessingPattern("barserver")}}
)
// Discharges for different cavs should not be cached.
d := mkDischarge(discharger.MintDischarge(argsCav, security.UnconstrainedUse()))
dcc.Add(d, emptyImp)
outdis := make([]*security.Discharge, 1)
if remaining := dcc.Discharges([]security.Caveat{methodCav}, []security.DischargeImpetus{emptyImp}, outdis); remaining == 0 {
t.Errorf("Discharge for different caveat should not have been in cache")
}
dcc.invalidate(d)
// Add some discharges into the cache.
dcc.Add(dArgs, argsImp)
dcc.Add(dMethod, methodImp)
dcc.Add(dServer, serverImp)
dcc.Add(dExpired, emptyImp)
testCases := []struct {
caveat security.Caveat // caveat that we are fetching discharges for.
queryImpetus security.DischargeImpetus // Impetus used to query the cache.
cachedDischarge *security.Discharge // Discharge that we expect to be returned from the cache, nil if the discharge should not be cached.
}{
// Expired discharges should not be returned by the cache.
{expiredCav, emptyImp, nil},
// Discharges with Impetuses that have Arguments should not be cached.
{argsCav, argsImp, nil},
{methodCav, methodImp, &dMethod},
{methodCav, otherMethodImp, nil},
{methodCav, emptyImp, nil},
{serverCav, serverImp, &dServer},
{serverCav, otherServerImp, nil},
{serverCav, emptyImp, nil},
}
for i, test := range testCases {
out := make([]*security.Discharge, 1)
remaining := dcc.Discharges([]security.Caveat{test.caveat}, []security.DischargeImpetus{test.queryImpetus}, out)
if test.cachedDischarge != nil {
got := "nil"
if remaining == 0 {
got = out[0].ID()
}
if got != test.cachedDischarge.ID() {
t.Errorf("#%d: got discharge %v, want %v, queried with %v", i, got, test.cachedDischarge.ID(), test.queryImpetus)
}
} else if remaining == 0 {
t.Errorf("#%d: discharge %v should not have been in cache, queried with %v", i, out[0].ID(), test.queryImpetus)
}
}
if t.Failed() {
t.Logf("dArgs.ID(): %v", dArgs.ID())
t.Logf("dMethod.ID(): %v", dMethod.ID())
t.Logf("dServer.ID(): %v", dServer.ID())
t.Logf("dExpired.ID(): %v", dExpired.ID())
}
}
func mkDischarge(d security.Discharge, err error) security.Discharge {
if err != nil {
panic(err)
}
return d
}