github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/dbaccessor/package_test.go (about)

     1  // Copyright 2022 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package dbaccessor
     5  
     6  import (
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/juju/clock"
    11  	jujutesting "github.com/juju/testing"
    12  	"go.uber.org/mock/gomock"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	databasetesting "github.com/juju/juju/database/testing"
    16  )
    17  
    18  //go:generate go run go.uber.org/mock/mockgen -package dbaccessor -destination package_mock_test.go github.com/juju/juju/worker/dbaccessor Logger,DBApp,NodeManager,TrackedDB,Hub,Client
    19  //go:generate go run go.uber.org/mock/mockgen -package dbaccessor -destination clock_mock_test.go github.com/juju/clock Clock,Timer
    20  //go:generate go run go.uber.org/mock/mockgen -package dbaccessor -destination metrics_mock_test.go github.com/prometheus/client_golang/prometheus Registerer
    21  
    22  func TestPackage(t *testing.T) {
    23  	gc.TestingT(t)
    24  }
    25  
    26  type baseSuite struct {
    27  	jujutesting.IsolationSuite
    28  
    29  	clock                *MockClock
    30  	hub                  *MockHub
    31  	timer                *MockTimer
    32  	logger               *MockLogger
    33  	dbApp                *MockDBApp
    34  	client               *MockClient
    35  	trackedDB            *MockTrackedDB
    36  	prometheusRegisterer *MockRegisterer
    37  	nodeManager          *MockNodeManager
    38  }
    39  
    40  func (s *baseSuite) setupMocks(c *gc.C) *gomock.Controller {
    41  	ctrl := gomock.NewController(c)
    42  
    43  	s.clock = NewMockClock(ctrl)
    44  	s.timer = NewMockTimer(ctrl)
    45  	s.logger = NewMockLogger(ctrl)
    46  	s.hub = NewMockHub(ctrl)
    47  	s.dbApp = NewMockDBApp(ctrl)
    48  	s.client = NewMockClient(ctrl)
    49  	s.trackedDB = NewMockTrackedDB(ctrl)
    50  	s.prometheusRegisterer = NewMockRegisterer(ctrl)
    51  	s.nodeManager = NewMockNodeManager(ctrl)
    52  
    53  	return ctrl
    54  }
    55  
    56  func (s *baseSuite) expectAnyLogs() {
    57  	s.logger.EXPECT().Errorf(gomock.Any()).AnyTimes()
    58  	s.logger.EXPECT().Warningf(gomock.Any(), gomock.Any()).AnyTimes()
    59  	s.logger.EXPECT().Infof(gomock.Any(), gomock.Any()).AnyTimes()
    60  	s.logger.EXPECT().Debugf(gomock.Any(), gomock.Any()).AnyTimes()
    61  	s.logger.EXPECT().Logf(gomock.Any(), gomock.Any()).AnyTimes()
    62  	s.logger.EXPECT().IsTraceEnabled().AnyTimes()
    63  }
    64  
    65  func (s *baseSuite) expectClock() {
    66  	s.clock.EXPECT().Now().Return(time.Now()).AnyTimes()
    67  }
    68  
    69  func (s *baseSuite) expectWorkerRetry() {
    70  	s.clock.EXPECT().After(10 * time.Second).AnyTimes().DoAndReturn(func(d time.Duration) <-chan time.Time {
    71  		return clock.WallClock.After(10 * time.Millisecond)
    72  	})
    73  }
    74  
    75  func (s *baseSuite) setupTimer() chan time.Time {
    76  	s.timer.EXPECT().Stop().MinTimes(1)
    77  	s.clock.EXPECT().NewTimer(PollInterval).Return(s.timer)
    78  
    79  	ch := make(chan time.Time)
    80  	s.timer.EXPECT().Chan().Return(ch).AnyTimes()
    81  	return ch
    82  }
    83  
    84  func (s *baseSuite) expectTick(ch chan time.Time, ticks int) <-chan struct{} {
    85  	done := make(chan struct{})
    86  	go func() {
    87  		defer close(done)
    88  
    89  		for i := 0; i < ticks; i++ {
    90  			ch <- time.Now()
    91  		}
    92  	}()
    93  	return done
    94  }
    95  
    96  func (s *baseSuite) expectTimer(ticks int) <-chan struct{} {
    97  	ch := s.setupTimer()
    98  	return s.expectTick(ch, ticks)
    99  }
   100  
   101  // expectTrackedDBKill accommodates termination of the TrackedDB.
   102  // the expectations are soft, because the worker may not have called the
   103  // NewDBWorker function before it is killed.
   104  func (s *baseSuite) expectTrackedDBKill() {
   105  	s.trackedDB.EXPECT().Kill().AnyTimes()
   106  	s.trackedDB.EXPECT().Wait().Return(nil).AnyTimes()
   107  }
   108  
   109  func (s *baseSuite) expectNodeStartupAndShutdown() {
   110  	appExp := s.dbApp.EXPECT()
   111  	appExp.Ready(gomock.Any()).Return(nil)
   112  	appExp.Client(gomock.Any()).Return(s.client, nil).MinTimes(1)
   113  	appExp.ID().Return(uint64(666))
   114  	appExp.Close().Return(nil)
   115  
   116  	// The worker created in openDatabase can retry if the dbApp isn't ready
   117  	// after it bounces.
   118  	s.expectWorkerRetry()
   119  }
   120  
   121  type dbBaseSuite struct {
   122  	databasetesting.ControllerSuite
   123  	baseSuite
   124  }
   125  
   126  func ensureStartup(c *gc.C, w *dbWorker) {
   127  	select {
   128  	case <-w.dbReady:
   129  	case <-time.After(jujutesting.LongWait):
   130  		c.Fatal("timed out waiting for Dqlite node start")
   131  	}
   132  }