github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/state/cloudimagemetadata/image_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cloudimagemetadata_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/txn" 11 txntesting "github.com/juju/txn/testing" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/mgo.v2" 14 15 "github.com/juju/juju/mongo" 16 "github.com/juju/juju/state/cloudimagemetadata" 17 ) 18 19 type cloudImageMetadataSuite struct { 20 testing.IsolatedMgoSuite 21 22 access *TestMongo 23 storage cloudimagemetadata.Storage 24 } 25 26 var _ = gc.Suite(&cloudImageMetadataSuite{}) 27 28 const ( 29 envName = "test-env" 30 collectionName = "test-collection" 31 ) 32 33 func (s *cloudImageMetadataSuite) SetUpTest(c *gc.C) { 34 s.IsolatedMgoSuite.SetUpTest(c) 35 36 db := s.MgoSuite.Session.DB("juju") 37 38 s.access = NewTestMongo(db) 39 s.storage = cloudimagemetadata.NewStorage(envName, collectionName, s.access) 40 } 41 42 func (s *cloudImageMetadataSuite) TestSaveMetadata(c *gc.C) { 43 attrs := cloudimagemetadata.MetadataAttributes{ 44 Stream: "stream", 45 Region: "region-test", 46 Series: "series", 47 Arch: "arch", 48 VirtType: "virtType-test", 49 RootStorageType: "rootStorageType-test"} 50 51 added := cloudimagemetadata.Metadata{attrs, "1"} 52 s.assertRecordMetadata(c, added) 53 s.assertMetadataRecorded(c, attrs, added) 54 55 } 56 57 func (s *cloudImageMetadataSuite) TestFindMetadataNotFound(c *gc.C) { 58 // No metadata is stored yet. 59 // So when looking for all and none is found, err. 60 found, err := s.storage.FindMetadata(cloudimagemetadata.MetadataFilter{}) 61 c.Assert(err, jc.Satisfies, errors.IsNotFound) 62 c.Assert(err, gc.ErrorMatches, "matching cloud image metadata not found") 63 c.Assert(found, gc.HasLen, 0) 64 65 // insert something... 66 attrs := cloudimagemetadata.MetadataAttributes{ 67 Stream: "stream", 68 Region: "region", 69 Series: "series", 70 Arch: "arch", 71 VirtType: "virtType", 72 RootStorageType: "rootStorageType"} 73 m := cloudimagemetadata.Metadata{attrs, "1"} 74 s.assertRecordMetadata(c, m) 75 76 // ...but look for something else. 77 none, err := s.storage.FindMetadata(cloudimagemetadata.MetadataFilter{ 78 Stream: "something else", 79 }) 80 // Make sure that we are explicit that we could not find what we wanted. 81 c.Assert(err, jc.Satisfies, errors.IsNotFound) 82 c.Assert(err, gc.ErrorMatches, "matching cloud image metadata not found") 83 c.Assert(none, gc.HasLen, 0) 84 } 85 86 func buildAttributesFilter(attrs cloudimagemetadata.MetadataAttributes) cloudimagemetadata.MetadataFilter { 87 filter := cloudimagemetadata.MetadataFilter{ 88 Stream: attrs.Stream, 89 Region: attrs.Region, 90 VirtType: attrs.VirtType, 91 RootStorageType: attrs.RootStorageType} 92 if attrs.Series != "" { 93 filter.Series = []string{attrs.Series} 94 } 95 if attrs.Arch != "" { 96 filter.Arches = []string{attrs.Arch} 97 } 98 return filter 99 } 100 101 func (s *cloudImageMetadataSuite) TestFindMetadata(c *gc.C) { 102 attrs := cloudimagemetadata.MetadataAttributes{ 103 Stream: "stream", 104 Region: "region", 105 Series: "series", 106 Arch: "arch", 107 VirtType: "virtType", 108 RootStorageType: "rootStorageType"} 109 110 m := cloudimagemetadata.Metadata{attrs, "1"} 111 112 _, err := s.storage.FindMetadata(buildAttributesFilter(attrs)) 113 c.Assert(err, jc.Satisfies, errors.IsNotFound) 114 115 s.assertRecordMetadata(c, m) 116 expected := []cloudimagemetadata.Metadata{m} 117 s.assertMetadataRecorded(c, attrs, expected...) 118 119 attrs.Stream = "another_stream" 120 m = cloudimagemetadata.Metadata{attrs, "2"} 121 s.assertRecordMetadata(c, m) 122 123 expected = append(expected, m) 124 // Should find both 125 s.assertMetadataRecorded(c, cloudimagemetadata.MetadataAttributes{Region: "region"}, expected...) 126 } 127 128 func (s *cloudImageMetadataSuite) TestSaveMetadataUpdateSameAttrsAndImages(c *gc.C) { 129 attrs := cloudimagemetadata.MetadataAttributes{ 130 Stream: "stream", 131 Series: "series", 132 Arch: "arch", 133 } 134 metadata0 := cloudimagemetadata.Metadata{attrs, "1"} 135 metadata1 := cloudimagemetadata.Metadata{attrs, "1"} 136 137 s.assertRecordMetadata(c, metadata0) 138 s.assertRecordMetadata(c, metadata1) 139 s.assertMetadataRecorded(c, attrs, metadata1) 140 } 141 142 func (s *cloudImageMetadataSuite) TestSaveMetadataUpdateSameAttrsDiffImages(c *gc.C) { 143 attrs := cloudimagemetadata.MetadataAttributes{ 144 Stream: "stream", 145 Series: "series", 146 Arch: "arch", 147 } 148 metadata0 := cloudimagemetadata.Metadata{attrs, "1"} 149 metadata1 := cloudimagemetadata.Metadata{attrs, "12"} 150 151 s.assertRecordMetadata(c, metadata0) 152 s.assertMetadataRecorded(c, attrs, metadata0) 153 s.assertRecordMetadata(c, metadata1) 154 s.assertMetadataRecorded(c, attrs, metadata1) 155 s.assertMetadataRecorded(c, cloudimagemetadata.MetadataAttributes{}, metadata1) 156 } 157 158 func (s *cloudImageMetadataSuite) TestSaveDiffMetadataConcurrentlyAndOrderByDateCreated(c *gc.C) { 159 attrs := cloudimagemetadata.MetadataAttributes{ 160 Stream: "stream", 161 Series: "series", 162 Arch: "arch", 163 } 164 metadata0 := cloudimagemetadata.Metadata{attrs, "0"} 165 metadata1 := cloudimagemetadata.Metadata{attrs, "1"} 166 metadata1.Stream = "scream" 167 168 s.assertConcurrentSave(c, 169 metadata0, // add this one 170 metadata1, // add this one 171 // last added should be first as order is by date created 172 metadata1, // verify it's in the list 173 metadata0, // verify it's in the list 174 ) 175 } 176 177 func (s *cloudImageMetadataSuite) TestSaveSameMetadataDiffImageConcurrently(c *gc.C) { 178 attrs := cloudimagemetadata.MetadataAttributes{ 179 Stream: "stream", 180 Series: "series", 181 Arch: "arch", 182 } 183 metadata0 := cloudimagemetadata.Metadata{attrs, "0"} 184 metadata1 := cloudimagemetadata.Metadata{attrs, "1"} 185 186 s.assertConcurrentSave(c, 187 metadata0, // add this one 188 metadata1, // overwrite it with this one 189 metadata1, // verify only the last one is in the list 190 ) 191 } 192 193 func (s *cloudImageMetadataSuite) TestSaveSameMetadataSameImageConcurrently(c *gc.C) { 194 attrs := cloudimagemetadata.MetadataAttributes{ 195 Stream: "stream", 196 Series: "series", 197 Arch: "arch", 198 } 199 metadata0 := cloudimagemetadata.Metadata{attrs, "0"} 200 201 s.assertConcurrentSave(c, 202 metadata0, // add this one 203 metadata0, // add it again 204 metadata0, // varify only one is in the list 205 ) 206 } 207 208 func (s *cloudImageMetadataSuite) TestSaveSameMetadataSameImageDiffSourceConcurrently(c *gc.C) { 209 attrs := cloudimagemetadata.MetadataAttributes{ 210 Stream: "stream", 211 Series: "series", 212 Arch: "arch", 213 Source: cloudimagemetadata.Public, 214 } 215 metadata0 := cloudimagemetadata.Metadata{attrs, "0"} 216 217 attrs.Source = cloudimagemetadata.Custom 218 metadata1 := cloudimagemetadata.Metadata{attrs, "0"} 219 220 s.assertConcurrentSave(c, 221 metadata0, 222 metadata1, 223 metadata0, 224 metadata1, 225 ) 226 } 227 228 func (s *cloudImageMetadataSuite) assertConcurrentSave(c *gc.C, metadata0, metadata1 cloudimagemetadata.Metadata, expected ...cloudimagemetadata.Metadata) { 229 addMetadata := func() { 230 s.assertRecordMetadata(c, metadata0) 231 } 232 defer txntesting.SetBeforeHooks(c, s.access.runner, addMetadata).Check() 233 s.assertRecordMetadata(c, metadata1) 234 s.assertMetadataRecorded(c, cloudimagemetadata.MetadataAttributes{}, expected...) 235 } 236 237 func (s *cloudImageMetadataSuite) assertRecordMetadata(c *gc.C, m cloudimagemetadata.Metadata) { 238 err := s.storage.SaveMetadata(m) 239 c.Assert(err, jc.ErrorIsNil) 240 } 241 242 func (s *cloudImageMetadataSuite) assertMetadataRecorded(c *gc.C, criteria cloudimagemetadata.MetadataAttributes, expected ...cloudimagemetadata.Metadata) { 243 metadata, err := s.storage.FindMetadata(buildAttributesFilter(criteria)) 244 c.Assert(err, jc.ErrorIsNil) 245 246 groups := make(map[cloudimagemetadata.SourceType][]cloudimagemetadata.Metadata) 247 for _, one := range expected { 248 groups[one.Source] = append(groups[one.Source], one) 249 } 250 c.Assert(metadata, jc.DeepEquals, groups) 251 } 252 253 type TestMongo struct { 254 database *mgo.Database 255 runner txn.Runner 256 } 257 258 func NewTestMongo(database *mgo.Database) *TestMongo { 259 return &TestMongo{ 260 database: database, 261 runner: txn.NewRunner(txn.RunnerParams{ 262 Database: database, 263 }), 264 } 265 } 266 267 func (m *TestMongo) GetCollection(name string) (mongo.Collection, func()) { 268 return mongo.CollectionFromName(m.database, name) 269 } 270 271 func (m *TestMongo) RunTransaction(getTxn txn.TransactionSource) error { 272 return m.runner.Run(getTxn) 273 }