launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/worker/uniter/charm/charm_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package charm_test
     5  
     6  import (
     7  	"crypto/sha256"
     8  	"encoding/hex"
     9  	"fmt"
    10  	"io/ioutil"
    11  	gc "launchpad.net/gocheck"
    12  	"net/url"
    13  	"os"
    14  	"path/filepath"
    15  	stdtesting "testing"
    16  	"time"
    17  
    18  	corecharm "launchpad.net/juju-core/charm"
    19  	"launchpad.net/juju-core/juju/testing"
    20  	"launchpad.net/juju-core/state"
    21  	"launchpad.net/juju-core/state/api"
    22  	"launchpad.net/juju-core/state/api/uniter"
    23  	coretesting "launchpad.net/juju-core/testing"
    24  	jc "launchpad.net/juju-core/testing/checkers"
    25  	"launchpad.net/juju-core/utils"
    26  	"launchpad.net/juju-core/worker/uniter/charm"
    27  )
    28  
    29  func TestPackage(t *stdtesting.T) {
    30  	coretesting.MgoTestPackage(t)
    31  }
    32  
    33  type BundlesDirSuite struct {
    34  	coretesting.HTTPSuite
    35  	testing.JujuConnSuite
    36  
    37  	st     *api.State
    38  	uniter *uniter.State
    39  }
    40  
    41  var _ = gc.Suite(&BundlesDirSuite{})
    42  
    43  func (s *BundlesDirSuite) SetUpSuite(c *gc.C) {
    44  	s.HTTPSuite.SetUpSuite(c)
    45  	s.JujuConnSuite.SetUpSuite(c)
    46  }
    47  
    48  func (s *BundlesDirSuite) TearDownSuite(c *gc.C) {
    49  	s.JujuConnSuite.TearDownSuite(c)
    50  	s.HTTPSuite.TearDownSuite(c)
    51  }
    52  
    53  func (s *BundlesDirSuite) SetUpTest(c *gc.C) {
    54  	s.HTTPSuite.SetUpTest(c)
    55  	s.JujuConnSuite.SetUpTest(c)
    56  
    57  	// Add a charm, service and unit to login to the API with.
    58  	charm := s.AddTestingCharm(c, "wordpress")
    59  	service := s.AddTestingService(c, "wordpress", charm)
    60  	unit, err := service.AddUnit()
    61  	c.Assert(err, gc.IsNil)
    62  	password, err := utils.RandomPassword()
    63  	c.Assert(err, gc.IsNil)
    64  	err = unit.SetPassword(password)
    65  	c.Assert(err, gc.IsNil)
    66  
    67  	s.st = s.OpenAPIAs(c, unit.Tag(), password)
    68  	c.Assert(s.st, gc.NotNil)
    69  	s.uniter = s.st.Uniter()
    70  	c.Assert(s.uniter, gc.NotNil)
    71  }
    72  
    73  func (s *BundlesDirSuite) TearDownTest(c *gc.C) {
    74  	err := s.st.Close()
    75  	c.Assert(err, gc.IsNil)
    76  	s.JujuConnSuite.TearDownTest(c)
    77  	s.HTTPSuite.TearDownTest(c)
    78  }
    79  
    80  func (s *BundlesDirSuite) AddCharm(c *gc.C) (*uniter.Charm, *state.Charm, []byte) {
    81  	curl := corecharm.MustParseURL("cs:quantal/dummy-1")
    82  	surl, err := url.Parse(s.URL("/some/charm.bundle"))
    83  	c.Assert(err, gc.IsNil)
    84  	bunpath := coretesting.Charms.BundlePath(c.MkDir(), "dummy")
    85  	bun, err := corecharm.ReadBundle(bunpath)
    86  	c.Assert(err, gc.IsNil)
    87  	bundata, hash := readHash(c, bunpath)
    88  	sch, err := s.State.AddCharm(bun, curl, surl, hash)
    89  	c.Assert(err, gc.IsNil)
    90  	apiCharm, err := s.uniter.Charm(sch.URL())
    91  	c.Assert(err, gc.IsNil)
    92  	return apiCharm, sch, bundata
    93  }
    94  
    95  func (s *BundlesDirSuite) TestGet(c *gc.C) {
    96  	basedir := c.MkDir()
    97  	bunsdir := filepath.Join(basedir, "random", "bundles")
    98  	d := charm.NewBundlesDir(bunsdir)
    99  
   100  	// Check it doesn't get created until it's needed.
   101  	_, err := os.Stat(bunsdir)
   102  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   103  
   104  	// Add a charm to state that we can try to get.
   105  	apiCharm, sch, bundata := s.AddCharm(c)
   106  
   107  	// Try to get the charm when the content doesn't match.
   108  	coretesting.Server.Response(200, nil, []byte("roflcopter"))
   109  	_, err = d.Read(apiCharm, nil)
   110  	prefix := fmt.Sprintf(`failed to download charm "cs:quantal/dummy-1" from %q: `, sch.BundleURL())
   111  	c.Assert(err, gc.ErrorMatches, prefix+fmt.Sprintf(`expected sha256 %q, got ".*"`, sch.BundleSha256()))
   112  
   113  	// Try to get a charm whose bundle doesn't exist.
   114  	coretesting.Server.Response(404, nil, nil)
   115  	_, err = d.Read(apiCharm, nil)
   116  	c.Assert(err, gc.ErrorMatches, prefix+`.* 404 Not Found`)
   117  
   118  	// Get a charm whose bundle exists and whose content matches.
   119  	coretesting.Server.Response(200, nil, bundata)
   120  	ch, err := d.Read(apiCharm, nil)
   121  	c.Assert(err, gc.IsNil)
   122  	assertCharm(c, ch, sch)
   123  
   124  	// Get the same charm again, without preparing a response from the server.
   125  	ch, err = d.Read(apiCharm, nil)
   126  	c.Assert(err, gc.IsNil)
   127  	assertCharm(c, ch, sch)
   128  
   129  	// Abort a download.
   130  	err = os.RemoveAll(bunsdir)
   131  	c.Assert(err, gc.IsNil)
   132  	abort := make(chan struct{})
   133  	done := make(chan bool)
   134  	go func() {
   135  		ch, err := d.Read(apiCharm, abort)
   136  		c.Assert(ch, gc.IsNil)
   137  		c.Assert(err, gc.ErrorMatches, prefix+"aborted")
   138  		close(done)
   139  	}()
   140  	close(abort)
   141  	coretesting.Server.Response(500, nil, nil)
   142  	select {
   143  	case <-done:
   144  	case <-time.After(coretesting.LongWait):
   145  		c.Fatalf("timed out waiting for abort")
   146  	}
   147  }
   148  
   149  func readHash(c *gc.C, path string) ([]byte, string) {
   150  	data, err := ioutil.ReadFile(path)
   151  	c.Assert(err, gc.IsNil)
   152  	hash := sha256.New()
   153  	hash.Write(data)
   154  	return data, hex.EncodeToString(hash.Sum(nil))
   155  }
   156  
   157  func assertCharm(c *gc.C, bun *corecharm.Bundle, sch *state.Charm) {
   158  	c.Assert(bun.Revision(), gc.Equals, sch.Revision())
   159  	c.Assert(bun.Meta(), gc.DeepEquals, sch.Meta())
   160  	c.Assert(bun.Config(), gc.DeepEquals, sch.Config())
   161  }