github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/cleaner/cleaner_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cleaner_test
     5  
     6  import (
     7  	"errors"
     8  	"time"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"launchpad.net/tomb"
    13  
    14  	coretesting "github.com/juju/juju/testing"
    15  	"github.com/juju/juju/watcher"
    16  	"github.com/juju/juju/worker"
    17  	"github.com/juju/juju/worker/cleaner"
    18  )
    19  
    20  type CleanerSuite struct {
    21  	coretesting.BaseSuite
    22  	mockState *cleanerMock
    23  }
    24  
    25  var _ = gc.Suite(&CleanerSuite{})
    26  
    27  func (s *CleanerSuite) SetUpTest(c *gc.C) {
    28  	s.BaseSuite.SetUpTest(c)
    29  	s.mockState = &cleanerMock{
    30  		calls: make(chan string),
    31  	}
    32  	s.mockState.watcher = s.newMockNotifyWatcher(nil)
    33  }
    34  
    35  func (s *CleanerSuite) AssertReceived(c *gc.C, expect string) {
    36  	select {
    37  	case call := <-s.mockState.calls:
    38  		c.Assert(call, gc.Matches, expect)
    39  	case <-time.After(coretesting.LongWait):
    40  		c.Fatalf("Timed out waiting for %s", expect)
    41  	}
    42  }
    43  
    44  func (s *CleanerSuite) AssertEmpty(c *gc.C) {
    45  	select {
    46  	case call, ok := <-s.mockState.calls:
    47  		c.Fatalf("Unexpected %s (ok: %v)", call, ok)
    48  	case <-time.After(coretesting.ShortWait):
    49  	}
    50  }
    51  
    52  func (s *CleanerSuite) TestCleaner(c *gc.C) {
    53  	cln, err := cleaner.NewCleaner(s.mockState)
    54  	c.Assert(err, jc.ErrorIsNil)
    55  	defer func() { c.Assert(worker.Stop(cln), jc.ErrorIsNil) }()
    56  
    57  	s.AssertReceived(c, "WatchCleanups")
    58  	s.AssertReceived(c, "Cleanup")
    59  
    60  	s.mockState.watcher.Change()
    61  	s.AssertReceived(c, "Cleanup")
    62  }
    63  
    64  func (s *CleanerSuite) TestWatchCleanupsError(c *gc.C) {
    65  	s.mockState.err = []error{errors.New("hello")}
    66  	cln, err := cleaner.NewCleaner(s.mockState)
    67  	c.Assert(err, jc.ErrorIsNil)
    68  
    69  	s.AssertReceived(c, "WatchCleanups")
    70  	s.AssertEmpty(c)
    71  	err = worker.Stop(cln)
    72  	c.Assert(err, gc.ErrorMatches, "hello")
    73  }
    74  
    75  func (s *CleanerSuite) TestCleanupError(c *gc.C) {
    76  	s.mockState.err = []error{nil, errors.New("hello")}
    77  	cln, err := cleaner.NewCleaner(s.mockState)
    78  	c.Assert(err, jc.ErrorIsNil)
    79  
    80  	s.AssertReceived(c, "WatchCleanups")
    81  	s.AssertReceived(c, "Cleanup")
    82  	err = worker.Stop(cln)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	log := c.GetTestLog()
    85  	c.Assert(log, jc.Contains, "ERROR juju.worker.cleaner cannot cleanup state: hello")
    86  }
    87  
    88  func (s *CleanerSuite) newMockNotifyWatcher(err error) *mockNotifyWatcher {
    89  	m := &mockNotifyWatcher{
    90  		changes: make(chan struct{}, 1),
    91  		err:     err,
    92  	}
    93  	go func() {
    94  		defer m.tomb.Done()
    95  		defer m.tomb.Kill(m.err)
    96  		<-m.tomb.Dying()
    97  	}()
    98  	s.AddCleanup(func(c *gc.C) {
    99  		err := worker.Stop(m)
   100  		c.Check(err, jc.ErrorIsNil)
   101  	})
   102  	m.Change()
   103  	return m
   104  }
   105  
   106  type mockNotifyWatcher struct {
   107  	watcher.NotifyWatcher
   108  
   109  	tomb    tomb.Tomb
   110  	err     error
   111  	changes chan struct{}
   112  }
   113  
   114  func (m *mockNotifyWatcher) Kill() {
   115  	m.tomb.Kill(nil)
   116  }
   117  
   118  func (m *mockNotifyWatcher) Wait() error {
   119  	return m.tomb.Wait()
   120  }
   121  
   122  func (m *mockNotifyWatcher) Changes() watcher.NotifyChannel {
   123  	return m.changes
   124  }
   125  
   126  func (m *mockNotifyWatcher) Change() {
   127  	m.changes <- struct{}{}
   128  }
   129  
   130  // cleanerMock is used to check the
   131  // calls of Cleanup() and WatchCleanups()
   132  type cleanerMock struct {
   133  	cleaner.StateCleaner
   134  	watcher *mockNotifyWatcher
   135  	calls   chan string
   136  	err     []error
   137  }
   138  
   139  func (m *cleanerMock) getError() (e error) {
   140  	if len(m.err) > 0 {
   141  		e = m.err[0]
   142  		m.err = m.err[1:]
   143  	}
   144  	return
   145  }
   146  
   147  func (m *cleanerMock) Cleanup() error {
   148  	m.calls <- "Cleanup"
   149  	return m.getError()
   150  }
   151  
   152  func (m *cleanerMock) WatchCleanups() (watcher.NotifyWatcher, error) {
   153  	m.calls <- "WatchCleanups"
   154  	return m.watcher, m.getError()
   155  }