github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/undertaker/mock_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package undertaker_test
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	"github.com/juju/clock/testclock"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/worker/v3"
    14  	"github.com/juju/worker/v3/workertest"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	"github.com/juju/juju/core/status"
    18  	"github.com/juju/juju/core/watcher"
    19  	"github.com/juju/juju/environs"
    20  	"github.com/juju/juju/environs/cloudspec"
    21  	"github.com/juju/juju/environs/config"
    22  	environscontext "github.com/juju/juju/environs/context"
    23  	"github.com/juju/juju/rpc/params"
    24  	"github.com/juju/juju/worker/undertaker"
    25  )
    26  
    27  type mockFacade struct {
    28  	stub         *testing.Stub
    29  	info         params.UndertakerModelInfoResult
    30  	clock        testclock.AdvanceableClock
    31  	advance      time.Duration
    32  	modelChanges chan struct{}
    33  }
    34  
    35  func (mock *mockFacade) ModelInfo() (params.UndertakerModelInfoResult, error) {
    36  	mock.stub.AddCall("ModelInfo")
    37  	if err := mock.stub.NextErr(); err != nil {
    38  		return params.UndertakerModelInfoResult{}, err
    39  	}
    40  	return mock.info, nil
    41  }
    42  
    43  func (mock *mockFacade) WatchModelResources() (watcher.NotifyWatcher, error) {
    44  	mock.stub.AddCall("WatchModelResources")
    45  	if mock.advance > 0 {
    46  		mock.clock.Advance(mock.advance)
    47  	}
    48  	if err := mock.stub.NextErr(); err != nil {
    49  		return nil, err
    50  	}
    51  	const count = 5
    52  	changes := make(chan struct{}, count)
    53  	for i := 0; i < count; i++ {
    54  		changes <- struct{}{}
    55  	}
    56  	return &mockWatcher{
    57  		Worker:  workertest.NewErrorWorker(nil),
    58  		changes: changes,
    59  	}, nil
    60  }
    61  
    62  func (mock *mockFacade) ProcessDyingModel() error {
    63  	mock.stub.AddCall("ProcessDyingModel")
    64  	time.Sleep(100 * time.Millisecond)
    65  	return mock.stub.NextErr()
    66  }
    67  
    68  func (mock *mockFacade) SetStatus(status status.Status, info string, data map[string]interface{}) error {
    69  	mock.stub.MethodCall(mock, "SetStatus", status, info, data)
    70  	return mock.stub.NextErr()
    71  }
    72  
    73  func (mock *mockFacade) RemoveModel() error {
    74  	mock.stub.AddCall("RemoveModel")
    75  	time.Sleep(100 * time.Millisecond)
    76  	return mock.stub.NextErr()
    77  }
    78  
    79  func (mock *mockFacade) ModelConfig() (*config.Config, error) {
    80  	mock.stub.AddCall("ModelConfig")
    81  	cfg, _ := config.New(config.NoDefaults, map[string]interface{}{
    82  		"uuid": "00000000-0000-0000-0000-000000000000",
    83  		"name": "name",
    84  	})
    85  	return cfg, mock.stub.NextErr()
    86  }
    87  
    88  func (mock *mockFacade) CloudSpec() (cloudspec.CloudSpec, error) {
    89  	mock.stub.AddCall("CloudSpec")
    90  	return cloudspec.CloudSpec{}, mock.stub.NextErr()
    91  }
    92  
    93  func (mock *mockFacade) WatchModel() (watcher.NotifyWatcher, error) {
    94  	mock.stub.AddCall("WatchModel")
    95  	if err := mock.stub.NextErr(); err != nil {
    96  		return nil, err
    97  	}
    98  	return &mockWatcher{
    99  		Worker:  workertest.NewErrorWorker(nil),
   100  		changes: mock.modelChanges,
   101  	}, nil
   102  }
   103  
   104  type mockDestroyer struct {
   105  	environs.Environ
   106  	stub *testing.Stub
   107  }
   108  
   109  func (mock *mockDestroyer) Destroy(ctx environscontext.ProviderCallContext) error {
   110  	mock.stub.AddCall("Destroy", ctx)
   111  	// A small delay to allow any timeout to expire.
   112  	time.Sleep(100 * time.Millisecond)
   113  	return mock.stub.NextErr()
   114  }
   115  
   116  type mockWatcher struct {
   117  	worker.Worker
   118  	changes chan struct{}
   119  }
   120  
   121  func (mock *mockWatcher) Changes() watcher.NotifyChannel {
   122  	return mock.changes
   123  }
   124  
   125  type fixture struct {
   126  	info    params.UndertakerModelInfoResult
   127  	errors  []error
   128  	dirty   bool
   129  	logger  fakeLogger
   130  	clock   testclock.AdvanceableClock
   131  	advance time.Duration
   132  }
   133  
   134  func (fix *fixture) cleanup(c *gc.C, w worker.Worker) {
   135  	if fix.dirty {
   136  		workertest.DirtyKill(c, w)
   137  	} else {
   138  		workertest.CleanKill(c, w)
   139  	}
   140  }
   141  
   142  func (fix *fixture) run(c *gc.C, test func(worker.Worker)) *testing.Stub {
   143  	stub := &testing.Stub{}
   144  	facade := &mockFacade{
   145  		stub:         stub,
   146  		info:         fix.info,
   147  		clock:        fix.clock,
   148  		advance:      fix.advance,
   149  		modelChanges: make(chan struct{}, 1),
   150  	}
   151  	facade.modelChanges <- struct{}{}
   152  	stub.SetErrors(fix.errors...)
   153  	w, err := undertaker.NewUndertaker(undertaker.Config{
   154  		Facade:        facade,
   155  		CredentialAPI: &fakeCredentialAPI{},
   156  		Logger:        &fix.logger,
   157  		Clock:         fix.clock,
   158  		NewCloudDestroyerFunc: func(ctx context.Context, op environs.OpenParams) (environs.CloudDestroyer, error) {
   159  			return &mockDestroyer{stub: stub}, nil
   160  		},
   161  	})
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	defer fix.cleanup(c, w)
   164  	test(w)
   165  	return stub
   166  }