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

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENSE file for details.
     3  
     4  package logsender_test
     5  
     6  import (
     7  	"fmt"
     8  	"strconv"
     9  	"time"
    10  
    11  	"github.com/juju/loggo"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker/logsender"
    17  	"github.com/juju/juju/worker/logsender/logsendertest"
    18  )
    19  
    20  const maxLen = 6
    21  
    22  type bufferedLogWriterSuite struct {
    23  	coretesting.BaseSuite
    24  	writer      *logsender.BufferedLogWriter
    25  	shouldClose bool
    26  }
    27  
    28  var _ = gc.Suite(&bufferedLogWriterSuite{})
    29  
    30  func (s *bufferedLogWriterSuite) SetUpTest(c *gc.C) {
    31  	s.BaseSuite.SetUpTest(c)
    32  	s.writer = logsender.NewBufferedLogWriter(maxLen)
    33  	s.shouldClose = true
    34  }
    35  
    36  func (s *bufferedLogWriterSuite) TearDownTest(c *gc.C) {
    37  	if s.shouldClose {
    38  		s.writer.Close()
    39  	}
    40  	s.BaseSuite.TearDownTest(c)
    41  }
    42  
    43  func (s *bufferedLogWriterSuite) TestOne(c *gc.C) {
    44  	s.writeAndReceive(c)
    45  }
    46  
    47  func (s *bufferedLogWriterSuite) TestMultiple(c *gc.C) {
    48  	for i := 0; i < 10; i++ {
    49  		s.writeAndReceive(c)
    50  	}
    51  }
    52  
    53  func (s *bufferedLogWriterSuite) TestBuffering(c *gc.C) {
    54  	// Write several log message before attempting to read them out.
    55  	const numMessages = 5
    56  	now := time.Now()
    57  	for i := 0; i < numMessages; i++ {
    58  		s.writer.Write(
    59  			loggo.Entry{
    60  				Level:     loggo.Level(i),
    61  				Module:    fmt.Sprintf("module%d", i),
    62  				Filename:  fmt.Sprintf("filename%d", i),
    63  				Line:      i,
    64  				Timestamp: now.Add(time.Duration(i)),
    65  				Message:   fmt.Sprintf("message%d", i),
    66  			})
    67  	}
    68  
    69  	for i := 0; i < numMessages; i++ {
    70  		c.Assert(*s.receiveOne(c), gc.DeepEquals, logsender.LogRecord{
    71  			Time:     now.Add(time.Duration(i)),
    72  			Module:   fmt.Sprintf("module%d", i),
    73  			Location: fmt.Sprintf("filename%d:%d", i, i),
    74  			Level:    loggo.Level(i),
    75  			Message:  fmt.Sprintf("message%d", i),
    76  		})
    77  	}
    78  }
    79  
    80  func (s *bufferedLogWriterSuite) TestLimiting(c *gc.C) {
    81  	write := func(msgNum int) {
    82  		s.writer.Write(
    83  			loggo.Entry{
    84  				Level:     loggo.INFO,
    85  				Module:    "module",
    86  				Filename:  "filename",
    87  				Line:      42,
    88  				Timestamp: time.Now(),
    89  				Message:   fmt.Sprintf("log%d", msgNum),
    90  			})
    91  	}
    92  
    93  	expect := func(msgNum, dropped int) {
    94  		rec := s.receiveOne(c)
    95  		c.Assert(rec.Message, gc.Equals, fmt.Sprintf("log%d", msgNum))
    96  		c.Assert(rec.DroppedAfter, gc.Equals, dropped)
    97  	}
    98  
    99  	// Write more logs than the buffer allows.
   100  	for i := 0; i < maxLen+3; i++ {
   101  		write(i)
   102  	}
   103  
   104  	// Read some logs from the writer.
   105  
   106  	// Even though logs have been dropped, log 0 is still seen
   107  	// first. This is useful because means the time range for dropped
   108  	// logs can be observed.
   109  	expect(0, 2) // logs 1 and 2 dropped here
   110  	expect(3, 0)
   111  	expect(4, 0)
   112  
   113  	// Now write more logs, again exceeding the limit.
   114  	for i := maxLen + 3; i < maxLen+3+maxLen; i++ {
   115  		write(i)
   116  	}
   117  
   118  	// Read all the remaining logs off.
   119  	expect(5, 3) // logs 6, 7 and 8 logs dropped here
   120  	for i := 9; i < maxLen+3+maxLen; i++ {
   121  		expect(i, 0)
   122  	}
   123  
   124  	logsendertest.ExpectLogStats(c, s.writer, logsender.LogStats{
   125  		Enqueued: maxLen*2 + 3,
   126  		Sent:     maxLen*2 + 3 - 5,
   127  		Dropped:  5,
   128  	})
   129  }
   130  
   131  func (s *bufferedLogWriterSuite) TestClose(c *gc.C) {
   132  	s.writer.Close()
   133  	s.shouldClose = false // Prevent the usual teardown (calling Close twice will panic)
   134  
   135  	// Output channel closing means the bufferedLogWriterSuite loop
   136  	// has finished.
   137  	select {
   138  	case _, ok := <-s.writer.Logs():
   139  		c.Assert(ok, jc.IsFalse)
   140  	case <-time.After(coretesting.LongWait):
   141  		c.Fatal("timed out waiting for output channel to close")
   142  	}
   143  
   144  	// Further Write attempts should fail.
   145  	c.Assert(func() { s.writeAndReceive(c) }, gc.PanicMatches, ".*send on closed channel")
   146  }
   147  
   148  func (s *bufferedLogWriterSuite) TestInstallBufferedLogWriter(c *gc.C) {
   149  	bufferedLogger, err := logsender.InstallBufferedLogWriter(10)
   150  	c.Assert(err, jc.ErrorIsNil)
   151  	defer logsender.UninstallBufferedLogWriter()
   152  
   153  	logger := loggo.GetLogger("bufferedLogWriter-test")
   154  
   155  	for i := 0; i < 5; i++ {
   156  		logger.Infof("%d", i)
   157  	}
   158  
   159  	logsCh := bufferedLogger.Logs()
   160  	for i := 0; i < 5; i++ {
   161  		select {
   162  		case rec := <-logsCh:
   163  			c.Assert(rec.Message, gc.Equals, strconv.Itoa(i))
   164  		case <-time.After(coretesting.LongWait):
   165  			c.Fatal("timed out waiting for logs")
   166  		}
   167  	}
   168  }
   169  
   170  func (s *bufferedLogWriterSuite) TestUninstallBufferedLogWriter(c *gc.C) {
   171  	_, err := logsender.InstallBufferedLogWriter(10)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	err = logsender.UninstallBufferedLogWriter()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  
   177  	// Second uninstall attempt should fail
   178  	err = logsender.UninstallBufferedLogWriter()
   179  	c.Assert(err, gc.ErrorMatches, "failed to uninstall log buffering: .+")
   180  }
   181  
   182  func (s *bufferedLogWriterSuite) writeAndReceive(c *gc.C) {
   183  	now := time.Now()
   184  	s.writer.Write(
   185  		loggo.Entry{
   186  			Level:     loggo.INFO,
   187  			Module:    "module",
   188  			Filename:  "filename",
   189  			Line:      99,
   190  			Timestamp: now,
   191  			Message:   "message",
   192  		})
   193  	c.Assert(*s.receiveOne(c), gc.DeepEquals, logsender.LogRecord{
   194  		Time:     now,
   195  		Module:   "module",
   196  		Location: "filename:99",
   197  		Level:    loggo.INFO,
   198  		Message:  "message",
   199  	})
   200  }
   201  
   202  func (s *bufferedLogWriterSuite) receiveOne(c *gc.C) *logsender.LogRecord {
   203  	select {
   204  	case rec := <-s.writer.Logs():
   205  		return rec
   206  	case <-time.After(coretesting.LongWait):
   207  		c.Fatal("timed out waiting for log record")
   208  	}
   209  	panic("should never get here")
   210  }