github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/worker/uniter/charm/charm_test.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package charm_test 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 stdtesting "testing" 11 12 corecharm "github.com/juju/charm" 13 charmtesting "github.com/juju/charm/testing" 14 "github.com/juju/utils/set" 15 gc "launchpad.net/gocheck" 16 17 coretesting "github.com/juju/juju/testing" 18 "github.com/juju/juju/worker/uniter/charm" 19 ) 20 21 func TestPackage(t *stdtesting.T) { 22 // TODO(fwereade) 2014-03-21 not-worth-a-bug-number 23 // rewrite BundlesDir tests to use the mocks below and not require an API 24 // server and associated gubbins. 25 coretesting.MgoTestPackage(t) 26 } 27 28 // bundleReader is a charm.BundleReader that lets us mock out the bundles we 29 // deploy to test the Deployers. 30 type bundleReader struct { 31 bundles map[string]charm.Bundle 32 stopWaiting <-chan struct{} 33 } 34 35 // EnableWaitForAbort allows us to test that a Deployer.Stage call passes its abort 36 // chan down to its BundleReader's Read method. If you call EnableWaitForAbort, the 37 // next call to Read will block until either the abort chan is closed (in which case 38 // it will return an error) or the stopWaiting chan is closed (in which case it 39 // will return the bundle). 40 func (br *bundleReader) EnableWaitForAbort() (stopWaiting chan struct{}) { 41 stopWaiting = make(chan struct{}) 42 br.stopWaiting = stopWaiting 43 return stopWaiting 44 } 45 46 // Read implements the BundleReader interface. 47 func (br *bundleReader) Read(info charm.BundleInfo, abort <-chan struct{}) (charm.Bundle, error) { 48 bundle, ok := br.bundles[info.URL().String()] 49 if !ok { 50 return nil, fmt.Errorf("no such charm!") 51 } 52 if br.stopWaiting != nil { 53 // EnableWaitForAbort is a one-time wait; make sure we clear it. 54 defer func() { br.stopWaiting = nil }() 55 select { 56 case <-abort: 57 return nil, fmt.Errorf("charm read aborted") 58 case <-br.stopWaiting: 59 // We can stop waiting for the abort chan and return the bundle. 60 } 61 } 62 return bundle, nil 63 } 64 65 func (br *bundleReader) AddCustomBundle(c *gc.C, url *corecharm.URL, customize func(path string)) charm.BundleInfo { 66 base := c.MkDir() 67 dirpath := charmtesting.Charms.ClonedDirPath(base, "dummy") 68 if customize != nil { 69 customize(dirpath) 70 } 71 dir, err := corecharm.ReadDir(dirpath) 72 c.Assert(err, gc.IsNil) 73 err = dir.SetDiskRevision(url.Revision) 74 c.Assert(err, gc.IsNil) 75 bunpath := filepath.Join(base, "bundle") 76 file, err := os.Create(bunpath) 77 c.Assert(err, gc.IsNil) 78 defer file.Close() 79 err = dir.BundleTo(file) 80 c.Assert(err, gc.IsNil) 81 bundle, err := corecharm.ReadBundle(bunpath) 82 c.Assert(err, gc.IsNil) 83 return br.AddBundle(c, url, bundle) 84 } 85 86 func (br *bundleReader) AddBundle(c *gc.C, url *corecharm.URL, bundle charm.Bundle) charm.BundleInfo { 87 if br.bundles == nil { 88 br.bundles = map[string]charm.Bundle{} 89 } 90 br.bundles[url.String()] = bundle 91 return &bundleInfo{nil, url} 92 } 93 94 type bundleInfo struct { 95 charm.BundleInfo 96 url *corecharm.URL 97 } 98 99 func (info *bundleInfo) URL() *corecharm.URL { 100 return info.url 101 } 102 103 type mockBundle struct { 104 paths set.Strings 105 expand func(dir string) error 106 } 107 108 func (b mockBundle) Manifest() (set.Strings, error) { 109 return set.NewStrings(b.paths.Values()...), nil 110 } 111 112 func (b mockBundle) ExpandTo(dir string) error { 113 if b.expand != nil { 114 return b.expand(dir) 115 } 116 return nil 117 } 118 119 func charmURL(revision int) *corecharm.URL { 120 baseURL := corecharm.MustParseURL("cs:s/c") 121 return baseURL.WithRevision(revision) 122 }