예제 #1
0
파일: ds_test.go 프로젝트: ipfs/go-blocks
func expectMatches(t *testing.T, expect []string, actualR dsq.Results) {
	actual, err := actualR.Rest()
	if err != nil {
		t.Error(err)
	}

	if len(actual) != len(expect) {
		t.Error("not enough", expect, actual)
	}
	for _, k := range expect {
		found := false
		for _, e := range actual {
			if e.Key == k {
				found = true
			}
		}
		if !found {
			t.Error(k, "not found")
		}
	}
}
예제 #2
0
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)
		}
	}

}