3
3
require 'stringio'
4
4
require 'fileutils'
5
5
require 'tempfile'
6
+ require 'active_support/concurrency/latch'
6
7
7
8
class LoggerTest < ActiveSupport ::TestCase
8
9
include MultibyteTestHelpers
@@ -113,6 +114,7 @@ def test_should_know_if_its_loglevel_is_below_a_given_level
113
114
end
114
115
115
116
def test_buffer_multibyte
117
+ @logger . level = Logger ::INFO
116
118
@logger . info ( UNICODE_STRING )
117
119
@logger . info ( BYTE_STRING )
118
120
assert @output . string . include? ( UNICODE_STRING )
@@ -130,4 +132,83 @@ def test_silencing_everything_but_errors
130
132
assert !@output . string . include? ( "NOT THERE" )
131
133
assert @output . string . include? ( "THIS IS HERE" )
132
134
end
135
+
136
+ def test_logger_level_per_object_thread_safety
137
+ logger1 = Logger . new ( StringIO . new )
138
+ logger2 = Logger . new ( StringIO . new )
139
+
140
+ level = Logger ::DEBUG
141
+ assert_equal level , logger1 . level , "Expected level #{ level_name ( level ) } , got #{ level_name ( logger1 . level ) } "
142
+ assert_equal level , logger2 . level , "Expected level #{ level_name ( level ) } , got #{ level_name ( logger2 . level ) } "
143
+
144
+ logger1 . level = Logger ::ERROR
145
+ assert_equal level , logger2 . level , "Expected level #{ level_name ( level ) } , got #{ level_name ( logger2 . level ) } "
146
+ end
147
+
148
+ def test_logger_level_main_thread_safety
149
+ @logger . level = Logger ::INFO
150
+ assert_level ( Logger ::INFO )
151
+
152
+ latch = ActiveSupport ::Concurrency ::Latch . new
153
+ latch2 = ActiveSupport ::Concurrency ::Latch . new
154
+
155
+ t = Thread . new do
156
+ latch . await
157
+ assert_level ( Logger ::INFO )
158
+ latch2 . release
159
+ end
160
+
161
+ @logger . silence ( Logger ::ERROR ) do
162
+ assert_level ( Logger ::ERROR )
163
+ latch . release
164
+ latch2 . await
165
+ end
166
+
167
+ t . join
168
+ end
169
+
170
+ def test_logger_level_local_thread_safety
171
+ @logger . level = Logger ::INFO
172
+ assert_level ( Logger ::INFO )
173
+
174
+ thread_1_latch = ActiveSupport ::Concurrency ::Latch . new
175
+ thread_2_latch = ActiveSupport ::Concurrency ::Latch . new
176
+
177
+ threads = ( 1 ..2 ) . collect do |thread_number |
178
+ Thread . new do
179
+ # force thread 2 to wait until thread 1 is already in @logger.silence
180
+ thread_2_latch . await if thread_number == 2
181
+
182
+ @logger . silence ( Logger ::ERROR ) do
183
+ assert_level ( Logger ::ERROR )
184
+ @logger . silence ( Logger ::DEBUG ) do
185
+ # allow thread 2 to finish but hold thread 1
186
+ if thread_number == 1
187
+ thread_2_latch . release
188
+ thread_1_latch . await
189
+ end
190
+ assert_level ( Logger ::DEBUG )
191
+ end
192
+ end
193
+
194
+ # allow thread 1 to finish
195
+ assert_level ( Logger ::INFO )
196
+ thread_1_latch . release if thread_number == 2
197
+ end
198
+ end
199
+
200
+ threads . each ( &:join )
201
+ assert_level ( Logger ::INFO )
202
+ end
203
+
204
+ private
205
+ def level_name ( level )
206
+ ::Logger ::Severity . constants . find do |severity |
207
+ Logger . const_get ( severity ) == level
208
+ end . to_s
209
+ end
210
+
211
+ def assert_level ( level )
212
+ assert_equal level , @logger . level , "Expected level #{ level_name ( level ) } , got #{ level_name ( @logger . level ) } "
213
+ end
133
214
end
0 commit comments