github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/logger/logger_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package logger_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 "github.com/juju/names/v5" 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/worker/v3" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/core/watcher" 18 "github.com/juju/juju/worker/logger" 19 ) 20 21 type LoggerSuite struct { 22 testing.IsolationSuite 23 24 context *loggo.Context 25 agent names.Tag 26 loggerAPI *mockAPI 27 config logger.WorkerConfig 28 29 value string 30 } 31 32 var _ = gc.Suite(&LoggerSuite{}) 33 34 func (s *LoggerSuite) SetUpTest(c *gc.C) { 35 s.IsolationSuite.SetUpTest(c) 36 s.context = loggo.NewContext(loggo.DEBUG) 37 s.agent = names.NewMachineTag("42") 38 s.loggerAPI = &mockAPI{ 39 config: s.context.Config().String(), 40 watcher: &mockNotifyWatcher{}, 41 } 42 s.config = logger.WorkerConfig{ 43 Context: s.context, 44 API: s.loggerAPI, 45 Tag: s.agent, 46 Logger: loggo.GetLogger("test"), 47 Callback: func(v string) error { 48 s.value = v 49 return nil 50 }, 51 } 52 s.value = "" 53 } 54 55 func (s *LoggerSuite) TestMissingContext(c *gc.C) { 56 s.config.Context = nil 57 w, err := logger.NewLogger(s.config) 58 c.Assert(w, gc.IsNil) 59 c.Assert(err, jc.Satisfies, errors.IsNotValid) 60 c.Assert(err.Error(), gc.Equals, "missing logging context not valid") 61 } 62 63 func (s *LoggerSuite) TestMissingAPI(c *gc.C) { 64 s.config.API = nil 65 w, err := logger.NewLogger(s.config) 66 c.Assert(w, gc.IsNil) 67 c.Assert(err, jc.Satisfies, errors.IsNotValid) 68 c.Assert(err.Error(), gc.Equals, "missing api not valid") 69 } 70 71 func (s *LoggerSuite) TestMissingLogger(c *gc.C) { 72 s.config.Logger = nil 73 w, err := logger.NewLogger(s.config) 74 c.Assert(w, gc.IsNil) 75 c.Assert(err, jc.Satisfies, errors.IsNotValid) 76 c.Assert(err.Error(), gc.Equals, "missing logger not valid") 77 } 78 79 func (s *LoggerSuite) waitLoggingInfo(c *gc.C, expected string) { 80 timeout := time.After(testing.LongWait) 81 for { 82 select { 83 case <-timeout: 84 c.Fatalf("timeout while waiting for logging info to change") 85 case <-time.After(10 * time.Millisecond): 86 loggerInfo := s.context.Config().String() 87 if loggerInfo != expected { 88 c.Logf("logging is %q, still waiting", loggerInfo) 89 continue 90 } 91 return 92 } 93 } 94 } 95 96 func (s *LoggerSuite) makeLogger(c *gc.C) worker.Worker { 97 w, err := logger.NewLogger(s.config) 98 c.Assert(err, jc.ErrorIsNil) 99 return w 100 } 101 102 func (s *LoggerSuite) TestRunStop(c *gc.C) { 103 loggingWorker := s.makeLogger(c) 104 c.Assert(worker.Stop(loggingWorker), gc.IsNil) 105 } 106 107 func (s *LoggerSuite) TestInitialState(c *gc.C) { 108 expected := s.context.Config().String() 109 110 initial := "<root>=DEBUG;wibble=ERROR" 111 c.Assert(expected, gc.Not(gc.Equals), initial) 112 113 s.context.ResetLoggerLevels() 114 err := s.context.ConfigureLoggers(initial) 115 c.Assert(err, jc.ErrorIsNil) 116 117 loggingWorker := s.makeLogger(c) 118 s.waitLoggingInfo(c, expected) 119 err = worker.Stop(loggingWorker) 120 c.Assert(err, jc.ErrorIsNil) 121 122 c.Check(s.value, gc.Equals, expected) 123 c.Check(s.loggerAPI.loggingTag, gc.Equals, s.agent) 124 c.Check(s.loggerAPI.watchingTag, gc.Equals, s.agent) 125 } 126 127 func (s *LoggerSuite) TestConfigOverride(c *gc.C) { 128 s.config.Override = "test=TRACE" 129 130 s.context.ResetLoggerLevels() 131 err := s.context.ConfigureLoggers("<root>=DEBUG;wibble=ERROR") 132 c.Assert(err, jc.ErrorIsNil) 133 134 loggingWorker := s.makeLogger(c) 135 defer worker.Stop(loggingWorker) 136 137 // When reset, the root defaults to WARNING. 138 expected := "<root>=WARNING;test=TRACE" 139 s.waitLoggingInfo(c, expected) 140 } 141 142 type mockNotifyWatcher struct { 143 changes chan struct{} 144 } 145 146 func (m *mockNotifyWatcher) Kill() {} 147 148 func (m *mockNotifyWatcher) Wait() error { 149 return nil 150 } 151 152 func (m *mockNotifyWatcher) Changes() watcher.NotifyChannel { 153 return m.changes 154 } 155 156 var _ watcher.NotifyWatcher = (*mockNotifyWatcher)(nil) 157 158 type mockAPI struct { 159 watcher *mockNotifyWatcher 160 config string 161 162 loggingTag names.Tag 163 watchingTag names.Tag 164 } 165 166 func (m *mockAPI) LoggingConfig(agentTag names.Tag) (string, error) { 167 m.loggingTag = agentTag 168 return m.config, nil 169 } 170 171 func (m *mockAPI) WatchLoggingConfig(agentTag names.Tag) (watcher.NotifyWatcher, error) { 172 m.watchingTag = agentTag 173 return m.watcher, nil 174 }