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