github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/environs/filestorage/filestorage_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package filestorage_test 5 6 // The filestorage structs are used as stubs in tests. 7 // The tests defined herein are simple smoke tests for the 8 // required reader and writer functionality. 9 10 import ( 11 "bytes" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "strings" 16 "testing" 17 18 "github.com/juju/errors" 19 jc "github.com/juju/testing/checkers" 20 "github.com/juju/utils" 21 gc "launchpad.net/gocheck" 22 23 "github.com/juju/juju/environs/filestorage" 24 "github.com/juju/juju/environs/storage" 25 ) 26 27 func TestPackage(t *testing.T) { 28 gc.TestingT(t) 29 } 30 31 type filestorageSuite struct { 32 dir string 33 reader storage.StorageReader 34 writer storage.StorageWriter 35 } 36 37 var _ = gc.Suite(&filestorageSuite{}) 38 39 func (s *filestorageSuite) SetUpTest(c *gc.C) { 40 s.dir = c.MkDir() 41 var err error 42 s.reader, err = filestorage.NewFileStorageReader(s.dir) 43 c.Assert(err, gc.IsNil) 44 s.writer, err = filestorage.NewFileStorageWriter(s.dir) 45 c.Assert(err, gc.IsNil) 46 } 47 48 func (s *filestorageSuite) createFile(c *gc.C, name string) (fullpath string, data []byte) { 49 fullpath = filepath.Join(s.dir, name) 50 dir := filepath.Dir(fullpath) 51 c.Assert(os.MkdirAll(dir, 0755), gc.IsNil) 52 data = []byte{1, 2, 3, 4, 5} 53 err := ioutil.WriteFile(fullpath, data, 0644) 54 c.Assert(err, gc.IsNil) 55 return fullpath, data 56 } 57 58 func (s *filestorageSuite) TestList(c *gc.C) { 59 names := []string{ 60 "a/b/c", 61 "a/bb", 62 "a/c", 63 "aa", 64 "b/c/d", 65 } 66 for _, name := range names { 67 s.createFile(c, name) 68 } 69 type test struct { 70 prefix string 71 expected []string 72 } 73 for i, test := range []test{ 74 {"a", []string{"a/b/c", "a/bb", "a/c", "aa"}}, 75 {"a/b", []string{"a/b/c", "a/bb"}}, 76 {"a/b/c", []string{"a/b/c"}}, 77 {"", names}, 78 } { 79 c.Logf("test %d: prefix=%q", i, test.prefix) 80 files, err := storage.List(s.reader, test.prefix) 81 c.Assert(err, gc.IsNil) 82 c.Assert(files, gc.DeepEquals, test.expected) 83 } 84 } 85 86 func (s *filestorageSuite) TestListHidesTempDir(c *gc.C) { 87 err := s.writer.Put("test-write", bytes.NewReader(nil), 0) 88 c.Assert(err, gc.IsNil) 89 files, err := storage.List(s.reader, "") 90 c.Assert(err, gc.IsNil) 91 c.Check(files, gc.DeepEquals, []string{"test-write"}) 92 files, err = storage.List(s.reader, "no-such-directory") 93 c.Assert(err, gc.IsNil) 94 c.Check(files, gc.DeepEquals, []string(nil)) 95 // We also pretend the .tmp directory doesn't exist. If you call a 96 // directory that doesn't exist, we just return an empty list of 97 // strings, so we force the same behavior for '.tmp' 98 // we poke in a file so it would have something to return 99 s.createFile(c, ".tmp/test-file") 100 files, err = storage.List(s.reader, ".tmp") 101 c.Assert(err, gc.IsNil) 102 c.Check(files, gc.DeepEquals, []string(nil)) 103 // For consistency, we refuse all other possibilities as well 104 s.createFile(c, ".tmp/foo/bar") 105 files, err = storage.List(s.reader, ".tmp/foo") 106 c.Assert(err, gc.IsNil) 107 c.Check(files, gc.DeepEquals, []string(nil)) 108 s.createFile(c, ".tmpother/foo") 109 files, err = storage.List(s.reader, ".tmpother") 110 c.Assert(err, gc.IsNil) 111 c.Check(files, gc.DeepEquals, []string(nil)) 112 } 113 114 func (s *filestorageSuite) TestURL(c *gc.C) { 115 expectedpath, _ := s.createFile(c, "test-file") 116 _, file := filepath.Split(expectedpath) 117 url, err := s.reader.URL(file) 118 c.Assert(err, gc.IsNil) 119 c.Assert(url, gc.Equals, "file://"+expectedpath) 120 } 121 122 func (s *filestorageSuite) TestGet(c *gc.C) { 123 expectedpath, data := s.createFile(c, "test-file") 124 _, file := filepath.Split(expectedpath) 125 rc, err := storage.Get(s.reader, file) 126 c.Assert(err, gc.IsNil) 127 defer rc.Close() 128 c.Assert(err, gc.IsNil) 129 b, err := ioutil.ReadAll(rc) 130 c.Assert(err, gc.IsNil) 131 c.Assert(b, gc.DeepEquals, data) 132 133 // Get on a non-existant path returns errors.NotFound 134 _, err = s.reader.Get("nowhere") 135 c.Assert(err, jc.Satisfies, errors.IsNotFound) 136 137 // Get on a directory returns errors.NotFound 138 s.createFile(c, "dir/file") 139 _, err = s.reader.Get("dir") 140 c.Assert(err, jc.Satisfies, errors.IsNotFound) 141 } 142 143 func (s *filestorageSuite) TestGetRefusesTemp(c *gc.C) { 144 s.createFile(c, ".tmp/test-file") 145 _, err := storage.Get(s.reader, ".tmp/test-file") 146 c.Check(err, gc.NotNil) 147 c.Check(err, jc.Satisfies, os.IsNotExist) 148 s.createFile(c, ".tmp/foo/test-file") 149 _, err = storage.Get(s.reader, ".tmp/foo/test-file") 150 c.Check(err, gc.NotNil) 151 c.Check(err, jc.Satisfies, os.IsNotExist) 152 } 153 154 func (s *filestorageSuite) TestPut(c *gc.C) { 155 data := []byte{1, 2, 3, 4, 5} 156 err := s.writer.Put("test-write", bytes.NewReader(data), int64(len(data))) 157 c.Assert(err, gc.IsNil) 158 b, err := ioutil.ReadFile(filepath.Join(s.dir, "test-write")) 159 c.Assert(err, gc.IsNil) 160 c.Assert(b, gc.DeepEquals, data) 161 } 162 163 func (s *filestorageSuite) TestPutRefusesTmp(c *gc.C) { 164 data := []byte{1, 2, 3, 4, 5} 165 err := s.writer.Put(".tmp/test-write", bytes.NewReader(data), int64(len(data))) 166 c.Assert(err, gc.NotNil) 167 c.Check(err, jc.Satisfies, os.IsPermission) 168 c.Check(*err.(*os.PathError), gc.Equals, os.PathError{ 169 Op: "Put", 170 Path: ".tmp/test-write", 171 Err: os.ErrPermission, 172 }) 173 _, err = ioutil.ReadFile(filepath.Join(s.dir, ".tmp", "test-write")) 174 c.Assert(err, jc.Satisfies, os.IsNotExist) 175 } 176 177 func (s *filestorageSuite) TestRemove(c *gc.C) { 178 expectedpath, _ := s.createFile(c, "test-file") 179 _, file := filepath.Split(expectedpath) 180 err := s.writer.Remove(file) 181 c.Assert(err, gc.IsNil) 182 _, err = ioutil.ReadFile(expectedpath) 183 c.Assert(err, gc.Not(gc.IsNil)) 184 } 185 186 func (s *filestorageSuite) TestRemoveAll(c *gc.C) { 187 expectedpath, _ := s.createFile(c, "test-file") 188 err := s.writer.RemoveAll() 189 c.Assert(err, gc.IsNil) 190 _, err = ioutil.ReadFile(expectedpath) 191 c.Assert(err, gc.Not(gc.IsNil)) 192 } 193 194 func (s *filestorageSuite) TestPutTmpDir(c *gc.C) { 195 // Put should create and clean up the temporary directory 196 err := s.writer.Put("test-write", bytes.NewReader(nil), 0) 197 c.Assert(err, gc.IsNil) 198 _, err = os.Stat(s.dir + "/.tmp") 199 c.Assert(err, jc.Satisfies, os.IsNotExist) 200 201 // To deal with recovering from hard failure, we 202 // don't care if the temporary directory already exists. It 203 // still removes it, though. 204 err = os.Mkdir(s.dir+"/.tmp", 0755) 205 c.Assert(err, gc.IsNil) 206 err = s.writer.Put("test-write", bytes.NewReader(nil), 0) 207 c.Assert(err, gc.IsNil) 208 _, err = os.Stat(s.dir + "/.tmp") 209 c.Assert(err, jc.Satisfies, os.IsNotExist) 210 } 211 212 func (s *filestorageSuite) TestPathRelativeToHome(c *gc.C) { 213 homeDir := utils.Home() 214 tempDir, err := ioutil.TempDir(homeDir, "") 215 c.Assert(err, gc.IsNil) 216 defer os.RemoveAll(tempDir) 217 dirName := strings.Replace(tempDir, homeDir, "", -1) 218 reader, err := filestorage.NewFileStorageReader(filepath.Join("~", dirName)) 219 c.Assert(err, gc.IsNil) 220 url, err := reader.URL("") 221 c.Assert(err, gc.IsNil) 222 c.Assert(url, gc.Equals, "file://"+filepath.Join(homeDir, dirName)) 223 } 224 225 func (s *filestorageSuite) TestRelativePath(c *gc.C) { 226 dir := c.MkDir() 227 err := os.MkdirAll(filepath.Join(dir, "a", "b", "c"), os.ModePerm) 228 c.Assert(err, gc.IsNil) 229 cwd, err := os.Getwd() 230 c.Assert(err, gc.IsNil) 231 err = os.Chdir(filepath.Join(dir, "a", "b", "c")) 232 c.Assert(err, gc.IsNil) 233 defer os.Chdir(cwd) 234 reader, err := filestorage.NewFileStorageReader("../..") 235 c.Assert(err, gc.IsNil) 236 url, err := reader.URL("") 237 c.Assert(err, gc.IsNil) 238 c.Assert(url, gc.Equals, "file://"+dir+"/a") 239 }