launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 gc "launchpad.net/gocheck" 15 16 "launchpad.net/juju-core/environs/httpstorage" 17 "launchpad.net/juju-core/environs/storage" 18 "launchpad.net/juju-core/errors" 19 coretesting "launchpad.net/juju-core/testing" 20 jc "launchpad.net/juju-core/testing/checkers" 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(), []byte(coretesting.CACert), testAuthkey) 31 c.Assert(err, gc.IsNil) 32 33 data := []byte("hello") 34 err = ioutil.WriteFile(filepath.Join(storageDir, "filename"), data, 0644) 35 c.Assert(err, gc.IsNil) 36 names, err := storage.List(stor, "filename") 37 c.Assert(err, gc.IsNil) 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(), []byte(coretesting.CACert), invalidAuthkey) 53 c.Assert(err, gc.IsNil) 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, gc.IsNil) 59 names, err := storage.List(stor, "filename") 60 c.Assert(err, gc.IsNil) 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, gc.IsNil) 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, gc.IsNil) 109 110 // check that it's ok to remove a file twice. 111 err = storage2.Remove(names[0]) 112 c.Check(err, gc.IsNil) 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, gc.IsNil) 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, gc.IsNil) 135 c.Assert(lnames, gc.DeepEquals, names) 136 } 137 138 type readerWithClose struct { 139 *bytes.Buffer 140 closeCalled bool 141 } 142 143 var _ io.Reader = (*readerWithClose)(nil) 144 var _ io.Closer = (*readerWithClose)(nil) 145 146 func (r *readerWithClose) Close() error { 147 r.closeCalled = true 148 return nil 149 } 150 151 func putFile(c *gc.C, stor storage.StorageWriter, name string, contents []byte) error { 152 c.Logf("check putting file %s ...", name) 153 reader := &readerWithClose{bytes.NewBuffer(contents), false} 154 err := stor.Put(name, reader, int64(len(contents))) 155 c.Assert(reader.closeCalled, jc.IsFalse) 156 return err 157 } 158 159 func checkPutFile(c *gc.C, stor storage.StorageWriter, name string, contents []byte) { 160 err := putFile(c, stor, name, contents) 161 c.Assert(err, gc.IsNil) 162 } 163 164 func checkFileDoesNotExist(c *gc.C, stor storage.StorageReader, name string) { 165 r, err := storage.Get(stor, name) 166 c.Assert(r, gc.IsNil) 167 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 168 } 169 170 func checkFileHasContents(c *gc.C, stor storage.StorageReader, name string, contents []byte) { 171 r, err := storage.Get(stor, name) 172 c.Assert(err, gc.IsNil) 173 c.Check(r, gc.NotNil) 174 defer r.Close() 175 data, err := ioutil.ReadAll(r) 176 c.Check(err, gc.IsNil) 177 c.Check(data, gc.DeepEquals, contents) 178 179 url, err := stor.URL(name) 180 c.Assert(err, gc.IsNil) 181 resp, err := http.Get(url) 182 c.Assert(err, gc.IsNil) 183 data, err = ioutil.ReadAll(resp.Body) 184 c.Assert(err, gc.IsNil) 185 defer resp.Body.Close() 186 c.Assert(resp.StatusCode, gc.Equals, http.StatusOK, gc.Commentf("error response: %s", data)) 187 c.Check(data, gc.DeepEquals, contents) 188 } 189 190 func checkRemoveAll(c *gc.C, stor storage.Storage) { 191 contents := []byte("File contents.") 192 aFile := "a-file.txt" 193 err := stor.Put(aFile, bytes.NewBuffer(contents), int64(len(contents))) 194 c.Assert(err, gc.IsNil) 195 err = stor.Put("empty-file", bytes.NewBuffer(nil), 0) 196 c.Assert(err, gc.IsNil) 197 198 err = stor.RemoveAll() 199 c.Assert(err, gc.IsNil) 200 201 files, err := storage.List(stor, "") 202 c.Assert(err, gc.IsNil) 203 c.Check(files, gc.HasLen, 0) 204 205 _, err = storage.Get(stor, aFile) 206 c.Assert(err, gc.NotNil) 207 c.Check(err, gc.ErrorMatches, fmt.Sprintf("file %q not found", aFile)) 208 }