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 }