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

     1  // Copyright 2022 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leaseexpiry_test
     5  
     6  import (
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/juju/clock"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils/v3"
    14  	"github.com/juju/worker/v3"
    15  	"github.com/juju/worker/v3/workertest"
    16  	"go.uber.org/mock/gomock"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/database/testing"
    20  	"github.com/juju/juju/worker/leaseexpiry"
    21  )
    22  
    23  type workerSuite struct {
    24  	testing.ControllerSuite
    25  }
    26  
    27  var _ = gc.Suite(&workerSuite{})
    28  
    29  func (s *workerSuite) TestConfigValidate(c *gc.C) {
    30  	validCfg := leaseexpiry.Config{
    31  		Clock:     clock.WallClock,
    32  		Logger:    leaseexpiry.StubLogger{},
    33  		TrackedDB: s.TrackedDB(),
    34  	}
    35  
    36  	cfg := validCfg
    37  	cfg.Clock = nil
    38  	c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue)
    39  
    40  	cfg = validCfg
    41  	cfg.Logger = nil
    42  	c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue)
    43  
    44  	cfg = validCfg
    45  	cfg.TrackedDB = nil
    46  	c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue)
    47  }
    48  
    49  func (s *workerSuite) TestWorkerDeletesExpiredLeases(c *gc.C) {
    50  	ctrl := gomock.NewController(c)
    51  	defer ctrl.Finish()
    52  
    53  	clk := NewMockClock(ctrl)
    54  	timer := NewMockTimer(ctrl)
    55  
    56  	var w worker.Worker
    57  	var wmutex sync.Mutex
    58  
    59  	clk.EXPECT().NewTimer(time.Second).Return(timer)
    60  
    61  	// Kill the worker on the first pass through the loop,
    62  	// after we've processed one expiration.
    63  	ch := make(chan time.Time, 1)
    64  	ch <- time.Now()
    65  	timer.EXPECT().Chan().Return(ch).MinTimes(1)
    66  	timer.EXPECT().Reset(time.Second).Do(func(any) {
    67  		wmutex.Lock()
    68  		defer wmutex.Unlock()
    69  		w.Kill()
    70  	})
    71  	timer.EXPECT().Stop().Return(true)
    72  
    73  	// Insert 2 leases, one with an expiry time in the past,
    74  	// another in the future.
    75  	q := `
    76  INSERT INTO lease (uuid, lease_type_id, model_uuid, name, holder, start, expiry)
    77  VALUES (?, 1, 'some-model-uuid', ?, ?, datetime('now'), datetime('now', ?))`[1:]
    78  
    79  	stmt, err := s.DB().Prepare(q)
    80  	c.Assert(err, jc.ErrorIsNil)
    81  
    82  	_, err = stmt.Exec(utils.MustNewUUID().String(), "postgresql", "postgresql/0", "+2 minutes")
    83  	c.Assert(err, jc.ErrorIsNil)
    84  
    85  	_, err = stmt.Exec(utils.MustNewUUID().String(), "redis", "redis/0", "-2 minutes")
    86  	c.Assert(err, jc.ErrorIsNil)
    87  
    88  	wmutex.Lock()
    89  	w, err = leaseexpiry.NewWorker(leaseexpiry.Config{
    90  		Clock:     clk,
    91  		Logger:    leaseexpiry.StubLogger{},
    92  		TrackedDB: s.TrackedDB(),
    93  	})
    94  	wmutex.Unlock()
    95  	c.Assert(err, jc.ErrorIsNil)
    96  
    97  	err = workertest.CheckKilled(c, w)
    98  	c.Assert(err, jc.ErrorIsNil)
    99  
   100  	// Only the postgresql lease (expiring in the future) should remain.
   101  	row := s.DB().QueryRow("SELECT name FROM LEASE")
   102  	var name string
   103  	err = row.Scan(&name)
   104  	c.Assert(err, jc.ErrorIsNil)
   105  	c.Assert(row.Err(), jc.ErrorIsNil)
   106  
   107  	c.Check(name, gc.Equals, "postgresql")
   108  }