12
12
from odoo .tests import TransactionCase
13
13
from odoo .tools import config
14
14
15
+ from ..const import to_int_if_defined
15
16
from ..hooks import initialize_sentry
16
17
17
18
GIT_SHA = "d670460b4b4aece5915caf5c68d12f560a9fe3e4"
@@ -56,22 +57,49 @@ def kill(self, *args, **kwargs):
56
57
pass
57
58
58
59
59
- class TestClientSetup (TransactionCase ):
60
+ class NoopHandler (logging .Handler ):
61
+ """
62
+ A Handler subclass that does nothing with any given log record.
63
+
64
+ Sentry's log patching works by having the integration process things after
65
+ the normal log handlers are run, so we use this handler to do nothing and
66
+ move to Sentry logic ASAP.
67
+ """
68
+
69
+ def emit (self , record ):
70
+ pass
71
+
72
+
73
+ class TestSentryCommon (TransactionCase ):
60
74
def setUp (self ):
61
- super (TestClientSetup , self ).setUp ()
75
+ super ().setUp ()
62
76
self .dsn = "http://public:secret@example.com/1"
77
+
78
+ def assertEventCaptured (self , client , event_level , event_msg ):
79
+ self .assertTrue (
80
+ client .transport .has_event (event_level , event_msg ),
81
+ msg = 'Event: "%s" was not captured' % event_msg ,
82
+ )
83
+
84
+ def assertEventNotCaptured (self , client , event_level , event_msg ):
85
+ self .assertFalse (
86
+ client .transport .has_event (event_level , event_msg ),
87
+ msg = 'Event: "%s" was captured' % event_msg ,
88
+ )
89
+
90
+
91
+ class TestClientSetupStartup (TestSentryCommon ):
92
+ def setUp (self ):
93
+ super ().setUp ()
63
94
config .options ["sentry_enabled" ] = True
64
95
config .options ["sentry_dsn" ] = self .dsn
96
+ config .options ["sentry_logging_level" ] = "info"
65
97
with patch (
66
98
"odoo.addons.sentry.const.select_transport" , return_value = InMemoryTransport
67
99
):
68
100
self .client = initialize_sentry (config )._client
69
101
self .handler = self .client .integrations ["logging" ]._handler
70
102
71
- def log (self , level , msg , exc_info = None ):
72
- record = logging .LogRecord (__name__ , level , __file__ , 42 , msg , (), exc_info )
73
- self .handler .emit (record )
74
-
75
103
def assertEventCaptured (self , client , event_level , event_msg ):
76
104
self .assertTrue (
77
105
client .transport .has_event (event_level , event_msg ),
@@ -97,53 +125,132 @@ def test_startup_event_disabled(self):
97
125
self .client = initialize_sentry (config )._client
98
126
self .assertEventNotCaptured (self .client , "info" , "Starting Odoo Server" )
99
127
128
+ def test_startup_event_disabled_if_warning_level (self ):
129
+ config .options ["sentry_enabled" ] = True
130
+ config .options ["sentry_dsn" ] = self .dsn
131
+ config .options ["sentry_ignore_startup_event" ] = True
132
+ config .options ["sentry_logging_level" ] = "warning"
133
+ with patch (
134
+ "odoo.addons.sentry.const.select_transport" , return_value = InMemoryTransport
135
+ ):
136
+ self .client = initialize_sentry (config )._client
137
+ self .assertEventNotCaptured (self .client , "info" , "Starting Odoo Server" )
138
+
139
+
140
+ class TestClientSetup (TestSentryCommon ):
141
+ def setUp (self ):
142
+ super ().setUp ()
143
+ self .patch_config (
144
+ {
145
+ "sentry_enabled" : True ,
146
+ "sentry_dsn" : self .dsn ,
147
+ "sentry_logging_level" : "error" ,
148
+ }
149
+ )
150
+ self .client = initialize_sentry (config )._client
151
+ self .client .transport = InMemoryTransport ({"dsn" : self .dsn })
152
+
153
+ # Setup our own logger so we don't flood stderr with error logs
154
+ self .logger = logging .getLogger ("odoo.sentry.test.logger" )
155
+ # Do not mutate list while iterating it
156
+ handlers = [handler for handler in self .logger .handlers ]
157
+ for handler in handlers :
158
+ self .logger .removeHandler (handler )
159
+ self .logger .addHandler (NoopHandler ())
160
+ self .logger .propagate = False
161
+
162
+ def patch_config (self , options : dict ):
163
+ """
164
+ Patch Odoo's config with the given `options`, ensuring that the patch
165
+ is undone when the test completes.
166
+ """
167
+ _config_patcher = patch .dict (
168
+ in_dict = config .options ,
169
+ values = options ,
170
+ )
171
+ _config_patcher .start ()
172
+ self .addCleanup (_config_patcher .stop )
173
+
174
+ def log (self , level , msg , exc_info = None ):
175
+ self .logger .log (level , msg , exc_info = exc_info )
176
+
100
177
def test_initialize_raven_sets_dsn (self ):
101
178
self .assertEqual (self .client .dsn , self .dsn )
102
179
103
- def test_capture_event (self ):
180
+ def test_ignore_low_level_event (self ):
104
181
level , msg = logging .WARNING , "Test event, can be ignored"
105
182
self .log (level , msg )
106
183
level = "warning"
184
+ self .assertEventNotCaptured (self .client , level , msg )
185
+
186
+ def test_capture_event (self ):
187
+ level , msg = logging .ERROR , "Test event, should be captured"
188
+ self .log (level , msg )
189
+ level = "error"
107
190
self .assertEventCaptured (self .client , level , msg )
108
191
109
192
def test_capture_event_exc (self ):
110
- level , msg = logging .WARNING , "Test event, can be ignored exception"
193
+ level , msg = logging .ERROR , "Test event, can be ignored exception"
111
194
try :
112
195
raise TestException (msg )
113
196
except TestException :
114
197
exc_info = sys .exc_info ()
115
198
self .log (level , msg , exc_info )
116
- level = "warning "
199
+ level = "error "
117
200
self .assertEventCaptured (self .client , level , msg )
118
201
119
202
def test_ignore_exceptions (self ):
120
- config .options ["sentry_ignore_exceptions" ] = "odoo.exceptions.UserError"
203
+ self .patch_config (
204
+ {
205
+ "sentry_ignore_exceptions" : "odoo.exceptions.UserError" ,
206
+ }
207
+ )
121
208
client = initialize_sentry (config )._client
122
209
client .transport = InMemoryTransport ({"dsn" : self .dsn })
123
- level , msg = logging .WARNING , "Test exception"
210
+ level , msg = logging .ERROR , "Test exception"
124
211
try :
125
212
raise exceptions .UserError (msg )
126
213
except exceptions .UserError :
127
214
exc_info = sys .exc_info ()
128
215
self .log (level , msg , exc_info )
129
- level = "warning "
216
+ level = "error "
130
217
self .assertEventNotCaptured (client , level , msg )
131
218
132
219
def test_exclude_logger (self ):
133
- config .options ["sentry_enabled" ] = True
134
- config .options ["sentry_exclude_loggers" ] = __name__
220
+ self .patch_config (
221
+ {
222
+ "sentry_enabled" : True ,
223
+ "sentry_exclude_loggers" : self .logger .name ,
224
+ }
225
+ )
135
226
client = initialize_sentry (config )._client
136
227
client .transport = InMemoryTransport ({"dsn" : self .dsn })
137
- level , msg = logging .WARNING , "Test exclude logger %s" % __name__
228
+ level , msg = logging .ERROR , "Test exclude logger %s" % __name__
138
229
self .log (level , msg )
139
- level = "warning "
230
+ level = "error "
140
231
# Revert ignored logger so it doesn't affect other tests
141
- remove_handler_ignore (__name__ )
232
+ remove_handler_ignore (self . logger . name )
142
233
self .assertEventNotCaptured (client , level , msg )
143
234
235
+ def test_invalid_logging_level (self ):
236
+ self .patch_config (
237
+ {
238
+ "sentry_logging_level" : "foo_bar" ,
239
+ }
240
+ )
241
+ client = initialize_sentry (config )._client
242
+ client .transport = InMemoryTransport ({"dsn" : self .dsn })
243
+ level , msg = logging .WARNING , "Test we use the default"
244
+ self .log (level , msg )
245
+ level = "warning"
246
+ self .assertEventCaptured (client , level , msg )
247
+
248
+ def test_undefined_to_int (self ):
249
+ self .assertIsNone (to_int_if_defined ("" ))
250
+
144
251
@patch ("odoo.addons.sentry.hooks.get_odoo_commit" , return_value = GIT_SHA )
145
252
def test_config_odoo_dir (self , get_odoo_commit ):
146
- config . options [ "sentry_odoo_dir" ] = "/opt/odoo/core"
253
+ self . patch_config ({ "sentry_odoo_dir" : "/opt/odoo/core" })
147
254
client = initialize_sentry (config )._client
148
255
149
256
self .assertEqual (
@@ -154,8 +261,12 @@ def test_config_odoo_dir(self, get_odoo_commit):
154
261
155
262
@patch ("odoo.addons.sentry.hooks.get_odoo_commit" , return_value = GIT_SHA )
156
263
def test_config_release (self , get_odoo_commit ):
157
- config .options ["sentry_odoo_dir" ] = "/opt/odoo/core"
158
- config .options ["sentry_release" ] = RELEASE
264
+ self .patch_config (
265
+ {
266
+ "sentry_odoo_dir" : "/opt/odoo/core" ,
267
+ "sentry_release" : RELEASE ,
268
+ }
269
+ )
159
270
client = initialize_sentry (config )._client
160
271
161
272
self .assertEqual (
0 commit comments