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 }