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  }