func (s *ManagerTestSuite) SetUpSuite(t *C) { s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, "sysconfig-manager-test") s.mockMonitor = mock.NewSysconfigMonitor() s.factory = mock.NewSysconfigMonitorFactory([]sysconfig.Monitor{s.mockMonitor}) s.tickChan = make(chan time.Time) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) }
func (s *SenderTestSuite) TestSendEmptyFile(t *C) { // Make mock spooler which returns a single file name and zero bytes // for that file. spool := mock.NewSpooler(nil) spool.FilesOut = []string{"empty.json"} spool.DataOut = map[string][]byte{"empty.json": []byte{}} // Start the sender. sender := data.NewSender(s.logger, s.client) err := sender.Start(spool, s.tickerChan, 5, false) t.Assert(err, IsNil) // Tick to make sender send. s.tickerChan <- time.Now() // Sender shouldn't zero-length data files... data := test.WaitBytes(s.dataChan) t.Check(data, HasLen, 0) err = sender.Stop() t.Assert(err, IsNil) // ...but it should remove them. t.Check(len(spool.DataOut), Equals, 0) }
func (s *SenderTestSuite) TestBlackhole(t *C) { spool := mock.NewSpooler(nil) slow001, err := ioutil.ReadFile(sample + "slow001.json") if err != nil { t.Fatal(err) } spool.FilesOut = []string{"slow001.json"} spool.DataOut = map[string][]byte{"slow001.json": slow001} sender := data.NewSender(s.logger, s.client) err = sender.Start(spool, s.tickerChan, 5, true) // <- true = enable blackhole if err != nil { t.Fatal(err) } s.tickerChan <- time.Now() data := test.WaitBytes(s.dataChan) if len(data) != 0 { t.Errorf("Data sent despite blackhole; got %+v", data) } select { case s.respChan <- &proto.Response{Code: 200}: // Should not recv response because no data was sent. t.Error("Sender receives prot.Response after sending data") case <-time.After(500 * time.Millisecond): } err = sender.Stop() t.Assert(err, IsNil) }
func (s *AggregatorTestSuite) SetUpSuite(t *C) { s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, "mm-manager-test") s.tickChan = make(chan time.Time) s.collectionChan = make(chan *mm.Collection) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN") if s.dsn == "" { t.Fatal("PCT_TEST_MYSQL_DSN is not set") } s.realmysql = mysql.NewConnection(s.dsn) if err := s.realmysql.Connect(1); err != nil { t.Fatal(err) } s.reset = []mysql.Query{ mysql.Query{Set: "SET GLOBAL slow_query_log=OFF"}, mysql.Query{Set: "SET GLOBAL long_query_time=10"}, } s.nullmysql = mock.NewNullMySQL() s.logChan = make(chan *proto.LogEntry, 1000) s.logger = pct.NewLogger(s.logChan, "qan-test") s.intervalChan = make(chan *qan.Interval, 1) s.iter = mock.NewMockIntervalIter(s.intervalChan) s.iterFactory = &mock.IntervalIterFactory{ Iters: []qan.IntervalIter{s.iter}, TickChans: make(map[qan.IntervalIter]chan time.Time), } s.dataChan = make(chan interface{}, 2) s.spool = mock.NewSpooler(s.dataChan) s.workerFactory = &qan.SlowLogWorkerFactory{} var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "db1", DSN: s.dsn, }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1} links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) }
func (s *SenderTestSuite) TestConnectErrors(t *C) { spool := mock.NewSpooler(nil) spool.FilesOut = []string{"slow001.json"} spool.DataOut = map[string][]byte{"slow001.json": []byte("...")} sender := data.NewSender(s.logger, s.client) err := sender.Start(spool, s.tickerChan, 60, false) t.Assert(err, IsNil) // Any connect error will do. s.client.ConnectError = io.EOF defer func() { s.client.ConnectError = nil }() // Tick causes send to connect and send all files. s.tickerChan <- time.Now() t0 := time.Now() // Wait for sender to start trying to connect... if !test.WaitStatus(5, sender, "data-sender", "Connecting") { t.Fatal("Timeout waiting for data-sender status=Connecting") } // ...then wait for it to finsih and return. if !test.WaitStatusPrefix(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT, sender, "data-sender", "Idle") { t.Fatal("Timeout waiting for data-sender status=Idle") } d := time.Now().Sub(t0).Seconds() // It should wait between reconnects, but not too long. if d < float64((data.MAX_SEND_ERRORS-1)*data.CONNECT_ERROR_WAIT) { t.Error("Waits between reconnects") } if d > float64(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT) { t.Error("Waited too long between reconnects") } err = sender.Stop() t.Assert(err, IsNil) // Couldn't connect, so it doesn't send or reject anything. t.Check(len(spool.DataOut), Equals, 1) t.Check(len(spool.RejectedFiles), Equals, 0) // It should have called ConnectOnce() serveral times, else it didn't // really try to reconnect. trace := test.DrainTraceChan(s.client.TraceChan) t.Check(trace, DeepEquals, []string{ "ConnectOnce", "ConnectOnce", "ConnectOnce", "DisconnectOnce", }) }
func (s *SenderTestSuite) Test500Error(t *C) { spool := mock.NewSpooler(nil) spool.FilesOut = []string{"file1", "file2", "file3"} spool.DataOut = map[string][]byte{ "file1": []byte("file1"), "file2": []byte("file2"), "file3": []byte("file3"), } sender := data.NewSender(s.logger, s.client) err := sender.Start(spool, s.tickerChan, 5, false) t.Assert(err, IsNil) s.tickerChan <- time.Now() got := test.WaitBytes(s.dataChan) if same, diff := test.IsDeeply(got[0], []byte("file1")); !same { t.Error(diff) } // 3 files before API error. t.Check(len(spool.DataOut), Equals, 3) // Simulate API error. select { case s.respChan <- &proto.Response{Code: 503}: case <-time.After(500 * time.Millisecond): t.Error("Sender receives prot.Response after sending data") } // Wait for it to finsih and return. if !test.WaitStatusPrefix(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT, sender, "data-sender", "Idle") { t.Fatal("Timeout waiting for data-sender status=Idle") } // Still 3 files after API error. t.Check(len(spool.DataOut), Equals, 3) t.Check(len(spool.RejectedFiles), Equals, 0) // There's only 1 call to SendBytes because after an API error // the send stops immediately. trace := test.DrainTraceChan(s.client.TraceChan) t.Check(trace, DeepEquals, []string{ "ConnectOnce", "SendBytes", "Recv", "DisconnectOnce", }) err = sender.Stop() t.Assert(err, IsNil) }
func (s *SenderTestSuite) TestSendData(t *C) { spool := mock.NewSpooler(nil) slow001, err := ioutil.ReadFile(sample + "slow001.json") if err != nil { t.Fatal(err) } spool.FilesOut = []string{"slow001.json"} spool.DataOut = map[string][]byte{"slow001.json": slow001} sender := data.NewSender(s.logger, s.client) err = sender.Start(spool, s.tickerChan, 5, false) if err != nil { t.Fatal(err) } data := test.WaitBytes(s.dataChan) if len(data) != 0 { t.Errorf("No data sent before tick; got %+v", data) } s.tickerChan <- time.Now() data = test.WaitBytes(s.dataChan) if same, diff := test.IsDeeply(data[0], slow001); !same { t.Error(diff) } t.Check(len(spool.DataOut), Equals, 1) select { case s.respChan <- &proto.Response{Code: 200}: case <-time.After(500 * time.Millisecond): t.Error("Sender receives prot.Response after sending data") } // Sender should include its websocket client status. We're using a mock ws client // which reports itself as "data-client: ok". status := sender.Status() t.Check(status["data-client"], Equals, "ok") err = sender.Stop() t.Assert(err, IsNil) t.Check(len(spool.DataOut), Equals, 0) t.Check(len(spool.RejectedFiles), Equals, 0) }
func (s *SenderTestSuite) TestBadFiles(t *C) { spool := mock.NewSpooler(nil) spool.FilesOut = []string{"file1", "file2", "file3"} spool.DataOut = map[string][]byte{ "file1": []byte("file1"), "file2": []byte("file2"), "file3": []byte("file3"), } sender := data.NewSender(s.logger, s.client) err := sender.Start(spool, s.tickerChan, 5, false) t.Assert(err, IsNil) doneChan := make(chan bool, 1) go func() { resp := []uint{400, 400, 200} for i := 0; i < 3; i++ { // Wait for sender to send data. select { case <-s.dataChan: case <-doneChan: return } // Simulate API returns 400. select { case s.respChan <- &proto.Response{Code: resp[i]}: case <-doneChan: return } } }() s.tickerChan <- time.Now() // Wait for sender to finish. if !test.WaitStatusPrefix(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT, sender, "data-sender", "Idle") { t.Fatal("Timeout waiting for data-sender status=Idle") } doneChan <- true err = sender.Stop() t.Assert(err, IsNil) // Bad files are removed, so all files should have been sent. t.Check(len(spool.DataOut), Equals, 0) t.Check(len(spool.RejectedFiles), Equals, 0) }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, "mm-manager-test") s.tickChan = make(chan time.Time) s.traceChan = make(chan string, 10) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "db1", DSN: "user:host@tcp:(127.0.0.1:3306)", }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) data, err = json.Marshal(&proto.ServerInstance{Hostname: "host1"}) t.Assert(err, IsNil) s.im.Add("server", 1, data, false) s.mysqlMonitor = mock.NewMmMonitor() s.systemMonitor = mock.NewMmMonitor() s.factory = mock.NewMmMonitorFactory(map[string]mm.Monitor{ "mysql-1": s.mysqlMonitor, "server-1": s.systemMonitor, }) links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) }
func (s *AnalyzerTestSuite) SetUpSuite(t *C) { s.nullmysql = mock.NewNullMySQL() s.logChan = make(chan *proto.LogEntry, 1000) s.logger = pct.NewLogger(s.logChan, "qan-test") s.intervalChan = make(chan *qan.Interval, 1) s.iter = mock.NewIter(s.intervalChan) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "bm-cloud-db01", Alias: "db01", DSN: "user:pass@tcp/", }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1} links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) s.restartChan = make(chan bool, 1) }
func (s *SenderTestSuite) TestRecvErrors(t *C) { spool := mock.NewSpooler(nil) spool.FilesOut = []string{"slow001.json"} spool.DataOut = map[string][]byte{"slow001.json": []byte("...")} sender := data.NewSender(s.logger, s.client) err := sender.Start(spool, s.tickerChan, 60, false) t.Assert(err, IsNil) // Any recv error will do. doneChan := make(chan bool) go func() { for { select { case s.client.RecvError <- io.EOF: case <-doneChan: return } } }() defer func() { doneChan <- true }() // Tick causes send to connect and send all files. s.tickerChan <- time.Now() t0 := time.Now() // Wait for sender to finsih and return. if !test.WaitStatusPrefix(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT, sender, "data-sender", "Idle") { t.Fatal("Timeout waiting for data-sender status=Idle") } d := time.Now().Sub(t0).Seconds() // It should wait between reconnects, but not too long. if d < float64((data.MAX_SEND_ERRORS-1)*data.CONNECT_ERROR_WAIT) { t.Error("Waits between reconnects") } if d > float64(data.MAX_SEND_ERRORS*data.CONNECT_ERROR_WAIT) { t.Error("Waited too long between reconnects") } err = sender.Stop() t.Assert(err, IsNil) // Didn't receive proper ack, so it doesn't remove any data. t.Check(len(spool.DataOut), Equals, 1) t.Check(len(spool.RejectedFiles), Equals, 0) // It should have called ConnectOnce() serveral times, else it didn't // really try to reconnect. trace := test.DrainTraceChan(s.client.TraceChan) t.Check(trace, DeepEquals, []string{ "ConnectOnce", "SendBytes", "Recv", "DisconnectOnce", "ConnectOnce", "SendBytes", "Recv", "DisconnectOnce", "ConnectOnce", "SendBytes", "Recv", "DisconnectOnce", "DisconnectOnce", }) }