logging 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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