tests for RoutingState

This commit is contained in:
Yusef Napora 2019-11-18 09:13:06 -06:00
parent be36d83110
commit 7d10658fce
5 changed files with 185 additions and 5 deletions

View File

@ -50,6 +50,19 @@ func TestEnvelopeHappyPath(t *testing.T) {
}
}
func TestMakeEnvelopeFailsWithEmptyDomain(t *testing.T) {
priv, _, err := test.RandTestKeyPair(Ed25519, 256)
if err != nil {
t.Error(err)
}
payload := []byte("happy hacking")
payloadType := []byte("/libp2p/testdata")
_, err = MakeEnvelope(priv, "", payloadType, payload)
if err == nil {
t.Errorf("making an envelope with an empty domain should fail")
}
}
func TestEnvelopeValidateFailsForDifferentDomain(t *testing.T) {
priv, _, err := test.RandTestKeyPair(Ed25519, 256)
if err != nil {

2
go.sum
View File

@ -68,6 +68,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM=
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg=

View File

@ -42,18 +42,26 @@ type RoutingState struct {
Addresses []*AnnotatedAddr
}
func RoutingStateFromAddrInfo(info *peer.AddrInfo) *RoutingState {
annotated := make([]*AnnotatedAddr, len(info.Addrs))
for i, a := range info.Addrs {
// RoutingStateWithMultiaddrs returns a RoutingState record for the given peer id
// that contains the given multiaddrs. It generates a timestamp-based sequence number.
func RoutingStateWithMultiaddrs(p peer.ID, addrs []ma.Multiaddr) *RoutingState {
annotated := make([]*AnnotatedAddr, len(addrs))
for i, a := range addrs {
annotated[i] = &AnnotatedAddr{Multiaddr: a}
}
return &RoutingState{
PeerID: info.ID,
PeerID: p,
Seq: statelessSeqNo(),
Addresses: annotated,
}
}
// RoutingStateFromAddrInfo converts a peer.AddrInfo into a RoutingState record.
// It generates a timestamp-based sequence number.
func RoutingStateFromAddrInfo(info *peer.AddrInfo) *RoutingState {
return RoutingStateWithMultiaddrs(info.ID, info.Addrs)
}
// UnmarshalRoutingState unpacks a peer RoutingState record from a serialized protobuf representation.
func UnmarshalRoutingState(serialized []byte) (*RoutingState, error) {
msg := pb.RoutingStateRecord{}
@ -72,7 +80,7 @@ func UnmarshalRoutingState(serialized []byte) (*RoutingState, error) {
}, nil
}
// RoutingStateFromEnvelope unwraps a peer RoutingState record from a SignedEnvelope.
// RoutingStateFromEnvelope unwraps a peer RoutingState record from a serialized SignedEnvelope.
// This method will fail if the signature is invalid, or if the record
// belongs to a peer other than the one that signed the envelope.
func RoutingStateFromEnvelope(envelopeBytes []byte) (*RoutingState, error) {
@ -126,6 +134,28 @@ func (s *RoutingState) Multiaddrs() []ma.Multiaddr {
return out
}
func (s *RoutingState) Equal(other *RoutingState) bool {
if s.Seq != other.Seq {
return false
}
if s.PeerID != other.PeerID {
return false
}
if len(s.Addresses) != len(other.Addresses) {
return false
}
for i, _ := range s.Addresses {
if !s.Addresses[i].Equal(other.Addresses[i]) {
return false
}
}
return true
}
func (a *AnnotatedAddr) Equal(other *AnnotatedAddr) bool {
return a.Multiaddr.Equal(other.Multiaddr)
}
func statelessSeqNo() uint64 {
return uint64(time.Now().UnixNano())
}

78
routing/state_test.go Normal file
View File

@ -0,0 +1,78 @@
package routing
import (
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/test"
"testing"
)
func TestRoutingStateFromAddrInfo(t *testing.T) {
id, _ := test.RandPeerID()
addrs := test.GenerateTestAddrs(10)
info := peer.AddrInfo{
ID: id,
Addrs: addrs,
}
state := RoutingStateFromAddrInfo(&info)
if state.PeerID != info.ID {
t.Fatalf("expected routing state to have peer id %s, got %s", id.Pretty(), state.PeerID.Pretty())
}
test.AssertAddressesEqual(t, addrs, state.Multiaddrs())
}
func TestRoutingStateFromEnvelope(t *testing.T) {
priv, pub, err := test.RandTestKeyPair(crypto.Ed25519, 256)
test.AssertNilError(t, err)
id, err := peer.IDFromPublicKey(pub)
test.AssertNilError(t, err)
addrs := test.GenerateTestAddrs(10)
state := RoutingStateWithMultiaddrs(id, addrs)
t.Run("can unwrap a RoutingState from a serialized envelope", func(t *testing.T) {
env, err := state.ToSignedEnvelope(priv)
test.AssertNilError(t, err)
envBytes, err := env.Marshal()
test.AssertNilError(t, err)
state2, err := RoutingStateFromEnvelope(envBytes)
if !state.Equal(state2) {
t.Error("expected routing state to be unaltered after wrapping in signed envelope")
}
})
t.Run("unwrapping from signed envelope fails if peer id does not match signing key", func(t *testing.T) {
priv2, _, err := test.RandTestKeyPair(crypto.Ed25519, 256)
test.AssertNilError(t, err)
env, err := state.ToSignedEnvelope(priv2)
test.AssertNilError(t, err)
envBytes, err := env.Marshal()
test.AssertNilError(t, err)
_, err = RoutingStateFromEnvelope(envBytes)
test.ExpectError(t, err, "unwrapping RoutingState from envelope should fail if peer id does not match key used to sign envelope")
})
t.Run("unwrapping from signed envelope fails if envelope has wrong domain string", func (t *testing.T) {
stateBytes, err := state.Marshal()
test.AssertNilError(t, err)
env, err := crypto.MakeEnvelope(priv, "wrong-domain", StateEnvelopePayloadType, stateBytes)
envBytes, err := env.Marshal()
_, err = RoutingStateFromEnvelope(envBytes)
test.ExpectError(t, err, "unwrapping RoutingState from envelope should fail if envelope was created with wrong domain string")
})
t.Run("unwrapping from signed envelope fails if envelope has wrong payload type", func (t *testing.T) {
stateBytes, err := state.Marshal()
test.AssertNilError(t, err)
payloadType := []byte("wrong-payload-type")
env, err := crypto.MakeEnvelope(priv, StateEnvelopeDomain, payloadType, stateBytes)
envBytes, err := env.Marshal()
_, err = RoutingStateFromEnvelope(envBytes)
test.ExpectError(t, err, "unwrapping RoutingState from envelope should fail if envelope was created with wrong payload type")
})
}

57
test/utils.go Normal file
View File

@ -0,0 +1,57 @@
package test
import (
"fmt"
"testing"
ma "github.com/multiformats/go-multiaddr"
)
func AssertNilError(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
}
func ExpectError(t *testing.T, err error, msg string) {
t.Helper()
if err == nil {
t.Error(msg)
}
}
func GenerateTestAddrs(n int) []ma.Multiaddr {
out := make([]ma.Multiaddr, n)
for i := 0; i < n; i++ {
a, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/1.2.3.4/tcp/%d", i))
if err != nil {
continue
}
out[i] = a
}
return out
}
func AssertAddressesEqual(t *testing.T, exp, act []ma.Multiaddr) {
t.Helper()
if len(exp) != len(act) {
t.Fatalf("lengths not the same. expected %d, got %d\n", len(exp), len(act))
}
for _, a := range exp {
found := false
for _, b := range act {
if a.Equal(b) {
found = true
break
}
}
if !found {
t.Fatalf("expected address %s not found", a)
}
}
}