github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/blobserver/localdisk/localdisk_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  	"path/filepath"
    24  	"runtime"
    25  	"strconv"
    26  	"sync"
    27  	"testing"
    28  
    29  	"camlistore.org/pkg/blob"
    30  	"camlistore.org/pkg/blobserver"
    31  	"camlistore.org/pkg/blobserver/storagetest"
    32  	"camlistore.org/pkg/test"
    33  	. "camlistore.org/pkg/test/asserts"
    34  )
    35  
    36  func cleanUp(ds *DiskStorage) {
    37  	os.RemoveAll(ds.root)
    38  }
    39  
    40  var (
    41  	epochLock sync.Mutex
    42  	rootEpoch = 0
    43  )
    44  
    45  func NewStorage(t *testing.T) *DiskStorage {
    46  	epochLock.Lock()
    47  	rootEpoch++
    48  	path := fmt.Sprintf("%s/camli-testroot-%d-%d", os.TempDir(), os.Getpid(), rootEpoch)
    49  	epochLock.Unlock()
    50  	if err := os.Mkdir(path, 0755); err != nil {
    51  		t.Fatalf("Failed to create temp directory %q: %v", path, err)
    52  	}
    53  	ds, err := New(path)
    54  	if err != nil {
    55  		t.Fatalf("Failed to run New: %v", err)
    56  	}
    57  	return ds
    58  }
    59  
    60  func TestUploadDup(t *testing.T) {
    61  	ds := NewStorage(t)
    62  	defer cleanUp(ds)
    63  	tb := &test.Blob{"Foo"}
    64  	tb.MustUpload(t, ds)
    65  	tb.MustUpload(t, ds)
    66  }
    67  
    68  func TestReceiveStat(t *testing.T) {
    69  	ds := NewStorage(t)
    70  	defer cleanUp(ds)
    71  
    72  	tb := &test.Blob{"Foo"}
    73  	tb.MustUpload(t, ds)
    74  
    75  	ch := make(chan blob.SizedRef, 0)
    76  	errch := make(chan error, 1)
    77  	go func() {
    78  		errch <- ds.StatBlobs(ch, tb.BlobRefSlice())
    79  		close(ch)
    80  	}()
    81  	got := 0
    82  	for sb := range ch {
    83  		got++
    84  		tb.AssertMatches(t, sb)
    85  		break
    86  	}
    87  	AssertInt(t, 1, got, "number stat results")
    88  	AssertNil(t, <-errch, "result from stat")
    89  }
    90  
    91  func TestMultiStat(t *testing.T) {
    92  	ds := NewStorage(t)
    93  	defer cleanUp(ds)
    94  
    95  	blobfoo := &test.Blob{"foo"}
    96  	blobbar := &test.Blob{"bar!"}
    97  	blobfoo.MustUpload(t, ds)
    98  	blobbar.MustUpload(t, ds)
    99  
   100  	need := make(map[blob.Ref]bool)
   101  	need[blobfoo.BlobRef()] = true
   102  	need[blobbar.BlobRef()] = true
   103  
   104  	blobs := []blob.Ref{blobfoo.BlobRef(), blobbar.BlobRef()}
   105  
   106  	// In addition to the two "foo" and "bar" blobs, add
   107  	// maxParallelStats other dummy blobs, to exercise the stat
   108  	// rate-limiting (which had a deadlock once after a cleanup)
   109  	for i := 0; i < maxParallelStats; i++ {
   110  		blobs = append(blobs, blob.SHA1FromString(strconv.Itoa(i)))
   111  	}
   112  
   113  	ch := make(chan blob.SizedRef, 0)
   114  	errch := make(chan error, 1)
   115  	go func() {
   116  		errch <- ds.StatBlobs(ch, blobs)
   117  		close(ch)
   118  	}()
   119  	got := 0
   120  	for sb := range ch {
   121  		got++
   122  		if !need[sb.Ref] {
   123  			t.Errorf("didn't need %s", sb.Ref)
   124  		}
   125  		delete(need, sb.Ref)
   126  	}
   127  	if want := 2; got != want {
   128  		t.Errorf("number stats = %d; want %d", got, want)
   129  	}
   130  	if err := <-errch; err != nil {
   131  		t.Errorf("StatBlobs: %v", err)
   132  	}
   133  	if len(need) != 0 {
   134  		t.Errorf("Not all stat results returned; still need %d", len(need))
   135  	}
   136  }
   137  
   138  func TestMissingGetReturnsNoEnt(t *testing.T) {
   139  	ds := NewStorage(t)
   140  	defer cleanUp(ds)
   141  	foo := &test.Blob{"foo"}
   142  
   143  	blob, _, err := ds.Fetch(foo.BlobRef())
   144  	if err != os.ErrNotExist {
   145  		t.Errorf("expected ErrNotExist; got %v", err)
   146  	}
   147  	if blob != nil {
   148  		t.Errorf("expected nil blob; got a value")
   149  	}
   150  }
   151  
   152  func rename(old, new string) error {
   153  	if err := os.Rename(old, new); err != nil {
   154  		if renameErr := mapRenameError(err, old, new); renameErr != nil {
   155  			return err
   156  		}
   157  	}
   158  	return nil
   159  }
   160  
   161  type file struct {
   162  	name     string
   163  	contents string
   164  }
   165  
   166  func TestRename(t *testing.T) {
   167  	if runtime.GOOS != "windows" {
   168  		t.Skip("Skipping test if not on windows")
   169  	}
   170  	files := []file{
   171  		file{name: filepath.Join(os.TempDir(), "foo"), contents: "foo"},
   172  		file{name: filepath.Join(os.TempDir(), "bar"), contents: "barr"},
   173  		file{name: filepath.Join(os.TempDir(), "baz"), contents: "foo"},
   174  	}
   175  	for _, v := range files {
   176  		if err := ioutil.WriteFile(v.name, []byte(v.contents), 0755); err != nil {
   177  			t.Fatal(err)
   178  		}
   179  	}
   180  
   181  	// overwriting "bar" with "foo" should not be allowed
   182  	if err := rename(files[0].name, files[1].name); err == nil {
   183  		t.Fatalf("Renaming %v into %v should not succeed", files[0].name, files[1].name)
   184  	}
   185  
   186  	// but overwriting "baz" with "foo" is ok because they have the same
   187  	// contents
   188  	if err := rename(files[0].name, files[2].name); err != nil {
   189  		t.Fatal(err)
   190  	}
   191  }
   192  
   193  func TestLocaldisk(t *testing.T) {
   194  	storagetest.Test(t, func(t *testing.T) (blobserver.Storage, func()) {
   195  		ds := NewStorage(t)
   196  		return ds, func() { cleanUp(ds) }
   197  	})
   198  }