logging 0.9.0 → 0.9.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,4 +1,12 @@
1
- == 0.9.0 / 2008-07-
1
+ == 0.9.1 / 2008-08-14
2
+
3
+ 1 minor enhancement
4
+ - added a method to show the logging configuration
5
+ 2 bug fixes
6
+ - checking for sync method on the IO streams before calling
7
+ - fixed the internal logging levels
8
+
9
+ == 0.9.0 / 2008-07-16
2
10
 
3
11
  2 minor enhancement
4
12
  - Exceptions from appenders are captured and logged
data/README.txt CHANGED
@@ -86,7 +86,8 @@ class names.
86
86
 
87
87
  == REQUIREMENTS
88
88
 
89
- Logging does not depend on any other installed libraries or gems.
89
+ Logging requires the "lockfile" gem to run and the "flexmock" gem to run the
90
+ tests"
90
91
 
91
92
  == LICENSE
92
93
 
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- # $Id$
2
1
 
3
2
  load 'tasks/setup.rb'
4
3
 
@@ -17,7 +16,7 @@ PROJ.rdoc.dir = 'doc/rdoc'
17
16
  #PROJ.rdoc.remote_dir = 'rdoc'
18
17
  PROJ.rdoc.remote_dir = ''
19
18
  PROJ.version = Logging::VERSION
20
- PROJ.release_name = 'Monkeyful Chimptacular'
19
+ PROJ.release_name = %q{Green Eggs & Ham}
21
20
 
22
21
  PROJ.exclude << %w[^tags$ ^tasks/archive ^coverage]
23
22
  PROJ.rdoc.exclude << '^data'
@@ -10,12 +10,12 @@ unless defined? Logging
10
10
  module Logging
11
11
 
12
12
  # :stopdoc:
13
- VERSION = '0.9.0'
13
+ VERSION = '0.9.1'
14
14
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
15
15
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
16
16
  WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
17
17
  LEVELS = {}
18
- LNAMES = {}
18
+ LNAMES = []
19
19
  # :startdoc:
20
20
 
21
21
  class << self
@@ -192,7 +192,8 @@ module Logging
192
192
  end
193
193
  end
194
194
 
195
- longest = names.values.inject {|x,y| (x.length > y.length) ? x : y}
195
+ longest = names.inject {|x,y| (x.length > y.length) ? x : y}
196
+ longest = 'off' if longest.length < 3
196
197
  module_eval "MAX_LEVEL_LENGTH = #{longest.length}", __FILE__, __LINE__
197
198
 
198
199
  levels.keys
@@ -258,6 +259,77 @@ module Logging
258
259
  Dir.glob(search_me).sort.each {|rb| require rb}
259
260
  end
260
261
 
