blockstore_test.go 4.9 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"

Jakub Sztandera's avatar
Jakub Sztandera committed
8 9 10
	ds "gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore"
	dsq "gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore/query"
	ds_sync "gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore/sync"
11
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
12

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

// TODO(brian): TestGetReturnsNil

func TestGetWhenKeyNotPresent(t *testing.T) {
	bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
21
	_, err := bs.Get(key.Key("not present"))
22 23 24 25 26 27 28 29

	if err != nil {
		t.Log("As expected, block is not present")
		return
	}
	t.Fail()
}

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 newBlockStoreWithKeys(t *testing.T, d ds.Datastore, N int) (Blockstore, []key.Key) {
57 58 59 60
	if d == nil {
		d = ds.NewMapDatastore()
	}
	bs := NewBlockstore(ds_sync.MutexWrap(d))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
61

62
	keys := make([]key.Key, N)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
63 64 65 66 67 68 69 70
	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()
	}
71 72 73
	return bs, keys
}

74 75
func collect(ch <-chan key.Key) []key.Key {
	var keys []key.Key
76 77 78 79 80 81
	for k := range ch {
		keys = append(keys, k)
	}
	return keys
}

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

85
	ctx := context.Background()
86
	ch, err := bs.AllKeysChan(ctx)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
87 88 89
	if err != nil {
		t.Fatal(err)
	}
90 91
	keys2 := collect(ch)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
92
	// for _, k2 := range keys2 {
Michael Muré's avatar
Michael Muré committed
93
	// 	t.Log("found ", k2.B58String())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
94 95 96
	// }

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

99 100 101 102 103 104 105 106 107 108 109 110
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{}{}
111
		ch, err := bs.AllKeysChan(ctx) // once without cancelling
112 113 114
		if err != nil {
			errors <- err
		}
115
		_ = collect(ch)
116 117 118 119
		done <- struct{}{}
		errors <- nil // a nil one to signal break
	}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
	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:
142 143
	}

144 145 146 147 148
	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
149

150 151 152 153
	// print any errors
	for err := range errors {
		if err == nil {
			break
154
		}
155
		t.Error(err)
156
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
157 158 159

}

160 161 162 163
func TestValueTypeMismatch(t *testing.T) {
	block := blocks.NewBlock([]byte("some data"))

	datastore := ds.NewMapDatastore()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
164 165
	k := BlockPrefix.Child(block.Key().DsKey())
	datastore.Put(k, "data that isn't a block!")
166 167 168 169 170 171 172 173

	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
174

175
func expectMatches(t *testing.T, expect, actual []key.Key) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

	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)
		}
	}
}
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

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)
}
222 223 224 225

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