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

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package statushistorypruner_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	coretesting "github.com/juju/juju/testing"
    14  	"github.com/juju/juju/worker"
    15  	"github.com/juju/juju/worker/statushistorypruner"
    16  )
    17  
    18  type statusHistoryPrunerSuite struct {
    19  	coretesting.BaseSuite
    20  }
    21  
    22  var _ = gc.Suite(&statusHistoryPrunerSuite{})
    23  
    24  func (s *statusHistoryPrunerSuite) TestWorkerCallsPrune(c *gc.C) {
    25  	fakeTimer := newMockTimer(coretesting.LongWait)
    26  
    27  	fakeTimerFunc := func(d time.Duration) worker.PeriodicTimer {
    28  		// construction of timer should be with 0 because we intend it to
    29  		// run once before waiting.
    30  		c.Assert(d, gc.Equals, 0*time.Nanosecond)
    31  		return fakeTimer
    32  	}
    33  	facade := newFakeFacade()
    34  	conf := statushistorypruner.Config{
    35  		Facade:         facade,
    36  		MaxHistoryTime: 1 * time.Second,
    37  		MaxHistoryMB:   3,
    38  		PruneInterval:  coretesting.ShortWait,
    39  		NewTimer:       fakeTimerFunc,
    40  	}
    41  
    42  	pruner, err := statushistorypruner.New(conf)
    43  	c.Check(err, jc.ErrorIsNil)
    44  	s.AddCleanup(func(*gc.C) {
    45  		c.Assert(worker.Stop(pruner), jc.ErrorIsNil)
    46  	})
    47  
    48  	err = fakeTimer.fire()
    49  	c.Check(err, jc.ErrorIsNil)
    50  
    51  	var passedMB int
    52  	select {
    53  	case passedMB = <-facade.passedMaxHistoryMB:
    54  	case <-time.After(coretesting.LongWait):
    55  		c.Fatal("timed out waiting for passed logs to pruner")
    56  	}
    57  	c.Assert(passedMB, gc.Equals, 3)
    58  
    59  	// Reset will have been called with the actual PruneInterval
    60  	var period time.Duration
    61  	select {
    62  	case period = <-fakeTimer.period:
    63  	case <-time.After(coretesting.LongWait):
    64  		c.Fatal("timed out waiting for period reset by pruner")
    65  	}
    66  	c.Assert(period, gc.Equals, coretesting.ShortWait)
    67  }
    68  
    69  func (s *statusHistoryPrunerSuite) TestWorkerWontCallPruneBeforeFiringTimer(c *gc.C) {
    70  	fakeTimer := newMockTimer(coretesting.LongWait)
    71  
    72  	fakeTimerFunc := func(d time.Duration) worker.PeriodicTimer {
    73  		// construction of timer should be with 0 because we intend it to
    74  		// run once before waiting.
    75  		c.Assert(d, gc.Equals, 0*time.Nanosecond)
    76  		return fakeTimer
    77  	}
    78  	facade := newFakeFacade()
    79  	conf := statushistorypruner.Config{
    80  		Facade:         facade,
    81  		MaxHistoryTime: 1 * time.Second,
    82  		MaxHistoryMB:   3,
    83  		PruneInterval:  coretesting.ShortWait,
    84  		NewTimer:       fakeTimerFunc,
    85  	}
    86  
    87  	pruner, err := statushistorypruner.New(conf)
    88  	c.Check(err, jc.ErrorIsNil)
    89  	s.AddCleanup(func(*gc.C) {
    90  		c.Assert(worker.Stop(pruner), jc.ErrorIsNil)
    91  	})
    92  
    93  	select {
    94  	case <-facade.passedMaxHistoryMB:
    95  		c.Fatal("called before firing timer.")
    96  	case <-time.After(coretesting.LongWait):
    97  	}
    98  }
    99  
   100  type mockTimer struct {
   101  	period chan time.Duration
   102  	c      chan time.Time
   103  }
   104  
   105  func (t *mockTimer) Reset(d time.Duration) bool {
   106  	select {
   107  	case t.period <- d:
   108  	case <-time.After(coretesting.LongWait):
   109  		panic("timed out waiting for timer to reset")
   110  	}
   111  	return true
   112  }
   113  
   114  func (t *mockTimer) CountDown() <-chan time.Time {
   115  	return t.c
   116  }
   117  
   118  func (t *mockTimer) fire() error {
   119  	select {
   120  	case t.c <- time.Time{}:
   121  	case <-time.After(coretesting.LongWait):
   122  		return errors.New("timed out waiting for pruner to run")
   123  	}
   124  	return nil
   125  }
   126  
   127  func newMockTimer(d time.Duration) *mockTimer {
   128  	return &mockTimer{period: make(chan time.Duration, 1),
   129  		c: make(chan time.Time),
   130  	}
   131  }
   132  
   133  type fakeFacade struct {
   134  	passedMaxHistoryMB chan int
   135  }
   136  
   137  func newFakeFacade() *fakeFacade {
   138  	return &fakeFacade{
   139  		passedMaxHistoryMB: make(chan int, 1),
   140  	}
   141  }
   142  
   143  // Prune implements Facade
   144  func (f *fakeFacade) Prune(_ time.Duration, maxHistoryMB int) error {
   145  	// TODO(perrito666) either make this send its actual args, or just use
   146  	// a stub and drop the unnecessary channel malarkey entirely
   147  	select {
   148  	case f.passedMaxHistoryMB <- maxHistoryMB:
   149  	case <-time.After(coretesting.LongWait):
   150  		return errors.New("timed out waiting for facade call Prune to run")
   151  	}
   152  	return nil
   153  }