github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/workers/restart_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package workers_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils/clock"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/state/workers"
    17  	"github.com/juju/juju/worker"
    18  	"github.com/juju/juju/worker/workertest"
    19  )
    20  
    21  type RestartWorkersSuite struct {
    22  	testing.IsolationSuite
    23  }
    24  
    25  var _ = gc.Suite(&RestartWorkersSuite{})
    26  
    27  func (*RestartWorkersSuite) TestValidateSuccess(c *gc.C) {
    28  	config := workers.RestartConfig{
    29  		Factory: struct{ workers.Factory }{},
    30  		Logger:  loggo.GetLogger("test"),
    31  		Clock:   struct{ clock.Clock }{},
    32  		Delay:   time.Nanosecond,
    33  	}
    34  	err := config.Validate()
    35  	c.Check(err, jc.ErrorIsNil)
    36  }
    37  
    38  func (*RestartWorkersSuite) TestValidateMissingFactory(c *gc.C) {
    39  	config := validRestartConfig()
    40  	config.Factory = nil
    41  	checkInvalidRestartConfig(c, config, "nil Factory not valid")
    42  }
    43  
    44  func (*RestartWorkersSuite) TestValidateUninitializedLogger(c *gc.C) {
    45  	config := validRestartConfig()
    46  	config.Logger = loggo.Logger{}
    47  	checkInvalidRestartConfig(c, config, "uninitialized Logger not valid")
    48  }
    49  
    50  func (*RestartWorkersSuite) TestValidateMissingClock(c *gc.C) {
    51  	config := validRestartConfig()
    52  	config.Clock = nil
    53  	checkInvalidRestartConfig(c, config, "nil Clock not valid")
    54  }
    55  
    56  func (*RestartWorkersSuite) TestValidateMissingDelay(c *gc.C) {
    57  	config := validRestartConfig()
    58  	config.Delay = 0
    59  	checkInvalidRestartConfig(c, config, "non-positive Delay not valid")
    60  }
    61  
    62  func (*RestartWorkersSuite) TestValidateNegativeDelay(c *gc.C) {
    63  	config := validRestartConfig()
    64  	config.Delay = -time.Second
    65  	checkInvalidRestartConfig(c, config, "non-positive Delay not valid")
    66  }
    67  
    68  func (*RestartWorkersSuite) TestNewLeadershipManagerError(c *gc.C) {
    69  	fix := Fixture{
    70  		LW_errors: []error{ErrFailStart},
    71  	}
    72  	fix.FailRestart(c, "cannot create leadership lease manager: bad start")
    73  }
    74  
    75  func (*RestartWorkersSuite) TestNewSingularManagerError(c *gc.C) {
    76  	fix := Fixture{
    77  		LW_errors: []error{nil},
    78  		SW_errors: []error{ErrFailStart},
    79  	}
    80  	fix.FailRestart(c, "cannot create singular lease manager: bad start")
    81  }
    82  
    83  func (*RestartWorkersSuite) TestNewTxnLogWatcherError(c *gc.C) {
    84  	fix := Fixture{
    85  		LW_errors:  []error{nil},
    86  		SW_errors:  []error{nil},
    87  		TLW_errors: []error{ErrFailStart},
    88  	}
    89  	fix.FailRestart(c, "cannot create transaction log watcher: bad start")
    90  }
    91  
    92  func (*RestartWorkersSuite) TestNewPresenceWatcherError(c *gc.C) {
    93  	fix := BasicFixture()
    94  	fix.PW_errors = []error{ErrFailStart}
    95  	fix.FailRestart(c, "cannot create presence watcher: bad start")
    96  }
    97  
    98  func (*RestartWorkersSuite) TestLeadershipManagerDelay(c *gc.C) {
    99  	fix := BasicFixture()
   100  	fix.LW_errors = []error{errors.New("oof")}
   101  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   102  		w := NextWorker(c, ctx.LWs())
   103  		c.Assert(w, gc.NotNil)
   104  		AssertWorker(c, rw.LeadershipManager(), w)
   105  		w.Kill()
   106  
   107  		clock := ctx.Clock()
   108  		WaitAlarms(c, clock, 1)
   109  		clock.Advance(almostFiveSeconds)
   110  		AssertWorker(c, rw.LeadershipManager(), w)
   111  
   112  		err := workertest.CheckKill(c, rw)
   113  		c.Check(err, gc.ErrorMatches, "error stopping leadership lease manager: oof")
   114  	})
   115  }
   116  
   117  func (*RestartWorkersSuite) TestSingularManagerDelay(c *gc.C) {
   118  	fix := BasicFixture()
   119  	fix.SW_errors = []error{errors.New("oof")}
   120  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   121  		w := NextWorker(c, ctx.SWs())
   122  		c.Assert(w, gc.NotNil)
   123  		AssertWorker(c, rw.SingularManager(), w)
   124  		w.Kill()
   125  
   126  		clock := ctx.Clock()
   127  		WaitAlarms(c, clock, 1)
   128  		clock.Advance(almostFiveSeconds)
   129  		AssertWorker(c, rw.SingularManager(), w)
   130  
   131  		err := workertest.CheckKill(c, rw)
   132  		c.Check(err, gc.ErrorMatches, "error stopping singular lease manager: oof")
   133  	})
   134  }
   135  
   136  func (*RestartWorkersSuite) TestTxnLogWatcherDelay(c *gc.C) {
   137  	fix := BasicFixture()
   138  	fix.TLW_errors = []error{errors.New("oof")}
   139  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   140  		w := NextWorker(c, ctx.TLWs())
   141  		c.Assert(w, gc.NotNil)
   142  		AssertWorker(c, rw.TxnLogWatcher(), w)
   143  		w.Kill()
   144  
   145  		clock := ctx.Clock()
   146  		WaitAlarms(c, clock, 1)
   147  		clock.Advance(almostFiveSeconds)
   148  		AssertWorker(c, rw.TxnLogWatcher(), w)
   149  
   150  		err := workertest.CheckKill(c, rw)
   151  		c.Check(err, gc.ErrorMatches, "error stopping transaction log watcher: oof")
   152  	})
   153  }
   154  
   155  func (*RestartWorkersSuite) TestPresenceWatcherDelay(c *gc.C) {
   156  	fix := BasicFixture()
   157  	fix.PW_errors = []error{errors.New("oof")}
   158  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   159  		w := NextWorker(c, ctx.PWs())
   160  		c.Assert(w, gc.NotNil)
   161  		AssertWorker(c, rw.PresenceWatcher(), w)
   162  		w.Kill()
   163  
   164  		clock := ctx.Clock()
   165  		WaitAlarms(c, clock, 1)
   166  		clock.Advance(almostFiveSeconds)
   167  		AssertWorker(c, rw.PresenceWatcher(), w)
   168  
   169  		err := workertest.CheckKill(c, rw)
   170  		c.Check(err, gc.ErrorMatches, "error stopping presence watcher: oof")
   171  	})
   172  }
   173  
   174  func (*RestartWorkersSuite) TestLeadershipManagerRestart(c *gc.C) {
   175  	fix := BasicFixture()
   176  	fix.LW_errors = []error{errors.New("oof"), nil}
   177  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   178  		origw := rw.LeadershipManager()
   179  		w := NextWorker(c, ctx.LWs())
   180  		c.Assert(w, gc.NotNil)
   181  		AssertWorker(c, rw.LeadershipManager(), w)
   182  		w.Kill()
   183  
   184  		clock := ctx.Clock()
   185  		WaitAlarms(c, clock, 1)
   186  		clock.Advance(fiveSeconds)
   187  		w2 := NextWorker(c, ctx.LWs())
   188  		c.Assert(w, gc.NotNil)
   189  		WaitWorker(c, LM_getter(rw), w2)
   190  
   191  		// The new worker should underlie the originally
   192  		// acquired leadership manager, so that restarts
   193  		// do not require callers to acquire a new manager
   194  		AssertWorker(c, origw, w2)
   195  
   196  		workertest.CleanKill(c, rw)
   197  	})
   198  }
   199  
   200  func (*RestartWorkersSuite) TestSingularManagerRestart(c *gc.C) {
   201  	fix := BasicFixture()
   202  	fix.SW_errors = []error{errors.New("oof"), nil}
   203  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   204  		origw := rw.SingularManager()
   205  		w := NextWorker(c, ctx.SWs())
   206  		c.Assert(w, gc.NotNil)
   207  		AssertWorker(c, rw.SingularManager(), w)
   208  		w.Kill()
   209  
   210  		clock := ctx.Clock()
   211  		WaitAlarms(c, clock, 1)
   212  		clock.Advance(fiveSeconds)
   213  		w2 := NextWorker(c, ctx.SWs())
   214  		c.Assert(w, gc.NotNil)
   215  		WaitWorker(c, SM_getter(rw), w2)
   216  
   217  		// The new worker should underlie the originally
   218  		// acquired singular manager, so that restarts
   219  		// do not require callers to acquire a new manager
   220  		AssertWorker(c, origw, w2)
   221  
   222  		workertest.CleanKill(c, rw)
   223  	})
   224  }
   225  
   226  func (*RestartWorkersSuite) TestTxnLogWatcherRestart(c *gc.C) {
   227  	fix := BasicFixture()
   228  	fix.TLW_errors = []error{errors.New("oof"), nil}
   229  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   230  		w := NextWorker(c, ctx.TLWs())
   231  		c.Assert(w, gc.NotNil)
   232  		AssertWorker(c, rw.TxnLogWatcher(), w)
   233  		w.Kill()
   234  
   235  		clock := ctx.Clock()
   236  		WaitAlarms(c, clock, 1)
   237  		clock.Advance(fiveSeconds)
   238  		w2 := NextWorker(c, ctx.TLWs())
   239  		c.Assert(w, gc.NotNil)
   240  		WaitWorker(c, TLW_getter(rw), w2)
   241  
   242  		workertest.CleanKill(c, rw)
   243  	})
   244  }
   245  
   246  func (*RestartWorkersSuite) TestPresenceWatcherRestart(c *gc.C) {
   247  	fix := BasicFixture()
   248  	fix.PW_errors = []error{errors.New("oof"), nil}
   249  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   250  		w := NextWorker(c, ctx.PWs())
   251  		c.Assert(w, gc.NotNil)
   252  		AssertWorker(c, rw.PresenceWatcher(), w)
   253  		w.Kill()
   254  
   255  		clock := ctx.Clock()
   256  		WaitAlarms(c, clock, 1)
   257  		clock.Advance(fiveSeconds)
   258  		w2 := NextWorker(c, ctx.PWs())
   259  		c.Assert(w, gc.NotNil)
   260  		WaitWorker(c, PW_getter(rw), w2)
   261  
   262  		workertest.CleanKill(c, rw)
   263  	})
   264  }
   265  
   266  func (*RestartWorkersSuite) TestStopsAllWorkers(c *gc.C) {
   267  	fix := BasicFixture()
   268  	fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) {
   269  		workertest.CleanKill(c, rw)
   270  		for _, ch := range []<-chan worker.Worker{
   271  			ctx.LWs(), ctx.SWs(), ctx.TLWs(), ctx.PWs(),
   272  		} {
   273  			w := NextWorker(c, ch)
   274  			workertest.CheckKilled(c, w)
   275  		}
   276  	})
   277  }
   278  
   279  func validRestartConfig() workers.RestartConfig {
   280  	return workers.RestartConfig{
   281  		Factory: struct{ workers.Factory }{},
   282  		Logger:  loggo.GetLogger("test"),
   283  		Clock:   struct{ clock.Clock }{},
   284  		Delay:   time.Nanosecond,
   285  	}
   286  }
   287  
   288  func checkInvalidRestartConfig(c *gc.C, config workers.RestartConfig, match string) {
   289  	check := func(err error) {
   290  		c.Check(err, jc.Satisfies, errors.IsNotValid)
   291  		c.Check(err, gc.ErrorMatches, match)
   292  	}
   293  
   294  	err := config.Validate()
   295  	check(err)
   296  
   297  	rw, err := workers.NewRestartWorkers(config)
   298  	if !c.Check(rw, gc.IsNil) {
   299  		workertest.DirtyKill(c, rw)
   300  	}
   301  	check(err)
   302  }