github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/charmrevision/worker_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package charmrevision_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	coretesting "github.com/juju/juju/testing"
    15  	"github.com/juju/juju/worker"
    16  	"github.com/juju/juju/worker/charmrevision"
    17  )
    18  
    19  type WorkerSuite struct {
    20  	testing.IsolationSuite
    21  }
    22  
    23  var _ = gc.Suite(&WorkerSuite{})
    24  
    25  func (s *WorkerSuite) TestUpdatesImmediately(c *gc.C) {
    26  	fix := newFixture(time.Minute)
    27  	fix.cleanTest(c, func(_ worker.Worker) {
    28  		fix.waitCall(c)
    29  		fix.waitNoCall(c)
    30  	})
    31  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions")
    32  }
    33  
    34  func (s *WorkerSuite) TestNoMoreUpdatesUntilPeriod(c *gc.C) {
    35  	fix := newFixture(time.Minute)
    36  	fix.cleanTest(c, func(_ worker.Worker) {
    37  		fix.waitCall(c)
    38  		fix.clock.Advance(time.Minute - time.Nanosecond)
    39  		fix.waitNoCall(c)
    40  	})
    41  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions")
    42  }
    43  
    44  func (s *WorkerSuite) TestUpdatesAfterPeriod(c *gc.C) {
    45  	fix := newFixture(time.Minute)
    46  	fix.cleanTest(c, func(_ worker.Worker) {
    47  		fix.waitCall(c)
    48  		if err := fix.clock.WaitAdvance(time.Minute, 1*time.Second, 1); err != nil {
    49  			c.Fatal(err)
    50  		}
    51  		fix.waitCall(c)
    52  		fix.waitNoCall(c)
    53  	})
    54  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions")
    55  }
    56  
    57  func (s *WorkerSuite) TestImmediateUpdateError(c *gc.C) {
    58  	fix := newFixture(time.Minute)
    59  	fix.revisionUpdater.stub.SetErrors(
    60  		errors.New("no updates for you"),
    61  	)
    62  	fix.dirtyTest(c, func(w worker.Worker) {
    63  		fix.waitCall(c)
    64  		c.Check(w.Wait(), gc.ErrorMatches, "no updates for you")
    65  		fix.waitNoCall(c)
    66  	})
    67  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions")
    68  }
    69  
    70  func (s *WorkerSuite) TestDelayedUpdateError(c *gc.C) {
    71  	fix := newFixture(time.Minute)
    72  	fix.revisionUpdater.stub.SetErrors(
    73  		nil,
    74  		errors.New("no more updates for you"),
    75  	)
    76  	fix.dirtyTest(c, func(w worker.Worker) {
    77  		fix.waitCall(c)
    78  		fix.clock.Advance(time.Minute)
    79  		fix.waitCall(c)
    80  		c.Check(w.Wait(), gc.ErrorMatches, "no more updates for you")
    81  		fix.waitNoCall(c)
    82  	})
    83  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions")
    84  }
    85  
    86  // workerFixture isolates a charmrevision worker for testing.
    87  type workerFixture struct {
    88  	revisionUpdater mockRevisionUpdater
    89  	clock           *testing.Clock
    90  	period          time.Duration
    91  }
    92  
    93  func newFixture(period time.Duration) workerFixture {
    94  	return workerFixture{
    95  		revisionUpdater: newMockRevisionUpdater(),
    96  		clock:           testing.NewClock(coretesting.ZeroTime()),
    97  		period:          period,
    98  	}
    99  }
   100  
   101  type testFunc func(worker.Worker)
   102  
   103  func (fix workerFixture) cleanTest(c *gc.C, test testFunc) {
   104  	fix.runTest(c, test, true)
   105  }
   106  
   107  func (fix workerFixture) dirtyTest(c *gc.C, test testFunc) {
   108  	fix.runTest(c, test, false)
   109  }
   110  
   111  func (fix workerFixture) runTest(c *gc.C, test testFunc, checkWaitErr bool) {
   112  	w, err := charmrevision.NewWorker(charmrevision.Config{
   113  		RevisionUpdater: fix.revisionUpdater,
   114  		Clock:           fix.clock,
   115  		Period:          fix.period,
   116  	})
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	defer func() {
   119  		err := worker.Stop(w)
   120  		if checkWaitErr {
   121  			c.Check(err, jc.ErrorIsNil)
   122  		}
   123  	}()
   124  	test(w)
   125  }
   126  
   127  func (fix workerFixture) waitCall(c *gc.C) {
   128  	select {
   129  	case <-fix.revisionUpdater.calls:
   130  	case <-time.After(coretesting.LongWait):
   131  		c.Fatalf("timed out")
   132  	}
   133  }
   134  
   135  func (fix workerFixture) waitNoCall(c *gc.C) {
   136  	select {
   137  	case <-fix.revisionUpdater.calls:
   138  		c.Fatalf("unexpected revisionUpdater call")
   139  	case <-time.After(coretesting.ShortWait):
   140  	}
   141  }
   142  
   143  // mockRevisionUpdater records (and notifies of) calls made to UpdateLatestRevisions.
   144  type mockRevisionUpdater struct {
   145  	stub  *testing.Stub
   146  	calls chan struct{}
   147  }
   148  
   149  func newMockRevisionUpdater() mockRevisionUpdater {
   150  	return mockRevisionUpdater{
   151  		stub:  &testing.Stub{},
   152  		calls: make(chan struct{}, 1000),
   153  	}
   154  }
   155  
   156  func (mock mockRevisionUpdater) UpdateLatestRevisions() error {
   157  	mock.stub.AddCall("UpdateLatestRevisions")
   158  	mock.calls <- struct{}{}
   159  	return mock.stub.NextErr()
   160  }