github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  		fix.clock.Advance(time.Minute)
    49  		fix.waitCall(c)
    50  		fix.waitNoCall(c)
    51  	})
    52  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions")
    53  }
    54  
    55  func (s *WorkerSuite) TestImmediateUpdateError(c *gc.C) {
    56  	fix := newFixture(time.Minute)
    57  	fix.revisionUpdater.stub.SetErrors(
    58  		errors.New("no updates for you"),
    59  	)
    60  	fix.dirtyTest(c, func(w worker.Worker) {
    61  		fix.waitCall(c)
    62  		c.Check(w.Wait(), gc.ErrorMatches, "no updates for you")
    63  		fix.waitNoCall(c)
    64  	})
    65  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions")
    66  }
    67  
    68  func (s *WorkerSuite) TestDelayedUpdateError(c *gc.C) {
    69  	fix := newFixture(time.Minute)
    70  	fix.revisionUpdater.stub.SetErrors(
    71  		nil,
    72  		errors.New("no more updates for you"),
    73  	)
    74  	fix.dirtyTest(c, func(w worker.Worker) {
    75  		fix.waitCall(c)
    76  		fix.clock.Advance(time.Minute)
    77  		fix.waitCall(c)
    78  		c.Check(w.Wait(), gc.ErrorMatches, "no more updates for you")
    79  		fix.waitNoCall(c)
    80  	})
    81  	fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions")
    82  }
    83  
    84  // workerFixture isolates a charmrevision worker for testing.
    85  type workerFixture struct {
    86  	revisionUpdater mockRevisionUpdater
    87  	clock           *coretesting.Clock
    88  	period          time.Duration
    89  }
    90  
    91  func newFixture(period time.Duration) workerFixture {
    92  	return workerFixture{
    93  		revisionUpdater: newMockRevisionUpdater(),
    94  		clock:           coretesting.NewClock(time.Now()),
    95  		period:          period,
    96  	}
    97  }
    98  
    99  type testFunc func(worker.Worker)
   100  
   101  func (fix workerFixture) cleanTest(c *gc.C, test testFunc) {
   102  	fix.runTest(c, test, true)
   103  }
   104  
   105  func (fix workerFixture) dirtyTest(c *gc.C, test testFunc) {
   106  	fix.runTest(c, test, false)
   107  }
   108  
   109  func (fix workerFixture) runTest(c *gc.C, test testFunc, checkWaitErr bool) {
   110  	w, err := charmrevision.NewWorker(charmrevision.Config{
   111  		RevisionUpdater: fix.revisionUpdater,
   112  		Clock:           fix.clock,
   113  		Period:          fix.period,
   114  	})
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	defer func() {
   117  		err := worker.Stop(w)
   118  		if checkWaitErr {
   119  			c.Check(err, jc.ErrorIsNil)
   120  		}
   121  	}()
   122  	test(w)
   123  }
   124  
   125  func (fix workerFixture) waitCall(c *gc.C) {
   126  	select {
   127  	case <-fix.revisionUpdater.calls:
   128  	case <-time.After(coretesting.LongWait):
   129  		c.Fatalf("timed out")
   130  	}
   131  }
   132  
   133  func (fix workerFixture) waitNoCall(c *gc.C) {
   134  	select {
   135  	case <-fix.revisionUpdater.calls:
   136  		c.Fatalf("unexpected revisionUpdater call")
   137  	case <-time.After(coretesting.ShortWait):
   138  	}
   139  }
   140  
   141  // mockRevisionUpdater records (and notifies of) calls made to UpdateLatestRevisions.
   142  type mockRevisionUpdater struct {
   143  	stub  *testing.Stub
   144  	calls chan struct{}
   145  }
   146  
   147  func newMockRevisionUpdater() mockRevisionUpdater {
   148  	return mockRevisionUpdater{
   149  		stub:  &testing.Stub{},
   150  		calls: make(chan struct{}, 1000),
   151  	}
   152  }
   153  
   154  func (mock mockRevisionUpdater) UpdateLatestRevisions() error {
   155  	mock.stub.AddCall("UpdateLatestRevisions")
   156  	mock.calls <- struct{}{}
   157  	return mock.stub.NextErr()
   158  }