github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/blocks/blockstore/blockstore_test.go (about) 1 package blockstore 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" 9 dsq "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/query" 10 ds_sync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" 11 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" 12 13 blocks "github.com/ipfs/go-ipfs/blocks" 14 key "github.com/ipfs/go-ipfs/blocks/key" 15 ) 16 17 // TODO(brian): TestGetReturnsNil 18 19 func TestGetWhenKeyNotPresent(t *testing.T) { 20 bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore())) 21 _, err := bs.Get(key.Key("not present")) 22 23 if err != nil { 24 t.Log("As expected, block is not present") 25 return 26 } 27 t.Fail() 28 } 29 30 func TestPutThenGetBlock(t *testing.T) { 31 bs := NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore())) 32 block := blocks.NewBlock([]byte("some data")) 33 34 err := bs.Put(block) 35 if err != nil { 36 t.Fatal(err) 37 } 38 39 blockFromBlockstore, err := bs.Get(block.Key()) 40 if err != nil { 41 t.Fatal(err) 42 } 43 if !bytes.Equal(block.Data, blockFromBlockstore.Data) { 44 t.Fail() 45 } 46 } 47 48 func newBlockStoreWithKeys(t *testing.T, d ds.Datastore, N int) (Blockstore, []key.Key) { 49 if d == nil { 50 d = ds.NewMapDatastore() 51 } 52 bs := NewBlockstore(ds_sync.MutexWrap(d)) 53 54 keys := make([]key.Key, N) 55 for i := 0; i < N; i++ { 56 block := blocks.NewBlock([]byte(fmt.Sprintf("some data %d", i))) 57 err := bs.Put(block) 58 if err != nil { 59 t.Fatal(err) 60 } 61 keys[i] = block.Key() 62 } 63 return bs, keys 64 } 65 66 func collect(ch <-chan key.Key) []key.Key { 67 var keys []key.Key 68 for k := range ch { 69 keys = append(keys, k) 70 } 71 return keys 72 } 73 74 func TestAllKeysSimple(t *testing.T) { 75 bs, keys := newBlockStoreWithKeys(t, nil, 100) 76 77 ctx := context.Background() 78 ch, err := bs.AllKeysChan(ctx) 79 if err != nil { 80 t.Fatal(err) 81 } 82 keys2 := collect(ch) 83 84 // for _, k2 := range keys2 { 85 // t.Log("found ", k2.Pretty()) 86 // } 87 88 expectMatches(t, keys, keys2) 89 } 90 91 func TestAllKeysRespectsContext(t *testing.T) { 92 N := 100 93 94 d := &queryTestDS{ds: ds.NewMapDatastore()} 95 bs, _ := newBlockStoreWithKeys(t, d, N) 96 97 started := make(chan struct{}, 1) 98 done := make(chan struct{}, 1) 99 errors := make(chan error, 100) 100 101 getKeys := func(ctx context.Context) { 102 started <- struct{}{} 103 ch, err := bs.AllKeysChan(ctx) // once without cancelling 104 if err != nil { 105 errors <- err 106 } 107 _ = collect(ch) 108 done <- struct{}{} 109 errors <- nil // a nil one to signal break 110 } 111 112 // Once without context, to make sure it all works 113 { 114 var results dsq.Results 115 var resultsmu = make(chan struct{}) 116 resultChan := make(chan dsq.Result) 117 d.SetFunc(func(q dsq.Query) (dsq.Results, error) { 118 results = dsq.ResultsWithChan(q, resultChan) 119 resultsmu <- struct{}{} 120 return results, nil 121 }) 122 123 go getKeys(context.Background()) 124 125 // make sure it's waiting. 126 <-started 127 <-resultsmu 128 select { 129 case <-done: 130 t.Fatal("sync is wrong") 131 case <-results.Process().Closing(): 132 t.Fatal("should not be closing") 133 case <-results.Process().Closed(): 134 t.Fatal("should not be closed") 135 default: 136 } 137 138 e := dsq.Entry{Key: BlockPrefix.ChildString("foo").String()} 139 resultChan <- dsq.Result{Entry: e} // let it go. 140 close(resultChan) 141 <-done // should be done now. 142 <-results.Process().Closed() // should be closed now 143 144 // print any errors 145 for err := range errors { 146 if err == nil { 147 break 148 } 149 t.Error(err) 150 } 151 } 152 153 // Once with 154 { 155 var results dsq.Results 156 var resultsmu = make(chan struct{}) 157 resultChan := make(chan dsq.Result) 158 d.SetFunc(func(q dsq.Query) (dsq.Results, error) { 159 results = dsq.ResultsWithChan(q, resultChan) 160 resultsmu <- struct{}{} 161 return results, nil 162 }) 163 164 ctx, cancel := context.WithCancel(context.Background()) 165 go getKeys(ctx) 166 167 // make sure it's waiting. 168 <-started 169 <-resultsmu 170 select { 171 case <-done: 172 t.Fatal("sync is wrong") 173 case <-results.Process().Closing(): 174 t.Fatal("should not be closing") 175 case <-results.Process().Closed(): 176 t.Fatal("should not be closed") 177 default: 178 } 179 180 cancel() // let it go. 181 182 select { 183 case <-done: 184 t.Fatal("sync is wrong") 185 case <-results.Process().Closed(): 186 t.Fatal("should not be closed") // should not be closed yet. 187 case <-results.Process().Closing(): 188 // should be closing now! 189 t.Log("closing correctly at this point.") 190 } 191 192 close(resultChan) 193 <-done // should be done now. 194 <-results.Process().Closed() // should be closed now 195 196 // print any errors 197 for err := range errors { 198 if err == nil { 199 break 200 } 201 t.Error(err) 202 } 203 } 204 205 } 206 207 func TestValueTypeMismatch(t *testing.T) { 208 block := blocks.NewBlock([]byte("some data")) 209 210 datastore := ds.NewMapDatastore() 211 k := BlockPrefix.Child(block.Key().DsKey()) 212 datastore.Put(k, "data that isn't a block!") 213 214 blockstore := NewBlockstore(ds_sync.MutexWrap(datastore)) 215 216 _, err := blockstore.Get(block.Key()) 217 if err != ValueTypeMismatch { 218 t.Fatal(err) 219 } 220 } 221 222 func expectMatches(t *testing.T, expect, actual []key.Key) { 223 224 if len(expect) != len(actual) { 225 t.Errorf("expect and actual differ: %d != %d", len(expect), len(actual)) 226 } 227 for _, ek := range expect { 228 found := false 229 for _, ak := range actual { 230 if ek == ak { 231 found = true 232 } 233 } 234 if !found { 235 t.Error("expected key not found: ", ek) 236 } 237 } 238 } 239 240 type queryTestDS struct { 241 cb func(q dsq.Query) (dsq.Results, error) 242 ds ds.Datastore 243 } 244 245 func (c *queryTestDS) SetFunc(f func(dsq.Query) (dsq.Results, error)) { c.cb = f } 246 247 func (c *queryTestDS) Put(key ds.Key, value interface{}) (err error) { 248 return c.ds.Put(key, value) 249 } 250 251 func (c *queryTestDS) Get(key ds.Key) (value interface{}, err error) { 252 return c.ds.Get(key) 253 } 254 255 func (c *queryTestDS) Has(key ds.Key) (exists bool, err error) { 256 return c.ds.Has(key) 257 } 258 259 func (c *queryTestDS) Delete(key ds.Key) (err error) { 260 return c.ds.Delete(key) 261 } 262 263 func (c *queryTestDS) Query(q dsq.Query) (dsq.Results, error) { 264 if c.cb != nil { 265 return c.cb(q) 266 } 267 return c.ds.Query(q) 268 } 269 270 func (c *queryTestDS) Batch() (ds.Batch, error) { 271 return ds.NewBasicBatch(c), nil 272 }