mono_logger 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- require 'logger'
2
-
3
- class MonoLogger < Logger
4
- VERSION = "1.1.0"
5
- end
1
+ require 'logger'
2
+
3
+ class MonoLogger < Logger
4
+ VERSION = "1.1.1"
5
+ end
data/mono_logger.gemspec CHANGED
@@ -1,25 +1,24 @@
1
- # coding: utf-8
2
-
3
- lib = File.expand_path('../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'mono_logger/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = "mono_logger"
9
- spec.version = MonoLogger::VERSION
10
- spec.authors = ["Steve Klabnik"]
11
- spec.email = ["steve@steveklabnik.com"]
12
- spec.description = %q{A lock-free logger compatible with Ruby 2.0. Ruby does not allow you to request a lock in a trap handler because that could deadlock, so Logger is not sufficient.}
13
- spec.summary = %q{A lock-free logger compatible with Ruby 2.0.}
14
- spec.homepage = "http://github.com/steveklabnik/mono_logger"
15
- spec.license = "MIT"
16
-
17
- spec.files = `git ls-files`.split($/)
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "bundler", "~> 1.3"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "minitest", "~> 4.0"
25
- end
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'mono_logger/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "mono_logger"
9
+ spec.version = MonoLogger::VERSION
10
+ spec.authors = ["Steve Klabnik"]
11
+ spec.email = ["steve@steveklabnik.com"]
12
+ spec.description = %q{A lock-free logger compatible with Ruby 2.0. Ruby does not allow you to request a lock in a trap handler because that could deadlock, so Logger is not sufficient.}
13
+ spec.summary = %q{A lock-free logger compatible with Ruby 2.0.}
14
+ spec.homepage = "http://github.com/steveklabnik/mono_logger"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest", "~> 5.0"
24
+ end
@@ -1,533 +1,550 @@
1
- # coding: US-ASCII
2
- require 'test/unit'
3
- require 'mono_logger'
4
- require 'tempfile'
5
-
6
- Logger = MonoLogger
7
-
8
-
9
- class TestLoggerSeverity < Test::Unit::TestCase
10
- def test_enum
11
- logger_levels = Logger.constants
12
- levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
13
- Logger::Severity.constants.each do |level|
14
- assert(levels.include?(level.to_s))
15
- assert(logger_levels.include?(level))
16
- end
17
- assert_equal(levels.size, Logger::Severity.constants.size)
18
- end
19
- end
20
-
21
-
22
- class TestLogger < Test::Unit::TestCase
23
- include Logger::Severity
24
-
25
- def setup
26
- @logger = Logger.new(nil)
27
- end
28
-
29
- class Log
30
- attr_reader :label, :datetime, :pid, :severity, :progname, :msg
31
- def initialize(line)
32
- /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
33
- @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
34
- end
35
- end
36
-
37
- def log_add(logger, severity, msg, progname = nil, &block)
38
- log(logger, :add, severity, msg, progname, &block)
39
- end
40
-
41
- def log(logger, msg_id, *arg, &block)
42
- Log.new(log_raw(logger, msg_id, *arg, &block))
43
- end
44
-
45
- def log_raw(logger, msg_id, *arg, &block)
46
- logdev = Tempfile.new(File.basename(__FILE__) + '.log')
47
- logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
48
- logger.__send__(msg_id, *arg, &block)
49
- logdev.open
50
- msg = logdev.read
51
- logdev.close
52
- msg
53
- end
54
-
55
- def test_level
56
- @logger.level = UNKNOWN
57
- assert_equal(UNKNOWN, @logger.level)
58
- @logger.level = INFO
59
- assert_equal(INFO, @logger.level)
60
- @logger.sev_threshold = ERROR
61
- assert_equal(ERROR, @logger.sev_threshold)
62
- @logger.sev_threshold = WARN
63
- assert_equal(WARN, @logger.sev_threshold)
64
- assert_equal(WARN, @logger.level)
65
-
66
- @logger.level = DEBUG
67
- assert(@logger.debug?)
68
- assert(@logger.info?)
69
- @logger.level = INFO
70
- assert(!@logger.debug?)
71
- assert(@logger.info?)
72
- assert(@logger.warn?)
73
- @logger.level = WARN
74
- assert(!@logger.info?)
75
- assert(@logger.warn?)
76
- assert(@logger.error?)
77
- @logger.level = ERROR
78
- assert(!@logger.warn?)
79
- assert(@logger.error?)
80
- assert(@logger.fatal?)
81
- @logger.level = FATAL
82
- assert(!@logger.error?)
83
- assert(@logger.fatal?)
84
- @logger.level = UNKNOWN
85
- assert(!@logger.error?)
86
- assert(!@logger.fatal?)
87
- end
88
-
89
- def test_progname
90
- assert_nil(@logger.progname)
91
- @logger.progname = "name"
92
- assert_equal("name", @logger.progname)
93
- end
94
-
95
- def test_datetime_format
96
- dummy = STDERR
97
- logger = Logger.new(dummy)
98
- log = log_add(logger, INFO, "foo")
99
- assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime)
100
- logger.datetime_format = "%d%b%Y@%H:%M:%S"
101
- log = log_add(logger, INFO, "foo")
102
- assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
103
- logger.datetime_format = ""
104
- log = log_add(logger, INFO, "foo")
105
- assert_match(/^$/, log.datetime)
106
- end
107
-
108
- def test_formatter
109
- dummy = STDERR
110
- logger = Logger.new(dummy)
111
- # default
112
- log = log(logger, :info, "foo")
113
- assert_equal("foo\n", log.msg)
114
- # config
115
- logger.formatter = proc { |severity, timestamp, progname, msg|
116
- "#{severity}:#{msg}\n\n"
117
- }
118
- line = log_raw(logger, :info, "foo")
119
- assert_equal("INFO:foo\n\n", line)
120
- # recover
121
- logger.formatter = nil
122
- log = log(logger, :info, "foo")
123
- assert_equal("foo\n", log.msg)
124
- # again
125
- o = Object.new
126
- def o.call(severity, timestamp, progname, msg)
127
- "<<#{severity}-#{msg}>>\n"
128
- end
129
- logger.formatter = o
130
- line = log_raw(logger, :info, "foo")
131
- assert_equal("<""<INFO-foo>>\n", line)
132
- end
133
-
134
- def test_initialize
135
- logger = Logger.new(STDERR)
136
- assert_nil(logger.progname)
137
- assert_equal(DEBUG, logger.level)
138
- assert_nil(logger.datetime_format)
139
- end
140
-
141
- def test_add
142
- logger = Logger.new(nil)
143
- logger.progname = "my_progname"
144
- assert(logger.add(INFO))
145
- log = log_add(logger, nil, "msg")
146
- assert_equal("ANY", log.severity)
147
- assert_equal("my_progname", log.progname)
148
- logger.level = WARN
149
- assert(logger.log(INFO))
150
- assert_nil(log_add(logger, INFO, "msg").msg)
151
- log = log_add(logger, WARN, nil) { "msg" }
152
- assert_equal("msg\n", log.msg)
153
- log = log_add(logger, WARN, "") { "msg" }
154
- assert_equal("\n", log.msg)
155
- assert_equal("my_progname", log.progname)
156
- log = log_add(logger, WARN, nil, "progname?")
157
- assert_equal("progname?\n", log.msg)
158
- assert_equal("my_progname", log.progname)
159
- end
160
-
161
- def test_level_log
162
- logger = Logger.new(nil)
163
- logger.progname = "my_progname"
164
- log = log(logger, :debug, "custom_progname") { "msg" }
165
- assert_equal("msg\n", log.msg)
166
- assert_equal("custom_progname", log.progname)
167
- assert_equal("DEBUG", log.severity)
168
- assert_equal("D", log.label)
169
- #
170
- log = log(logger, :debug) { "msg_block" }
171
- assert_equal("msg_block\n", log.msg)
172
- assert_equal("my_progname", log.progname)
173
- log = log(logger, :debug, "msg_inline")
174
- assert_equal("msg_inline\n", log.msg)
175
- assert_equal("my_progname", log.progname)
176
- #
177
- log = log(logger, :info, "custom_progname") { "msg" }
178
- assert_equal("msg\n", log.msg)
179
- assert_equal("custom_progname", log.progname)
180
- assert_equal("INFO", log.severity)
181
- assert_equal("I", log.label)
182
- #
183
- log = log(logger, :warn, "custom_progname") { "msg" }
184
- assert_equal("msg\n", log.msg)
185
- assert_equal("custom_progname", log.progname)
186
- assert_equal("WARN", log.severity)
187
- assert_equal("W", log.label)
188
- #
189
- log = log(logger, :error, "custom_progname") { "msg" }
190
- assert_equal("msg\n", log.msg)
191
- assert_equal("custom_progname", log.progname)
192
- assert_equal("ERROR", log.severity)
193
- assert_equal("E", log.label)
194
- #
195
- log = log(logger, :fatal, "custom_progname") { "msg" }
196
- assert_equal("msg\n", log.msg)
197
- assert_equal("custom_progname", log.progname)
198
- assert_equal("FATAL", log.severity)
199
- assert_equal("F", log.label)
200
- #
201
- log = log(logger, :unknown, "custom_progname") { "msg" }
202
- assert_equal("msg\n", log.msg)
203
- assert_equal("custom_progname", log.progname)
204
- assert_equal("ANY", log.severity)
205
- assert_equal("A", log.label)
206
- end
207
-
208
- def test_close
209
- r, w = IO.pipe
210
- assert(!w.closed?)
211
- logger = Logger.new(w)
212
- logger.close
213
- assert(w.closed?)
214
- r.close
215
- end
216
-
217
- class MyError < StandardError
218
- end
219
-
220
- class MyMsg
221
- def inspect
222
- "my_msg"
223
- end
224
- end
225
-
226
- def test_format
227
- logger = Logger.new(nil)
228
- log = log_add(logger, INFO, "msg\n")
229
- assert_equal("msg\n\n", log.msg)
230
- begin
231
- raise MyError.new("excn")
232
- rescue MyError => e
233
- log = log_add(logger, INFO, e)
234
- assert_match(/^excn \(TestLogger::MyError\)/, log.msg)
235
- # expects backtrace is dumped across multi lines. 10 might be changed.
236
- assert(log.msg.split(/\n/).size >= 10)
237
- end
238
- log = log_add(logger, INFO, MyMsg.new)
239
- assert_equal("my_msg\n", log.msg)
240
- end
241
-
242
- def test_lshift
243
- r, w = IO.pipe
244
- logger = Logger.new(w)
245
- logger << "msg"
246
- read_ready, = IO.select([r], nil, nil, 0.1)
247
- w.close
248
- msg = r.read
249
- r.close
250
- assert_equal("msg", msg)
251
- #
252
- r, w = IO.pipe
253
- logger = Logger.new(w)
254
- logger << "msg2\n\n"
255
- read_ready, = IO.select([r], nil, nil, 0.1)
256
- w.close
257
- msg = r.read
258
- r.close
259
- assert_equal("msg2\n\n", msg)
260
- end
261
- end
262
-
263
- class TestLogDevice < Test::Unit::TestCase
264
- class LogExcnRaiser
265
- def write(*arg)
266
- raise 'disk is full'
267
- end
268
-
269
- def close
270
- end
271
-
272
- def stat
273
- Object.new
274
- end
275
- end
276
-
277
- def setup
278
- @tempfile = Tempfile.new("logger")
279
- @tempfile.close
280
- @filename = @tempfile.path
281
- File.unlink(@filename)
282
- end
283
-
284
- def teardown
285
- @tempfile.close(true)
286
- end
287
-
288
- def d(log, opt = {})
289
- Logger::LogDevice.new(log, opt)
290
- end
291
-
292
- def test_initialize
293
- logdev = d(STDERR)
294
- assert_equal(STDERR, logdev.dev)
295
- assert_nil(logdev.filename)
296
- assert_raises(TypeError) do
297
- d(nil)
298
- end
299
- #
300
- logdev = d(@filename)
301
- begin
302
- assert(File.exist?(@filename))
303
- assert(logdev.dev.sync)
304
- assert_equal(@filename, logdev.filename)
305
- logdev.write('hello')
306
- ensure
307
- logdev.close
308
- end
309
- # create logfile whitch is already exist.
310
- logdev = d(@filename)
311
- begin
312
- logdev.write('world')
313
- logfile = File.read(@filename)
314
- assert_equal(2, logfile.split(/\n/).size)
315
- assert_match(/^helloworld$/, logfile)
316
- ensure
317
- logdev.close
318
- end
319
- end
320
-
321
- def test_write
322
- r, w = IO.pipe
323
- logdev = d(w)
324
- logdev.write("msg2\n\n")
325
- read_ready, = IO.select([r], nil, nil, 0.1)
326
- w.close
327
- msg = r.read
328
- r.close
329
- assert_equal("msg2\n\n", msg)
330
- #
331
- logdev = d(LogExcnRaiser.new)
332
- class << (stderr = '')
333
- alias write <<
334
- end
335
- $stderr, stderr = stderr, $stderr
336
- begin
337
- assert_nothing_raised do
338
- logdev.write('hello')
339
- end
340
- ensure
341
- logdev.close
342
- $stderr, stderr = stderr, $stderr
343
- end
344
- assert_equal "log writing failed. disk is full\n", stderr
345
- end
346
-
347
- def test_close
348
- r, w = IO.pipe
349
- logdev = d(w)
350
- logdev.write("msg2\n\n")
351
- read_ready, = IO.select([r], nil, nil, 0.1)
352
- assert(!w.closed?)
353
- logdev.close
354
- assert(w.closed?)
355
- r.close
356
- end
357
-
358
- def test_shifting_size
359
- skip("shifting age doesn't work because rotation doesn't work")
360
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_1.log'])
361
- logfile = tmpfile.path
362
- logfile0 = logfile + '.0'
363
- logfile1 = logfile + '.1'
364
- logfile2 = logfile + '.2'
365
- logfile3 = logfile + '.3'
366
- tmpfile.close(true)
367
- File.unlink(logfile) if File.exist?(logfile)
368
- File.unlink(logfile0) if File.exist?(logfile0)
369
- File.unlink(logfile1) if File.exist?(logfile1)
370
- File.unlink(logfile2) if File.exist?(logfile2)
371
- logger = Logger.new(logfile, 4, 100)
372
- logger.error("0" * 15)
373
- assert(File.exist?(logfile))
374
- assert(!File.exist?(logfile0))
375
- logger.error("0" * 15)
376
- assert(File.exist?(logfile0))
377
- assert(!File.exist?(logfile1))
378
- logger.error("0" * 15)
379
- assert(File.exist?(logfile1))
380
- assert(!File.exist?(logfile2))
381
- logger.error("0" * 15)
382
- assert(File.exist?(logfile2))
383
- assert(!File.exist?(logfile3))
384
- logger.error("0" * 15)
385
- assert(!File.exist?(logfile3))
386
- logger.error("0" * 15)
387
- assert(!File.exist?(logfile3))
388
- logger.close
389
- File.unlink(logfile)
390
- File.unlink(logfile0)
391
- File.unlink(logfile1)
392
- File.unlink(logfile2)
393
-
394
- tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_2.log'])
395
- logfile = tmpfile.path
396
- logfile0 = logfile + '.0'
397
- logfile1 = logfile + '.1'
398
- logfile2 = logfile + '.2'
399
- logfile3 = logfile + '.3'
400
- tmpfile.close(true)
401
- logger = Logger.new(logfile, 4, 150)
402
- logger.error("0" * 15)
403
- assert(File.exist?(logfile))
404
- assert(!File.exist?(logfile0))
405
- logger.error("0" * 15)
406
- assert(!File.exist?(logfile0))
407
- logger.error("0" * 15)
408
- assert(File.exist?(logfile0))
409
- assert(!File.exist?(logfile1))
410
- logger.error("0" * 15)
411
- assert(!File.exist?(logfile1))
412
- logger.error("0" * 15)
413
- assert(File.exist?(logfile1))
414
- assert(!File.exist?(logfile2))
415
- logger.error("0" * 15)
416
- assert(!File.exist?(logfile2))
417
- logger.error("0" * 15)
418
- assert(File.exist?(logfile2))
419
- assert(!File.exist?(logfile3))
420
- logger.error("0" * 15)
421
- assert(!File.exist?(logfile3))
422
- logger.error("0" * 15)
423
- assert(!File.exist?(logfile3))
424
- logger.error("0" * 15)
425
- assert(!File.exist?(logfile3))
426
- logger.close
427
- File.unlink(logfile)
428
- File.unlink(logfile0)
429
- File.unlink(logfile1)
430
- File.unlink(logfile2)
431
- end
432
-
433
- def test_shifting_age_variants
434
- skip("shifting age doesn't work because rotation doesn't work")
435
- logger = Logger.new(@filename, 'daily')
436
- logger.info('daily')
437
- logger.close
438
- logger = Logger.new(@filename, 'weekly')
439
- logger.info('weekly')
440
- logger.close
441
- logger = Logger.new(@filename, 'monthly')
442
- logger.info('monthly')
443
- logger.close
444
- end
445
-
446
- def test_shifting_age
447
- skip("shifting age doesn't work because rotation doesn't work")
448
- # shift_age other than 'daily', 'weekly', and 'monthly' means 'everytime'
449
- yyyymmdd = Time.now.strftime("%Y%m%d")
450
- filename1 = @filename + ".#{yyyymmdd}"
451
- filename2 = @filename + ".#{yyyymmdd}.1"
452
- filename3 = @filename + ".#{yyyymmdd}.2"
453
- begin
454
- logger = Logger.new(@filename, 'now')
455
- assert(File.exist?(@filename))
456
- assert(!File.exist?(filename1))
457
- assert(!File.exist?(filename2))
458
- assert(!File.exist?(filename3))
459
- logger.info("0" * 15)
460
- assert(File.exist?(@filename))
461
- assert(File.exist?(filename1))
462
- assert(!File.exist?(filename2))
463
- assert(!File.exist?(filename3))
464
- logger.warn("0" * 15)
465
- assert(File.exist?(@filename))
466
- assert(File.exist?(filename1))
467
- assert(File.exist?(filename2))
468
- assert(!File.exist?(filename3))
469
- logger.error("0" * 15)
470
- assert(File.exist?(@filename))
471
- assert(File.exist?(filename1))
472
- assert(File.exist?(filename2))
473
- assert(File.exist?(filename3))
474
- ensure
475
- logger.close if logger
476
- [filename1, filename2, filename3].each do |filename|
477
- File.unlink(filename) if File.exist?(filename)
478
- end
479
- end
480
- end
481
- end
482
-
483
-
484
- class TestLoggerApplication < Test::Unit::TestCase
485
- def setup
486
- @app = Logger::Application.new('appname')
487
- @tempfile = Tempfile.new("logger")
488
- @tempfile.close
489
- @filename = @tempfile.path
490
- File.unlink(@filename)
491
- end
492
-
493
- def teardown
494
- @tempfile.close(true)
495
- end
496
-
497
- def test_initialize
498
- app = Logger::Application.new('appname')
499
- assert_equal('appname', app.appname)
500
- end
501
-
502
- def test_start
503
- @app.set_log(@filename)
504
- begin
505
- @app.level = Logger::UNKNOWN
506
- @app.start # logs FATAL log
507
- assert_equal(1, File.read(@filename).split(/\n/).size)
508
- ensure
509
- @app.logger.close
510
- end
511
- end
512
-
513
- def test_logger
514
- @app.level = Logger::WARN
515
- @app.set_log(@filename)
516
- begin
517
- assert_equal(Logger::WARN, @app.logger.level)
518
- ensure
519
- @app.logger.close
520
- end
521
- @app.logger = logger = Logger.new(STDOUT)
522
- assert_equal(logger, @app.logger)
523
- assert_equal(Logger::WARN, @app.logger.level)
524
- @app.log = @filename
525
- begin
526
- assert(logger != @app.logger)
527
- assert_equal(Logger::WARN, @app.logger.level)
528
- ensure
529
- @app.logger.close
530
- end
531
- end
532
- end
533
-
1
+ # coding: US-ASCII
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter do |source_file|
5
+ source_file.filename =~ /test/
6
+ end
7
+ end
8
+
9
+ require 'coveralls'
10
+ Coveralls.wear!
11
+
12
+ require 'minitest/autorun'
13
+ require 'mono_logger'
14
+ # Logger::Application was dropped at Ruby 2.2.
15
+ require 'logger-application' unless defined?(Logger::Application)
16
+ require 'tempfile'
17
+
18
+ if defined? Minitest::Test
19
+ # We're on Minitest 5+. Nothing to do here.
20
+ else
21
+ # Minitest 4 doesn't have Minitest::Test yet.
22
+ Minitest::Test = MiniTest::Unit::TestCase
23
+ end
24
+
25
+ Logger = MonoLogger
26
+
27
+
28
+ class TestLoggerSeverity < Minitest::Test
29
+ def test_enum
30
+ logger_levels = Logger.constants
31
+ levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
32
+ Logger::Severity.constants.each do |level|
33
+ assert(levels.include?(level.to_s))
34
+ assert(logger_levels.include?(level))
35
+ end
36
+ assert_equal(levels.size, Logger::Severity.constants.size)
37
+ end
38
+ end
39
+
40
+
41
+ class TestLogger < Minitest::Test
42
+ include Logger::Severity
43
+
44
+ def setup
45
+ @logger = Logger.new(nil)
46
+ end
47
+
48
+ class Log
49
+ attr_reader :label, :datetime, :pid, :severity, :progname, :msg
50
+ def initialize(line)
51
+ /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
52
+ @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
53
+ end
54
+ end
55
+
56
+ def log_add(logger, severity, msg, progname = nil, &block)
57
+ log(logger, :add, severity, msg, progname, &block)
58
+ end
59
+
60
+ def log(logger, msg_id, *arg, &block)
61
+ Log.new(log_raw(logger, msg_id, *arg, &block))
62
+ end
63
+
64
+ def log_raw(logger, msg_id, *arg, &block)
65
+ logdev = Tempfile.new(File.basename(__FILE__) + '.log')
66
+ logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
67
+ logger.__send__(msg_id, *arg, &block)
68
+ logdev.open
69
+ msg = logdev.read
70
+ logdev.close
71
+ msg
72
+ end
73
+
74
+ def test_level
75
+ @logger.level = UNKNOWN
76
+ assert_equal(UNKNOWN, @logger.level)
77
+ @logger.level = INFO
78
+ assert_equal(INFO, @logger.level)
79
+ @logger.sev_threshold = ERROR
80
+ assert_equal(ERROR, @logger.sev_threshold)
81
+ @logger.sev_threshold = WARN
82
+ assert_equal(WARN, @logger.sev_threshold)
83
+ assert_equal(WARN, @logger.level)
84
+
85
+ @logger.level = DEBUG
86
+ assert(@logger.debug?)
87
+ assert(@logger.info?)
88
+ @logger.level = INFO
89
+ assert(!@logger.debug?)
90
+ assert(@logger.info?)
91
+ assert(@logger.warn?)
92
+ @logger.level = WARN
93
+ assert(!@logger.info?)
94
+ assert(@logger.warn?)
95
+ assert(@logger.error?)
96
+ @logger.level = ERROR
97
+ assert(!@logger.warn?)
98
+ assert(@logger.error?)
99
+ assert(@logger.fatal?)
100
+ @logger.level = FATAL
101
+ assert(!@logger.error?)
102
+ assert(@logger.fatal?)
103
+ @logger.level = UNKNOWN
104
+ assert(!@logger.error?)
105
+ assert(!@logger.fatal?)
106
+ end
107
+
108
+ def test_progname
109
+ assert_nil(@logger.progname)
110
+ @logger.progname = "name"
111
+ assert_equal("name", @logger.progname)
112
+ end
113
+
114
+ def test_datetime_format
115
+ dummy = STDERR
116
+ logger = Logger.new(dummy)
117
+ log = log_add(logger, INFO, "foo")
118
+ assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime)
119
+ logger.datetime_format = "%d%b%Y@%H:%M:%S"
120
+ log = log_add(logger, INFO, "foo")
121
+ assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
122
+ logger.datetime_format = ""
123
+ log = log_add(logger, INFO, "foo")
124
+ assert_match(/^$/, log.datetime)
125
+ end
126
+
127
+ def test_formatter
128
+ dummy = STDERR
129
+ logger = Logger.new(dummy)
130
+ # default
131
+ log = log(logger, :info, "foo")
132
+ assert_equal("foo\n", log.msg)
133
+ # config
134
+ logger.formatter = proc { |severity, timestamp, progname, msg|
135
+ "#{severity}:#{msg}\n\n"
136
+ }
137
+ line = log_raw(logger, :info, "foo")
138
+ assert_equal("INFO:foo\n\n", line)
139
+ # recover
140
+ logger.formatter = nil
141
+ log = log(logger, :info, "foo")
142
+ assert_equal("foo\n", log.msg)
143
+ # again
144
+ o = Object.new
145
+ def o.call(severity, timestamp, progname, msg)
146
+ "<<#{severity}-#{msg}>>\n"
147
+ end
148
+ logger.formatter = o
149
+ line = log_raw(logger, :info, "foo")
150
+ assert_equal("<""<INFO-foo>>\n", line)
151
+ end
152
+
153
+ def test_initialize
154
+ logger = Logger.new(STDERR)
155
+ assert_nil(logger.progname)
156
+ assert_equal(DEBUG, logger.level)
157
+ assert_nil(logger.datetime_format)
158
+ end
159
+
160
+ def test_add
161
+ logger = Logger.new(nil)
162
+ logger.progname = "my_progname"
163
+ assert(logger.add(INFO))
164
+ log = log_add(logger, nil, "msg")
165
+ assert_equal("ANY", log.severity)
166
+ assert_equal("my_progname", log.progname)
167
+ logger.level = WARN
168
+ assert(logger.log(INFO))
169
+ assert_nil(log_add(logger, INFO, "msg").msg)
170
+ log = log_add(logger, WARN, nil) { "msg" }
171
+ assert_equal("msg\n", log.msg)
172
+ log = log_add(logger, WARN, "") { "msg" }
173
+ assert_equal("\n", log.msg)
174
+ assert_equal("my_progname", log.progname)
175
+ log = log_add(logger, WARN, nil, "progname?")
176
+ assert_equal("progname?\n", log.msg)
177
+ assert_equal("my_progname", log.progname)
178
+ end
179
+
180
+ def test_level_log
181
+ logger = Logger.new(nil)
182
+ logger.progname = "my_progname"
183
+ log = log(logger, :debug, "custom_progname") { "msg" }
184
+ assert_equal("msg\n", log.msg)
185
+ assert_equal("custom_progname", log.progname)
186
+ assert_equal("DEBUG", log.severity)
187
+ assert_equal("D", log.label)
188
+ #
189
+ log = log(logger, :debug) { "msg_block" }
190
+ assert_equal("msg_block\n", log.msg)
191
+ assert_equal("my_progname", log.progname)
192
+ log = log(logger, :debug, "msg_inline")
193
+ assert_equal("msg_inline\n", log.msg)
194
+ assert_equal("my_progname", log.progname)
195
+ #
196
+ log = log(logger, :info, "custom_progname") { "msg" }
197
+ assert_equal("msg\n", log.msg)
198
+ assert_equal("custom_progname", log.progname)
199
+ assert_equal("INFO", log.severity)
200
+ assert_equal("I", log.label)
201
+ #
202
+ log = log(logger, :warn, "custom_progname") { "msg" }
203
+ assert_equal("msg\n", log.msg)
204
+ assert_equal("custom_progname", log.progname)
205
+ assert_equal("WARN", log.severity)
206
+ assert_equal("W", log.label)
207
+ #
208
+ log = log(logger, :error, "custom_progname") { "msg" }
209
+ assert_equal("msg\n", log.msg)
210
+ assert_equal("custom_progname", log.progname)
211
+ assert_equal("ERROR", log.severity)
212
+ assert_equal("E", log.label)
213
+ #
214
+ log = log(logger, :fatal, "custom_progname") { "msg" }
215
+ assert_equal("msg\n", log.msg)
216
+ assert_equal("custom_progname", log.progname)
217
+ assert_equal("FATAL", log.severity)
218
+ assert_equal("F", log.label)
219
+ #
220
+ log = log(logger, :unknown, "custom_progname") { "msg" }
221
+ assert_equal("msg\n", log.msg)
222
+ assert_equal("custom_progname", log.progname)
223
+ assert_equal("ANY", log.severity)
224
+ assert_equal("A", log.label)
225
+ end
226
+
227
+ def test_close
228
+ r, w = IO.pipe
229
+ assert(!w.closed?)
230
+ logger = Logger.new(w)
231
+ logger.close
232
+ assert(w.closed?)
233
+ r.close
234
+ end
235
+
236
+ class MyError < StandardError
237
+ end
238
+
239
+ class MyMsg
240
+ def inspect
241
+ "my_msg"
242
+ end
243
+ end
244
+
245
+ def test_format
246
+ logger = Logger.new(nil)
247
+ log = log_add(logger, INFO, "msg\n")
248
+ assert_equal("msg\n\n", log.msg)
249
+ begin
250
+ raise MyError.new("excn")
251
+ rescue MyError => e
252
+ log = log_add(logger, INFO, e)
253
+ assert_match(/^excn \(TestLogger::MyError\)/, log.msg)
254
+ # expects backtrace is dumped across multi lines. 10 might be changed.
255
+ assert(log.msg.split(/\n/).size >= 10)
256
+ end
257
+ log = log_add(logger, INFO, MyMsg.new)
258
+ assert_equal("my_msg\n", log.msg)
259
+ end
260
+
261
+ def test_lshift
262
+ r, w = IO.pipe
263
+ logger = Logger.new(w)
264
+ logger << "msg"
265
+ _, = IO.select([r], nil, nil, 0.1)
266
+ w.close
267
+ msg = r.read
268
+ r.close
269
+ assert_equal("msg", msg)
270
+ #
271
+ r, w = IO.pipe
272
+ logger = Logger.new(w)
273
+ logger << "msg2\n\n"
274
+ _, = IO.select([r], nil, nil, 0.1)
275
+ w.close
276
+ msg = r.read
277
+ r.close
278
+ assert_equal("msg2\n\n", msg)
279
+ end
280
+ end
281
+
282
+ class TestLogDevice < Minitest::Test
283
+ class LogExcnRaiser
284
+ def write(*arg)
285
+ raise 'disk is full'
286
+ end
287
+
288
+ def close
289
+ end
290
+
291
+ def stat
292
+ Object.new
293
+ end
294
+ end
295
+
296
+ def setup
297
+ @tempfile = Tempfile.new("logger")
298
+ @tempfile.close
299
+ @filename = @tempfile.path
300
+ File.unlink(@filename)
301
+ end
302
+
303
+ def teardown
304
+ @tempfile.close(true)
305
+ end
306
+
307
+ def d(log, opt = {})
308
+ Logger::LogDevice.new(log, **opt)
309
+ end
310
+
311
+ def test_initialize
312
+ logdev = d(STDERR)
313
+ assert_equal(STDERR, logdev.dev)
314
+ assert_nil(logdev.filename)
315
+ assert_raises(TypeError) do
316
+ d(nil)
317
+ end
318
+ #
319
+ logdev = d(@filename)
320
+ begin
321
+ assert(File.exist?(@filename))
322
+ assert(logdev.dev.sync)
323
+ assert_equal(@filename, logdev.filename)
324
+ logdev.write('hello')
325
+ ensure
326
+ logdev.close
327
+ end
328
+ # create logfile whitch is already exist.
329
+ logdev = d(@filename)
330
+ begin
331
+ logdev.write('world')
332
+ logfile = File.read(@filename)
333
+ assert_equal(2, logfile.split(/\n/).size)
334
+ assert_match(/^helloworld$/, logfile)
335
+ ensure
336
+ logdev.close
337
+ end
338
+ end
339
+
340
+ def test_write
341
+ r, w = IO.pipe
342
+ logdev = d(w)
343
+ logdev.write("msg2\n\n")
344
+ _, = IO.select([r], nil, nil, 0.1)
345
+ w.close
346
+ msg = r.read
347
+ r.close
348
+ assert_equal("msg2\n\n", msg)
349
+ #
350
+ logdev = d(LogExcnRaiser.new)
351
+ class << (stderr = '')
352
+ alias write <<
353
+ end
354
+ $stderr, stderr = stderr, $stderr
355
+ begin
356
+ logdev.write('hello')
357
+ ensure
358
+ logdev.close
359
+ $stderr, stderr = stderr, $stderr
360
+ end
361
+ assert_equal "log writing failed. disk is full\n", stderr
362
+ end
363
+
364
+ def test_close
365
+ r, w = IO.pipe
366
+ logdev = d(w)
367
+ logdev.write("msg2\n\n")
368
+ _, = IO.select([r], nil, nil, 0.1)
369
+ assert(!w.closed?)
370
+ logdev.close
371
+ assert(w.closed?)
372
+ r.close
373
+ end
374
+
375
+ def test_shifting_size
376
+ skip("shifting age doesn't work because rotation doesn't work")
377
+ tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_1.log'])
378
+ logfile = tmpfile.path
379
+ logfile0 = logfile + '.0'
380
+ logfile1 = logfile + '.1'
381
+ logfile2 = logfile + '.2'
382
+ logfile3 = logfile + '.3'
383
+ tmpfile.close(true)
384
+ File.unlink(logfile) if File.exist?(logfile)
385
+ File.unlink(logfile0) if File.exist?(logfile0)
386
+ File.unlink(logfile1) if File.exist?(logfile1)
387
+ File.unlink(logfile2) if File.exist?(logfile2)
388
+ logger = Logger.new(logfile, 4, 100)
389
+ logger.error("0" * 15)
390
+ assert(File.exist?(logfile))
391
+ assert(!File.exist?(logfile0))
392
+ logger.error("0" * 15)
393
+ assert(File.exist?(logfile0))
394
+ assert(!File.exist?(logfile1))
395
+ logger.error("0" * 15)
396
+ assert(File.exist?(logfile1))
397
+ assert(!File.exist?(logfile2))
398
+ logger.error("0" * 15)
399
+ assert(File.exist?(logfile2))
400
+ assert(!File.exist?(logfile3))
401
+ logger.error("0" * 15)
402
+ assert(!File.exist?(logfile3))
403
+ logger.error("0" * 15)
404
+ assert(!File.exist?(logfile3))
405
+ logger.close
406
+ File.unlink(logfile)
407
+ File.unlink(logfile0)
408
+ File.unlink(logfile1)
409
+ File.unlink(logfile2)
410
+
411
+ tmpfile = Tempfile.new([File.basename(__FILE__, '.*'), '_2.log'])
412
+ logfile = tmpfile.path
413
+ logfile0 = logfile + '.0'
414
+ logfile1 = logfile + '.1'
415
+ logfile2 = logfile + '.2'
416
+ logfile3 = logfile + '.3'
417
+ tmpfile.close(true)
418
+ logger = Logger.new(logfile, 4, 150)
419
+ logger.error("0" * 15)
420
+ assert(File.exist?(logfile))
421
+ assert(!File.exist?(logfile0))
422
+ logger.error("0" * 15)
423
+ assert(!File.exist?(logfile0))
424
+ logger.error("0" * 15)
425
+ assert(File.exist?(logfile0))
426
+ assert(!File.exist?(logfile1))
427
+ logger.error("0" * 15)
428
+ assert(!File.exist?(logfile1))
429
+ logger.error("0" * 15)
430
+ assert(File.exist?(logfile1))
431
+ assert(!File.exist?(logfile2))
432
+ logger.error("0" * 15)
433
+ assert(!File.exist?(logfile2))
434
+ logger.error("0" * 15)
435
+ assert(File.exist?(logfile2))
436
+ assert(!File.exist?(logfile3))
437
+ logger.error("0" * 15)
438
+ assert(!File.exist?(logfile3))
439
+ logger.error("0" * 15)
440
+ assert(!File.exist?(logfile3))
441
+ logger.error("0" * 15)
442
+ assert(!File.exist?(logfile3))
443
+ logger.close
444
+ File.unlink(logfile)
445
+ File.unlink(logfile0)
446
+ File.unlink(logfile1)
447
+ File.unlink(logfile2)
448
+ end
449
+
450
+ def test_shifting_age_variants
451
+ skip("shifting age doesn't work because rotation doesn't work")
452
+ logger = Logger.new(@filename, 'daily')
453
+ logger.info('daily')
454
+ logger.close
455
+ logger = Logger.new(@filename, 'weekly')
456
+ logger.info('weekly')
457
+ logger.close
458
+ logger = Logger.new(@filename, 'monthly')
459
+ logger.info('monthly')
460
+ logger.close
461
+ end
462
+
463
+ def test_shifting_age
464
+ skip("shifting age doesn't work because rotation doesn't work")
465
+ # shift_age other than 'daily', 'weekly', and 'monthly' means 'everytime'
466
+ yyyymmdd = Time.now.strftime("%Y%m%d")
467
+ filename1 = @filename + ".#{yyyymmdd}"
468
+ filename2 = @filename + ".#{yyyymmdd}.1"
469
+ filename3 = @filename + ".#{yyyymmdd}.2"
470
+ begin
471
+ logger = Logger.new(@filename, 'now')
472
+ assert(File.exist?(@filename))
473
+ assert(!File.exist?(filename1))
474
+ assert(!File.exist?(filename2))
475
+ assert(!File.exist?(filename3))
476
+ logger.info("0" * 15)
477
+ assert(File.exist?(@filename))
478
+ assert(File.exist?(filename1))
479
+ assert(!File.exist?(filename2))
480
+ assert(!File.exist?(filename3))
481
+ logger.warn("0" * 15)
482
+ assert(File.exist?(@filename))
483
+ assert(File.exist?(filename1))
484
+ assert(File.exist?(filename2))
485
+ assert(!File.exist?(filename3))
486
+ logger.error("0" * 15)
487
+ assert(File.exist?(@filename))
488
+ assert(File.exist?(filename1))
489
+ assert(File.exist?(filename2))
490
+ assert(File.exist?(filename3))
491
+ ensure
492
+ logger.close if logger
493
+ [filename1, filename2, filename3].each do |filename|
494
+ File.unlink(filename) if File.exist?(filename)
495
+ end
496
+ end
497
+ end
498
+ end
499
+
500
+
501
+ class TestLoggerApplication < Minitest::Test
502
+ def setup
503
+ @app = Logger::Application.new('appname')
504
+ @tempfile = Tempfile.new("logger")
505
+ @tempfile.close
506
+ @filename = @tempfile.path
507
+ File.unlink(@filename)
508
+ end
509
+
510
+ def teardown
511
+ @tempfile.close(true)
512
+ end
513
+
514
+ def test_initialize
515
+ app = Logger::Application.new('appname')
516
+ assert_equal('appname', app.appname)
517
+ end
518
+
519
+ def test_start
520
+ @app.set_log(@filename)
521
+ begin
522
+ @app.level = Logger::UNKNOWN
523
+ @app.start # logs FATAL log
524
+ assert_equal(1, File.read(@filename).split(/\n/).size)
525
+ ensure
526
+ @app.logger.close
527
+ end
528
+ end
529
+
530
+ def test_logger
531
+ @app.level = Logger::WARN
532
+ @app.set_log(@filename)
533
+ begin
534
+ assert_equal(Logger::WARN, @app.logger.level)
535
+ ensure
536
+ @app.logger.close
537
+ end
538
+ @app.logger = logger = Logger.new(STDOUT)
539
+ assert_equal(logger, @app.logger)
540
+ assert_equal(Logger::WARN, @app.logger.level)
541
+ @app.log = @filename
542
+ begin
543
+ assert(logger != @app.logger)
544
+ assert_equal(Logger::WARN, @app.logger.level)
545
+ ensure
546
+ @app.logger.close
547
+ end
548
+ end
549
+ end
550
+