github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/environs/simplestreams/simplestreams_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package simplestreams_test 5 6 import ( 7 "bytes" 8 "strings" 9 "testing" 10 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils" 13 gc "launchpad.net/gocheck" 14 15 "github.com/juju/juju/environs/simplestreams" 16 sstesting "github.com/juju/juju/environs/simplestreams/testing" 17 ) 18 19 func Test(t *testing.T) { 20 registerSimpleStreamsTests() 21 gc.Suite(&signingSuite{}) 22 gc.Suite(&jsonSuite{}) 23 gc.TestingT(t) 24 } 25 26 func registerSimpleStreamsTests() { 27 gc.Suite(&simplestreamsSuite{ 28 LocalLiveSimplestreamsSuite: sstesting.LocalLiveSimplestreamsSuite{ 29 Source: simplestreams.NewURLDataSource("test", "test:", utils.VerifySSLHostnames), 30 RequireSigned: false, 31 DataType: "image-ids", 32 ValidConstraint: sstesting.NewTestConstraint(simplestreams.LookupParams{ 33 CloudSpec: simplestreams.CloudSpec{ 34 Region: "us-east-1", 35 Endpoint: "https://ec2.us-east-1.amazonaws.com", 36 }, 37 Series: []string{"precise"}, 38 Arches: []string{"amd64", "arm"}, 39 }), 40 }, 41 }) 42 } 43 44 type simplestreamsSuite struct { 45 sstesting.TestDataSuite 46 sstesting.LocalLiveSimplestreamsSuite 47 } 48 49 func (s *simplestreamsSuite) SetUpSuite(c *gc.C) { 50 s.LocalLiveSimplestreamsSuite.SetUpSuite(c) 51 s.TestDataSuite.SetUpSuite(c) 52 } 53 54 func (s *simplestreamsSuite) TearDownSuite(c *gc.C) { 55 s.TestDataSuite.TearDownSuite(c) 56 s.LocalLiveSimplestreamsSuite.TearDownSuite(c) 57 } 58 59 func (s *simplestreamsSuite) TestGetProductsPath(c *gc.C) { 60 indexRef, err := s.GetIndexRef(sstesting.Index_v1) 61 c.Assert(err, gc.IsNil) 62 path, err := indexRef.GetProductsPath(s.ValidConstraint) 63 c.Assert(err, gc.IsNil) 64 c.Assert(path, gc.Equals, "streams/v1/image_metadata.json") 65 } 66 67 func (*simplestreamsSuite) TestExtractCatalogsForProductsAcceptsNil(c *gc.C) { 68 empty := simplestreams.CloudMetadata{} 69 c.Check(simplestreams.ExtractCatalogsForProducts(empty, nil), gc.HasLen, 0) 70 } 71 72 func (*simplestreamsSuite) TestExtractCatalogsForProductsReturnsMatch(c *gc.C) { 73 metadata := simplestreams.CloudMetadata{ 74 Products: map[string]simplestreams.MetadataCatalog{ 75 "foo": {}, 76 }, 77 } 78 c.Check( 79 simplestreams.ExtractCatalogsForProducts(metadata, []string{"foo"}), 80 gc.DeepEquals, 81 []simplestreams.MetadataCatalog{metadata.Products["foo"]}) 82 } 83 84 func (*simplestreamsSuite) TestExtractCatalogsForProductsIgnoresNonMatches(c *gc.C) { 85 metadata := simplestreams.CloudMetadata{ 86 Products: map[string]simplestreams.MetadataCatalog{ 87 "one-product": {}, 88 }, 89 } 90 absentProducts := []string{"another-product"} 91 c.Check(simplestreams.ExtractCatalogsForProducts(metadata, absentProducts), gc.HasLen, 0) 92 } 93 94 func (*simplestreamsSuite) TestExtractCatalogsForProductsPreservesOrder(c *gc.C) { 95 products := map[string]simplestreams.MetadataCatalog{ 96 "1": {}, 97 "2": {}, 98 "3": {}, 99 "4": {}, 100 } 101 102 metadata := simplestreams.CloudMetadata{Products: products} 103 104 c.Check( 105 simplestreams.ExtractCatalogsForProducts(metadata, []string{"1", "3", "4", "2"}), 106 gc.DeepEquals, 107 []simplestreams.MetadataCatalog{ 108 products["1"], 109 products["3"], 110 products["4"], 111 products["2"], 112 }) 113 } 114 115 func (*simplestreamsSuite) TestExtractIndexesAcceptsNil(c *gc.C) { 116 ind := simplestreams.Indices{} 117 c.Check(simplestreams.ExtractIndexes(ind), gc.HasLen, 0) 118 } 119 120 func (*simplestreamsSuite) TestExtractIndexesReturnsIndex(c *gc.C) { 121 metadata := simplestreams.IndexMetadata{} 122 ind := simplestreams.Indices{Indexes: map[string]*simplestreams.IndexMetadata{"foo": &metadata}} 123 c.Check(simplestreams.ExtractIndexes(ind), gc.DeepEquals, simplestreams.IndexMetadataSlice{&metadata}) 124 } 125 126 func (*simplestreamsSuite) TestExtractIndexesReturnsAllIndexes(c *gc.C) { 127 ind := simplestreams.Indices{ 128 Indexes: map[string]*simplestreams.IndexMetadata{ 129 "foo": {}, 130 "bar": {}, 131 }, 132 } 133 134 array := simplestreams.ExtractIndexes(ind) 135 136 c.Assert(array, gc.HasLen, len(ind.Indexes)) 137 c.Check(array[0], gc.NotNil) 138 c.Check(array[1], gc.NotNil) 139 c.Check(array[0], gc.Not(gc.Equals), array[1]) 140 c.Check( 141 (array[0] == ind.Indexes["foo"]), 142 gc.Not(gc.Equals), 143 (array[1] == ind.Indexes["foo"])) 144 c.Check( 145 (array[0] == ind.Indexes["bar"]), 146 gc.Not(gc.Equals), 147 (array[1] == ind.Indexes["bar"])) 148 } 149 150 func (*simplestreamsSuite) TestHasCloudAcceptsNil(c *gc.C) { 151 metadata := simplestreams.IndexMetadata{Clouds: nil} 152 c.Check(simplestreams.HasCloud(metadata, simplestreams.CloudSpec{}), jc.IsTrue) 153 } 154 155 func (*simplestreamsSuite) TestHasCloudFindsMatch(c *gc.C) { 156 metadata := simplestreams.IndexMetadata{ 157 Clouds: []simplestreams.CloudSpec{ 158 {Region: "r1", Endpoint: "http://e1"}, 159 {Region: "r2", Endpoint: "http://e2"}, 160 }, 161 } 162 c.Check(simplestreams.HasCloud(metadata, metadata.Clouds[1]), jc.IsTrue) 163 } 164 165 func (*simplestreamsSuite) TestHasCloudFindsMatchWithTrailingSlash(c *gc.C) { 166 metadata := simplestreams.IndexMetadata{ 167 Clouds: []simplestreams.CloudSpec{ 168 {Region: "r1", Endpoint: "http://e1/"}, 169 {Region: "r2", Endpoint: "http://e2"}, 170 }, 171 } 172 spec := simplestreams.CloudSpec{Region: "r1", Endpoint: "http://e1"} 173 c.Check(simplestreams.HasCloud(metadata, spec), jc.IsTrue) 174 spec = simplestreams.CloudSpec{Region: "r1", Endpoint: "http://e1/"} 175 c.Check(simplestreams.HasCloud(metadata, spec), jc.IsTrue) 176 spec = simplestreams.CloudSpec{Region: "r2", Endpoint: "http://e2/"} 177 c.Check(simplestreams.HasCloud(metadata, spec), jc.IsTrue) 178 } 179 180 func (*simplestreamsSuite) TestHasCloudReturnsFalseIfCloudsDoNotMatch(c *gc.C) { 181 metadata := simplestreams.IndexMetadata{ 182 Clouds: []simplestreams.CloudSpec{ 183 {Region: "r1", Endpoint: "http://e1"}, 184 {Region: "r2", Endpoint: "http://e2"}, 185 }, 186 } 187 otherCloud := simplestreams.CloudSpec{Region: "r9", Endpoint: "http://e9"} 188 c.Check(simplestreams.HasCloud(metadata, otherCloud), jc.IsFalse) 189 } 190 191 func (*simplestreamsSuite) TestHasCloudRequiresIdenticalRegion(c *gc.C) { 192 metadata := simplestreams.IndexMetadata{ 193 Clouds: []simplestreams.CloudSpec{ 194 {Region: "around", Endpoint: "http://nearby"}, 195 }, 196 } 197 similarCloud := metadata.Clouds[0] 198 similarCloud.Region = "elsewhere" 199 c.Assert(similarCloud, gc.Not(gc.Equals), metadata.Clouds[0]) 200 201 c.Check(simplestreams.HasCloud(metadata, similarCloud), jc.IsFalse) 202 } 203 204 func (*simplestreamsSuite) TestHasCloudRequiresIdenticalEndpoint(c *gc.C) { 205 metadata := simplestreams.IndexMetadata{ 206 Clouds: []simplestreams.CloudSpec{ 207 {Region: "around", Endpoint: "http://nearby"}, 208 }, 209 } 210 similarCloud := metadata.Clouds[0] 211 similarCloud.Endpoint = "http://far" 212 c.Assert(similarCloud, gc.Not(gc.Equals), metadata.Clouds[0]) 213 214 c.Check(simplestreams.HasCloud(metadata, similarCloud), jc.IsFalse) 215 } 216 217 func (*simplestreamsSuite) TestHasProductAcceptsNils(c *gc.C) { 218 metadata := simplestreams.IndexMetadata{} 219 c.Check(simplestreams.HasProduct(metadata, nil), jc.IsFalse) 220 } 221 222 func (*simplestreamsSuite) TestHasProductFindsMatchingProduct(c *gc.C) { 223 metadata := simplestreams.IndexMetadata{ProductIds: []string{"x", "y", "z"}} 224 c.Check( 225 simplestreams.HasProduct(metadata, []string{"a", "b", metadata.ProductIds[1]}), 226 gc.Equals, 227 true) 228 } 229 230 func (*simplestreamsSuite) TestHasProductReturnsFalseIfProductsDoNotMatch(c *gc.C) { 231 metadata := simplestreams.IndexMetadata{ProductIds: []string{"x", "y", "z"}} 232 c.Check(simplestreams.HasProduct(metadata, []string{"a", "b", "c"}), jc.IsFalse) 233 } 234 235 func (*simplestreamsSuite) TestFilterReturnsNothingForEmptyArray(c *gc.C) { 236 empty := simplestreams.IndexMetadataSlice{} 237 c.Check( 238 simplestreams.Filter(empty, func(*simplestreams.IndexMetadata) bool { return true }), 239 gc.HasLen, 240 0) 241 } 242 243 func (*simplestreamsSuite) TestFilterRemovesNonMatches(c *gc.C) { 244 array := simplestreams.IndexMetadataSlice{&simplestreams.IndexMetadata{}} 245 c.Check( 246 simplestreams.Filter(array, func(*simplestreams.IndexMetadata) bool { return false }), 247 gc.HasLen, 248 0) 249 } 250 251 func (*simplestreamsSuite) TestFilterIncludesMatches(c *gc.C) { 252 metadata := simplestreams.IndexMetadata{} 253 array := simplestreams.IndexMetadataSlice{&metadata} 254 c.Check( 255 simplestreams.Filter(array, func(*simplestreams.IndexMetadata) bool { return true }), 256 gc.DeepEquals, 257 simplestreams.IndexMetadataSlice{&metadata}) 258 } 259 260 func (*simplestreamsSuite) TestFilterLeavesOriginalUnchanged(c *gc.C) { 261 item1 := simplestreams.IndexMetadata{CloudName: "aws"} 262 item2 := simplestreams.IndexMetadata{CloudName: "openstack"} 263 array := simplestreams.IndexMetadataSlice{&item1, &item2} 264 265 result := simplestreams.Filter(array, func(metadata *simplestreams.IndexMetadata) bool { 266 return metadata.CloudName == "aws" 267 }) 268 // This exercises both the "leave out" and the "include" code paths. 269 c.Assert(result, gc.HasLen, 1) 270 271 // The original, however, has not changed. 272 c.Assert(array, gc.HasLen, 2) 273 c.Check(array, gc.DeepEquals, simplestreams.IndexMetadataSlice{&item1, &item2}) 274 } 275 276 func (*simplestreamsSuite) TestFilterPreservesOrder(c *gc.C) { 277 array := simplestreams.IndexMetadataSlice{ 278 &simplestreams.IndexMetadata{CloudName: "aws"}, 279 &simplestreams.IndexMetadata{CloudName: "maas"}, 280 &simplestreams.IndexMetadata{CloudName: "openstack"}, 281 } 282 283 c.Check( 284 simplestreams.Filter(array, func(metadata *simplestreams.IndexMetadata) bool { return true }), 285 gc.DeepEquals, 286 array) 287 } 288 289 func (*simplestreamsSuite) TestFilterCombinesMatchesAndNonMatches(c *gc.C) { 290 array := simplestreams.IndexMetadataSlice{ 291 &simplestreams.IndexMetadata{Format: "1.0"}, 292 &simplestreams.IndexMetadata{Format: "1.1"}, 293 &simplestreams.IndexMetadata{Format: "2.0"}, 294 &simplestreams.IndexMetadata{Format: "2.1"}, 295 } 296 297 dotOFormats := simplestreams.Filter(array, func(metadata *simplestreams.IndexMetadata) bool { 298 return strings.HasSuffix(metadata.Format, ".0") 299 }) 300 301 c.Check(dotOFormats, gc.DeepEquals, simplestreams.IndexMetadataSlice{array[0], array[2]}) 302 } 303 304 // countingSource is used to check that a DataSource has been queried. 305 type countingSource struct { 306 simplestreams.DataSource 307 count int 308 } 309 310 func (s *countingSource) URL(path string) (string, error) { 311 s.count++ 312 return s.DataSource.URL(path) 313 } 314 315 func (s *simplestreamsSuite) TestGetMetadataNoMatching(c *gc.C) { 316 source := &countingSource{ 317 DataSource: simplestreams.NewURLDataSource( 318 "test", "test:/daily", utils.VerifySSLHostnames, 319 ), 320 } 321 sources := []simplestreams.DataSource{source, source, source} 322 params := simplestreams.ValueParams{DataType: "image-ids"} 323 constraint := sstesting.NewTestConstraint(simplestreams.LookupParams{ 324 CloudSpec: simplestreams.CloudSpec{ 325 Region: "us-east-1", 326 Endpoint: "https://ec2.us-east-1.amazonaws.com", 327 }, 328 Series: []string{"precise"}, 329 Arches: []string{"not-a-real-arch"}, // never matches 330 }) 331 332 items, resolveInfo, err := simplestreams.GetMetadata( 333 sources, 334 simplestreams.DefaultIndexPath, 335 constraint, 336 false, 337 params, 338 ) 339 c.Assert(err, gc.IsNil) 340 c.Assert(items, gc.HasLen, 0) 341 c.Assert(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{ 342 Source: "test", 343 Signed: false, 344 IndexURL: "test:/daily/streams/v1/index.json", 345 MirrorURL: "", 346 }) 347 348 // There should be 2 calls to each data-source: 349 // one for .sjson, one for .json. 350 c.Assert(source.count, gc.Equals, 2*len(sources)) 351 } 352 353 func (s *simplestreamsSuite) TestMetadataCatalog(c *gc.C) { 354 metadata := s.AssertGetMetadata(c) 355 c.Check(len(metadata.Products), gc.Equals, 2) 356 c.Check(len(metadata.Aliases), gc.Equals, 1) 357 metadataCatalog := metadata.Products["com.ubuntu.cloud:server:12.04:amd64"] 358 c.Check(len(metadataCatalog.Items), gc.Equals, 2) 359 c.Check(metadataCatalog.Series, gc.Equals, "precise") 360 c.Check(metadataCatalog.Version, gc.Equals, "12.04") 361 c.Check(metadataCatalog.Arch, gc.Equals, "amd64") 362 c.Check(metadataCatalog.RegionName, gc.Equals, "au-east-1") 363 c.Check(metadataCatalog.Endpoint, gc.Equals, "https://somewhere") 364 } 365 366 func (s *simplestreamsSuite) TestItemCollection(c *gc.C) { 367 ic := s.AssertGetItemCollections(c, "20121218") 368 c.Check(ic.RegionName, gc.Equals, "au-east-2") 369 c.Check(ic.Endpoint, gc.Equals, "https://somewhere-else") 370 c.Assert(len(ic.Items) > 0, jc.IsTrue) 371 ti := ic.Items["usww2he"].(*sstesting.TestItem) 372 c.Check(ti.Id, gc.Equals, "ami-442ea674") 373 c.Check(ti.Storage, gc.Equals, "ebs") 374 c.Check(ti.VirtType, gc.Equals, "hvm") 375 c.Check(ti.RegionName, gc.Equals, "us-east-1") 376 c.Check(ti.Endpoint, gc.Equals, "https://ec2.us-east-1.amazonaws.com") 377 } 378 379 func (s *simplestreamsSuite) TestDenormalisationFromCollection(c *gc.C) { 380 ic := s.AssertGetItemCollections(c, "20121218") 381 ti := ic.Items["usww1pe"].(*sstesting.TestItem) 382 c.Check(ti.RegionName, gc.Equals, ic.RegionName) 383 c.Check(ti.Endpoint, gc.Equals, ic.Endpoint) 384 } 385 386 func (s *simplestreamsSuite) TestDenormalisationFromCatalog(c *gc.C) { 387 metadata := s.AssertGetMetadata(c) 388 metadataCatalog := metadata.Products["com.ubuntu.cloud:server:12.04:amd64"] 389 ic := metadataCatalog.Items["20111111"] 390 ti := ic.Items["usww3pe"].(*sstesting.TestItem) 391 c.Check(ti.RegionName, gc.Equals, metadataCatalog.RegionName) 392 c.Check(ti.Endpoint, gc.Equals, metadataCatalog.Endpoint) 393 } 394 395 func (s *simplestreamsSuite) TestDealiasing(c *gc.C) { 396 metadata := s.AssertGetMetadata(c) 397 metadataCatalog := metadata.Products["com.ubuntu.cloud:server:12.04:amd64"] 398 ic := metadataCatalog.Items["20121218"] 399 ti := ic.Items["usww3he"].(*sstesting.TestItem) 400 c.Check(ti.RegionName, gc.Equals, "us-west-3") 401 c.Check(ti.Endpoint, gc.Equals, "https://ec2.us-west-3.amazonaws.com") 402 } 403 404 var getMirrorTests = []struct { 405 region string 406 endpoint string 407 err string 408 mirrorURL string 409 path string 410 }{{ 411 // defaults 412 mirrorURL: "http://some-mirror/", 413 path: "com.ubuntu.juju:download.json", 414 }, { 415 // default mirror index entry 416 region: "some-region", 417 endpoint: "https://some-endpoint.com", 418 mirrorURL: "http://big-mirror/", 419 path: "big:download.json", 420 }, { 421 // endpoint with trailing "/" 422 region: "some-region", 423 endpoint: "https://some-endpoint.com/", 424 mirrorURL: "http://big-mirror/", 425 path: "big:download.json", 426 }} 427 428 func (s *simplestreamsSuite) TestGetMirrorMetadata(c *gc.C) { 429 for i, t := range getMirrorTests { 430 c.Logf("test %d", i) 431 if t.region == "" { 432 t.region = "us-east-2" 433 } 434 if t.endpoint == "" { 435 t.endpoint = "https://ec2.us-east-2.amazonaws.com" 436 } 437 cloud := simplestreams.CloudSpec{t.region, t.endpoint} 438 params := simplestreams.ValueParams{ 439 DataType: "content-download", 440 MirrorContentId: "com.ubuntu.juju:released:tools", 441 } 442 indexRef, err := simplestreams.GetIndexWithFormat( 443 s.Source, s.IndexPath(), sstesting.Index_v1, s.RequireSigned, cloud, params) 444 if !c.Check(err, gc.IsNil) { 445 continue 446 } 447 if t.err != "" { 448 c.Check(err, gc.ErrorMatches, t.err) 449 continue 450 } 451 if !c.Check(err, gc.IsNil) { 452 continue 453 } 454 mirrorURL, err := indexRef.Source.URL("") 455 if !c.Check(err, gc.IsNil) { 456 continue 457 } 458 c.Check(mirrorURL, gc.Equals, t.mirrorURL) 459 c.Check(indexRef.MirroredProductsPath, gc.Equals, t.path) 460 } 461 } 462 463 var testSigningKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- 464 Version: GnuPG v1.4.10 (GNU/Linux) 465 466 lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp 467 idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn 468 vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB 469 AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X 470 0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL 471 IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk 472 VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn 473 gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 474 TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx 475 q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz 476 dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA 477 CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 478 ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ 479 eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid 480 AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV 481 bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK 482 /UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA 483 A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX 484 TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc 485 lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 486 rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN 487 oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 488 QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU 489 nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC 490 AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp 491 BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad 492 AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL 493 VrM0m72/jnpKo04= 494 =zNCn 495 -----END PGP PRIVATE KEY BLOCK----- 496 ` 497 498 var validClearsignInput = ` 499 -----BEGIN PGP SIGNED MESSAGE----- 500 Hash: SHA1 501 502 Hello world 503 line 2 504 ` 505 506 var invalidClearsignInput = ` 507 -----BEGIN PGP SIGNED MESSAGE----- 508 Hash: SHA1 509 510 Invalid 511 ` 512 513 var testSig = `-----BEGIN PGP SIGNATURE----- 514 Version: GnuPG v1.4.10 (GNU/Linux) 515 516 iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 517 pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog 518 2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 519 MyTpno24AjIAGb+mH1U= 520 =hIJ6 521 -----END PGP SIGNATURE----- 522 ` 523 524 type signingSuite struct{} 525 526 func (s *signingSuite) TestDecodeCheckValidSignature(c *gc.C) { 527 r := bytes.NewReader([]byte(validClearsignInput + testSig)) 528 txt, err := simplestreams.DecodeCheckSignature(r, testSigningKey) 529 c.Assert(err, gc.IsNil) 530 c.Assert(txt, gc.DeepEquals, []byte("Hello world\nline 2\n")) 531 } 532 533 func (s *signingSuite) TestDecodeCheckInvalidSignature(c *gc.C) { 534 r := bytes.NewReader([]byte(invalidClearsignInput + testSig)) 535 _, err := simplestreams.DecodeCheckSignature(r, testSigningKey) 536 c.Assert(err, gc.Not(gc.IsNil)) 537 _, ok := err.(*simplestreams.NotPGPSignedError) 538 c.Assert(ok, jc.IsFalse) 539 } 540 541 func (s *signingSuite) TestDecodeCheckMissingSignature(c *gc.C) { 542 r := bytes.NewReader([]byte("foo")) 543 _, err := simplestreams.DecodeCheckSignature(r, testSigningKey) 544 _, ok := err.(*simplestreams.NotPGPSignedError) 545 c.Assert(ok, jc.IsTrue) 546 }