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