2016-05-16 17:01:00 -07:00
|
|
|
package providers
|
|
|
|
|
|
|
|
import (
|
2016-10-05 12:34:28 -07:00
|
|
|
"context"
|
2016-05-16 17:01:00 -07:00
|
|
|
"fmt"
|
2016-11-14 17:02:02 -08:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2016-05-16 17:01:00 -07:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2019-05-26 23:33:15 +01:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
|
2016-09-30 10:56:47 -07:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2016-08-21 17:18:58 +01:00
|
|
|
ds "github.com/ipfs/go-datastore"
|
2019-04-12 22:03:39 -07:00
|
|
|
dsq "github.com/ipfs/go-datastore/query"
|
|
|
|
dssync "github.com/ipfs/go-datastore/sync"
|
2016-09-30 10:56:47 -07:00
|
|
|
u "github.com/ipfs/go-ipfs-util"
|
2016-11-22 17:56:36 -05:00
|
|
|
//
|
|
|
|
// used by TestLargeProvidersSet: do not remove
|
|
|
|
// lds "github.com/ipfs/go-ds-leveldb"
|
2016-05-16 17:01:00 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestProviderManager(t *testing.T) {
|
2018-02-16 18:52:29 -08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2016-05-16 17:01:00 -07:00
|
|
|
mid := peer.ID("testing")
|
2019-04-12 22:03:39 -07:00
|
|
|
p := NewProviderManager(ctx, mid, dssync.MutexWrap(ds.NewMapDatastore()))
|
2016-09-30 10:56:47 -07:00
|
|
|
a := cid.NewCidV0(u.Hash([]byte("test")))
|
2016-05-16 17:01:00 -07:00
|
|
|
p.AddProvider(ctx, a, peer.ID("testingprovider"))
|
2019-04-12 23:36:53 -07:00
|
|
|
|
|
|
|
// Not cached
|
2016-05-16 17:01:00 -07:00
|
|
|
resp := p.GetProviders(ctx, a)
|
|
|
|
if len(resp) != 1 {
|
|
|
|
t.Fatal("Could not retrieve provider.")
|
|
|
|
}
|
2019-04-12 23:36:53 -07:00
|
|
|
|
|
|
|
// Cached
|
|
|
|
resp = p.GetProviders(ctx, a)
|
|
|
|
if len(resp) != 1 {
|
|
|
|
t.Fatal("Could not retrieve provider.")
|
|
|
|
}
|
2016-05-16 17:01:00 -07:00
|
|
|
p.proc.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProvidersDatastore(t *testing.T) {
|
|
|
|
old := lruCacheSize
|
|
|
|
lruCacheSize = 10
|
|
|
|
defer func() { lruCacheSize = old }()
|
|
|
|
|
2018-02-16 18:52:29 -08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2016-05-16 17:01:00 -07:00
|
|
|
mid := peer.ID("testing")
|
2019-04-12 22:03:39 -07:00
|
|
|
p := NewProviderManager(ctx, mid, dssync.MutexWrap(ds.NewMapDatastore()))
|
2016-05-16 17:01:00 -07:00
|
|
|
defer p.proc.Close()
|
|
|
|
|
|
|
|
friend := peer.ID("friend")
|
2018-09-05 03:02:31 -04:00
|
|
|
var cids []cid.Cid
|
2016-05-16 17:01:00 -07:00
|
|
|
for i := 0; i < 100; i++ {
|
2016-09-30 10:56:47 -07:00
|
|
|
c := cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))
|
|
|
|
cids = append(cids, c)
|
|
|
|
p.AddProvider(ctx, c, friend)
|
2016-05-16 17:01:00 -07:00
|
|
|
}
|
|
|
|
|
2016-09-30 10:56:47 -07:00
|
|
|
for _, c := range cids {
|
|
|
|
resp := p.GetProviders(ctx, c)
|
2016-05-16 17:01:00 -07:00
|
|
|
if len(resp) != 1 {
|
|
|
|
t.Fatal("Could not retrieve provider.")
|
|
|
|
}
|
|
|
|
if resp[0] != friend {
|
|
|
|
t.Fatal("expected provider to be 'friend'")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProvidersSerialization(t *testing.T) {
|
2019-04-12 22:03:39 -07:00
|
|
|
dstore := dssync.MutexWrap(ds.NewMapDatastore())
|
2016-05-16 17:01:00 -07:00
|
|
|
|
2016-09-30 10:56:47 -07:00
|
|
|
k := cid.NewCidV0(u.Hash(([]byte("my key!"))))
|
2016-06-25 22:59:57 -07:00
|
|
|
p1 := peer.ID("peer one")
|
|
|
|
p2 := peer.ID("peer two")
|
|
|
|
pt1 := time.Now()
|
|
|
|
pt2 := pt1.Add(time.Hour)
|
2016-05-16 17:01:00 -07:00
|
|
|
|
2016-06-25 22:59:57 -07:00
|
|
|
err := writeProviderEntry(dstore, k, p1, pt1)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = writeProviderEntry(dstore, k, p2, pt2)
|
2016-05-16 17:01:00 -07:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
pset, err := loadProvSet(dstore, k)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-06-25 22:59:57 -07:00
|
|
|
lt1, ok := pset.set[p1]
|
|
|
|
if !ok {
|
|
|
|
t.Fatal("failed to load set correctly")
|
|
|
|
}
|
|
|
|
|
2017-08-23 14:52:31 +02:00
|
|
|
if !pt1.Equal(lt1) {
|
|
|
|
t.Fatalf("time wasnt serialized correctly, %v != %v", pt1, lt1)
|
2016-06-25 22:59:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
lt2, ok := pset.set[p2]
|
2016-05-16 17:01:00 -07:00
|
|
|
if !ok {
|
|
|
|
t.Fatal("failed to load set correctly")
|
|
|
|
}
|
|
|
|
|
2017-09-13 16:57:36 -07:00
|
|
|
if !pt2.Equal(lt2) {
|
|
|
|
t.Fatalf("time wasnt serialized correctly, %v != %v", pt1, lt1)
|
2016-05-16 17:01:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProvidesExpire(t *testing.T) {
|
|
|
|
pval := ProvideValidity
|
|
|
|
cleanup := defaultCleanupInterval
|
|
|
|
ProvideValidity = time.Second / 2
|
|
|
|
defaultCleanupInterval = time.Second / 2
|
|
|
|
defer func() {
|
|
|
|
ProvideValidity = pval
|
|
|
|
defaultCleanupInterval = cleanup
|
|
|
|
}()
|
|
|
|
|
2018-02-16 18:52:29 -08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2019-04-18 16:31:05 -07:00
|
|
|
ds := dssync.MutexWrap(ds.NewMapDatastore())
|
2016-05-16 17:01:00 -07:00
|
|
|
mid := peer.ID("testing")
|
2019-04-18 16:31:05 -07:00
|
|
|
p := NewProviderManager(ctx, mid, ds)
|
2016-05-16 17:01:00 -07:00
|
|
|
|
|
|
|
peers := []peer.ID{"a", "b"}
|
2018-09-05 03:02:31 -04:00
|
|
|
var cids []cid.Cid
|
2016-05-16 17:01:00 -07:00
|
|
|
for i := 0; i < 10; i++ {
|
2016-09-30 10:56:47 -07:00
|
|
|
c := cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))
|
|
|
|
cids = append(cids, c)
|
2019-04-18 16:31:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cids[:5] {
|
2016-09-30 10:56:47 -07:00
|
|
|
p.AddProvider(ctx, c, peers[0])
|
|
|
|
p.AddProvider(ctx, c, peers[1])
|
2016-05-16 17:01:00 -07:00
|
|
|
}
|
|
|
|
|
2019-04-18 16:31:05 -07:00
|
|
|
time.Sleep(time.Second / 4)
|
|
|
|
|
|
|
|
for _, c := range cids[5:] {
|
|
|
|
p.AddProvider(ctx, c, peers[0])
|
|
|
|
p.AddProvider(ctx, c, peers[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cids {
|
|
|
|
out := p.GetProviders(ctx, c)
|
2016-05-16 17:01:00 -07:00
|
|
|
if len(out) != 2 {
|
|
|
|
t.Fatal("expected providers to still be there")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 16:31:05 -07:00
|
|
|
time.Sleep(3 * time.Second / 8)
|
|
|
|
|
|
|
|
for _, c := range cids[:5] {
|
|
|
|
out := p.GetProviders(ctx, c)
|
2016-09-30 10:56:47 -07:00
|
|
|
if len(out) > 0 {
|
|
|
|
t.Fatal("expected providers to be cleaned up, got: ", out)
|
2016-05-16 17:01:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 16:31:05 -07:00
|
|
|
for _, c := range cids[5:] {
|
|
|
|
out := p.GetProviders(ctx, c)
|
|
|
|
if len(out) != 2 {
|
|
|
|
t.Fatal("expected providers to still be there")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(time.Second / 2)
|
|
|
|
|
|
|
|
// Stop to prevent data races
|
|
|
|
p.Process().Close()
|
|
|
|
|
2016-05-16 17:01:00 -07:00
|
|
|
if p.providers.Len() != 0 {
|
|
|
|
t.Fatal("providers map not cleaned up")
|
|
|
|
}
|
|
|
|
|
2019-04-18 16:31:05 -07:00
|
|
|
res, err := ds.Query(dsq.Query{Prefix: providersKeyPrefix})
|
2016-05-16 17:01:00 -07:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-04-12 22:03:39 -07:00
|
|
|
rest, err := res.Rest()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(rest) > 0 {
|
2016-05-16 17:01:00 -07:00
|
|
|
t.Fatal("expected everything to be cleaned out of the datastore")
|
|
|
|
}
|
|
|
|
}
|
2016-11-11 10:13:12 -08:00
|
|
|
|
2016-11-14 17:41:05 -08:00
|
|
|
var _ = ioutil.NopCloser
|
|
|
|
var _ = os.DevNull
|
|
|
|
|
|
|
|
/* This can be used for profiling. Keeping it commented out for now to avoid incurring extra CI time
|
2016-11-11 10:13:12 -08:00
|
|
|
func TestLargeProvidersSet(t *testing.T) {
|
|
|
|
old := lruCacheSize
|
|
|
|
lruCacheSize = 10
|
|
|
|
defer func() { lruCacheSize = old }()
|
|
|
|
|
|
|
|
dirn, err := ioutil.TempDir("", "provtest")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
opts := &lds.Options{
|
|
|
|
NoSync: true,
|
|
|
|
Compression: 1,
|
|
|
|
}
|
|
|
|
lds, err := lds.NewDatastore(dirn, opts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
_ = lds
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
os.RemoveAll(dirn)
|
|
|
|
}()
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
var peers []peer.ID
|
|
|
|
for i := 0; i < 3000; i++ {
|
|
|
|
peers = append(peers, peer.ID(fmt.Sprint(i)))
|
|
|
|
}
|
|
|
|
|
|
|
|
mid := peer.ID("myself")
|
|
|
|
p := NewProviderManager(ctx, mid, lds)
|
|
|
|
defer p.proc.Close()
|
|
|
|
|
2018-09-05 03:02:31 -04:00
|
|
|
var cids []cid.Cid
|
2016-11-11 10:13:12 -08:00
|
|
|
for i := 0; i < 1000; i++ {
|
|
|
|
c := cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))
|
|
|
|
cids = append(cids, c)
|
|
|
|
for _, pid := range peers {
|
|
|
|
p.AddProvider(ctx, c, pid)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 17:56:36 -05:00
|
|
|
for i := 0; i < 5; i++ {
|
|
|
|
start := time.Now()
|
|
|
|
for _, c := range cids {
|
|
|
|
_ = p.GetProviders(ctx, c)
|
|
|
|
}
|
|
|
|
elapsed := time.Since(start)
|
|
|
|
fmt.Printf("query %f ms\n", elapsed.Seconds()*1000)
|
2016-11-11 10:13:12 -08:00
|
|
|
}
|
|
|
|
}
|
2016-11-22 17:56:36 -05:00
|
|
|
*/
|
2016-11-16 15:47:40 +02:00
|
|
|
|
|
|
|
func TestUponCacheMissProvidersAreReadFromDatastore(t *testing.T) {
|
|
|
|
old := lruCacheSize
|
|
|
|
lruCacheSize = 1
|
|
|
|
defer func() { lruCacheSize = old }()
|
2018-02-16 18:52:29 -08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
2016-11-16 15:47:40 +02:00
|
|
|
|
|
|
|
p1, p2 := peer.ID("a"), peer.ID("b")
|
2016-11-28 13:22:43 -08:00
|
|
|
c1 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("1")))
|
|
|
|
c2 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("2")))
|
2019-04-12 22:03:39 -07:00
|
|
|
pm := NewProviderManager(ctx, p1, dssync.MutexWrap(ds.NewMapDatastore()))
|
2016-11-16 15:47:40 +02:00
|
|
|
|
2019-04-12 23:36:53 -07:00
|
|
|
// add provider
|
2016-11-16 15:47:40 +02:00
|
|
|
pm.AddProvider(ctx, c1, p1)
|
|
|
|
// make the cached provider for c1 go to datastore
|
|
|
|
pm.AddProvider(ctx, c2, p1)
|
|
|
|
// now just offloaded record should be brought back and joined with p2
|
|
|
|
pm.AddProvider(ctx, c1, p2)
|
|
|
|
|
|
|
|
c1Provs := pm.GetProviders(ctx, c1)
|
|
|
|
if len(c1Provs) != 2 {
|
|
|
|
t.Fatalf("expected c1 to be provided by 2 peers, is by %d", len(c1Provs))
|
|
|
|
}
|
|
|
|
}
|
2019-04-12 23:36:53 -07:00
|
|
|
|
|
|
|
func TestWriteUpdatesCache(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
p1, p2 := peer.ID("a"), peer.ID("b")
|
|
|
|
c1 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("1")))
|
|
|
|
pm := NewProviderManager(ctx, p1, dssync.MutexWrap(ds.NewMapDatastore()))
|
|
|
|
|
|
|
|
// add provider
|
|
|
|
pm.AddProvider(ctx, c1, p1)
|
|
|
|
// force into the cache
|
|
|
|
pm.GetProviders(ctx, c1)
|
|
|
|
// add a second provider
|
|
|
|
pm.AddProvider(ctx, c1, p2)
|
|
|
|
|
|
|
|
c1Provs := pm.GetProviders(ctx, c1)
|
|
|
|
if len(c1Provs) != 2 {
|
|
|
|
t.Fatalf("expected c1 to be provided by 2 peers, is by %d", len(c1Provs))
|
|
|
|
}
|
|
|
|
}
|