blockstore_test.go 5.67 KB
Newer Older
1 2 3 4
package blockstore

import (
	"bytes"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
5
	"fmt"
6 7
	"testing"

Jeromy's avatar
Jeromy committed
8 9 10
	ds "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore"
	dsq "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/query"
	ds_sync "gx/ipfs/QmNgqJarToRiq2GBaPJhkmW4B5BxS5B74E1rkGvv2JoaTp/go-datastore/sync"
11
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
12
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
13

14
	blocks "github.com/ipfs/go-ipfs/blocks"
15
	key "github.com/ipfs/go-ipfs/blocks/key"
16 17 18 19
)

func TestGetWhenKeyNotPresent(t *testing.T) {
	bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
20
	bl, err := bs.Get(key.Key("not present"))
21

22 23 24 25 26
	if bl != nil {
		t.Error("nil block expected")
	}
	if err == nil {
		t.Error("error expected, got nil")
27 28 29
	}
}

jbenet's avatar
jbenet committed
30 31 32 33 34 35 36 37
func TestGetWhenKeyIsEmptyString(t *testing.T) {
	bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
	_, err := bs.Get(key.Key(""))
	if err != ErrNotFound {
		t.Fail()
	}
}

38 39 40 41 42 43 44 45 46 47 48 49 50
func TestPutThenGetBlock(t *testing.T) {
	bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
	block := blocks.NewBlock([]byte("some data"))

	err := bs.Put(block)
	if err != nil {
		t.Fatal(err)
	}

	blockFromBlockstore, err := bs.Get(block.Key())
	if err != nil {
		t.Fatal(err)
	}
51
	if !bytes.Equal(block.Data(), blockFromBlockstore.Data()) {
52 53 54 55
		t.Fail()
	}
}

56
func TestRuntimeHashing(t *testing.T) {
57 58 59 60 61 62
	orginalDebug := u.Debug
	defer (func() {
		u.Debug = orginalDebug
	})()
	u.Debug = false

63 64 65 66
	bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
	bl := blocks.NewBlock([]byte("some data"))
	blBad, err := blocks.NewBlockWithHash([]byte("some other data"), bl.Key().ToMultihash())
	if err != nil {
67
		t.Fatal("debug is off, still got an error")
68
	}
69
	bl2 := blocks.NewBlock([]byte("some other data"))
70
	bs.Put(blBad)
71
	bs.Put(bl2)
72 73 74
	bs.RuntimeHashing(true)

	if _, err := bs.Get(bl.Key()); err != ErrHashMismatch {
75
		t.Fatalf("expected '%v' got '%v'\n", ErrHashMismatch, err)
76
	}
77 78 79 80

	if b, err := bs.Get(bl2.Key()); err != nil || b.String() != bl2.String() {
		t.Fatal("got wrong blocks")
	}
81 82
}

83
func newBlockStoreWithKeys(t *testing.T, d ds.Datastore, N int) (Blockstore, []key.Key) {
84 85 86 87
	if d == nil {
		d = ds.NewMapDatastore()
	}
	bs := NewBlockstore(ds_sync.MutexWrap(d))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
88

89
	keys := make([]key.Key, N)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
90 91 92 93 94 95 96 97
	for i := 0; i < N; i++ {
		block := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i)))
		err := bs.Put(block)
		if err != nil {
			t.Fatal(err)
		}
		keys[i] = block.Key()
	}
98 99 100
	return bs, keys
}

101 102
func collect(ch <-chan key.Key) []key.Key {
	var keys []key.Key
103 104 105 106 107 108
	for k := range ch {
		keys = append(keys, k)
	}
	return keys
}