262
+ # call-seq:
263
+ # show_configuration( io = STDOUT, logger = 'root' )
264
+ #
265
+ # This method is used to show the configuration of the logging
266
+ # framework. The information is written to the given _io_ stream
267
+ # (defaulting to stdout). Normally the configuration is dumped starting
268
+ # with the root logger, but any logger name can be given.
269
+ #
270
+ # Each line contains information for a single logger and it's appenders.
271
+ # A child logger is indented two spaces from it's parent logger. Each
272
+ # line contains the logger name, level, additivity, and trace settings.
273
+ # Here is a brief example:
274
+ #
275
+ # root ........................... *info -T
276
+ # LoggerA ...................... info +A -T
277
+ # LoggerA::LoggerB ........... info +A -T
278
+ # LoggerA::LoggerC ........... *debug +A -T
279
+ # LoggerD ...................... *warn -A +T
280
+ #
281
+ # The lines can be deciphered as follows:
282
+ #
283
+ # 1) name - the name of the logger
284
+ #
285
+ # 2) level - the logger level; if it is preceeded by an
286
+ # asterisk then the level was explicitly set for that
287
+ # logger (as opposed to being inherited from the parent
288
+ # logger)
289
+ #
290
+ # 3) additivity - a "+A" shows the logger is additive, and log events
291
+ # will be passed up to the parent logger; "-A" shows
292
+ # that the logger will *not* pass log events up to the
293
+ # parent logger
294
+ #
295
+ # 4) trace - a "+T" shows that the logger will include trace
296
+ # information in generated log events (this includes
297
+ # filename and line number of the log message; "-T"
298
+ # shows that the logger does not include trace
299
+ # information in the log events)
300
+ #
301
+ # If a logger has appenders then they are listed, on per line,
302
+ # immediately below the logger. Appender lines are pre-pended with a
303
+ # single dash:
304
+ #
305
+ # root ........................... *info -T
306
+ # - <Appenders::Stdout:0x8b02a4 name="stdout">
307
+ # LoggerA ...................... info +A -T
308
+ # LoggerA::LoggerB ........... info +A -T
309
+ # LoggerA::LoggerC ........... *debug +A -T
310
+ # LoggerD ...................... *warn -A +T
311
+ # - <Appenders::Stderr:0x8b04ca name="stderr">
312
+ #
313
+ # We can see in this configuration dump that all the loggers will append
314
+ # to stdout via the Stdout appender configured in the root logger. All
315
+ # the loggers are additive, and so their generated log events will be
316
+ # passed up to the root logger.
317
+ #
318
+ # The exception in this configuration is LoggerD. Its additivity is set
319
+ # to false. It uses its own appender to send messages to stderr.
320
+ #
321
+ def show_configuration( io = STDOUT, logger = 'root', indent = 0 )
322
+ logger = ::Logging::Logger[logger] unless ::Logging::Logger === logger
323
+
324
+ logger._dump_configuration(io, indent)
325
+
326
+ indent += 2
327
+ children = ::Logging::Repository.instance.children(logger.name)
328
+ children.sort {|a,b| a.name <=> b.name}.each do |child|
329
+ ::Logging.show_configuration(io, child, indent)
330
+ end
331
+ end
332
+
261
333
  # :stopdoc:
262
334
  # Convert the given level into a connaconical form - a lowercase string.
263
335
  def levelify( level )
@@ -275,6 +347,11 @@ module Logging
275
347
  when 'off'; LEVELS.length
276
348
  else begin; Integer(l); rescue ArgumentError; LEVELS[l] end end
277
349
  end
350
+
351
+ # Internal logging method for use by the framework.
352
+ def log_internal( level = 1, &block )
353
+ ::Logging::Logger[::Logging].__send__(levelify(LNAMES[level]), &block)
354
+ end
278
355
  # :startdoc:
279
356
  end
280
357
  end # module Logging
@@ -70,8 +70,7 @@ class Appender
70
70
 
71
71
  end # class << self
72
72
 
73
- attr_reader :name, :layout, :level, :log
74
- private :log
73
+ attr_reader :name, :layout, :level
75
74
 
76
75
  # call-seq:
77
76
  # Appender.new( name )
@@ -82,9 +81,12 @@ class Appender
82
81
  # layout will be written to the logging destination when the Appender is
83
82
  # created.
84
83
  #
84
+ # Options:
85
+ #
86
+ # :layout => the layout to use when formatting log events
87
+ # :level => the level at which to log
88
+ #
85
89
  def initialize( name, opts = {} )
86
- @log = ::Logging::Logger[self]
87
-
88
90
  @name = name.to_s
89
91
  @closed = false
90
92
 
@@ -98,7 +100,7 @@ class Appender
98
100
  begin
99
101
  sync {write(header)}
100
102
  rescue StandardError => err
101
- log.error err
103
+ ::Logging.log_internal(-2) {err}
102
104
  end
103
105
  end
104
106
 
@@ -123,7 +125,7 @@ class Appender
123
125
  begin
124
126
  sync {write(event)}
125
127
  rescue StandardError => err
126
- log.error err
128
+ ::Logging.log_internal(-2) {err}
127
129
  end
