veyron/security/caveat: Move common caveats out of veyron/runtimes/google
to the veyron/security/caveat package.

These caveat implementations are generic and do not depend on the Google
runtime.  While at it, also added unittests for these caveats.

Change-Id: I5dd70dc6292148b778d9b77859a6d174790def0c
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 4784673..4260de9 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -19,7 +19,7 @@
 	"veyron/runtimes/google/ipc/version"
 	inaming "veyron/runtimes/google/naming"
 	isecurity "veyron/runtimes/google/security"
-	icaveat "veyron/runtimes/google/security/caveat"
+	"veyron/security/caveat"
 
 	"veyron2"
 	"veyron2/ipc"
@@ -298,11 +298,11 @@
 	authorizeErr := "has one or more invalid caveats"
 	nameErr := "does not have a name matching the provided pattern"
 
-	cavOnlyV1 := security.UniversalCaveat(&icaveat.PeerIdentity{Peers: []security.PrincipalPattern{"client/v1"}})
+	cavOnlyV1 := security.UniversalCaveat(caveat.PeerIdentity{"client/v1"})
 	now := time.Now()
 	cavExpired := security.ServiceCaveat{
 		Service: security.AllPrincipals,
-		Caveat:  &icaveat.Expiry{IssueTime: now, ExpiryTime: now},
+		Caveat:  &caveat.Expiry{IssueTime: now, ExpiryTime: now},
 	}
 
 	clientV1ID := derive(clientID, "v1")
@@ -419,12 +419,12 @@
 func TestRPCAuthorization(t *testing.T) {
 	cavOnlyEcho := security.ServiceCaveat{
 		Service: security.AllPrincipals,
-		Caveat:  &icaveat.MethodRestriction{[]string{"Echo"}},
+		Caveat:  caveat.MethodRestriction{"Echo"},
 	}
 	now := time.Now()
 	cavExpired := security.ServiceCaveat{
 		Service: security.AllPrincipals,
-		Caveat:  &icaveat.Expiry{IssueTime: now, ExpiryTime: now},
+		Caveat:  &caveat.Expiry{IssueTime: now, ExpiryTime: now},
 	}
 
 	blessedByServerOnlyEcho := derive(serverID, "onlyEcho", cavOnlyEcho)
@@ -436,7 +436,7 @@
 		aclAuthErr   = "no matching ACL entry found"
 	)
 	invalidMethodErr := func(method string) string {
-		return fmt.Sprintf("caveat.MethodRestriction{Methods:[Echo]} forbids invocation of method %s", method)
+		return fmt.Sprintf(`caveat.MethodRestriction{"Echo"} forbids invocation of method %s`, method)
 	}
 
 	type v []interface{}
diff --git a/runtimes/google/security/caveat/caveat.go b/runtimes/google/security/caveat/caveat.go
index 11f9595..b589811 100644
--- a/runtimes/google/security/caveat/caveat.go
+++ b/runtimes/google/security/caveat/caveat.go
@@ -1,89 +1,2 @@
-// Package caveat provides a collection of standard caveats that can be validated
-// by the framework. All these caveats implement the security.Caveat interface.
+// Package caveat provides some third-party caveat implementations for the Google runtime.
 package caveat
