github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/migrationflag/util_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package migrationflag_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  	"gopkg.in/juju/worker.v1"
    13  	dt "gopkg.in/juju/worker.v1/dependency/testing"
    14  	"gopkg.in/juju/worker.v1/workertest"
    15  
    16  	"github.com/juju/juju/api/base"
    17  	"github.com/juju/juju/core/migration"
    18  	"github.com/juju/juju/core/watcher"
    19  	"github.com/juju/juju/worker/migrationflag"
    20  )
    21  
    22  // newMockFacade returns a mock Facade that will add calls to the
    23  // supplied testing.Stub, and return errors in the sequences it
    24  // specifies; if any Phase call does not return an error, it will
    25  // return a phase consumed from the head of the supplied list (or
    26  // panic if it's empty).
    27  func newMockFacade(stub *testing.Stub, phases ...migration.Phase) *mockFacade {
    28  	return &mockFacade{
    29  		stub:   stub,
    30  		phases: phases,
    31  	}
    32  }
    33  
    34  // mockFacade implements migrationflag.Facade for use in the tests.
    35  type mockFacade struct {
    36  	stub   *testing.Stub
    37  	phases []migration.Phase
    38  }
    39  
    40  // Phase is part of the migrationflag.Facade interface.
    41  func (mock *mockFacade) Phase(uuid string) (migration.Phase, error) {
    42  	mock.stub.AddCall("Phase", uuid)
    43  	if err := mock.stub.NextErr(); err != nil {
    44  		return 0, err
    45  	}
    46  	return mock.nextPhase(), nil
    47  }
    48  
    49  // nextPhase consumes a phase and returns it, or panics.
    50  func (mock *mockFacade) nextPhase() migration.Phase {
    51  	phase := mock.phases[0]
    52  	mock.phases = mock.phases[1:]
    53  	return phase
    54  }
    55  
    56  // Watch is part of the migrationflag.Facade interface.
    57  func (mock *mockFacade) Watch(uuid string) (watcher.NotifyWatcher, error) {
    58  	mock.stub.AddCall("Watch", uuid)
    59  	if err := mock.stub.NextErr(); err != nil {
    60  		return nil, err
    61  	}
    62  	return newMockWatcher(), nil
    63  }
    64  
    65  // newMockWatcher returns a watcher.NotifyWatcher that always
    66  // sends 3 changes and then sits quietly until killed.
    67  func newMockWatcher() *mockWatcher {
    68  	const count = 3
    69  	changes := make(chan struct{}, count)
    70  	for i := 0; i < count; i++ {
    71  		changes <- struct{}{}
    72  	}
    73  	return &mockWatcher{
    74  		Worker:  workertest.NewErrorWorker(nil),
    75  		changes: changes,
    76  	}
    77  }
    78  
    79  // mockWatcher implements watcher.NotifyWatcher for use in the tests.
    80  type mockWatcher struct {
    81  	worker.Worker
    82  	changes chan struct{}
    83  }
    84  
    85  // Changes is part of the watcher.NotifyWatcher interface.
    86  func (mock *mockWatcher) Changes() watcher.NotifyChannel {
    87  	return mock.changes
    88  }
    89  
    90  // checkCalls checks that all the supplied call names were invoked
    91  // in the supplied order, and that every one was passed [validUUID].
    92  func checkCalls(c *gc.C, stub *testing.Stub, names ...string) {
    93  	stub.CheckCallNames(c, names...)
    94  	for _, call := range stub.Calls() {
    95  		c.Check(call.Args, jc.DeepEquals, []interface{}{validUUID})
    96  	}
    97  }
    98  
    99  // validUUID is the model UUID we're using in the tests.
   100  var validUUID = "01234567-89ab-cdef-0123-456789abcdef"
   101  
   102  // panicCheck is a Config.Check value that should not be called.
   103  func panicCheck(migration.Phase) bool { panic("unexpected") }
   104  
   105  // neverCheck is a Config.Check value that always returns false.
   106  func neverCheck(migration.Phase) bool { return false }
   107  
   108  // panicFacade is a NewFacade that should not be called.
   109  func panicFacade(base.APICaller) (migrationflag.Facade, error) {
   110  	panic("panicFacade")
   111  }
   112  
   113  // panicWorker is a NewWorker that should not be called.
   114  func panicWorker(migrationflag.Config) (worker.Worker, error) {
   115  	panic("panicWorker")
   116  }
   117  
   118  // isQuiesce is a Config.Check value that returns whether the phase is QUIESCE.
   119  func isQuiesce(p migration.Phase) bool { return p == migration.QUIESCE }
   120  
   121  // validConfig returns a minimal config stuffed with dummy objects that
   122  // will explode when used.
   123  func validConfig() migrationflag.Config {
   124  	return migrationflag.Config{
   125  		Facade: struct{ migrationflag.Facade }{},
   126  		Model:  validUUID,
   127  		Check:  panicCheck,
   128  	}
   129  }
   130  
   131  // checkNotValid checks that the supplied migrationflag.Config fails to
   132  // Validate, and cannot be used to construct a migrationflag.Worker.
   133  func checkNotValid(c *gc.C, config migrationflag.Config, expect string) {
   134  	check := func(err error) {
   135  		c.Check(err, gc.ErrorMatches, expect)
   136  		c.Check(err, jc.Satisfies, errors.IsNotValid)
   137  	}
   138  
   139  	err := config.Validate()
   140  	check(err)
   141  
   142  	worker, err := migrationflag.New(config)
   143  	c.Check(worker, gc.IsNil)
   144  	check(err)
   145  }
   146  
   147  // validManifoldConfig returns a minimal config stuffed with dummy objects
   148  // that will explode when used.
   149  func validManifoldConfig() migrationflag.ManifoldConfig {
   150  	return migrationflag.ManifoldConfig{
   151  		APICallerName: "api-caller",
   152  		Check:         panicCheck,
   153  		NewFacade:     panicFacade,
   154  		NewWorker:     panicWorker,
   155  	}
   156  }
   157  
   158  // checkManifoldNotValid checks that the supplied ManifoldConfig creates
   159  // a manifold that cannot be started.
   160  func checkManifoldNotValid(c *gc.C, config migrationflag.ManifoldConfig, expect string) {
   161  	manifold := migrationflag.Manifold(config)
   162  	worker, err := manifold.Start(dt.StubContext(nil, nil))
   163  	c.Check(worker, gc.IsNil)
   164  	c.Check(err, gc.ErrorMatches, expect)
   165  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   166  }
   167  
   168  // stubCaller is a base.APICaller that only implements ModelTag.
   169  type stubCaller struct {
   170  	base.APICaller
   171  }
   172  
   173  // ModelTag is part of the base.APICaller interface.
   174  func (*stubCaller) ModelTag() (names.ModelTag, bool) {
   175  	return names.NewModelTag(validUUID), true
   176  }