128
130
  end
129
131
 
@@ -146,7 +148,7 @@ class Appender
146
148
  begin
147
149
  sync {write(str)}
148
150
  rescue StandardError => err
149
- log.error err
151
+ ::Logging.log_internal(-2) {err}
150
152
  end
151
153
  end
152
154
  self
@@ -225,7 +227,7 @@ class Appender
225
227
  begin
226
228
  sync {write(footer)}
227
229
  rescue StandardError => err
228
- log.error err
230
+ ::Logging.log_internal(-2) {err}
229
231
  end
230
232
  end
231
233
  end
@@ -253,6 +255,19 @@ class Appender
253
255
  self
254
256
  end
255
257
 
258
+ # call-seq:
259
+ # inspect => string
260
+ #
261
+ # Returns a string representation of the appender.
262
+ #
263
+ def inspect
264
+ "<%s:0x%x name=\"%s\">" % [
265
+ self.class.name.sub(%r/^Logging::/, ''),
266
+ self.object_id,
267
+ self.name
268
+ ]
269
+ end
270
+
256
271
 
257
272
  private
258
273
 
@@ -8,14 +8,24 @@ module Logging::Appenders
8
8
  class Stdout < ::Logging::Appenders::IO
9
9
 
10
10
  # call-seq:
11
- # Stdout.new
11
+ # Stdout.new( name = 'stdout' )
12
12
  # Stdout.new( :layout => layout )
13
+ # Stdout.new( name = 'stdout', :level => 'info' )
13
14
  #
14
- # Creates a new Stdout Appender. The name 'stdout' will always be used
15
- # for this appender.
15
+ # Creates a new Stdout Appender. The name 'stdout' will be used unless
16
+ # another is given. Optionally, a layout can be given for the appender
17
+ # to use (otherwise a basic appender will be created) and a log level
18
+ # can be specified.
16
19
  #
17
- def initialize( name = nil, opts = {} )
18
- name ||= 'stdout'
20
+ # Options:
21
+ #
22
+ # :layout => the layout to use when formatting log events
23
+ # :level => the level at which to log
24
+ #
25
+ def initialize( *args )
26
+ opts = Hash === args.last ? args.pop : {}
27
+ name = args.empty? ? 'stdout' : args.shift
28
+
19
29
  super(name, STDOUT, opts)
20
30
  end
21
31
  end # class Stdout
@@ -25,14 +35,24 @@ module Logging::Appenders
25
35
  class Stderr < ::Logging::Appenders::IO
26
36
 
27
37
  # call-seq:
28
- # Stderr.new
38
+ # Stderr.new( name = 'stderr' )
29
39
  # Stderr.new( :layout => layout )
40
+ # Stderr.new( name = 'stderr', :level => 'warn' )
30
41
  #
31
- # Creates a new Stderr Appender. The name 'stderr' will always be used
32
- # for this appender.
42
+ # Creates a new Stderr Appender. The name 'stderr' will be used unless
43
+ # another is given. Optionally, a layout can be given for the appender
44
+ # to use (otherwise a basic appender will be created) and a log level
45
+ # can be specified.
33
46
  #
34
- def initialize( name = nil, opts = {} )
35
- name ||= 'stderr'
47
+ # Options:
48
+ #
49
+ # :layout => the layout to use when formatting log events
50
+ # :level => the level at which to log
51
+ #
52
+ def initialize( *args )
53
+ opts = Hash === args.last ? args.pop : {}
54
+ name = args.empty? ? 'stderr' : args.shift
55
+
36
56
  super(name, STDERR, opts)
37
57
  end
38
58
  end # class Stderr
@@ -117,8 +117,8 @@ class Email < ::Logging::Appender
117
117
  Net::SMTP.start(*@params) {|smtp| smtp.sendmail(rfc822msg, @from, @to)}
118
118
  rescue StandardError => err
119
119
  self.level = :off
