func TestGetBlocks(t *testing.T) { store := bstore() ex := Exchange(store) g := blocksutil.NewBlockGenerator() expected := g.Blocks(2) for _, b := range expected { if err := ex.HasBlock(context.Background(), b); err != nil { t.Fail() } } request := func() []key.Key { var ks []key.Key for _, b := range expected { ks = append(ks, b.Key()) } return ks }() received, err := ex.GetBlocks(context.Background(), request) if err != nil { t.Fatal(err) } var count int for _ = range received { count++ } if len(expected) != count { t.Fail() } }
// Context returns a context that cancels when the waitable is closing. func Context(w Waitable) context.Context { ctx, cancel := context.WithCancel(context.Background()) go func() { <-w.Closing() cancel() }() return ctx }
func TestBlockReturnsErr(t *testing.T) { off := Exchange(bstore()) _, err := off.GetBlock(context.Background(), key.Key("foo")) if err != nil { return // as desired } t.Fail() }
func ExampleWithTimeout() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) select { case <-time.After(200 * time.Millisecond): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) // prints "context deadline exceeded" } // Output: // context deadline exceeded }
func TestHasBlockReturnsNil(t *testing.T) { store := bstore() ex := Exchange(store) block := blocks.NewBlock([]byte("data")) err := ex.HasBlock(context.Background(), block) if err != nil { t.Fail() } if _, err := store.Get(block.Key()); err != nil { t.Fatal(err) } }
func TestAllKeysSimple(t *testing.T) { bs, keys := newBlockStoreWithKeys(t, nil, 100) ctx := context.Background() ch, err := bs.AllKeysChan(ctx) if err != nil { t.Fatal(err) } keys2 := collect(ch) // for _, k2 := range keys2 { // t.Log("found ", k2.Pretty()) // } expectMatches(t, keys, keys2) }
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{}{} ch, err := bs.AllKeysChan(ctx) // once without cancelling if err != nil { errors <- err } _ = collect(ch) done <- struct{}{} errors <- nil // a nil one to signal break } // Once without context, to make sure it all works { 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: } 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 // print any errors for err := range errors { if err == nil { break } t.Error(err) } } // Once with { 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 }) ctx, cancel := context.WithCancel(context.Background()) go getKeys(ctx) // 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: } cancel() // let it go. select { case <-done: t.Fatal("sync is wrong") case <-results.Process().Closed(): t.Fatal("should not be closed") // should not be closed yet. case <-results.Process().Closing(): // should be closing now! t.Log("closing correctly at this point.") } close(resultChan) <-done // should be done now. <-results.Process().Closed() // should be closed now // print any errors for err := range errors { if err == nil { break } t.Error(err) } } }