-
-import (
-	"fmt"
-	"time"
-
-	"veyron2/security"
-	"veyron2/vom"
-)
-
-// Expiry implements security.Caveat. It specifies a restriction
-// on the validity period of the credential that bears the caveat.
-type Expiry struct {
-	IssueTime  time.Time
-	ExpiryTime time.Time
-}
-
-func (c *Expiry) String() string {
-	return fmt.Sprintf("%T%+v", *c, *c)
-}
-
-// Validate checks that the current time is within the IssueTime and ExpiryTime
-// specified by the caveat.
-func (c *Expiry) Validate(context security.Context) error {
-	now := time.Now()
-	if now.Before(c.IssueTime) || now.After(c.ExpiryTime) {
-		return fmt.Errorf("ExpiryCaveat %v forbids credential from being used at this time(%v)", c, now)
-	}
-	return nil
-}
-
-// MethodRestriction implements security.Caveat. It restricts the methods
-// that can be invoked using a credential bearing the caveat to the set
-// of methods specified on the caveat. An empty set indicates that no method
-// can be invoked.
-type MethodRestriction struct {
-	Methods []string
-}
-
-func (c *MethodRestriction) String() string {
-	return fmt.Sprintf("%T%+v", *c, *c)
-}
-
-// Validate checks that if a method is being invoked then its name is present on the set
-// specified on the caveat.
-func (c *MethodRestriction) Validate(ctx security.Context) error {
-	// If the context has an empty Method then the caveat validates.
-	if ctx.Method() == "" {
-		return nil
-	}
-	for _, m := range c.Methods {
-		if m == ctx.Method() {
-			return nil
-		}
-	}
-	return fmt.Errorf("%v forbids invocation of method %s", c, ctx.Method())
-}
-
-// PeerIdentity implements security.Caveat. A credential bearing this caveat
-// can be used to make and receive RPCs from only those peers whose identities
-// match one of the provided security.PrincipalPatterns. If no
-// security.PrincipalPatterns are provided then communication with all peers is
-// forbidden.
-type PeerIdentity struct {
-	Peers []security.PrincipalPattern
-}
-
-func (c *PeerIdentity) String() string {
-	return fmt.Sprintf("%T%+v", *c, *c)
-}
-
-// Validate checks that the identity of the peer is present on the set of services
-// identified by the PrincipalPatterns on the caveat.
-func (c *PeerIdentity) Validate(ctx security.Context) error {
-	for _, p := range c.Peers {
-		if ctx.LocalID() != nil && ctx.LocalID().Match(p) {
-			return nil
-		}
-	}
-	return fmt.Errorf("%v forbids RPCing with peer %s", c, ctx.LocalID())
-}
-
-func init() {
-	vom.Register(Expiry{})
-	vom.Register(MethodRestriction{})
-	vom.Register(PeerIdentity{})
-}
diff --git a/runtimes/google/security/caveat/util.go b/runtimes/google/security/caveat/util.go
index 7f8ad4e..723067a 100644
--- a/runtimes/google/security/caveat/util.go
+++ b/runtimes/google/security/caveat/util.go
@@ -9,6 +9,7 @@
 	"time"
 
 	"veyron/runtimes/google/security/wire"
+	"veyron/security/caveat"
 
 	"veyron2/security"
 )
@@ -47,7 +48,7 @@
 	}
 
 	now := time.Now()
-	expiryCaveat := &Expiry{IssueTime: now, ExpiryTime: now.Add(duration)}
+	expiryCaveat := &caveat.Expiry{IssueTime: now, ExpiryTime: now.Add(duration)}
 	caveats = append(caveats, security.UniversalCaveat(expiryCaveat))
 
 	encodedCaveats, err := wire.EncodeCaveats(caveats)
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 2f62091..849e795 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -11,9 +11,10 @@
 	"reflect"
 	"time"
 
-	"veyron/runtimes/google/security/caveat"
+	icaveat "veyron/runtimes/google/security/caveat"
 	"veyron/runtimes/google/security/keys"
 	"veyron/runtimes/google/security/wire"
+	"veyron/security/caveat"
 
 	"veyron2/security"
 	"veyron2/vom"
@@ -196,8 +197,8 @@
 
 func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
 	switch c := cav.(type) {
-	case *caveat.PublicKeyCaveat:
-		return caveat.NewPublicKeyDischarge(c, id.privateKey, duration, dischargeCaveats)
+	case *icaveat.PublicKeyCaveat:
+		return icaveat.NewPublicKeyDischarge(c, id.privateKey, duration, dischargeCaveats)
 	}
 	return nil, fmt.Errorf("discharge cannot be constructed for ThirdPartyCaveat of type %T from PrivateID of type %T", cav, id)
 }
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 2011a93..a1bad90 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -327,7 +327,7 @@
 			tests: []rpc{
 				{server: bob, method: "Hello", authName: "veyron/alice"},
 				{server: bob, authName: "veyron/alice"},
-				{server: googleTree.PublicID(), method: "Hello", authErr: "caveat.MethodRestriction{Methods:[Play]} forbids invocation of method Hello"},
+				{server: googleTree.PublicID(), method: "Hello", authErr: `caveat.MethodRestriction{"Play"} forbids invocation of method Hello`},
 				{server: googleTree.PublicID(), method: "Play", authName: "veyron/alice"},
 				{server: googleTree.PublicID(), authName: "veyron/alice"},
 			},
