sgeorgi-logging 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +262 -0
- data/README.rdoc +115 -0
- data/Rakefile +32 -0
- data/data/bad_logging_1.rb +13 -0
- data/data/bad_logging_2.rb +21 -0
- data/data/logging.rb +42 -0
- data/data/logging.yaml +63 -0
- data/data/simple_logging.rb +13 -0
- data/examples/appenders.rb +47 -0
- data/examples/classes.rb +41 -0
- data/examples/consolidation.rb +83 -0
- data/examples/fork.rb +37 -0
- data/examples/formatting.rb +51 -0
- data/examples/hierarchies.rb +73 -0
- data/examples/layouts.rb +48 -0
- data/examples/loggers.rb +29 -0
- data/examples/names.rb +43 -0
- data/examples/simple.rb +17 -0
- data/lib/logging.rb +528 -0
- data/lib/logging/appender.rb +260 -0
- data/lib/logging/appenders.rb +137 -0
- data/lib/logging/appenders/buffering.rb +178 -0
- data/lib/logging/appenders/console.rb +60 -0
- data/lib/logging/appenders/email.rb +75 -0
- data/lib/logging/appenders/file.rb +75 -0
- data/lib/logging/appenders/growl.rb +197 -0
- data/lib/logging/appenders/io.rb +69 -0
- data/lib/logging/appenders/rolling_file.rb +327 -0
- data/lib/logging/appenders/string_io.rb +68 -0
- data/lib/logging/appenders/syslog.rb +210 -0
- data/lib/logging/config/configurator.rb +188 -0
- data/lib/logging/config/yaml_configurator.rb +191 -0
- data/lib/logging/layout.rb +117 -0
- data/lib/logging/layouts.rb +47 -0
- data/lib/logging/layouts/basic.rb +32 -0
- data/lib/logging/layouts/parseable.rb +211 -0
- data/lib/logging/layouts/pattern.rb +311 -0
- data/lib/logging/log_event.rb +45 -0
- data/lib/logging/logger.rb +504 -0
- data/lib/logging/repository.rb +232 -0
- data/lib/logging/root_logger.rb +61 -0
- data/lib/logging/stats.rb +278 -0
- data/lib/logging/utils.rb +201 -0
- data/lib/spec/logging_helper.rb +34 -0
- data/test/appenders/test_buffered_io.rb +176 -0
- data/test/appenders/test_console.rb +66 -0
- data/test/appenders/test_email.rb +170 -0
- data/test/appenders/test_file.rb +95 -0
- data/test/appenders/test_growl.rb +127 -0
- data/test/appenders/test_io.rb +129 -0
- data/test/appenders/test_rolling_file.rb +209 -0
- data/test/appenders/test_syslog.rb +194 -0
- data/test/benchmark.rb +86 -0
- data/test/config/test_configurator.rb +70 -0
- data/test/config/test_yaml_configurator.rb +40 -0
- data/test/layouts/test_basic.rb +42 -0
- data/test/layouts/test_json.rb +112 -0
- data/test/layouts/test_pattern.rb +198 -0
- data/test/layouts/test_yaml.rb +121 -0
- data/test/setup.rb +43 -0
- data/test/test_appender.rb +152 -0
- data/test/test_consolidate.rb +46 -0
- data/test/test_layout.rb +110 -0
- data/test/test_log_event.rb +80 -0
- data/test/test_logger.rb +699 -0
- data/test/test_logging.rb +267 -0
- data/test/test_repository.rb +158 -0
- data/test/test_root_logger.rb +81 -0
- data/test/test_stats.rb +274 -0
- data/test/test_utils.rb +116 -0
- data/version.txt +1 -0
- metadata +227 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[.. setup])
|
3
|
+
|
4
|
+
module TestLogging
|
5
|
+
module TestLayouts
|
6
|
+
|
7
|
+
class TestYaml < Test::Unit::TestCase
|
8
|
+
include LoggingTestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
super
|
12
|
+
@layout = Logging.layouts.yaml({})
|
13
|
+
@levels = Logging::LEVELS
|
14
|
+
@date_fmt = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
|
15
|
+
Thread.current[:name] = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_format
|
19
|
+
h = {
|
20
|
+
'level' => 'INFO',
|
21
|
+
'logger' => 'ArrayLogger',
|
22
|
+
'message' => 'log message'
|
23
|
+
}
|
24
|
+
|
25
|
+
event = Logging::LogEvent.new('ArrayLogger', @levels['info'],
|
26
|
+
'log message', false)
|
27
|
+
assert_yaml_match h, @layout.format(event)
|
28
|
+
|
29
|
+
event.data = [1, 2, 3, 4]
|
30
|
+
h['message'] = "<Array> #{[1,2,3,4]}"
|
31
|
+
assert_yaml_match h, @layout.format(event)
|
32
|
+
|
33
|
+
event.level = @levels['debug']
|
34
|
+
event.data = 'and another message'
|
35
|
+
h['level'] = 'DEBUG'
|
36
|
+
h['message'] = 'and another message'
|
37
|
+
assert_yaml_match h, @layout.format(event)
|
38
|
+
|
39
|
+
event.logger = 'Test'
|
40
|
+
event.level = @levels['fatal']
|
41
|
+
event.data = Exception.new
|
42
|
+
h['level'] = 'FATAL'
|
43
|
+
h['logger'] = 'Test'
|
44
|
+
h['message'] = '<Exception> Exception'
|
45
|
+
assert_yaml_match h, @layout.format(event)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_items
|
49
|
+
assert_equal %w[timestamp level logger message], @layout.items
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_items_eq
|
53
|
+
event = Logging::LogEvent.new('TestLogger', @levels['info'],
|
54
|
+
['log message'], false)
|
55
|
+
|
56
|
+
@layout.items = %w[timestamp]
|
57
|
+
assert_equal %w[timestamp], @layout.items
|
58
|
+
assert_match %r/--- \ntimestamp: #@date_fmt\n/, @layout.format(event)
|
59
|
+
|
60
|
+
# 'foo' is not a recognized item
|
61
|
+
assert_raise(ArgumentError) {
|
62
|
+
@layout.items = %w[timestamp logger foo]
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_items_all
|
67
|
+
event = Logging::LogEvent.new('TestLogger', @levels['info'],
|
68
|
+
'log message', false)
|
69
|
+
event.file = 'test_file.rb'
|
70
|
+
event.line = 123
|
71
|
+
event.method = 'method_name'
|
72
|
+
|
73
|
+
@layout.items = %w[logger]
|
74
|
+
assert_equal %Q[--- \nlogger: TestLogger\n], @layout.format(event)
|
75
|
+
|
76
|
+
@layout.items = %w[file]
|
77
|
+
assert_equal %Q[--- \nfile: test_file.rb\n], @layout.format(event)
|
78
|
+
|
79
|
+
@layout.items = %w[level]
|
80
|
+
assert_equal %Q[--- \nlevel: INFO\n], @layout.format(event)
|
81
|
+
|
82
|
+
@layout.items = %w[line]
|
83
|
+
assert_equal %Q[--- \nline: 123\n], @layout.format(event)
|
84
|
+
|
85
|
+
@layout.items = %w[message]
|
86
|
+
assert_equal %Q[--- \nmessage: log message\n], @layout.format(event)
|
87
|
+
|
88
|
+
@layout.items = %w[method]
|
89
|
+
assert_equal %Q[--- \nmethod: method_name\n], @layout.format(event)
|
90
|
+
|
91
|
+
@layout.items = %w[pid]
|
92
|
+
assert_match %r/\A--- \npid: \d+\n\z/, @layout.format(event)
|
93
|
+
|
94
|
+
@layout.items = %w[millis]
|
95
|
+
assert_match %r/\A--- \nmillis: \d+\n\z/, @layout.format(event)
|
96
|
+
|
97
|
+
@layout.items = %w[thread_id]
|
98
|
+
assert_match %r/\A--- \nthread_id: -?\d+\n\z/, @layout.format(event)
|
99
|
+
|
100
|
+
@layout.items = %w[thread]
|
101
|
+
assert_equal %Q[--- \nthread: \n], @layout.format(event)
|
102
|
+
Thread.current[:name] = "Main"
|
103
|
+
assert_equal %Q[--- \nthread: Main\n], @layout.format(event)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def assert_yaml_match( expected, actual )
|
109
|
+
actual = YAML.load(actual)
|
110
|
+
|
111
|
+
assert_match %r/#@date_fmt/o, actual['timestamp']
|
112
|
+
assert_equal expected['level'], actual['level']
|
113
|
+
assert_equal expected['logger'], actual['logger']
|
114
|
+
assert_equal expected['message'], actual['message']
|
115
|
+
end
|
116
|
+
|
117
|
+
end # class TestYaml
|
118
|
+
end # module TestLayouts
|
119
|
+
end # module TestLogging
|
120
|
+
|
121
|
+
# EOF
|
data/test/setup.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
# Equivalent to a header guard in C/C++
|
3
|
+
# Used to prevent the class/module from being loaded more than once
|
4
|
+
unless defined? LOGGING_TEST_SETUP
|
5
|
+
LOGGING_TEST_SETUP = true
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'test/unit'
|
9
|
+
begin
|
10
|
+
require 'turn'
|
11
|
+
rescue LoadError; end
|
12
|
+
|
13
|
+
# This line is needed for Ruby 1.9 -- hashes throw a "KeyError" in 1.9
|
14
|
+
# whereas they throw an "IndexError" in 1.8
|
15
|
+
#
|
16
|
+
KeyError = IndexError if not defined? KeyError
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__), %w[.. lib logging])
|
19
|
+
|
20
|
+
|
21
|
+
module TestLogging
|
22
|
+
module LoggingTestCase
|
23
|
+
|
24
|
+
TMP = 'tmp'
|
25
|
+
|
26
|
+
def setup
|
27
|
+
super
|
28
|
+
Logging.reset
|
29
|
+
FileUtils.rm_rf TMP
|
30
|
+
FileUtils.mkdir TMP
|
31
|
+
end
|
32
|
+
|
33
|
+
def teardown
|
34
|
+
super
|
35
|
+
FileUtils.rm_rf TMP
|
36
|
+
end
|
37
|
+
|
38
|
+
end # module LoggingTestCase
|
39
|
+
end # module TestLogging
|
40
|
+
|
41
|
+
end # unless defined?
|
42
|
+
|
43
|
+
# EOF
|
@@ -0,0 +1,152 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[setup])
|
3
|
+
|
4
|
+
module TestLogging
|
5
|
+
|
6
|
+
class TestAppender < Test::Unit::TestCase
|
7
|
+
include LoggingTestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
|
12
|
+
::Logging.init
|
13
|
+
@levels = ::Logging::LEVELS
|
14
|
+
@event = ::Logging::LogEvent.new('logger', @levels['debug'],
|
15
|
+
'message', false)
|
16
|
+
@appender = ::Logging::Appender.new 'test_appender'
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_append
|
20
|
+
ary = []
|
21
|
+
@appender.instance_variable_set :@ary, ary
|
22
|
+
def @appender.write( event )
|
23
|
+
str = event.instance_of?(::Logging::LogEvent) ?
|
24
|
+
@layout.format(event) : event.to_s
|
25
|
+
@ary << str
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_nothing_raised {@appender.append @event}
|
29
|
+
assert_equal "DEBUG logger : message\n", ary.pop
|
30
|
+
|
31
|
+
@appender.level = :info
|
32
|
+
@appender.append @event
|
33
|
+
assert_nil ary.pop
|
34
|
+
|
35
|
+
@event.level = @levels['info']
|
36
|
+
@appender.append @event
|
37
|
+
assert_equal " INFO logger : message\n", ary.pop
|
38
|
+
|
39
|
+
@appender.close
|
40
|
+
assert_raise(RuntimeError) {@appender.append @event}
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_close
|
44
|
+
assert_equal false, @appender.closed?
|
45
|
+
|
46
|
+
@appender.close
|
47
|
+
assert_equal true, @appender.closed?
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_closed_eh
|
51
|
+
assert_equal false, @appender.closed?
|
52
|
+
|
53
|
+
@appender.close
|
54
|
+
assert_equal true, @appender.closed?
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_concat
|
58
|
+
ary = []
|
59
|
+
@appender.instance_variable_set :@ary, ary
|
60
|
+
def @appender.write( event )
|
61
|
+
str = event.instance_of?(::Logging::LogEvent) ?
|
62
|
+
@layout.format(event) : event.to_s
|
63
|
+
@ary << str
|
64
|
+
end
|
65
|
+
|
66
|
+
assert_nothing_raised {@appender << 'log message'}
|
67
|
+
assert_equal 'log message', ary.pop
|
68
|
+
|
69
|
+
@appender.level = :off
|
70
|
+
@appender << 'another log message'
|
71
|
+
assert_nil ary.pop
|
72
|
+
|
73
|
+
layout = @appender.layout
|
74
|
+
def layout.footer() 'this is the footer' end
|
75
|
+
|
76
|
+
@appender.close
|
77
|
+
assert_raise(RuntimeError) {@appender << 'log message'}
|
78
|
+
assert_equal 'this is the footer', ary.pop
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_flush
|
82
|
+
assert_same @appender, @appender.flush
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_initialize
|
86
|
+
assert_raise(TypeError) {::Logging::Appender.new 'test', :layout => []}
|
87
|
+
|
88
|
+
layout = ::Logging::Layouts::Basic.new
|
89
|
+
@appender = ::Logging::Appender.new 'test', :layout => layout
|
90
|
+
assert_same layout, @appender.instance_variable_get(:@layout)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_layout
|
94
|
+
assert_instance_of ::Logging::Layouts::Basic, @appender.layout
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_layout_eq
|
98
|
+
layout = ::Logging::Layouts::Basic.new
|
99
|
+
assert_not_equal layout, @appender.layout
|
100
|
+
|
101
|
+
assert_raise(TypeError) {@appender.layout = Object.new}
|
102
|
+
assert_raise(TypeError) {@appender.layout = 'not a layout'}
|
103
|
+
|
104
|
+
@appender.layout = layout
|
105
|
+
assert_same layout, @appender.layout
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_level
|
109
|
+
assert_equal 0, @appender.level
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_level_eq
|
113
|
+
assert_equal 0, @appender.level
|
114
|
+
|
115
|
+
assert_raise(ArgumentError) {@appender.level = -1}
|
116
|
+
assert_raise(ArgumentError) {@appender.level = 6}
|
117
|
+
assert_raise(ArgumentError) {@appender.level = Object}
|
118
|
+
assert_raise(ArgumentError) {@appender.level = 'bob'}
|
119
|
+
assert_raise(ArgumentError) {@appender.level = :wtf}
|
120
|
+
|
121
|
+
@appender.level = 'INFO'
|
122
|
+
assert_equal 1, @appender.level
|
123
|
+
|
124
|
+
@appender.level = :warn
|
125
|
+
assert_equal 2, @appender.level
|
126
|
+
|
127
|
+
@appender.level = 'error'
|
128
|
+
assert_equal 3, @appender.level
|
129
|
+
|
130
|
+
@appender.level = 4
|
131
|
+
assert_equal 4, @appender.level
|
132
|
+
|
133
|
+
@appender.level = 'off'
|
134
|
+
assert_equal 5, @appender.level
|
135
|
+
|
136
|
+
@appender.level = :all
|
137
|
+
assert_equal 0, @appender.level
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_name
|
141
|
+
assert_equal 'test_appender', @appender.name
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_inspect
|
145
|
+
expected = "<Appender:0x%x name=\"test_appender\">" % @appender.object_id
|
146
|
+
assert_equal expected, @appender.inspect
|
147
|
+
end
|
148
|
+
|
149
|
+
end # class TestAppender
|
150
|
+
end # module TestLogging
|
151
|
+
|
152
|
+
# EOF
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[setup])
|
3
|
+
|
4
|
+
module TestLogging
|
5
|
+
|
6
|
+
class TestConsolidate < Test::Unit::TestCase
|
7
|
+
include LoggingTestCase
|
8
|
+
|
9
|
+
def test_root
|
10
|
+
Logging.consolidate :root
|
11
|
+
root = Logging.logger.root
|
12
|
+
|
13
|
+
assert_same root, Logging.logger['Foo']
|
14
|
+
assert_same root, Logging.logger['Foo::Bar']
|
15
|
+
assert_same root, Logging.logger[Array]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_foo
|
19
|
+
Logging.consolidate 'Foo'
|
20
|
+
logger = Logging.logger['Foo::Bar::Baz']
|
21
|
+
|
22
|
+
assert_same Logging.logger['Foo'], logger
|
23
|
+
assert_not_same Logging.logger.root, logger
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_many
|
27
|
+
Logging.consolidate 'Foo', 'root', 'Foo::Bar::Baz'
|
28
|
+
|
29
|
+
root = Logging.logger.root
|
30
|
+
foo = Logging.logger['Foo']
|
31
|
+
fbb = Logging.logger['Foo::Bar::Baz']
|
32
|
+
|
33
|
+
assert_not_same root, foo
|
34
|
+
assert_not_same root, fbb
|
35
|
+
assert_not_same foo, fbb
|
36
|
+
|
37
|
+
assert_same root, Logging.logger[Hash]
|
38
|
+
assert_same root, Logging.logger['ActiveRecord::Base']
|
39
|
+
assert_same foo, Logging.logger['Foo::Bar']
|
40
|
+
assert_same fbb, Logging.logger['Foo::Bar::Baz::Buz']
|
41
|
+
end
|
42
|
+
|
43
|
+
end # class TestConsolidate
|
44
|
+
end # module TestLogging
|
45
|
+
|
46
|
+
# EOF
|
data/test/test_layout.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[setup])
|
3
|
+
|
4
|
+
module TestLogging
|
5
|
+
|
6
|
+
class TestLayout < Test::Unit::TestCase
|
7
|
+
include LoggingTestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
@layout = ::Logging::Layout.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_header
|
15
|
+
assert_equal '', @layout.header
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_initialize
|
19
|
+
obj_format = lambda {|l| l.instance_variable_get :@obj_format}
|
20
|
+
|
21
|
+
assert_equal :string, obj_format[@layout]
|
22
|
+
|
23
|
+
@layout = ::Logging::Layout.new 'format_as' => 'blah'
|
24
|
+
assert_equal :string, obj_format[@layout]
|
25
|
+
|
26
|
+
@layout = ::Logging::Layout.new :format_as => :inspect
|
27
|
+
assert_equal :inspect, obj_format[@layout]
|
28
|
+
|
29
|
+
@layout = ::Logging::Layout.new 'format_as' => :yaml
|
30
|
+
assert_equal :yaml, obj_format[@layout]
|
31
|
+
|
32
|
+
@layout = ::Logging::Layout.new
|
33
|
+
assert_equal :string, obj_format[@layout]
|
34
|
+
|
35
|
+
::Logging.format_as :yaml
|
36
|
+
@layout = ::Logging::Layout.new
|
37
|
+
assert_equal :yaml, obj_format[@layout]
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_footer
|
41
|
+
assert_equal '', @layout.footer
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_format
|
45
|
+
assert_nil @layout.format(::Logging::LogEvent.new('a','b','c',false))
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_format_obj
|
49
|
+
obj = 'test string'
|
50
|
+
r = @layout.format_obj obj
|
51
|
+
assert_same obj, r
|
52
|
+
|
53
|
+
obj = RuntimeError.new
|
54
|
+
r = @layout.format_obj obj
|
55
|
+
assert_equal '<RuntimeError> RuntimeError', r
|
56
|
+
|
57
|
+
obj = TypeError.new 'only works with Integers'
|
58
|
+
r = @layout.format_obj obj
|
59
|
+
assert_equal '<TypeError> only works with Integers', r
|
60
|
+
|
61
|
+
obj = Exception.new 'some exception'
|
62
|
+
obj.set_backtrace %w( this is the backtrace )
|
63
|
+
r = @layout.format_obj obj
|
64
|
+
obj = "<Exception> some exception\n\tthis\n\tis\n\tthe\n\tbacktrace"
|
65
|
+
assert_equal obj, r
|
66
|
+
|
67
|
+
obj = [1, 2, 3, 4]
|
68
|
+
r = @layout.format_obj obj
|
69
|
+
assert_equal "<Array> #{[1,2,3,4]}", r
|
70
|
+
|
71
|
+
obj = %w( one two three four )
|
72
|
+
@layout = ::Logging::Layout.new :format_as => :inspect
|
73
|
+
r = @layout.format_obj obj
|
74
|
+
assert_equal '<Array> ["one", "two", "three", "four"]', r
|
75
|
+
|
76
|
+
@layout = ::Logging::Layout.new :format_as => :yaml
|
77
|
+
r = @layout.format_obj obj
|
78
|
+
assert_equal "<Array> \n--- \n- one\n- two\n- three\n- four\n", r
|
79
|
+
|
80
|
+
r = @layout.format_obj Class
|
81
|
+
assert_equal "<Class> Class", r
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_format_obj_without_backtrace
|
85
|
+
@layout = ::Logging::Layout.new :backtrace => 'off'
|
86
|
+
|
87
|
+
obj = Exception.new 'some exception'
|
88
|
+
obj.set_backtrace %w( this is the backtrace )
|
89
|
+
r = @layout.format_obj obj
|
90
|
+
obj = "<Exception> some exception"
|
91
|
+
assert_equal obj, r
|
92
|
+
|
93
|
+
::Logging.backtrace :off
|
94
|
+
@layout = ::Logging::Layout.new
|
95
|
+
|
96
|
+
obj = ArgumentError.new 'wrong type of argument'
|
97
|
+
obj.set_backtrace %w( this is the backtrace )
|
98
|
+
r = @layout.format_obj obj
|
99
|
+
obj = "<ArgumentError> wrong type of argument"
|
100
|
+
assert_equal obj, r
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_initializer
|
104
|
+
assert_raise(ArgumentError) {::Logging::Layout.new :backtrace => 'foo'}
|
105
|
+
end
|
106
|
+
|
107
|
+
end # class TestLayout
|
108
|
+
end # module TestLogging
|
109
|
+
|
110
|
+
# EOF
|