kubo/namesys/namesys_test.go
2019-10-07 17:33:38 +09:00

166 lines
5.5 KiB
Go

package namesys
import (
"context"
"fmt"
"testing"
"time"
ds "github.com/ipfs/go-datastore"
dssync "github.com/ipfs/go-datastore/sync"
offroute "github.com/ipfs/go-ipfs-routing/offline"
ipns "github.com/ipfs/go-ipns"
path "github.com/ipfs/go-path"
"github.com/ipfs/go-unixfs"
opts "github.com/ipfs/interface-go-ipfs-core/options/namesys"
ci "github.com/libp2p/go-libp2p-core/crypto"
peer "github.com/libp2p/go-libp2p-core/peer"
pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem"
record "github.com/libp2p/go-libp2p-record"
)
type mockResolver struct {
entries map[string]string
}
func testResolution(t *testing.T, resolver Resolver, name string, depth uint, expected string, expError error) {
t.Helper()
p, err := resolver.Resolve(context.Background(), name, opts.Depth(depth))
if err != expError {
t.Fatal(fmt.Errorf(
"expected %s with a depth of %d to have a '%s' error, but got '%s'",
name, depth, expError, err))
}
if p.String() != expected {
t.Fatal(fmt.Errorf(
"%s with depth %d resolved to %s != %s",
name, depth, p.String(), expected))
}
}
func (r *mockResolver) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult {
p, err := path.ParsePath(r.entries[name])
out := make(chan onceResult, 1)
out <- onceResult{value: p, err: err}
close(out)
return out
}
func mockResolverOne() *mockResolver {
return &mockResolver{
entries: map[string]string{
"QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy": "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj",
"QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n": "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy",
"QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD": "/ipns/ipfs.io",
"QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei": "/ipfs/QmP3ouCnU8NNLsW6261pAx2pNLV2E4dQoisB1sgda12Act",
},
}
}
func mockResolverTwo() *mockResolver {
return &mockResolver{
entries: map[string]string{
"ipfs.io": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n",
},
}
}
func TestNamesysResolution(t *testing.T) {
r := &mpns{
ipnsResolver: mockResolverOne(),
dnsResolver: mockResolverTwo(),
}
testResolution(t, r, "Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil)
testResolution(t, r, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil)
testResolution(t, r, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil)
testResolution(t, r, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", 1, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion)
testResolution(t, r, "/ipns/ipfs.io", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil)
testResolution(t, r, "/ipns/ipfs.io", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion)
testResolution(t, r, "/ipns/ipfs.io", 2, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion)
testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", opts.DefaultDepthLimit, "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", nil)
testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 1, "/ipns/ipfs.io", ErrResolveRecursion)
testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 2, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion)
testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 3, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion)
}
func TestPublishWithCache0(t *testing.T) {
dst := dssync.MutexWrap(ds.NewMapDatastore())
priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048)
if err != nil {
t.Fatal(err)
}
ps := pstoremem.NewPeerstore()
pid, err := peer.IDFromPrivateKey(priv)
if err != nil {
t.Fatal(err)
}
err = ps.AddPrivKey(pid, priv)
if err != nil {
t.Fatal(err)
}
routing := offroute.NewOfflineRouter(dst, record.NamespacedValidator{
"ipns": ipns.Validator{KeyBook: ps},
"pk": record.PublicKeyValidator{},
})
nsys := NewNameSystem(routing, dst, 0)
p, err := path.ParsePath(unixfs.EmptyDirNode().Cid().String())
if err != nil {
t.Fatal(err)
}
err = nsys.Publish(context.Background(), priv, p)
if err != nil {
t.Fatal(err)
}
}
func TestPublishWithTTL(t *testing.T) {
dst := dssync.MutexWrap(ds.NewMapDatastore())
priv, _, err := ci.GenerateKeyPair(ci.RSA, 2048)
if err != nil {
t.Fatal(err)
}
ps := pstoremem.NewPeerstore()
pid, err := peer.IDFromPrivateKey(priv)
if err != nil {
t.Fatal(err)
}
err = ps.AddPrivKey(pid, priv)
if err != nil {
t.Fatal(err)
}
routing := offroute.NewOfflineRouter(dst, record.NamespacedValidator{
"ipns": ipns.Validator{KeyBook: ps},
"pk": record.PublicKeyValidator{},
})
nsys := NewNameSystem(routing, dst, 128)
p, err := path.ParsePath(unixfs.EmptyDirNode().Cid().String())
if err != nil {
t.Fatal(err)
}
ttl := 1 * time.Second
eol := time.Now().Add(2 * time.Second)
ctx := context.WithValue(context.Background(), "ipns-publish-ttl", ttl)
err = nsys.Publish(ctx, priv, p)
if err != nil {
t.Fatal(err)
}
ientry, ok := nsys.(*mpns).cache.Get(pid.Pretty())
if !ok {
t.Fatal("cache get failed")
}
entry, ok := ientry.(cacheEntry)
if !ok {
t.Fatal("bad cache item returned")
}
if entry.eol.Sub(eol) > 10*time.Millisecond {
t.Fatalf("bad cache ttl: expected %s, got %s", eol, entry.eol)
}
}