func (s *ManagerTestSuite) TestLogService(t *C) { config := &log.Config{ File: s.logFile, Level: "info", } pct.Basedir.WriteConfig("log", config) m := log.NewManager(s.client, s.logChan) err := m.Start() t.Assert(err, IsNil) relay := m.Relay() t.Assert(relay, NotNil) logger := pct.NewLogger(relay.LogChan(), "log-svc-test") logger.Info("i'm a log entry") // Log entry should be sent to API. got := test.WaitLog(s.recvChan, 3) if len(got) == 0 { t.Fatal("No log entries") } var gotLog proto.LogEntry for _, l := range got { if l.Service == "log-svc-test" { gotLog = l break } } t.Assert(gotLog, NotNil) expectLog := proto.LogEntry{Ts: test.Ts, Level: proto.LOG_INFO, Service: "log-svc-test", Msg: "i'm a log entry"} if same, diff := test.IsDeeply(gotLog, expectLog); !same { t.Logf("%+v", got) t.Error(diff) } // Since there's a log file, entry should be written to it too. size, _ := test.FileSize(s.logFile) test.WaitFileSize(s.logFile, size) var content []byte content, err = ioutil.ReadFile(s.logFile) t.Assert(err, IsNil) if !strings.Contains(string(content), "i'm a log entry") { t.Error("Writes log entry to log file, got\n", string(content)) } // Can't stop log service, but Stop() should work and not return error. err = m.Stop() t.Assert(err, IsNil) /** * Change log level and file */ newLogFile := s.logFile + "-2" defer os.Remove(newLogFile) config = &log.Config{ File: newLogFile, Level: "warning", } configData, err := json.Marshal(config) t.Assert(err, IsNil) cmd := &proto.Cmd{ User: "******", Service: "log", Cmd: "SetConfig", Data: configData, } gotReply := m.Handle(cmd) expectReply := cmd.Reply(config) if same, diff := test.IsDeeply(gotReply, expectReply); !same { t.Logf("%+v", gotReply) t.Error(diff) } // Log entry should NOT be sent to API if log level was really changed. logger.Info("i'm lost") got = test.WaitLog(s.recvChan, 3) if len(got) != 0 { t.Logf("%+v", got) t.Error("Log level changed dynamically") } logger.Warn("blah") got = test.WaitLog(s.recvChan, 3) gotLog = proto.LogEntry{} for _, l := range got { if l.Service == "log-svc-test" { gotLog = l break } } expectLog = proto.LogEntry{Ts: test.Ts, Level: proto.LOG_WARNING, Service: "log-svc-test", Msg: "blah"} if same, diff := test.IsDeeply(gotLog, expectLog); !same { t.Logf("%+v", got) t.Error(diff) } // Entry should be written to new log file if it was really changed. size, _ = test.FileSize(newLogFile) test.WaitFileSize(newLogFile, size) content, err = ioutil.ReadFile(newLogFile) t.Assert(err, IsNil) if !strings.Contains(string(content), "blah") { t.Error("Log file changed dynamically, got\n", string(content)) } // Verify new log config on disk. data, err := ioutil.ReadFile(pct.Basedir.ConfigFile("log")) t.Assert(err, IsNil) gotConfig := &log.Config{} if err := json.Unmarshal(data, gotConfig); err != nil { t.Fatal(err) } if same, diff := test.IsDeeply(gotConfig, config); !same { test.Dump(gotConfig) t.Error(diff) } /** * GetConfig */ cmd = &proto.Cmd{ User: "******", Service: "log", Cmd: "GetConfig", } reply := m.Handle(cmd) t.Assert(reply.Error, Equals, "") t.Assert(reply.Data, NotNil) gotConfigRes := []proto.AgentConfig{} if err := json.Unmarshal(reply.Data, &gotConfigRes); err != nil { t.Fatal(err) } expectConfigRes := []proto.AgentConfig{ { InternalService: "log", Config: string(configData), Running: true, }, } if same, diff := test.IsDeeply(gotConfigRes, expectConfigRes); !same { test.Dump(gotConfigRes) t.Error(diff) } /** * Status (internal status of log and relay) */ status := m.Status() t.Check(status["ws"], Equals, "Connected") t.Check(status["log-file"], Equals, newLogFile) t.Check(status["log-level"], Equals, "warning") }
func (s *RelayTestSuite) TestLogFile(t *C) { /** * This test is going to be a real pain in the ass because it writes/reads * disk and the disk can be surprisingly slow on a test box. On top of that, * there's concurrency so we also have to wait for the CPU to run goroutines. */ r := s.relay l := s.logger // Online log should work without file log. l.Warn("It's a trap!") got := test.WaitLog(s.recvChan, 1) expect := []proto.LogEntry{ {Ts: test.Ts, Level: proto.LOG_WARNING, Service: "test", Msg: "It's a trap!"}, } t.Check(got, DeepEquals, expect) log, err := ioutil.ReadFile(s.logFile) if !os.IsNotExist(err) { t.Error("We haven't enabled the log file yet, so it shouldn't exist yet") } // Enable the log file. r.LogFileChan() <- s.logFile // Online log should work with the file log. l.Warn("It's another trap!") got = test.WaitLog(s.recvChan, 1) expect = []proto.LogEntry{ {Ts: test.Ts, Level: proto.LOG_WARNING, Service: "test", Msg: "It's another trap!"}, } t.Check(got, DeepEquals, expect) // Log file should exist. size, _ := test.FileSize(s.logFile) test.WaitFileSize(s.logFile, size) log, err = ioutil.ReadFile(s.logFile) if err != nil { t.Fatalf("Log file should exist: %s", err) } if !strings.Contains(string(log), "It's another trap!") { t.Error("Log file contains entry after being enabled, got\n", string(log)) } if strings.Contains(string(log), "It's a trap!") { t.Error("Log file does not contain entry before being enabled, got\n", string(log)) } l.Debug("Hello") if strings.Contains(string(log), "Hello") { t.Error("Log file should respect the log level") } // We should be able to change the log file. newLogFile := s.logFile + "-new" defer func() { os.Remove(newLogFile) }() r.LogFileChan() <- newLogFile l.Warn("Foo") size, _ = test.FileSize(newLogFile) test.WaitFileSize(newLogFile, size) log, err = ioutil.ReadFile(newLogFile) if err != nil { t.Errorf("New log file should exist: %s", err) return } if !strings.Contains(string(log), "Foo") { t.Error("New log file contains only the new log entry, got\n", string(log)) } if strings.Contains(string(log), "It's another trap!") { t.Error("New log file should contain only the new log entry") } log, err = ioutil.ReadFile(s.logFile) if err != nil { t.Errorf("Old log file should still exist: %s", err) return } if strings.Contains(string(log), "Foo") { t.Error("Old log file should not contain the new log entry") } }