120
- log.warn 'e-mail notifications have been disabled'
121
- log.error err
120
+ ::Logging.log_internal {'e-mail notifications have been disabled'}
121
+ ::Logging.log_internal(-2) {err}
122
122
  ensure
123
123
  @buff.clear
124
124
  end
@@ -34,7 +34,7 @@ module Logging::Appenders
34
34
  # make sure the growlnotify command can be called
35
35
  unless system('growlnotify -v 2>&1 > /dev/null')
36
36
  self.level = :off
37
- log.warn 'growl notifications have been disabled'
37
+ ::Logging.log_internal {'growl notifications have been disabled'}
38
38
  end
39
39
  end
40
40
 
@@ -183,7 +183,7 @@ module Logging::Appenders
183
183
  def call_growl( *args )
184
184
  unless system(@growl % args)
185
185
  self.level = :off
186
- log.warn 'growl notifications have been disabled'
186
+ ::Logging.log_internal {'growl notifications have been disabled'}
187
187
  end
188
188
  end
189
189
 
@@ -19,7 +19,7 @@ module Logging::Appenders
19
19
  end
20
20
 
21
21
  @io = io
22
- @io.sync = true
22
+ @io.sync = true if @io.respond_to?('sync') rescue nil
23
23
  super(name, opts)
24
24
  end
25
25
 
@@ -162,13 +162,10 @@ module Logging::Appenders
162
162
  if roll_required?(str)
163
163
  return roll unless @lockfile
164
164
 
165
- begin
166
- @lockfile.lock
165
+ @lockfile.lock {
167
166
  check_logfile
168
167
  roll if roll_required?
169
- ensure
170
- @lockfile.unlock
171
- end
168
+ }
172
169
  end
173
170
  end
174
171
 
@@ -432,6 +432,58 @@ module Logging
432
432
  @level = opts.getopt(:level)
433
433
  ::Logging::Logger.define_log_methods(self)
434
434
  end
435
+
436
+ # call-seq:
437
+ # _dump_configuration( io = STDOUT, indent = 0 )
438
+ #
439
+ # An internal method that is used to dump this logger's configuration to
440
+ # the given _io_ stream. The configuration includes the logger's name,
441
+ # level, additivity, and trace settings. The configured appenders are
442
+ # also printed to the _io_ stream.
443
+ #
444
+ def _dump_configuration( io = STDOUT, indent = 0 )
445
+ str, spacer, base = '', ' ', 50
446
+ indent_str = indent == 0 ? '' : ' ' * indent
447
+
448
+ str << indent_str
449
+ str << self.name.reduce(base - indent)
450
+ if (str.length + spacer.length) < base
451
+ str << spacer
452
+ str << '.' * (base - str.length)
453
+ end
454
+ io.print(str.ljust(base))
455
+ io.print(spacer)
456
+
457
+ level_str = @level.nil? ? '' : '*'
458
+ level_str << if level < ::Logging::LEVELS.length
459
+ ::Logging.levelify(::Logging::LNAMES[level])
460
+ else
461
+ 'off'
462
+ end
463
+ level_len = ::Logging::MAX_LEVEL_LENGTH + 1
464
+
465
+ io.print("%#{level_len}s" % level_str)
466
+ io.print(spacer)
467
+
468
+ if self.respond_to?(:additive)
469
+ io.print(additive ? '+A' : '-A')
470
+ else
471
+ io.print(' ')
472
+ end
473
+
474
+ io.print(spacer)
475
+ io.print(trace ? '+T' : '-T')
476
+ io.print("\n")
477
+
478
+ @appenders.each do |appender|
479
+ io.print(indent_str)
480
+ io.print('- ')
481
+ io.print(appender.inspect)
482
+ io.print("\n")
483
+ end
484
+
485
+ return io
486
+ end
435
487
  # :startdoc:
436
488
 
437
489
  end # class Logger
@@ -20,6 +20,7 @@ module Logging
20
20
  def initialize
