github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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.Level(i),
    59  			fmt.Sprintf("module%d", i),
    60  			fmt.Sprintf("filename%d", i),
    61  			i, // line number
    62  			now.Add(time.Duration(i)),
    63  			fmt.Sprintf("message%d", i),
    64  		)
    65  	}
    66  
    67  	for i := 0; i < numMessages; i++ {
    68  		c.Assert(*s.receiveOne(c), gc.DeepEquals, logsender.LogRecord{
    69  			Time:     now.Add(time.Duration(i)),
    70  			Module:   fmt.Sprintf("module%d", i),
    71  			Location: fmt.Sprintf("filename%d:%d", i, i),
    72  			Level:    loggo.Level(i),
    73  			Message:  fmt.Sprintf("message%d", i),
    74  		})
    75  	}
    76  }
    77  
    78  func (s *bufferedLogWriterSuite) TestLimiting(c *gc.C) {
    79  	write := func(msgNum int) {
    80  		s.writer.Write(loggo.INFO, "module", "filename", 42, time.Now(), fmt.Sprintf("log%d", msgNum))
    81  	}
    82  
    83  	expect := func(msgNum, dropped int) {
    84  		rec := s.receiveOne(c)
    85  		c.Assert(rec.Message, gc.Equals, fmt.Sprintf("log%d", msgNum))
    86  		c.Assert(rec.DroppedAfter, gc.Equals, dropped)
    87  	}
    88  
    89  	// Write more logs than the buffer allows.
    90  	for i := 0; i < maxLen+3; i++ {
    91  		write(i)
    92  	}
    93  
    94  	// Read some logs from the writer.
    95  
    96  	// Even though logs have been dropped, log 0 is still seen
    97  	// first. This is useful because means the time range for dropped
    98  	// logs can be observed.
    99  	expect(0, 2) // logs 1 and 2 dropped here
   100  	expect(3, 0)
   101  	expect(4, 0)
   102  
   103  	// Now write more logs, again exceeding the limit.
   104  	for i := maxLen + 3; i < maxLen+3+maxLen; i++ {
   105  		write(i)
   106  	}
   107  
   108  	// Read all the remaining logs off.
   109  	expect(5, 3) // logs 6, 7 and 8 logs dropped here
   110  	for i := 9; i < maxLen+3+maxLen; i++ {
   111  		expect(i, 0)
   112  	}
   113  }
   114  
   115  func (s *bufferedLogWriterSuite) TestClose(c *gc.C) {
   116  	s.writer.Close()
   117  	s.shouldClose = false // Prevent the usual teardown (calling Close twice will panic)
   118  
   119  	// Output channel closing means the bufferedLogWriterSuite loop
   120  	// has finished.
   121  	select {
   122  	case _, ok := <-s.writer.Logs():
   123  		c.Assert(ok, jc.IsFalse)
   124  	case <-time.After(coretesting.LongWait):
   125  		c.Fatal("timed out waiting for output channel to close")
   126  	}
   127  
   128  	// Further Write attempts should fail.
   129  	c.Assert(func() { s.writeAndReceive(c) }, gc.PanicMatches, ".*send on closed channel")
   130  }
   131  
   132  func (s *bufferedLogWriterSuite) TestInstallBufferedLogWriter(c *gc.C) {
   133  	logsCh, err := logsender.InstallBufferedLogWriter(10)
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	defer logsender.UninstallBufferedLogWriter()
   136  
   137  	logger := loggo.GetLogger("bufferedLogWriter-test")
   138  
   139  	for i := 0; i < 5; i++ {
   140  		logger.Infof("%d", i)
   141  	}
   142  
   143  	for i := 0; i < 5; i++ {
   144  		select {
   145  		case rec := <-logsCh:
   146  			c.Assert(rec.Message, gc.Equals, strconv.Itoa(i))
   147  		case <-time.After(coretesting.LongWait):
   148  			c.Fatal("timed out waiting for logs")
   149  		}
   150  	}
   151  }
   152  
   153  func (s *bufferedLogWriterSuite) TestUninstallBufferedLogWriter(c *gc.C) {
   154  	_, err := logsender.InstallBufferedLogWriter(10)
   155  	c.Assert(err, jc.ErrorIsNil)
   156  
   157  	err = logsender.UninstallBufferedLogWriter()
   158  	c.Assert(err, jc.ErrorIsNil)
   159  
   160  	// Second uninstall attempt should fail
   161  	err = logsender.UninstallBufferedLogWriter()
   162  	c.Assert(err, gc.ErrorMatches, "failed to uninstall log buffering: .+")
   163  }
   164  
   165  func (s *bufferedLogWriterSuite) writeAndReceive(c *gc.C) {
   166  	now := time.Now()
   167  	s.writer.Write(loggo.INFO, "module", "filename", 99, now, "message")
   168  	c.Assert(*s.receiveOne(c), gc.DeepEquals, logsender.LogRecord{
   169  		Time:     now,
   170  		Module:   "module",
   171  		Location: "filename:99",
   172  		Level:    loggo.INFO,
   173  		Message:  "message",
   174  	})
   175  }
   176  
   177  func (s *bufferedLogWriterSuite) receiveOne(c *gc.C) *logsender.LogRecord {
   178  	select {
   179  	case rec := <-s.writer.Logs():
   180  		return rec
   181  	case <-time.After(coretesting.LongWait):
   182  		c.Fatal("timed out waiting for log record")
   183  	}
   184  	panic("should never get here")
   185  }