github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/blobserver/localdisk/enumerate_test.go (about)

     1  /*
     2  Copyright 2011 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package localdisk
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"sort"
    24  	"testing"
    25  
    26  	"camlistore.org/pkg/blob"
    27  	"camlistore.org/pkg/context"
    28  	"camlistore.org/pkg/test"
    29  	. "camlistore.org/pkg/test/asserts"
    30  )
    31  
    32  func TestEnumerate(t *testing.T) {
    33  	ds := NewStorage(t)
    34  	defer cleanUp(ds)
    35  
    36  	// For test simplicity foo, bar, and baz all have ascending
    37  	// sha1s and lengths.
    38  	foo := &test.Blob{"foo"}   // 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
    39  	bar := &test.Blob{"baar"}  // b23361951dde70cb3eca44c0c674181673a129dc
    40  	baz := &test.Blob{"bazzz"} // e0eb17003ce1c2812ca8f19089fff44ca32b3710
    41  	foo.MustUpload(t, ds)
    42  	bar.MustUpload(t, ds)
    43  	baz.MustUpload(t, ds)
    44  
    45  	limit := 5000
    46  	ch := make(chan blob.SizedRef)
    47  	errCh := make(chan error)
    48  	go func() {
    49  		errCh <- ds.EnumerateBlobs(context.New(), ch, "", limit)
    50  	}()
    51  
    52  	var (
    53  		sb blob.SizedRef
    54  		ok bool
    55  	)
    56  	sb, ok = <-ch
    57  	Assert(t, ok, "got 1st blob")
    58  	ExpectInt(t, 3, int(sb.Size), "1st blob size")
    59  	sb, ok = <-ch
    60  	Assert(t, ok, "got 2nd blob")
    61  	ExpectInt(t, 4, int(sb.Size), "2nd blob size")
    62  	sb, ok = <-ch
    63  	Assert(t, ok, "got 3rd blob")
    64  	ExpectInt(t, 5, int(sb.Size), "3rd blob size")
    65  	sb, ok = <-ch
    66  	Assert(t, !ok, "got channel close")
    67  	ExpectNil(t, <-errCh, "EnumerateBlobs return value")
    68  
    69  	// Now again, but skipping foo's blob
    70  	ch = make(chan blob.SizedRef)
    71  	go func() {
    72  		errCh <- ds.EnumerateBlobs(context.New(),
    73  			ch,
    74  			foo.BlobRef().String(),
    75  			limit)
    76  	}()
    77  	sb, ok = <-ch
    78  	Assert(t, ok, "got 1st blob, skipping foo")
    79  	ExpectInt(t, 4, int(sb.Size), "blob size")
    80  	sb, ok = <-ch
    81  	Assert(t, ok, "got 2nd blob, skipping foo")
    82  	ExpectInt(t, 5, int(sb.Size), "blob size")
    83  	sb, ok = <-ch
    84  	Assert(t, !ok, "got final nil")
    85  	ExpectNil(t, <-errCh, "EnumerateBlobs return value")
    86  }
    87  
    88  func TestEnumerateEmpty(t *testing.T) {
    89  	ds := NewStorage(t)
    90  	defer cleanUp(ds)
    91  
    92  	limit := 5000
    93  	ch := make(chan blob.SizedRef)
    94  	errCh := make(chan error)
    95  	go func() {
    96  		errCh <- ds.EnumerateBlobs(context.New(), ch, "", limit)
    97  	}()
    98  
    99  	_, ok := <-ch
   100  	Expect(t, !ok, "no first blob")
   101  	ExpectNil(t, <-errCh, "EnumerateBlobs return value")
   102  }
   103  
   104  type SortedSizedBlobs []blob.SizedRef
   105  
   106  func (sb SortedSizedBlobs) Len() int {
   107  	return len(sb)
   108  }
   109  
   110  func (sb SortedSizedBlobs) Less(i, j int) bool {
   111  	return sb[i].Ref.String() < sb[j].Ref.String()
   112  }
   113  
   114  func (sb SortedSizedBlobs) Swap(i, j int) {
   115  	panic("not needed")
   116  }
   117  
   118  func TestEnumerateIsSorted(t *testing.T) {
   119  	ds := NewStorage(t)
   120  	defer cleanUp(ds)
   121  
   122  	const blobsToMake = 250
   123  	t.Logf("Uploading test blobs...")
   124  	for i := 0; i < blobsToMake; i++ {
   125  		blob := &test.Blob{fmt.Sprintf("blob-%d", i)}
   126  		blob.MustUpload(t, ds)
   127  	}
   128  
   129  	// Make some fake blobs in other partitions to confuse the
   130  	// enumerate code.
   131  	// TODO(bradfitz): remove this eventually.
   132  	fakeDir := ds.root + "/partition/queue-indexer/sha1/1f0/710"
   133  	ExpectNil(t, os.MkdirAll(fakeDir, 0755), "creating fakeDir")
   134  	ExpectNil(t, ioutil.WriteFile(fakeDir+"/sha1-1f07105465650aa243cfc1b1bbb1c68ea95c6812.dat",
   135  		[]byte("fake file"), 0644), "writing fake blob")
   136  
   137  	// And the same for a "cache" directory, used by the default configuration.
   138  	fakeDir = ds.root + "/cache/sha1/1f0/710"
   139  	ExpectNil(t, os.MkdirAll(fakeDir, 0755), "creating cache fakeDir")
   140  	ExpectNil(t, ioutil.WriteFile(fakeDir+"/sha1-1f07105465650aa243cfc1b1bbb1c68ea95c6812.dat",
   141  		[]byte("fake file"), 0644), "writing fake blob")
   142  
   143  	var tests = []struct {
   144  		limit int
   145  		after string
   146  	}{
   147  		{200, ""},
   148  		{blobsToMake, ""},
   149  		{200, "sha1-2"},
   150  		{200, "sha1-3"},
   151  		{200, "sha1-4"},
   152  		{200, "sha1-5"},
   153  		{200, "sha1-e"},
   154  		{200, "sha1-f"},
   155  		{200, "sha1-ff"},
   156  	}
   157  	for _, test := range tests {
   158  		limit := test.limit
   159  		ch := make(chan blob.SizedRef)
   160  		errCh := make(chan error)
   161  		go func() {
   162  			errCh <- ds.EnumerateBlobs(context.New(), ch, test.after, limit)
   163  		}()
   164  		got := make([]blob.SizedRef, 0, blobsToMake)
   165  		for sb := range ch {
   166  			got = append(got, sb)
   167  		}
   168  		if err := <-errCh; err != nil {
   169  			t.Errorf("case %+v; enumerate error: %v", test, err)
   170  			continue
   171  		}
   172  		if !sort.IsSorted(SortedSizedBlobs(got)) {
   173  			t.Errorf("case %+v: expected sorted; got: %q", test, got)
   174  		}
   175  	}
   176  }