21
21
  @h = {:root => ::Logging::RootLogger.new}
22
22
 
23
+ # configures the internal logger which is disabled by default
23
24
  logger = ::Logging::Logger.allocate
24
25
  logger._setup(
25
26
  to_key(::Logging),
@@ -97,9 +98,14 @@ module Logging
97
98
  #
98
99
  # Returns the parent logger for the logger identified by _key_ where
99
100
  # _key_ follows the same identification rules described in
100
- # +Repository#[]+. A parent is returned regardless of the
101
+ # <tt>Repository#[]</tt>. A parent is returned regardless of the
101
102
  # existence of the logger referenced by _key_.
102
103
  #
104
+ # A note about parents -
105
+ #
106
+ # If you have a class A::B::C, then the parent of C is B, and the parent
107
+ # of B is A. Parents are determined by namespace.
108
+ #
103
109
  def parent( key )
104
110
  return if 'root' == key.to_s
105
111
 
@@ -40,4 +40,33 @@ class Hash
40
40
  end
41
41
  end
42
42
 
43
+ class String
44
+
45
+ # call-seq:
46
+ # reduce( width, ellipses = '...' ) #=> string
47
+ #
48
+ # Reduce the size of the current string to the given _width_ by remove
49
+ # characters from the middle of ths tring and replacing them with
50
+ # _ellipses_. If the _width_ is greater than the length of the string, the
51
+ # string is returned unchanged. If the _width_ is less than the length of
52
+ # the _ellipses_, then the _ellipses_ are returned.
53
+ #
54
+ def reduce( width, ellipses = '...')
55
+ raise ArgumentError, "width cannot be negative: #{width}" if width < 0
56
+
57
+ return self if length <= width
58
+
59
+ remove = length - width + ellipses.length
60
+ return ellipses.dup if remove >= length
61
+
62
+ left_end = (length + 1 - remove) / 2
63
+ right_start = left_end + remove
64
+
65
+ left = self[0,left_end]
66
+ right = self[right_start,length-right_start]
67
+
68
+ left << ellipses << right
69
+ end
70
+ end
71
+
43
72
  # EOF
@@ -8,6 +8,8 @@ module TestAppenders
8
8
  include LoggingTestCase
9
9
 
10
10
  def test_initialize
11
+ ::Logging::Repository.instance
12
+
11
13
  appender = ::Logging::Appenders::Stdout.new
12
14
  assert_equal 'stdout', appender.name
13
15
  assert_same STDOUT, appender.instance_variable_get(:@io)
@@ -15,13 +17,27 @@ module TestAppenders
15
17
  appender.close
16
18
  assert_equal true, appender.closed?
17
19
  assert_equal false, STDOUT.closed?
20
+
21
+ appender = ::Logging::Appenders::Stdout.new('foo')
22
+ assert_equal 'foo', appender.name
23
+
24
+ appender = ::Logging::Appenders::Stdout.new(:level => :warn)
25
+ assert_equal 'stdout', appender.name
26
+ assert_equal 2, appender.level
27
+
28
+ appender = ::Logging::Appenders::Stdout.new('bar', :level => :error)
29
+ assert_equal 'bar', appender.name
30
+ assert_equal 3, appender.level
18
31
  end
19
32
 
20
33
  end # class TestStdout
21
34
 
22
35
  class TestStderr < Test::Unit::TestCase
36
+ include LoggingTestCase
23
37
 
24
38
  def test_initialize
39
+ ::Logging::Repository.instance
40
+
25
41
  appender = ::Logging::Appenders::Stderr.new
26
42
  assert_equal 'stderr', appender.name
27
43
  assert_same STDERR, appender.instance_variable_get(:@io)
@@ -29,6 +45,17 @@ module TestAppenders
29
45
  appender.close
30
46
  assert_equal true, appender.closed?
31
47
  assert_equal false, STDERR.closed?
48
+
49
+ appender = ::Logging::Appenders::Stderr.new('foo')
50
+ assert_equal 'foo', appender.name
51
+
52
+ appender = ::Logging::Appenders::Stderr.new(:level => :warn)
53
+ assert_equal 'stderr', appender.name
54
+ assert_equal 2, appender.level
55
+
56
+ appender = ::Logging::Appenders::Stderr.new('bar', :level => :error)
57
+ assert_equal 'bar', appender.name
58
+ assert_equal 3, appender.level
32
59
  end
33
60
 
34
61
  end # class TestStderr
@@ -38,10 +38,10 @@ module TestAppenders
38
38
  # setup an internal logger to capture error messages from the IO
39
39
  # appender
40
40
  log = StringIO.new
41
- Logging::Logger[Logging::Appenders::IO].add_appenders(
41
+ Logging::Logger[Logging].add_appenders(
42
42
  Logging::Appenders::IO.new('__internal_io', log)
43
43
  )
44
- Logging::Logger[Logging::Appenders::IO].level = 'all'
44
+ Logging::Logger[Logging].level = 'all'
45
45
 
46
46
 
47
47
  # close the string IO object so we get an error
@@ -51,7 +51,7 @@ module TestAppenders
51
51
  @appender.append event
52
52
 
53
53
  log.seek 0
54
- assert_equal "ERROR Logging::Appenders::IO : <IOError> not opened for writing", log.readline.strip
54
+ assert_equal "ERROR Logging : <IOError> not opened for writing", log.readline.strip
55
55
 
56
56
  assert_equal false, @appender.closed?
57
57
  assert_equal 5, @appender.level
@@ -92,17 +92,17 @@ module TestAppenders
92
92
  # setup an internal logger to capture error messages from the IO
93
93
  # appender
94
94
  log = StringIO.new
95
- Logging::Logger[Logging::Appenders::IO].add_appenders(
95
+ Logging::Logger[Logging].add_appenders(
96
96
  Logging::Appenders::IO.new('__internal_io', log)
97
97
  )
98
- Logging::Logger[Logging::Appenders::IO].level = 'all'
98
+ Logging::Logger[Logging].level = 'all'
99
99
 
100
100
  # close the string IO object so we get an error
101
101
  @sio.close
102
102
  @appender << 'oopsy'
103
103
 
104
104
  log.seek 0
105
- assert_equal "ERROR Logging::Appenders::IO : <IOError> not opened for writing", log.readline.strip
105
+ assert_equal "ERROR Logging : <IOError> not opened for writing", log.readline.strip
106
106
 
107
107
  # and the appender does not close itself
108
108
  assert_equal false, @appender.closed?
@@ -155,6 +155,11 @@ module TestLogging
155
155
  assert_equal 'test_appender', @appender.name
156
156
  end
157
157
 
158
+ def test_inspect
159
+ expected = "<Appender:0x%x name=\"test_appender\">" % @appender.object_id
160
+ assert_equal expected, @appender.inspect
161
+ end
162
+
158
163
  end # class TestAppender
159
164
  end # module TestLogging
160
165
 
@@ -638,6 +638,64 @@ module TestLogging
638
638
  assert_raise(ArgumentError) {log.trace = Object}
639
639
  end
640
640
 
641
+ def test_dump_configuration
642
+ log_a = ::Logging::Logger['A-logger']
643
+ log_b = ::Logging::Logger['A-logger::B-logger']
644
+ log_c = ::Logging::Logger['A-logger::B-logger::C-logger']
645
+ log_d = ::Logging::Logger['A-logger::D-logger']
646
+
647
+ sio = StringIO.new
648
+
649
+ log_a._dump_configuration( sio )
650
+ assert_equal(
651
+ "A-logger ........................................ debug +A -T\n", sio.to_s)
652
+
653
+ log_b._dump_configuration( sio )
654
+ assert_equal(
655
+ "A-logger::B-logger .............................. debug +A -T\n", sio.to_s)
656
+
657
+ log_c._dump_configuration( sio )
658
+ assert_equal(
659
+ "A-logger::B-logger::C-logger .................... debug +A -T\n", sio.to_s)
660
+
661
+ log_d._dump_configuration( sio )
662
+ assert_equal(
663
+ "A-logger::D-logger .............................. debug +A -T\n", sio.to_s)
664
+
665
+ log_b.level = :warn
666
+ log_b.trace = true
667
+ log_b._dump_configuration( sio )
668
+ assert_equal(
669
+ "A-logger::B-logger .............................. *warn +A +T\n", sio.to_s)
670
+
671
+ log_c.additive = false
672
+ log_c._dump_configuration( sio )
673
+ assert_equal(
674
+ "A-logger::B-logger::C-logger .................... warn -A -T\n", sio.to_s)
675
+
676
+ # with an indent specified
677
+ log_a._dump_configuration( sio, 4 )
678
+ assert_equal(
679
+ " A-logger .................................... debug +A -T\n", sio.to_s)
680
+
681
+ log_b._dump_configuration( sio, 8 )
682
+ assert_equal(
683
+ " A-logger::B-logger ...................... *warn +A +T\n", sio.to_s)
684
+
685
+ log_c._dump_configuration( sio, 10 )
686
+ assert_equal(
687
+ " A-logger::B-logger::C-logger .......... warn -A -T\n", sio.to_s)
688
+
689
+ log_d._dump_configuration( sio, 22 )
690
+ assert_equal(
691
+ " A-logger::D-logger ........ debug +A -T\n", sio.to_s)
692
+
693
+ log_c.level = 0
694
+ log_c._dump_configuration( sio, 26 )
695
+ assert_equal(
696
+ " A-logger::B...::C-logger *debug -A -T\n", sio.to_s)
697
+ end
698
+
641
699
  end # class TestLogger
642
700
 
643
701
  class SioAppender < ::Logging::Appenders::IO
@@ -661,6 +719,16 @@ module TestLogging
661
719
  end
662
720
 
663
721
  end # class SioAppender
722
+
664
723
  end # module TestLogging
665
724
 
725
+ class StringIO
726
+ def to_s
727
+ seek 0
728
+ str = read
729
+ seek 0
730
+ return str
731
+ end
732
+ end
733
+
666
734
  # EOF
@@ -20,10 +20,7 @@ module TestLogging
20
20
 
21
21
  ::Logging.configure 'data/logging.yaml'
22
22
 
23
- names = {
24
- 0 => 'DEB', 1 => 'INF', 2 => 'PRT',
25
- 3 => 'WRN', 4 => 'ERR', 5 => 'FAT'
26
- }
23
+ names = %w[DEB INF PRT WRN ERR FAT]
27
24
  assert_equal names, ::Logging::LNAMES
28
25
  assert_equal :inspect, ::Logging::OBJ_FORMAT
29
26
  assert_equal 3, ::Logging::Logger.root.level
@@ -54,7 +51,7 @@ module TestLogging
54
51
 
55
52
  # verify the loggers
56
53
  h = ::Logging::Repository.instance.instance_variable_get :@h
57
- assert_equal 6, h.length
54
+ assert_equal 4, h.length
58
55
 
59
56
  # mylogger
60
57
  mylogger = ::Logging::Logger['mylogger']
@@ -118,9 +115,8 @@ module TestLogging
118
115
  end
119
116
 
120
117
  def test_init_default
121
- empty = {}
122
- assert_equal empty, @levels
123
- assert_equal empty, @lnames
118
+ assert_equal({}, @levels)
119
+ assert_equal([], @lnames)
124
120
  assert_same false, ::Logging.const_defined?(:MAX_LEVEL_LENGTH)
125
121
 
126
122
  ::Logging::Repository.instance
@@ -143,9 +139,8 @@ module TestLogging
143
139
  end
144
140
 
145
141
  def test_init_special
146
- empty = {}
147
- assert_equal empty, @levels
148
- assert_equal empty, @lnames
142
+ assert_equal({}, @levels)
143
+ assert_equal([], @lnames)
149
144
  assert_same false, ::Logging.const_defined?(:MAX_LEVEL_LENGTH)
150
145
 
151
146
  assert_raise(ArgumentError) {::Logging.init(1, 2, 3, 4)}
@@ -170,16 +165,15 @@ module TestLogging
170
165
  end
171
166
 
172
167
  def test_init_all_off
173
- empty = {}
174
- assert_equal empty, @levels
175
- assert_equal empty, @lnames
168
+ assert_equal({}, @levels)
169
+ assert_equal([], @lnames)
176
170
  assert_same false, ::Logging.const_defined?(:MAX_LEVEL_LENGTH)
177
171
 
178
172
  ::Logging.init %w(a b all c off d)
179
173
 
180
174
  assert_equal 4, @levels.length
181
175
  assert_equal 4, @lnames.length
182
- assert_equal 1, ::Logging::MAX_LEVEL_LENGTH
176
+ assert_equal 3, ::Logging::MAX_LEVEL_LENGTH
183
177
 
184
178
  assert_equal 0, @levels['a']
185
179
  assert_equal 1, @levels['b']
@@ -5,7 +5,7 @@ module TestLogging
5
5
 
6
6
  class TestUtils < Test::Unit::TestCase
7
7
 
8
- def test_getopt
8
+ def test_hash_getopt
9
9
  opts = {
10
10
  :foo => 'foo_value',
11
11
  'bar' => 'bar_value',
@@ -41,6 +41,49 @@ module TestLogging
41
41
  assert_nil opts.getopt(:key, :as => Symbol)
42
42
  end
43
43
 
44
+ def test_string_reduce
45
+ str = 'this is the foobar string'
46
+ len = str.length
47
+
48
+ r = str.reduce(len + 1)
49
+ assert_same str, r
50
+
51
+ r = str.reduce(len)
52
+ assert_same str, r
53
+
54
+ r = str.reduce(len - 1)
55
+ assert_equal 'this is the...bar string', r
56
+
57
+ r = str.reduce(len - 10)
58
+ assert_equal 'this i...string', r
59
+
60
+ r = str.reduce(4)
61
+ assert_equal 't...', r
62
+
63
+ r = str.reduce(3)
64
+ assert_equal '...', r
65
+
66
+ r = str.reduce(0)
67
+ assert_equal '...', r
68
+
69
+ assert_raises(ArgumentError) { str.reduce(-1) }
70
+
71
+ r = str.reduce(len - 1, '##')
72
+ assert_equal 'this is the##obar string', r
73
+
74
+ r = str.reduce(len - 10, '##')
75
+ assert_equal 'this is##string', r
76
+
77
+ r = str.reduce(4, '##')
78
+ assert_equal 't##g', r
79
+
80
+ r = str.reduce(3, '##')
81
+ assert_equal 't##', r
82
+
83
+ r = str.reduce(0, '##')
84
+ assert_equal '##', r
85
+ end
86
+
44
87
  end # class TestUtils
45
88
  end # module TestLogging
46
89
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,20 +9,22 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-16 00:00:00 -06:00
12
+ date: 2008-08-14 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: flexmock
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
21
  - - ">="
21
22
  - !ruby/object:Gem::Version
22
- version: 0.8.0
23
+ version: 0.8.2
23
24
  version:
24
25
  - !ruby/object:Gem::Dependency
25
26
  name: lockfile
27
+ type: :runtime
26
28
  version_requirement:
27
29
  version_requirements: !ruby/object:Gem::Requirement
28
30
  requirements:
@@ -123,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
125
  requirements: []
124
126
 
125
127
  rubyforge_project: logging
126
- rubygems_version: 1.1.1
128
+ rubygems_version: 1.2.0
127
129
  signing_key:
128
130
  specification_version: 2
129
131
  summary: A flexible and extendable logging library for Ruby