github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/state/bakerystorage/storage_test.go (about) 1 // Copyright 2014-2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package bakerystorage 5 6 import ( 7 "errors" 8 "time" // Only used for time types. 9 10 gitjujutesting "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/macaroon-bakery.v1/bakery" 14 "gopkg.in/mgo.v2" 15 16 "github.com/juju/juju/mongo" 17 "github.com/juju/juju/testing" 18 ) 19 20 type StorageSuite struct { 21 testing.BaseSuite 22 gitjujutesting.Stub 23 collection mockCollection 24 closeCollection func() 25 config Config 26 } 27 28 var _ = gc.Suite(&StorageSuite{}) 29 30 func (s *StorageSuite) SetUpTest(c *gc.C) { 31 s.BaseSuite.SetUpTest(c) 32 s.Stub.ResetCalls() 33 s.collection = mockCollection{Stub: &s.Stub} 34 s.closeCollection = func() { 35 s.AddCall("Close") 36 s.PopNoErr() 37 } 38 s.config = Config{ 39 GetCollection: func() (mongo.Collection, func()) { 40 s.AddCall("GetCollection") 41 s.PopNoErr() 42 return &s.collection, s.closeCollection 43 }, 44 } 45 } 46 47 func (s *StorageSuite) TestValidateConfigGetCollection(c *gc.C) { 48 s.config.GetCollection = nil 49 _, err := New(s.config) 50 c.Assert(err, gc.ErrorMatches, "validating config: nil GetCollection not valid") 51 } 52 53 func (s *StorageSuite) TestPut(c *gc.C) { 54 store, err := New(s.config) 55 c.Assert(err, jc.ErrorIsNil) 56 57 err = store.Put("foo", "bar") 58 c.Assert(err, jc.ErrorIsNil) 59 s.CheckCalls(c, []gitjujutesting.StubCall{ 60 {"GetCollection", nil}, 61 {"Writeable", nil}, 62 {"UpsertId", []interface{}{"foo", storageDoc{ 63 Location: "foo", 64 Item: "bar", 65 }}}, 66 {"Close", nil}, 67 }) 68 } 69 70 func (s *StorageSuite) TestExpireAt(c *gc.C) { 71 store, err := New(s.config) 72 c.Assert(err, jc.ErrorIsNil) 73 74 expiryTime := testing.NonZeroTime().Add(24 * time.Hour) 75 store = store.ExpireAt(expiryTime) 76 77 err = store.Put("foo", "bar") 78 c.Assert(err, jc.ErrorIsNil) 79 s.CheckCalls(c, []gitjujutesting.StubCall{ 80 {"GetCollection", nil}, 81 {"Writeable", nil}, 82 {"UpsertId", []interface{}{"foo", storageDoc{ 83 Location: "foo", 84 Item: "bar", 85 ExpireAt: expiryTime.Add(-1 * time.Second), 86 }}}, 87 {"Close", nil}, 88 }) 89 } 90 91 func (s *StorageSuite) TestPutError(c *gc.C) { 92 store, err := New(s.config) 93 c.Assert(err, jc.ErrorIsNil) 94 s.SetErrors(nil, nil, errors.New("failed to upsert")) 95 err = store.Put("foo", "bar") 96 c.Assert(err, gc.ErrorMatches, `cannot store item for location "foo": failed to upsert`) 97 } 98 99 func (s *StorageSuite) TestGet(c *gc.C) { 100 store, err := New(s.config) 101 c.Assert(err, jc.ErrorIsNil) 102 item, err := store.Get("foo") 103 c.Assert(err, jc.ErrorIsNil) 104 c.Assert(item, gc.Equals, "item-value") 105 s.CheckCalls(c, []gitjujutesting.StubCall{ 106 {"GetCollection", nil}, 107 {"FindId", []interface{}{"foo"}}, 108 {"One", []interface{}{&storageDoc{ 109 // Set by mock, not in input. Unimportant anyway. 110 Location: "foo", 111 Item: "item-value", 112 }}}, 113 {"Close", nil}, 114 }) 115 } 116 117 func (s *StorageSuite) TestGetNotFound(c *gc.C) { 118 store, err := New(s.config) 119 c.Assert(err, jc.ErrorIsNil) 120 s.SetErrors(nil, nil, mgo.ErrNotFound) 121 _, err = store.Get("foo") 122 c.Assert(err, gc.Equals, bakery.ErrNotFound) 123 } 124 125 func (s *StorageSuite) TestGetError(c *gc.C) { 126 store, err := New(s.config) 127 c.Assert(err, jc.ErrorIsNil) 128 s.SetErrors(nil, nil, errors.New("failed to read")) 129 _, err = store.Get("foo") 130 c.Assert(err, gc.ErrorMatches, `cannot get item for location "foo": failed to read`) 131 } 132 133 func (s *StorageSuite) TestDel(c *gc.C) { 134 store, err := New(s.config) 135 c.Assert(err, jc.ErrorIsNil) 136 137 err = store.Del("foo") 138 c.Assert(err, jc.ErrorIsNil) 139 s.CheckCalls(c, []gitjujutesting.StubCall{ 140 {"GetCollection", nil}, 141 {"Writeable", nil}, 142 {"RemoveId", []interface{}{"foo"}}, 143 {"Close", nil}, 144 }) 145 } 146 147 func (s *StorageSuite) TestDelNotFound(c *gc.C) { 148 store, err := New(s.config) 149 c.Assert(err, jc.ErrorIsNil) 150 s.SetErrors(nil, nil, mgo.ErrNotFound) 151 err = store.Del("foo") 152 c.Assert(err, jc.ErrorIsNil) 153 } 154 155 func (s *StorageSuite) TestDelError(c *gc.C) { 156 store, err := New(s.config) 157 c.Assert(err, jc.ErrorIsNil) 158 s.SetErrors(nil, nil, errors.New("failed to remove")) 159 err = store.Del("foo") 160 c.Assert(err, gc.ErrorMatches, `cannot remove item for location "foo": failed to remove`) 161 } 162 163 type mockCollection struct { 164 mongo.WriteCollection 165 *gitjujutesting.Stub 166 } 167 168 func (c *mockCollection) FindId(id interface{}) mongo.Query { 169 c.MethodCall(c, "FindId", id) 170 c.PopNoErr() 171 return &mockQuery{Stub: c.Stub, id: id} 172 } 173 174 func (c *mockCollection) UpsertId(id, update interface{}) (*mgo.ChangeInfo, error) { 175 c.MethodCall(c, "UpsertId", id, update) 176 return &mgo.ChangeInfo{}, c.NextErr() 177 } 178 179 func (c *mockCollection) RemoveId(id interface{}) error { 180 c.MethodCall(c, "RemoveId", id) 181 return c.NextErr() 182 } 183 184 func (c *mockCollection) Writeable() mongo.WriteCollection { 185 c.MethodCall(c, "Writeable") 186 c.PopNoErr() 187 return c 188 } 189 190 type mockQuery struct { 191 mongo.Query 192 *gitjujutesting.Stub 193 id interface{} 194 } 195 196 func (q *mockQuery) One(result interface{}) error { 197 q.MethodCall(q, "One", result) 198 *result.(*storageDoc) = storageDoc{ 199 Location: q.id.(string), 200 Item: "item-value", 201 } 202 return q.NextErr() 203 }