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