github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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 11 "github.com/juju/collections/set" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 corecharm "gopkg.in/juju/charm.v6" 15 16 "github.com/juju/juju/testcharms" 17 "github.com/juju/juju/worker/uniter/charm" 18 ) 19 20 // bundleReader is a charm.BundleReader that lets us mock out the bundles we 21 // deploy to test the Deployers. 22 type bundleReader struct { 23 bundles map[string]charm.Bundle 24 stopWaiting <-chan struct{} 25 } 26 27 // EnableWaitForAbort allows us to test that a Deployer.Stage call passes its abort 28 // chan down to its BundleReader's Read method. If you call EnableWaitForAbort, the 29 // next call to Read will block until either the abort chan is closed (in which case 30 // it will return an error) or the stopWaiting chan is closed (in which case it 31 // will return the bundle). 32 func (br *bundleReader) EnableWaitForAbort() (stopWaiting chan struct{}) { 33 stopWaiting = make(chan struct{}) 34 br.stopWaiting = stopWaiting 35 return stopWaiting 36 } 37 38 // Read implements the BundleReader interface. 39 func (br *bundleReader) Read(info charm.BundleInfo, abort <-chan struct{}) (charm.Bundle, error) { 40 bundle, ok := br.bundles[info.URL().String()] 41 if !ok { 42 return nil, fmt.Errorf("no such charm!") 43 } 44 if br.stopWaiting != nil { 45 // EnableWaitForAbort is a one-time wait; make sure we clear it. 46 defer func() { br.stopWaiting = nil }() 47 select { 48 case <-abort: 49 return nil, fmt.Errorf("charm read aborted") 50 case <-br.stopWaiting: 51 // We can stop waiting for the abort chan and return the bundle. 52 } 53 } 54 return bundle, nil 55 } 56 57 func (br *bundleReader) AddCustomBundle(c *gc.C, url *corecharm.URL, customize func(path string)) charm.BundleInfo { 58 base := c.MkDir() 59 dirpath := testcharms.Repo.ClonedDirPath(base, "dummy") 60 if customize != nil { 61 customize(dirpath) 62 } 63 dir, err := corecharm.ReadCharmDir(dirpath) 64 c.Assert(err, jc.ErrorIsNil) 65 err = dir.SetDiskRevision(url.Revision) 66 c.Assert(err, jc.ErrorIsNil) 67 bunpath := filepath.Join(base, "bundle") 68 file, err := os.Create(bunpath) 69 c.Assert(err, jc.ErrorIsNil) 70 defer file.Close() 71 err = dir.ArchiveTo(file) 72 c.Assert(err, jc.ErrorIsNil) 73 bundle, err := corecharm.ReadCharmArchive(bunpath) 74 c.Assert(err, jc.ErrorIsNil) 75 return br.AddBundle(c, url, bundle) 76 } 77 78 func (br *bundleReader) AddBundle(c *gc.C, url *corecharm.URL, bundle charm.Bundle) charm.BundleInfo { 79 if br.bundles == nil { 80 br.bundles = map[string]charm.Bundle{} 81 } 82 br.bundles[url.String()] = bundle 83 return &bundleInfo{nil, url} 84 } 85 86 type bundleInfo struct { 87 charm.BundleInfo 88 url *corecharm.URL 89 } 90 91 func (info *bundleInfo) URL() *corecharm.URL { 92 return info.url 93 } 94 95 type mockBundle struct { 96 paths set.Strings 97 expand func(dir string) error 98 } 99 100 func (b mockBundle) Manifest() (set.Strings, error) { 101 // TODO(dfc) this looks like set.Strings().Duplicate() 102 return set.NewStrings(b.paths.Values()...), nil 103 } 104 105 func (b mockBundle) ExpandTo(dir string) error { 106 if b.expand != nil { 107 return b.expand(dir) 108 } 109 return nil 110 } 111 112 func charmURL(revision int) *corecharm.URL { 113 baseURL := corecharm.MustParseURL("cs:s/c") 114 return baseURL.WithRevision(revision) 115 }