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

     1  // Copyright 2023 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package querylogger
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	time "time"
    11  
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/worker/v3/workertest"
    15  	"go.uber.org/mock/gomock"
    16  	gc "gopkg.in/check.v1"
    17  )
    18  
    19  type loggerSuite struct {
    20  	testing.IsolationSuite
    21  
    22  	clock  *MockClock
    23  	timer  *MockTimer
    24  	logger *MockLogger
    25  }
    26  
    27  var _ = gc.Suite(&loggerSuite{})
    28  
    29  func (s *loggerSuite) TestLogger(c *gc.C) {
    30  	defer s.setupMocks(c).Finish()
    31  
    32  	dir := c.MkDir()
    33  
    34  	ch := make(chan time.Time)
    35  	s.timer.EXPECT().Chan().Return(ch).AnyTimes()
    36  
    37  	w := s.newWorker(c, dir)
    38  	defer workertest.DirtyKill(c, w)
    39  
    40  	args := []any{0.1, "SELECT * FROM foo"}
    41  	s.logger.EXPECT().Warningf("slow query: hello", args)
    42  
    43  	w.RecordSlowQuery("hello", "SELECT * FROM foo", args, 0.1)
    44  
    45  	select {
    46  	case ch <- time.Now():
    47  	case <-time.After(testing.ShortWait):
    48  		c.Fatal("timed out waiting for log to be written")
    49  	}
    50  
    51  	s.expectLogResult(c, dir, `
    52  slow query took 0.100s for statement: SELECT * FROM foo
    53  stack trace:
    54  dummy stack
    55  
    56  `[1:])
    57  
    58  	workertest.CleanKill(c, w)
    59  }
    60  
    61  func (s *loggerSuite) TestLoggerMultipleTimes(c *gc.C) {
    62  	defer s.setupMocks(c).Finish()
    63  
    64  	dir := c.MkDir()
    65  
    66  	ch := make(chan time.Time)
    67  	s.timer.EXPECT().Chan().Return(ch).AnyTimes()
    68  
    69  	w := s.newWorker(c, dir)
    70  	defer workertest.DirtyKill(c, w)
    71  
    72  	for i := 0; i < 100; i++ {
    73  		stmt := fmt.Sprintf("SELECT %d FROM foo", i)
    74  		args := []any{i, stmt}
    75  
    76  		s.logger.EXPECT().Warningf("slow query: hello", args)
    77  
    78  		w.RecordSlowQuery("hello", stmt, args, float64(i))
    79  	}
    80  
    81  	select {
    82  	case ch <- time.Now():
    83  	case <-time.After(testing.ShortWait):
    84  		c.Fatal("timed out waiting for log to be written")
    85  	}
    86  
    87  	template := `
    88  slow query took %0.3fs for statement: SELECT %d FROM foo
    89  stack trace:
    90  dummy stack
    91  
    92  `[1:]
    93  
    94  	var expected string
    95  	for i := 0; i < 100; i++ {
    96  		expected += fmt.Sprintf(template, float64(i), i)
    97  	}
    98  
    99  	s.expectLogResult(c, dir, expected)
   100  
   101  	workertest.CleanKill(c, w)
   102  }
   103  
   104  func (s *loggerSuite) expectLogResult(c *gc.C, dir string, match string) {
   105  	data, err := os.ReadFile(filepath.Join(dir, filename))
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	c.Assert(string(data), gc.Equals, match)
   108  }
   109  
   110  func (s *loggerSuite) setupMocks(c *gc.C) *gomock.Controller {
   111  	ctrl := gomock.NewController(c)
   112  
   113  	s.timer = NewMockTimer(ctrl)
   114  	s.timer.EXPECT().Reset(PollInterval)
   115  	s.timer.EXPECT().Stop()
   116  
   117  	s.clock = NewMockClock(ctrl)
   118  	s.clock.EXPECT().NewTimer(PollInterval).Return(s.timer)
   119  
   120  	s.logger = NewMockLogger(ctrl)
   121  
   122  	return ctrl
   123  }
   124  
   125  func (s *loggerSuite) newWorker(c *gc.C, dir string) *loggerWorker {
   126  	w, err := newWorker(&WorkerConfig{
   127  		LogDir: dir,
   128  		Clock:  s.clock,
   129  		Logger: s.logger,
   130  		StackGatherer: func() []byte {
   131  			return []byte("dummy stack")
   132  		},
   133  	})
   134  	c.Assert(err, jc.ErrorIsNil)
   135  
   136  	return w
   137  }