@@ -335,7 +335,7 @@
 		{
 			client: bless(cAlice, veyronChain, "alice", cavOnlyGoogle),
 			tests: []rpc{
-				{server: bob, method: "Hello", authErr: "caveat.PeerIdentity{Peers:[google]} forbids RPCing with peer untrusted/bob"},
+				{server: bob, method: "Hello", authErr: `caveat.PeerIdentity{"google"} forbids RPCing with peer untrusted/bob`},
 				{server: googleTree.PublicID(), method: "Hello", authName: "veyron/alice"},
 				{server: googleTree.PublicID(), method: "Play", authName: "veyron/alice"},
 			},
@@ -343,15 +343,15 @@
 		{
 			client: bless(cAlice, veyronChain, "alice", append(cavOnlyGoogle, cavOnlyPlayAtGoogle...)),
 			tests: []rpc{
-				{server: bob, method: "Hello", authErr: "caveat.PeerIdentity{Peers:[google]} forbids RPCing with peer untrusted/bob"},
-				{server: googleTree.PublicID(), method: "Hello", authErr: "caveat.MethodRestriction{Methods:[Play]} forbids invocation of method Hello"},
+				{server: bob, method: "Hello", authErr: `caveat.PeerIdentity{"google"} forbids RPCing with peer untrusted/bob`},
+				{server: googleTree.PublicID(), method: "Hello", authErr: `caveat.MethodRestriction{"Play"} forbids invocation of method Hello`},
 				{server: googleTree.PublicID(), method: "Play", authName: "veyron/alice"},
 			},
 		},
 		{
 			client: bless(cAlice, veyronChain, "alice", cavOnlyPublicProfile),
 			tests: []rpc{
-				{server: cVeyronAliceTV, method: "PrivateProfile", authErr: "caveat.MethodRestriction{Methods:[PublicProfile]} forbids invocation of method PrivateProfile"},
+				{server: cVeyronAliceTV, method: "PrivateProfile", authErr: `caveat.MethodRestriction{"PublicProfile"} forbids invocation of method PrivateProfile`},
 				{server: cVeyronAliceTV, method: "PublicProfile", authName: "veyron/alice"},
 			},
 		},
diff --git a/runtimes/google/security/identity_tree.go b/runtimes/google/security/identity_tree.go
index 80b6930..4425759 100644
--- a/runtimes/google/security/identity_tree.go
+++ b/runtimes/google/security/identity_tree.go
@@ -13,9 +13,10 @@
 	"strings"
 	"time"
 
-	"veyron/runtimes/google/security/caveat"
+	icaveat "veyron/runtimes/google/security/caveat"
 	"veyron/runtimes/google/security/keys"
 	"veyron/runtimes/google/security/wire"
+	"veyron/security/caveat"
 	"veyron2/security"
 	"veyron2/vom"
 )
@@ -232,8 +233,8 @@
 
 func (id *treePrivateID) MintDischarge(cav security.ThirdPartyCaveat, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
 	switch c := cav.(type) {
-	case *caveat.PublicKeyCaveat:
-		return caveat.NewPublicKeyDischarge(c, id.privateKey, duration, dischargeCaveats)
+	case *icaveat.PublicKeyCaveat:
+		return icaveat.NewPublicKeyDischarge(c, id.privateKey, duration, dischargeCaveats)
 	}
 	return nil, fmt.Errorf("discharge cannot be constructed for ThirdPartyCaveat of type %T from PrivateID of type %T", cav, id)
 }
diff --git a/runtimes/google/security/util_test.go b/runtimes/google/security/util_test.go
index 15955bc..667fad6 100644
--- a/runtimes/google/security/util_test.go
+++ b/runtimes/google/security/util_test.go
@@ -8,8 +8,8 @@
 	"testing"
 	"time"
 
-	"veyron/runtimes/google/security/caveat"
 	"veyron/runtimes/google/security/keys"
+	"veyron/security/caveat"
 
 	"veyron2/security"
 	"veyron2/vom"
