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