109 110
func TestAllKeysSimple(t *testing.T) {
	bs, keys := newBlockStoreWithKeys(t, nil, 100)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
111

112
	ctx := context.Background()
113
	ch, err := bs.AllKeysChan(ctx)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
114 115 116
	if err != nil {
		t.Fatal(err)
	}
117 118
	keys2 := collect(ch)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
119
	// for _, k2 := range keys2 {
Michael Muré's avatar
Michael Muré committed
120
	// 	t.Log("found ", k2.B58String())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
121 122 123
	// }

	expectMatches(t, keys, keys2)
124
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
125

126 127 128 129 130 131 132 133 134 135 136 137
func TestAllKeysRespectsContext(t *testing.T) {
	N := 100

	d := &queryTestDS{ds: ds.NewMapDatastore()}
	bs, _ := newBlockStoreWithKeys(t, d, N)

	started := make(chan struct{}, 1)
	done := make(chan struct{}, 1)
	errors := make(chan error, 100)

	getKeys := func(ctx context.Context) {
		started <- struct{}{}
138
		ch, err := bs.AllKeysChan(ctx) // once without cancelling
139 140 141
		if err != nil {
			errors <- err
		}
142
		_ = collect(ch)
143 144 145 146
		done <- struct{}{}
		errors <- nil // a nil one to signal break
	}

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	var results dsq.Results
	var resultsmu = make(chan struct{})
	resultChan := make(chan dsq.Result)
	d.SetFunc(func(q dsq.Query) (dsq.Results, error) {
		results = dsq.ResultsWithChan(q, resultChan)
		resultsmu <- struct{}{}
		return results, nil
	})

	go getKeys(context.Background())

	// make sure it's waiting.
	<-started
	<-resultsmu
	select {
	case <-done:
		t.Fatal("sync is wrong")
	case <-results.Process().Closing():
		t.Fatal("should not be closing")
	case <-results.Process().Closed():
		t.Fatal("should not be closed")
	default:
169 170
	}

171 172 173 174 175
	e := dsq.Entry{Key: BlockPrefix.ChildString("foo").String()}
	resultChan <- dsq.Result{Entry: e} // let it go.
	close(resultChan)
	<-done                       // should be done now.
	<-results.Process().Closed() // should be closed now
176

177 178 179 180
	// print any errors
	for err := range errors {
		if err == nil {
			break
181
		}
182
		t.Error(err)
183
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
184 185 186

}

187 188 189 190
func TestValueTypeMismatch(t *testing.T) {
	block := blocks.NewBlock([]byte("some data"))

	datastore := ds.NewMapDatastore()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
191 192
	k := BlockPrefix.Child(block.Key().DsKey())
	datastore.Put(k, "data that isn't a block!")
193 194 195 196 197 198 199 200

	blockstore := NewBlockstore(ds_sync.MutexWrap(datastore))

	_, err := blockstore.Get(block.Key())
	if err != ValueTypeMismatch {
		t.Fatal(err)
	}
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
201

202
func expectMatches(t *testing.T, expect, actual []key.Key) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

	if len(expect) != len(actual) {
		t.Errorf("expect and actual differ: %d != %d", len(expect), len(actual))
	}
	for _, ek := range expect {
		found := false
		for _, ak := range actual {
			if ek == ak {
				found = true
			}
		}
		if !found {
			t.Error("expected key not found: ", ek)
		}
	}
}
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

type queryTestDS struct {
	cb func(q dsq.Query) (dsq.Results, error)
	ds ds.Datastore
}

func (c *queryTestDS) SetFunc(f func(dsq.Query) (dsq.Results, error)) { c.cb = f }

func (c *queryTestDS) Put(key ds.Key, value interface{}) (err error) {
	return c.ds.Put(key, value)
}

func (c *queryTestDS) Get(key ds.Key) (value interface{}, err error) {
	return c.ds.Get(key)
}

func (c *queryTestDS) Has(key ds.Key) (exists bool, err error) {
	return c.ds.Has(key)
}

func (c *queryTestDS) Delete(key ds.Key) (err error) {
	return c.ds.Delete(key)
}

func (c *queryTestDS) Query(q dsq.Query) (dsq.Results, error) {
	if c.cb != nil {
		return c.cb(q)
	}
	return c.ds.Query(q)
}
249 250 251 252

func (c *queryTestDS) Batch() (ds.Batch, error) {
	return ds.NewBasicBatch(c), nil
}