providers_test.go 5.08 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 21 22 23
)

func TestProviderManager(t *testing.T) {
	ctx := context.Background()
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
24
	a := cid.NewCidV0(u.Hash([]byte("test")))
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
	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 }()

	ctx := context.Background()
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
	defer p.proc.Close()

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

51 52
	for _, c := range cids {
		resp := p.GetProviders(ctx, c)
53 54 55 56 57 58 59 60 61 62 63 64
		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()

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

Jeromy's avatar
Jeromy committed
71 72 73 74 75 76
	err := writeProviderEntry(dstore, k, p1, pt1)
	if err != nil {
		t.Fatal(err)
	}

	err = writeProviderEntry(dstore, k, p2, pt2)
77 78 79 80 81 82 83 84 85
	if err != nil {
		t.Fatal(err)
	}

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

Jeromy's avatar
Jeromy committed
86 87 88 89 90
	lt1, ok := pset.set[p1]
	if !ok {
		t.Fatal("failed to load set correctly")
	}

91 92
	if !pt1.Equal(lt1) {
		t.Fatalf("time wasnt serialized correctly, %v != %v", pt1, lt1)
Jeromy's avatar
Jeromy committed
93 94 95
	}

	lt2, ok := pset.set[p2]
96 97 98 99
	if !ok {
		t.Fatal("failed to load set correctly")
	}

Jeromy's avatar
Jeromy committed
100
	if pt2 != lt2 {
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
		t.Fatal("time wasnt serialized correctly")
	}
}

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

	ctx := context.Background()
	mid := peer.ID("testing")
	p := NewProviderManager(ctx, mid, ds.NewMapDatastore())

	peers := []peer.ID{"a", "b"}
120
	var cids []*cid.Cid
121
	for i := 0; i < 10; i++ {
122 123 124 125
		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])
126 127 128
	}

	for i := 0; i < 10; i++ {
129
		out := p.GetProviders(ctx, cids[i])
130 131 132 133 134 135 136
		if len(out) != 2 {
			t.Fatal("expected providers to still be there")
		}
	}

	time.Sleep(time.Second)
	for i := 0; i < 10; i++ {
137 138 139
		out := p.GetProviders(ctx, cids[i])
		if len(out) > 0 {
			t.Fatal("expected providers to be cleaned up, got: ", out)
140 141 142 143 144 145 146
		}
	}

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

147
	proviter, err := p.getProvKeys()
148 149 150 151
	if err != nil {
		t.Fatal(err)
	}

152 153
	_, ok := proviter()
	if ok {
154 155 156
		t.Fatal("expected everything to be cleaned out of the datastore")
	}
}
157

158 159 160 161
var _ = ioutil.NopCloser
var _ = os.DevNull

/* This can be used for profiling. Keeping it commented out for now to avoid incurring extra CI time
162 163 164 165 166 167 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 202 203 204
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()

	var cids []*cid.Cid
	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)
		}
	}

205 206 207 208 209 210 211
	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)
212 213
	}
}
214
*/
215 216 217 218 219 220 221 222

func TestUponCacheMissProvidersAreReadFromDatastore(t *testing.T) {
	old := lruCacheSize
	lruCacheSize = 1
	defer func() { lruCacheSize = old }()
	ctx := context.Background()

	p1, p2 := peer.ID("a"), peer.ID("b")
223 224
	c1 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("1")))
	c2 := cid.NewCidV1(cid.DagCBOR, u.Hash([]byte("2")))
225 226 227 228 229 230 231 232 233 234 235 236 237
	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))
	}
}