providers_test.go 5.28 KB
Newer Older
1 2 3
package providers

import (
4
	"context"
5
	"fmt"
6 7
	"io/ioutil"
	"os"
8 9 10
	"testing"
	"time"

11
	cid "github.com/ipfs/go-cid"
12
	ds "github.com/ipfs/go-datastore"
13
	u "github.com/ipfs/go-ipfs-util"
14
	peer "github.com/libp2p/go-libp2p-peer"
15 16 17
	//
	// used by TestLargeProvidersSet: do not remove
	// lds "github.com/ipfs/go-ds-leveldb"
18 19 20
)

func TestProviderManager(t *testing.T) {
Steven Allen's avatar
Steven Allen committed
21 22 23
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

24 25
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
26
	a := cid.NewCidV0(u.Hash([]byte("test")))
27 28 29 30 31 32 33 34 35 36 37 38 39
	p.AddProvider(ctx, a, peer.ID("testingprovider"))
	resp := p.GetProviders(ctx, a)
	if len(resp) != 1 {
		t.Fatal("Could not retrieve provider.")
	}
	p.proc.Close()
}

func TestProvidersDatastore(t *testing.T) {
	old := lruCacheSize
	lruCacheSize = 10
	defer func() { lruCacheSize = old }()

Steven Allen's avatar
Steven Allen committed
40 41 42
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

43 44 45 46 47
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
	defer p.proc.Close()

	friend := peer.ID("friend")
48
	var cids []cid.Cid
49
	for i := 0; i < 100; i++ {
50 51 52
		c := cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))
		cids = append(cids, c)
		p.AddProvider(ctx, c, friend)
53 54
	}

55 56
	for _, c := range cids {
		resp := p.GetProviders(ctx, c)
57 58 59 60 61 62 63 64 65 66 67 68
		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) {
	dstore := ds.NewMapDatastore()

69
	k := cid.NewCidV0(u.Hash(([]byte("my key!"))))
Jeromy's avatar
Jeromy committed
70 71 72 73
	p1 := peer.ID("peer one")
	p2 := peer.ID("peer two")
	pt1 := time.Now()
	pt2 := pt1.Add(time.Hour)
74

Jeromy's avatar
Jeromy committed
75 76 77 78 79 80
	err := writeProviderEntry(dstore, k, p1, pt1)
	if err != nil {
		t.Fatal(err)
	}

	err = writeProviderEntry(dstore, k, p2, pt2)
81 82 83 84 85 86 87 88 89
	if err != nil {
		t.Fatal(err)
	}

	pset, err := loadProvSet(dstore, k)
	if err != nil {
		t.Fatal(err)
	}

Jeromy's avatar
Jeromy committed
90 91 92 93 94
	lt1, ok := pset.set[p1]
	if !ok {
		t.Fatal("failed to load set correctly")
	}

95 96
	if !pt1.Equal(lt1) {
		t.Fatalf("time wasnt serialized correctly, %v != %v", pt1, lt1)
Jeromy's avatar
Jeromy committed
97 98 99
	}

	lt2, ok := pset.set[p2]
100 101 102 103
	if !ok {
		t.Fatal("failed to load set correctly")
	}

104 105
	if !pt2.Equal(lt2) {
		t.Fatalf("time wasnt serialized correctly, %v != %v", pt1, lt1)
106 107 108 109 110 111 112 113 114 115 116 117 118
	}
}

func TestProvidesExpire(t *testing.T) {
	pval := ProvideValidity
	cleanup := defaultCleanupInterval
	ProvideValidity = time.Second / 2
	defaultCleanupInterval = time.Second / 2
	defer func() {
		ProvideValidity = pval
		defaultCleanupInterval = cleanup
	}()

Steven Allen's avatar
Steven Allen committed
119 120 121
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

122 123 124 125
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())

	peers := []peer.ID{"a", "b"}
126
	var cids []cid.Cid
127
	for i := 0; i < 10; i++ {
128 129 130 131
		c := cid.NewCidV0(u.Hash([]byte(fmt.Sprint(i))))
		cids = append(cids, c)
		p.AddProvider(ctx, c, peers[0])
		p.AddProvider(ctx, c, peers[1])
132 133 134
	}

	for i := 0; i < 10; i++ {
135
		out := p.GetProviders(ctx, cids[i])
136 137 138 139 140 141 142
		if len(out) != 2 {
			t.Fatal("expected providers to still be there")
		}
	}

	time.Sleep(time.Second)
	for i := 0; i < 10; i++ {
143 144 145
		out := p.GetProviders(ctx, cids[i])
		if len(out) > 0 {
			t.Fatal("expected providers to be cleaned up, got: ", out)
146 147 148 149 150 151 152
		}
	}

	if p.providers.Len() != 0 {
		t.Fatal("providers map not cleaned up")
	}

153
	proviter, err := p.getProvKeys()
154 155 156 157
	if err != nil {
		t.Fatal(err)
	}

158 159
	_, ok := proviter()
	if ok {
160 161 162
		t.Fatal("expected everything to be cleaned out of the datastore")
	}
}
163

164 165 166 167
var _ = ioutil.NopCloser
var _ = os.DevNull

/* This can be used for profiling. Keeping it commented out for now to avoid incurring extra CI time
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
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()

202
	var cids []cid.Cid
203 204 205 206 207 208 209 210
	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)
		}
	}

211 212 213 214 215 216 217
	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)
218 219
	}
}
220
*/
221 222 223 224 225

func TestUponCacheMissProvidersAreReadFromDatastore(t *testing.T) {
	old := lruCacheSize
	lruCacheSize = 1
	defer func() { lruCacheSize = old }()
Steven Allen's avatar
Steven Allen committed
226 227
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
228 229

	p1, p2 := peer.ID("a"), peer.ID("b")
230 231
	c1 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("1")))
	c2 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("2")))
232 233 234 235 236 237 238 239 240 241 242 243 244
	pm := NewProviderManager(ctx, p1, ds.NewMapDatastore())

	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))
	}
}