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  }