github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/environs/httpstorage/storage_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package httpstorage_test 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "net/http" 12 "path/filepath" 13 14 "github.com/juju/errors" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 18 "github.com/juju/juju/environs/httpstorage" 19 "github.com/juju/juju/environs/storage" 20 coretesting "github.com/juju/juju/testing" 21 ) 22 23 type storageSuite struct{} 24 25 var _ = gc.Suite(&storageSuite{}) 26 27 func (s *storageSuite) TestClientTLS(c *gc.C) { 28 listener, _, storageDir := startServerTLS(c) 29 defer listener.Close() 30 stor, err := httpstorage.ClientTLS(listener.Addr().String(), coretesting.CACert, testAuthkey) 31 c.Assert(err, jc.ErrorIsNil) 32 33 data := []byte("hello") 34 err = ioutil.WriteFile(filepath.Join(storageDir, "filename"), data, 0644) 35 c.Assert(err, jc.ErrorIsNil) 36 names, err := storage.List(stor, "filename") 37 c.Assert(err, jc.ErrorIsNil) 38 c.Assert(names, gc.DeepEquals, []string{"filename"}) 39 checkFileHasContents(c, stor, "filename", data) 40 41 // Put, Remove and RemoveAll should all succeed. 42 checkPutFile(c, stor, "filenamethesecond", data) 43 checkFileHasContents(c, stor, "filenamethesecond", data) 44 c.Assert(stor.Remove("filenamethesecond"), gc.IsNil) 45 c.Assert(stor.RemoveAll(), gc.IsNil) 46 } 47 48 func (s *storageSuite) TestClientTLSInvalidAuth(c *gc.C) { 49 listener, _, storageDir := startServerTLS(c) 50 defer listener.Close() 51 const invalidAuthkey = testAuthkey + "!" 52 stor, err := httpstorage.ClientTLS(listener.Addr().String(), coretesting.CACert, invalidAuthkey) 53 c.Assert(err, jc.ErrorIsNil) 54 55 // Get and List should succeed. 56 data := []byte("hello") 57 err = ioutil.WriteFile(filepath.Join(storageDir, "filename"), data, 0644) 58 c.Assert(err, jc.ErrorIsNil) 59 names, err := storage.List(stor, "filename") 60 c.Assert(err, jc.ErrorIsNil) 61 c.Assert(names, gc.DeepEquals, []string{"filename"}) 62 checkFileHasContents(c, stor, "filename", data) 63 64 // Put, Remove and RemoveAll should all fail. 65 const authErrorPattern = ".*401 Unauthorized" 66 err = putFile(c, stor, "filenamethesecond", data) 67 c.Assert(err, gc.ErrorMatches, authErrorPattern) 68 c.Assert(stor.Remove("filenamethesecond"), gc.ErrorMatches, authErrorPattern) 69 c.Assert(stor.RemoveAll(), gc.ErrorMatches, authErrorPattern) 70 } 71 72 func (s *storageSuite) TestList(c *gc.C) { 73 listener, _, _ := startServer(c) 74 defer listener.Close() 75 stor := httpstorage.Client(listener.Addr().String()) 76 names, err := storage.List(stor, "a/b/c") 77 c.Assert(err, jc.ErrorIsNil) 78 c.Assert(names, gc.HasLen, 0) 79 } 80 81 // TestPersistence tests the adding, reading, listing and removing 82 // of files from the local storage. 83 func (s *storageSuite) TestPersistence(c *gc.C) { 84 listener, _, _ := startServer(c) 85 defer listener.Close() 86 87 stor := httpstorage.Client(listener.Addr().String()) 88 names := []string{ 89 "aa", 90 "zzz/aa", 91 "zzz/bb", 92 } 93 for _, name := range names { 94 checkFileDoesNotExist(c, stor, name) 95 checkPutFile(c, stor, name, []byte(name)) 96 } 97 checkList(c, stor, "", names) 98 checkList(c, stor, "a", []string{"aa"}) 99 checkList(c, stor, "zzz/", []string{"zzz/aa", "zzz/bb"}) 100 101 storage2 := httpstorage.Client(listener.Addr().String()) 102 for _, name := range names { 103 checkFileHasContents(c, storage2, name, []byte(name)) 104 } 105 106 // remove the first file and check that the others remain. 107 err := storage2.Remove(names[0]) 108 c.Check(err, jc.ErrorIsNil) 109 110 // check that it's ok to remove a file twice. 111 err = storage2.Remove(names[0]) 112 c.Check(err, jc.ErrorIsNil) 113 114 // ... and check it's been removed in the other environment 115 checkFileDoesNotExist(c, stor, names[0]) 116 117 // ... and that the rest of the files are still around 118 checkList(c, storage2, "", names[1:]) 119 120 for _, name := range names[1:] { 121 err := storage2.Remove(name) 122 c.Assert(err, jc.ErrorIsNil) 123 } 124 125 // check they've all gone 126 checkList(c, storage2, "", nil) 127 128 // Check that RemoveAll works. 129 checkRemoveAll(c, storage2) 130 } 131 132 func checkList(c *gc.C, stor storage.StorageReader, prefix string, names []string) { 133 lnames, err := storage.List(stor, prefix) 134 c.Assert(err, jc.ErrorIsNil) 135 i := len(lnames) 136 j := len(names) 137 c.Assert(i, gc.Equals, j) 138 for i := range lnames { 139 c.Assert(lnames[i], jc.SamePath, names[i]) 140 } 141 } 142 143 type readerWithClose struct { 144 *bytes.Buffer 145 closeCalled bool 146 } 147 148 var _ io.Reader = (*readerWithClose)(nil) 149 var _ io.Closer = (*readerWithClose)(nil) 150 151 func (r *readerWithClose) Close() error { 152 r.closeCalled = true 153 return nil 154 } 155 156 func putFile(c *gc.C, stor storage.StorageWriter, name string, contents []byte) error { 157 c.Logf("check putting file %s ...", name) 158 reader := &readerWithClose{bytes.NewBuffer(contents), false} 159 err := stor.Put(name, reader, int64(len(contents))) 160 c.Assert(reader.closeCalled, jc.IsFalse) 161 return err 162 } 163 164 func checkPutFile(c *gc.C, stor storage.StorageWriter, name string, contents []byte) { 165 err := putFile(c, stor, name, contents) 166 c.Assert(err, jc.ErrorIsNil) 167 } 168 169 func checkFileDoesNotExist(c *gc.C, stor storage.StorageReader, name string) { 170 r, err := storage.Get(stor, name) 171 c.Assert(r, gc.IsNil) 172 c.Assert(err, jc.Satisfies, errors.IsNotFound) 173 } 174 175 func checkFileHasContents(c *gc.C, stor storage.StorageReader, name string, contents []byte) { 176 r, err := storage.Get(stor, name) 177 c.Assert(err, jc.ErrorIsNil) 178 c.Check(r, gc.NotNil) 179 defer r.Close() 180 data, err := ioutil.ReadAll(r) 181 c.Check(err, jc.ErrorIsNil) 182 c.Check(data, gc.DeepEquals, contents) 183 184 url, err := stor.URL(name) 185 c.Assert(err, jc.ErrorIsNil) 186 resp, err := http.Get(url) 187 c.Assert(err, jc.ErrorIsNil) 188 data, err = ioutil.ReadAll(resp.Body) 189 c.Assert(err, jc.ErrorIsNil) 190 defer resp.Body.Close() 191 c.Assert(resp.StatusCode, gc.Equals, http.StatusOK, gc.Commentf("error response: %s", data)) 192 c.Check(data, gc.DeepEquals, contents) 193 } 194 195 func checkRemoveAll(c *gc.C, stor storage.Storage) { 196 contents := []byte("File contents.") 197 aFile := "a-file.txt" 198 err := stor.Put(aFile, bytes.NewBuffer(contents), int64(len(contents))) 199 c.Assert(err, jc.ErrorIsNil) 200 err = stor.Put("empty-file", bytes.NewBuffer(nil), 0) 201 c.Assert(err, jc.ErrorIsNil) 202 203 err = stor.RemoveAll() 204 c.Assert(err, jc.ErrorIsNil) 205 206 files, err := storage.List(stor, "") 207 c.Assert(err, jc.ErrorIsNil) 208 c.Check(files, gc.HasLen, 0) 209 210 _, err = storage.Get(stor, aFile) 211 c.Assert(err, gc.NotNil) 212 c.Check(err, gc.ErrorMatches, fmt.Sprintf("file %q not found", aFile)) 213 }