@@ -104,14 +104,12 @@
 
 func methodRestrictionCaveat(service security.PrincipalPattern, methods []string) []security.ServiceCaveat {
 	return []security.ServiceCaveat{
-		{Service: service, Caveat: &caveat.MethodRestriction{Methods: methods}},
+		{Service: service, Caveat: caveat.MethodRestriction(methods)},
 	}
 }
 
 func peerIdentityCaveat(p security.PrincipalPattern) []security.ServiceCaveat {
-	return []security.ServiceCaveat{
-		security.UniversalCaveat(&caveat.PeerIdentity{Peers: []security.PrincipalPattern{p}}),
-	}
+	return []security.ServiceCaveat{security.UniversalCaveat(caveat.PeerIdentity{p})}
 }
 
 func init() {
diff --git a/security/caveat/caveat.go b/security/caveat/caveat.go
new file mode 100644
index 0000000..6cb4735
--- /dev/null
+++ b/security/caveat/caveat.go
@@ -0,0 +1,66 @@
+// Package caveat provides common security.Caveat implementations.
+package caveat
+
+import (
+	"fmt"
+	"time"
+
+	"veyron2/security"
+	"veyron2/vom"
+)
+
+// Expiry is a security.Caveat that restricts the validity period of
+// the credential bearing this caveat.
+type Expiry struct {
+	IssueTime  time.Time
+	ExpiryTime time.Time
+}
+
+func (c *Expiry) Validate(context security.Context) error {
+	now := time.Now()
+	if now.Before(c.IssueTime) || now.After(c.ExpiryTime) {
+		return fmt.Errorf("%#v forbids credential from being used at this time(%v)", c, now)
+	}
+	return nil
+}
+
+// MethodRestriction is a security.Caveat that restricts the set of
+// methods that can be invoked by a credential bearing the caveat.
+// An empty set indicates that no methods can be invoked.
+type MethodRestriction []string
+
+func (c MethodRestriction) Validate(ctx security.Context) error {
+	// If the context has an empty Method then the caveat validates.
+	if ctx.Method() == "" {
+		return nil
+	}
+	for _, m := range c {
+		if m == ctx.Method() {
+			return nil
+		}
+	}
+	return fmt.Errorf("%#v forbids invocation of method %s", c, ctx.Method())
+}
+
+// PeerIdentity is a security.Caveat that restricts the bearer of a credential
+// with this caveat from making or receiving RPCs to a limited set of peers -
+// those whose identities match one of the provided security.PrincipalPatterns.
+// An empty set indicates that no peers can be communicated with.
+type PeerIdentity []security.PrincipalPattern
+
+// Validate checks that the identity of the peer is present on the set of services
+// identified by the PrincipalPatterns on the caveat.
+func (c PeerIdentity) Validate(ctx security.Context) error {
+	for _, p := range c {
+		if ctx.LocalID() != nil && ctx.LocalID().Match(p) {
+			return nil
+		}
+	}
+	return fmt.Errorf("%#v forbids RPCing with peer %s", c, ctx.LocalID())
+}
+
+func init() {
+	vom.Register(Expiry{})
+	vom.Register(MethodRestriction(nil))
+	vom.Register(PeerIdentity(nil))
+}
diff --git a/security/caveat/caveat_test.go b/security/caveat/caveat_test.go
new file mode 100644
index 0000000..8c7efdf
--- /dev/null
+++ b/security/caveat/caveat_test.go
@@ -0,0 +1,50 @@
+package caveat_test
+
+import (
+	"testing"
+	"time"
+
+	"veyron/security/caveat"
+	"veyron2/security"
+)
+
+type context struct {
+	local, remote security.PublicID
+	method        string
+}
+
+func (c *context) Method() string                                { return c.method }
+func (c *context) Name() string                                  { return "some_name" }
+func (c *context) Suffix() string                                { return "some_suffix" }
+func (c *context) Label() security.Label                         { return security.AdminLabel }
+func (c *context) CaveatDischarges() security.CaveatDischargeMap { return nil }
+func (c *context) LocalID() security.PublicID                    { return c.local }
+func (c *context) RemoteID() security.PublicID                   { return c.remote }
+
+func TestCaveats(t *testing.T) {
+	var (
+		alice = security.FakePublicID("alice")
+		bob   = security.FakePublicID("bob")
+	)
+	now := time.Now()
+	tests := []struct {
+		c  security.Caveat
+		ok bool
+	}{
+		{&caveat.Expiry{IssueTime: now, ExpiryTime: now.Add(time.Hour)}, true},
+		{&caveat.Expiry{IssueTime: now.Add(-1 * time.Hour), ExpiryTime: now.Add(-1 * time.Minute)}, false},
+		{caveat.MethodRestriction(nil), false},
+		{caveat.MethodRestriction{"Pause", "Play"}, true},
+		{caveat.MethodRestriction{"List"}, false},
+		{caveat.PeerIdentity(nil), false},
+		{caveat.PeerIdentity{"fake/alice"}, true},
+		{caveat.PeerIdentity{"fake/carol"}, false},
+		{caveat.PeerIdentity{"fake/alice", "fake/carol"}, true},
+	}
+	ctx := &context{local: alice, remote: bob, method: "Play"}
+	for _, test := range tests {
+		if err := test.c.Validate(ctx); test.ok != (err == nil) {
+			t.Errorf("Caveat:%#v. Got error:%v, want error:%v", test.c, err, test.ok)
+		}
+	}
+}
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index 28eb42f..f4a908f 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -19,7 +19,7 @@
 )
 
 var (
-	errNamingLoop  = verror.Make(verror.BadArg, "Loop in namespace")
+	errNamingLoop = verror.Make(verror.BadArg, "Loop in namespace")
 )
 
 // mountTable represents a namespace.  One exists per server instance.
@@ -200,7 +200,7 @@
 
 // A useful node has children or an active mount.
 func (n *node) isUseful() bool {
-	return len(n.children) > 0  || n.mount.isActive()
+	return len(n.children) > 0 || n.mount.isActive()
 }
 
 // removeUseless removes a node and all of its ascendants that are not useful.