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