github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/logsender/worker_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package logsender_test 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/loggo" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/mgo.v2/bson" 15 16 "github.com/juju/juju/api" 17 apilogsender "github.com/juju/juju/api/logsender" 18 jujutesting "github.com/juju/juju/juju/testing" 19 "github.com/juju/juju/testing" 20 "github.com/juju/juju/testing/factory" 21 "github.com/juju/juju/worker/logsender" 22 ) 23 24 type workerSuite struct { 25 jujutesting.JujuConnSuite 26 27 // machineTag holds the tag of a machine created 28 // for the test. 29 machineTag names.Tag 30 31 // APIState holds an API connection authenticated 32 // as the above machine. 33 APIState api.Connection 34 } 35 36 var _ = gc.Suite(&workerSuite{}) 37 38 func (s *workerSuite) SetUpTest(c *gc.C) { 39 s.JujuConnSuite.SetUpTest(c) 40 41 // Create a machine for the client to log in as. 42 nonce := "some-nonce" 43 machine, password := s.Factory.MakeMachineReturningPassword(c, 44 &factory.MachineParams{Nonce: nonce}) 45 apiInfo := s.APIInfo(c) 46 apiInfo.Tag = machine.Tag() 47 apiInfo.Password = password 48 apiInfo.Nonce = nonce 49 st, err := api.Open(apiInfo, api.DefaultDialOpts()) 50 c.Assert(err, gc.IsNil) 51 s.APIState = st 52 s.machineTag = machine.Tag() 53 } 54 55 func (s *workerSuite) TearDownTest(c *gc.C) { 56 s.APIState.Close() 57 s.JujuConnSuite.TearDownTest(c) 58 } 59 60 func (s *workerSuite) logSenderAPI() *apilogsender.API { 61 return apilogsender.NewAPI(s.APIState) 62 } 63 64 func (s *workerSuite) TestLogSending(c *gc.C) { 65 const logCount = 5 66 logsCh := make(chan *logsender.LogRecord, logCount) 67 68 // Start the logsender worker. 69 worker := logsender.New(logsCh, s.logSenderAPI()) 70 defer func() { 71 worker.Kill() 72 c.Check(worker.Wait(), jc.ErrorIsNil) 73 }() 74 75 // Send some logs, also building up what should appear in the 76 // database. 77 var expectedDocs []bson.M 78 for i := 0; i < logCount; i++ { 79 ts := time.Now().Truncate(time.Millisecond) 80 location := fmt.Sprintf("loc%d", i) 81 message := fmt.Sprintf("%d", i) 82 83 logsCh <- &logsender.LogRecord{ 84 Time: ts, 85 Module: "logsender-test", 86 Location: location, 87 Level: loggo.INFO, 88 Message: message, 89 } 90 91 expectedDocs = append(expectedDocs, bson.M{ 92 "t": ts, 93 "e": s.State.ModelUUID(), 94 "n": s.machineTag.String(), 95 "m": "logsender-test", 96 "l": location, 97 "v": int(loggo.INFO), 98 "x": message, 99 }) 100 } 101 102 // Wait for the logs to appear in the database. 103 var docs []bson.M 104 logsColl := s.State.MongoSession().DB("logs").C("logs") 105 for a := testing.LongAttempt.Start(); a.Next(); { 106 err := logsColl.Find(bson.M{"m": "logsender-test"}).All(&docs) 107 c.Assert(err, jc.ErrorIsNil) 108 if len(docs) == logCount { 109 break 110 } 111 } 112 113 // Check that the logs are correct. 114 c.Assert(docs, gc.HasLen, logCount) 115 for i := 0; i < logCount; i++ { 116 doc := docs[i] 117 delete(doc, "_id") 118 c.Assert(doc, gc.DeepEquals, expectedDocs[i]) 119 } 120 } 121 122 func (s *workerSuite) TestDroppedLogs(c *gc.C) { 123 logsCh := make(logsender.LogRecordCh) 124 125 // Start the logsender worker. 126 worker := logsender.New(logsCh, s.logSenderAPI()) 127 defer func() { 128 worker.Kill() 129 c.Check(worker.Wait(), jc.ErrorIsNil) 130 }() 131 132 // Send a log record which indicates some messages after it were 133 // dropped. 134 ts := time.Now().Truncate(time.Millisecond) 135 logsCh <- &logsender.LogRecord{ 136 Time: ts, 137 Module: "aaa", 138 Location: "loc", 139 Level: loggo.INFO, 140 Message: "message0", 141 DroppedAfter: 42, 142 } 143 144 // Send another log record with no drops indicated. 145 logsCh <- &logsender.LogRecord{ 146 Time: time.Now(), 147 Module: "zzz", 148 Location: "loc", 149 Level: loggo.INFO, 150 Message: "message1", 151 } 152 153 // Wait for the logs to appear in the database. 154 var docs []bson.M 155 logsColl := s.State.MongoSession().DB("logs").C("logs") 156 for a := testing.LongAttempt.Start(); a.Next(); { 157 if !a.HasNext() { 158 c.Fatal("timed out waiting for logs") 159 } 160 err := logsColl.Find(nil).Sort("m").All(&docs) 161 c.Assert(err, jc.ErrorIsNil) 162 // Expect the 2 messages sent along with a message about 163 // dropped messages. 164 if len(docs) == 3 { 165 break 166 } 167 } 168 169 // Check that the log records sent are present as well as an additional 170 // message in between indicating that some messages were dropped. 171 c.Assert(docs[0]["x"], gc.Equals, "message0") 172 delete(docs[1], "_id") 173 c.Assert(docs[1], gc.DeepEquals, bson.M{ 174 "t": ts, // Should share timestamp with previous message. 175 "e": s.State.ModelUUID(), 176 "n": s.machineTag.String(), 177 "m": "juju.worker.logsender", 178 "l": "", 179 "v": int(loggo.WARNING), 180 "x": "42 log messages dropped due to lack of API connectivity", 181 }) 182 c.Assert(docs[2]["x"], gc.Equals, "message1") 183 }