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 }