indy 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.md +29 -22
- data/Rakefile +6 -12
- data/features/file.feature +1 -1
- data/features/step_definitions/find_by.steps.rb +0 -12
- data/features/step_definitions/log_file.steps.rb +4 -0
- data/features/step_definitions/support/env.rb +4 -0
- data/features/step_definitions/support/transforms.rb +0 -4
- data/indy.gemspec +3 -2
- data/lib/indy.rb +10 -7
- data/lib/indy/formats.rb +3 -0
- data/lib/indy/indy.rb +112 -189
- data/lib/indy/log_formats.rb +26 -4
- data/lib/indy/notes.txt +9 -0
- data/lib/indy/result_set.rb +8 -8
- data/lib/indy/source.rb +129 -0
- data/lib/scanf.rb +13 -0
- data/performance/profile_spec.rb +3 -3
- data/spec/helper.rb +5 -1
- data/spec/indy_spec.rb +128 -56
- data/spec/log_format_spec.rb +11 -11
- data/spec/multiline.log +10 -0
- data/spec/search_spec.rb +2 -25
- data/spec/source_spec.rb +85 -0
- data/spec/time_spec.rb +9 -4
- metadata +26 -70
- data/lib/indy/patterns.rb +0 -25
data/lib/indy/log_formats.rb
CHANGED
@@ -3,10 +3,9 @@ class Indy
|
|
3
3
|
#
|
4
4
|
# LogFormats defines the building blocks of Indy's built in log patterns.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# Indy::
|
8
|
-
# Indy::
|
9
|
-
# Indy::LOG4R_DEFAULT_PATTERN
|
6
|
+
# Indy::COMMON_LOG_FORMAT
|
7
|
+
# Indy::COMBINED_LOG_FORMAT
|
8
|
+
# Indy::LOG4R_DEFAULT_FORMAT
|
10
9
|
#
|
11
10
|
module LogFormats
|
12
11
|
|
@@ -36,4 +35,27 @@ class Indy
|
|
36
35
|
LOG4R_DEFAULT_FIELDS = [:level, :application, :message]
|
37
36
|
LOG4R_DEFAULT_REGEXP = /(?:\s+)?([A-Z]+) (\S+): (.*)$/
|
38
37
|
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Indy default log format
|
41
|
+
# e.g.:
|
42
|
+
# INFO 2000-09-07 MyApp - Entering APPLICATION.
|
43
|
+
#
|
44
|
+
DEFAULT_LOG_FORMAT = [LogFormats::DEFAULT_LOG_REGEXP, LogFormats::DEFAULT_LOG_FIELDS].flatten
|
45
|
+
|
46
|
+
#
|
47
|
+
# Uncustomized Log4r log format
|
48
|
+
#
|
49
|
+
LOG4R_DEFAULT_FORMAT = [LogFormats::LOG4R_DEFAULT_REGEXP, LogFormats::LOG4R_DEFAULT_FIELDS].flatten
|
50
|
+
|
51
|
+
#
|
52
|
+
# NCSA Common Log Format log format
|
53
|
+
#
|
54
|
+
COMMON_LOG_FORMAT = [LogFormats::COMMON_REGEXP, LogFormats::COMMON_FIELDS].flatten
|
55
|
+
|
56
|
+
#
|
57
|
+
# NCSA Combined Log Format log format
|
58
|
+
#
|
59
|
+
COMBINED_LOG_FORMAT = [LogFormats::COMBINED_REGEXP, LogFormats::COMBINED_FIELDS].flatten
|
60
|
+
|
39
61
|
end
|
data/lib/indy/notes.txt
ADDED
data/lib/indy/result_set.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#
|
2
|
-
# The current implementation extends an Array. However, as this
|
3
|
-
# has not been tested with a large data set it may need some new
|
4
|
-
# Enumerable object that is multi-threaded and performance friendly
|
5
|
-
#
|
6
|
-
class ResultSet < Array
|
7
|
-
|
8
|
-
end
|
1
|
+
#
|
2
|
+
# The current implementation extends an Array. However, as this
|
3
|
+
# has not been tested with a large data set it may need some new
|
4
|
+
# Enumerable object that is multi-threaded and performance friendly
|
5
|
+
#
|
6
|
+
class ResultSet < Array
|
7
|
+
|
8
|
+
end
|
data/lib/indy/source.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
class Indy
|
2
|
+
|
3
|
+
#
|
4
|
+
# A StringIO interface to the underlying log source.
|
5
|
+
#
|
6
|
+
class Source
|
7
|
+
|
8
|
+
# log source type. :cmd, :file, or :string
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
# log source connection string (cmd, filename or log data)
|
12
|
+
attr_reader :connection
|
13
|
+
|
14
|
+
# the StringIO object
|
15
|
+
attr_reader :io
|
16
|
+
|
17
|
+
# Exception raised when unable to open source
|
18
|
+
class Invalid < Exception; end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates a Source object.
|
22
|
+
#
|
23
|
+
# @param [String, Hash] param The source content String, filepath String, or :cmd => 'command' Hash
|
24
|
+
#
|
25
|
+
def initialize(param)
|
26
|
+
raise Indy::Source::Invalid if param.nil?
|
27
|
+
if param.respond_to?(:keys)
|
28
|
+
set_connection(:cmd, param[:cmd]) if param[:cmd]
|
29
|
+
set_connection(:file, param[:file]) if ( param[:file] and param[:file].size > 0 )
|
30
|
+
set_connection(:string, param[:string]) if param[:string]
|
31
|
+
elsif param.respond_to?(:read) and param.respond_to?(:rewind)
|
32
|
+
set_connection(:file, param)
|
33
|
+
elsif param.respond_to?(:to_s) and param.respond_to?(:length)
|
34
|
+
# fall back to source being the string passed in
|
35
|
+
set_connection(:string, param)
|
36
|
+
else
|
37
|
+
raise Indy::Source::Invalid
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# set the source connection type and connection_string
|
45
|
+
#
|
46
|
+
def set_connection(type, value)
|
47
|
+
@type = type
|
48
|
+
@connection = value
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Return a StringIO object to provide access to the underlying log source
|
53
|
+
#
|
54
|
+
def open(time_search=nil)
|
55
|
+
begin
|
56
|
+
|
57
|
+
case @type
|
58
|
+
when :cmd
|
59
|
+
@io = StringIO.new( exec_command(@connection).read )
|
60
|
+
raise "Failed to execute command (#{@connection})" if @io.nil?
|
61
|
+
|
62
|
+
when :file
|
63
|
+
@connection.rewind
|
64
|
+
@io = StringIO.new(@connection.read)
|
65
|
+
raise "Failed to open file: #{@connection}" if @io.nil?
|
66
|
+
|
67
|
+
when :string
|
68
|
+
@io = StringIO.new( @connection )
|
69
|
+
|
70
|
+
else
|
71
|
+
raise RuntimeError, "Invalid log source type: #{@type.inspect}"
|
72
|
+
end
|
73
|
+
|
74
|
+
rescue Exception => e
|
75
|
+
raise Indy::Source::Invalid, "Unable to open log source. (#{e.message})"
|
76
|
+
end
|
77
|
+
|
78
|
+
# scope_by_time(source_io) if time_search
|
79
|
+
|
80
|
+
@io
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Execute the source's connection string, returning an IO object
|
85
|
+
#
|
86
|
+
# @param [String] command_string string of command that will return log contents
|
87
|
+
#
|
88
|
+
def exec_command(command_string)
|
89
|
+
begin
|
90
|
+
io = IO.popen(command_string)
|
91
|
+
return nil if io.eof?
|
92
|
+
rescue
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
io
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
#
|
101
|
+
# the number of lines in the source
|
102
|
+
#
|
103
|
+
def num_lines
|
104
|
+
load_data unless @num_lines
|
105
|
+
@num_lines
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# array of log lines from source
|
110
|
+
#
|
111
|
+
def lines
|
112
|
+
load_data unless @lines
|
113
|
+
@lines
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# read source data and populate instance variables
|
118
|
+
#
|
119
|
+
# TODO: hmmm... not called when Source#open is called directly, but #load_data would call open again. :(
|
120
|
+
#
|
121
|
+
def load_data
|
122
|
+
self.open
|
123
|
+
@lines = @io.readlines
|
124
|
+
@io.rewind
|
125
|
+
@num_lines = @lines.count
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
data/lib/scanf.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
require 'scanf'
|
3
|
+
|
4
|
+
f = File.open('spec/multiline.log')
|
5
|
+
|
6
|
+
first_capture_regexp = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
|
7
|
+
|
8
|
+
full_regexp = "^(#{first_capture_regexp})\\s+([A-Z]+)\\s+(.+?)(?=^#{first_capture_regexp}|\\z)"
|
9
|
+
|
10
|
+
f.read.scan(/#{full_regexp}/m) do |entry|
|
11
|
+
puts "Entry::::\n#{entry}"
|
12
|
+
end
|
13
|
+
|
data/performance/profile_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe "Search Performance" do
|
|
4
4
|
|
5
5
|
context "with a 10000 line log file" do
|
6
6
|
|
7
|
-
large_file = "#{File.dirname(__FILE__)}/large.log"
|
7
|
+
large_file = File.open("#{File.dirname(__FILE__)}/large.log", 'r')
|
8
8
|
before(:all) do
|
9
9
|
@indy = Indy.search(large_file).with([/^\[([^\|]+)\|([^\]]+)\] (.*)$/,:severity, :time, :message])
|
10
10
|
end
|
@@ -33,11 +33,11 @@ describe "Search Performance" do
|
|
33
33
|
|
34
34
|
context "with a 10000 line log file" do
|
35
35
|
|
36
|
-
large_file = "#{File.dirname(__FILE__)}/large.log"
|
36
|
+
large_file = File.open("#{File.dirname(__FILE__)}/large.log", 'r')
|
37
37
|
before(:all) do
|
38
38
|
@indy = Indy.new(
|
39
39
|
:source => large_file,
|
40
|
-
:
|
40
|
+
:log_format => [/^\[([^\|]+)\|([^\]]+)\] (.*)$/,:severity, :time, :message],
|
41
41
|
:time_format => '%d-%m-%Y %H:%M:%S')
|
42
42
|
end
|
43
43
|
|
data/spec/helper.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start if ENV["COVERAGE"]
|
3
|
+
# SimpleCov.root("#{File.dirname(__FILE__)}/../..")
|
4
|
+
|
1
5
|
require File.expand_path("#{File.dirname(__FILE__)}/../lib/indy") unless
|
2
6
|
$:.include? File.expand_path("#{File.dirname(__FILE__)}/../lib/indy")
|
3
7
|
|
4
|
-
require 'rspec'
|
8
|
+
# require 'rspec'
|
data/spec/indy_spec.rb
CHANGED
@@ -6,30 +6,31 @@ describe 'Indy' do
|
|
6
6
|
|
7
7
|
# http://log4r.rubyforge.org/rdoc/Log4r/rdoc/patternformatter.html
|
8
8
|
it "should accept a log4r pattern string without error" do
|
9
|
-
|
9
|
+
Indy.new(:log_format => ["(%d) (%i) (%c) - (%m)", :time, :info, :class, :message]).class.should == Indy
|
10
10
|
end
|
11
11
|
|
12
12
|
# http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
|
13
13
|
it "should accept a log4j pattern string without error" do
|
14
|
-
|
14
|
+
Indy.new(:log_format => ["%d [%M] %p %C{1} - %m", :time, :info, :class, :message]).class.should == Indy
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should not raise error with non-conforming data" do
|
18
|
-
@indy = Indy.new(:source => " \nfoobar\n\n baz", :
|
19
|
-
|
18
|
+
@indy = Indy.new(:source => " \nfoobar\n\n baz", :log_format => ['([^\s]+) (\w+)', :time, :message])
|
19
|
+
@indy.for(:all).class.should == Array
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should accept time_format parameter" do
|
23
|
-
@indy = Indy.new(:time_format => '%d-%m-%Y', :source => "1-13-2000 yes", :
|
24
|
-
|
23
|
+
@indy = Indy.new(:time_format => '%d-%m-%Y', :source => "1-13-2000 yes", :log_format => ['^([^\s]+) (\w+)$', :time, :message])
|
24
|
+
@indy.for(:all).class.should == Array
|
25
25
|
@indy.instance_variable_get(:@time_format).should == '%d-%m-%Y'
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should accept an initialization hash passed to #search" do
|
29
29
|
hash = {:time_format => '%d-%m-%Y',
|
30
30
|
:source => "1-13-2000 yes",
|
31
|
-
:
|
32
|
-
|
31
|
+
:log_format => ['^([^\s]+) (\w+)$', :time, :message]}
|
32
|
+
@indy = Indy.search(hash)
|
33
|
+
@indy.class.should == Indy
|
33
34
|
@indy.for(:all).length.should == 1
|
34
35
|
end
|
35
36
|
|
@@ -39,7 +40,7 @@ describe 'Indy' do
|
|
39
40
|
context 'instance' do
|
40
41
|
|
41
42
|
before(:all) do
|
42
|
-
@indy = Indy.new(:source => '1/2/2002 string', :
|
43
|
+
@indy = Indy.new(:source => '1/2/2002 string', :log_format => ['([^\s]+) (\w+)', :time, :message])
|
43
44
|
end
|
44
45
|
|
45
46
|
context "method" do
|
@@ -60,16 +61,18 @@ describe 'Indy' do
|
|
60
61
|
|
61
62
|
context ':search' do
|
62
63
|
|
64
|
+
let(:log_file) { "#{File.dirname(__FILE__)}/data.log" }
|
65
|
+
|
63
66
|
it "should be a class method" do
|
64
67
|
Indy.should respond_to(:search)
|
65
68
|
end
|
66
69
|
|
67
70
|
it "should accept a string parameter" do
|
68
|
-
|
71
|
+
Indy.search("String Log").class.should == Indy
|
69
72
|
end
|
70
73
|
|
71
74
|
it "should accept a :cmd symbol and a command string parameter" do
|
72
|
-
|
75
|
+
Indy.search(:cmd =>"ls").class.should == Indy
|
73
76
|
end
|
74
77
|
|
75
78
|
it "should return an instance of Indy" do
|
@@ -77,63 +80,46 @@ describe 'Indy' do
|
|
77
80
|
Indy.search(:cmd => "ls").should be_kind_of(Indy)
|
78
81
|
end
|
79
82
|
|
83
|
+
it "should return an instance of Indy" do
|
84
|
+
Indy.search(:source => {:cmd => 'ls'}, :log_format => Indy::DEFAULT_LOG_FORMAT).class.should == Indy
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
it "should create an instance of Indy::Source" do
|
89
|
+
Indy.search("source string").instance_variable_get(:@source).should be_kind_of(Indy::Source)
|
90
|
+
end
|
91
|
+
|
80
92
|
it "the instance should have the source specified" do
|
81
93
|
Indy.search("source string").source.should_not be_nil
|
82
94
|
Indy.search(:cmd => "ls").source.should_not be_nil
|
83
95
|
end
|
84
96
|
|
85
|
-
it "the instance should raise an exception when passed an invalid source
|
86
|
-
lambda{ Indy.search(
|
97
|
+
it "the instance should raise an exception when passed an invalid source" do
|
98
|
+
lambda{ Indy.search(nil) }.should raise_error Indy::Source::Invalid
|
87
99
|
end
|
88
100
|
|
89
101
|
it "the instance should raise an exception when passed an invalid source: nil" do
|
90
|
-
lambda{ Indy.search(nil) }.should raise_error Indy::
|
102
|
+
lambda{ Indy.search(nil) }.should raise_error Indy::Source::Invalid
|
91
103
|
end
|
92
104
|
|
93
105
|
it "the instance should raise an exception when the arity is incorrect" do
|
94
|
-
lambda{ Indy.search( ) }.should raise_error Indy::
|
106
|
+
lambda{ Indy.search( ) }.should raise_error Indy::Source::Invalid
|
95
107
|
end
|
96
108
|
|
97
|
-
context "
|
98
|
-
|
99
|
-
let(:log_file) { "#{File.dirname(__FILE__)}/data.log" }
|
100
|
-
|
101
|
-
context "treat it first like a file" do
|
102
|
-
|
103
|
-
it "should attempt to open the file" do
|
104
|
-
File.should_receive(:exist?).with("possible_file.ext").ordered
|
105
|
-
Indy.search("possible_file.ext")
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should not throw an error for a non-existent file" do
|
109
|
-
lambda { Indy.search("possible_file.ext") }.should_not raise_error
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should return an IO object when there is a file" do
|
113
|
-
File.should_receive(:exist?).with("file_exists.ext").and_return( true )
|
114
|
-
File.should_receive(:open).and_return(StringIO.new("2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION."))
|
115
|
-
Indy.search("file_exists.ext").for(:application => 'MyApp').length.should == 1
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should handle a real file" do
|
119
|
-
Indy.search(log_file).for(:application => 'MyApp').length.should == 2
|
120
|
-
end
|
109
|
+
context "treat it second like a string" do
|
121
110
|
|
111
|
+
it "should attempt to treat it as a string" do
|
112
|
+
string = "2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION."
|
113
|
+
string_io = StringIO.new(string)
|
114
|
+
StringIO.should_receive(:new).with(string).ordered.and_return(string_io)
|
115
|
+
Indy.search(string).for(:application => 'MyApp').length.should == 1
|
122
116
|
end
|
123
117
|
|
124
|
-
|
125
|
-
|
126
|
-
it "should attempt to treat it as a string" do
|
127
|
-
string = "2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION."
|
128
|
-
string_io = StringIO.new(string)
|
129
|
-
StringIO.should_receive(:new).with(string).ordered.and_return(string_io)
|
130
|
-
Indy.search(string).for(:application => 'MyApp').length.should == 1
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
118
|
+
end
|
134
119
|
|
120
|
+
context "with explicit source hash" do
|
135
121
|
|
136
|
-
context "
|
122
|
+
context ":cmd" do
|
137
123
|
|
138
124
|
it "should attempt open the command" do
|
139
125
|
IO.stub!(:popen).with('ssh user@system "bash --login -c \"cat /var/log/standard.log\" "')
|
@@ -142,7 +128,7 @@ describe 'Indy' do
|
|
142
128
|
|
143
129
|
it "should not throw an error for an invalid command" do
|
144
130
|
IO.stub!(:popen).with('an invalid command').and_return('')
|
145
|
-
|
131
|
+
Indy.search(:cmd => "an invalid command").class.should == Indy
|
146
132
|
end
|
147
133
|
|
148
134
|
it "should return an IO object upon a successful command" do
|
@@ -154,6 +140,32 @@ describe 'Indy' do
|
|
154
140
|
Indy.search(:cmd => "cat #{log_file}").for(:application => 'MyApp').length.should == 2
|
155
141
|
end
|
156
142
|
|
143
|
+
it "should return an IO object upon a successful command" do
|
144
|
+
IO.stub!(:popen).with("zzzzzzzzzzzz").and_return('Invalid command')
|
145
|
+
lambda{ Indy.search(:cmd => "zzzzzzzzzzzz").for(:all) }.should raise_error( Indy::Source::Invalid, /Unable to open log source/)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should raise error for an invalid command" do
|
149
|
+
lambda{ Indy.search(:cmd => "zzzzzzzzzzzz").for(:all) }.should raise_error( Indy::Source::Invalid, /Unable to open log source/)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
it ":file" do
|
155
|
+
require 'tempfile'
|
156
|
+
file = stub!(:size).and_return(1)
|
157
|
+
lambda{ Indy.search(:file => file) }
|
158
|
+
end
|
159
|
+
|
160
|
+
it ":string" do
|
161
|
+
string = "2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION."
|
162
|
+
string_io = StringIO.new(string)
|
163
|
+
StringIO.should_receive(:new).with(string).ordered.and_return(string_io)
|
164
|
+
Indy.search(:string => string).for(:application => 'MyApp').length.should == 1
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should raise error when invalid" do
|
168
|
+
lambda{ Indy.search(:foo => "a string").for(:all) }.should raise_error( Indy::Source::Invalid )
|
157
169
|
end
|
158
170
|
|
159
171
|
end
|
@@ -183,7 +195,7 @@ describe 'Indy' do
|
|
183
195
|
"2000-09-07 14:07:42 DEBUG MyApp - Initializing APPLICATION.",
|
184
196
|
"2000-09-07 14:07:43 INFO MyApp - Exiting APPLICATION with data:\nApplications data\nMore data\n\tlast Application data."].join("\n")
|
185
197
|
regexp = "^((#{Indy::LogFormats::DEFAULT_DATE_TIME})\\s+(#{Indy::LogFormats::DEFAULT_SEVERITY_PATTERN})\\s+(#{Indy::LogFormats::DEFAULT_APPLICATION})\\s+-\\s+(.*?)(?=#{Indy::LogFormats::DEFAULT_DATE_TIME}|\\z))"
|
186
|
-
@indy = Indy.new(:source => log, :
|
198
|
+
@indy = Indy.new(:source => log, :log_format => [regexp, :time,:severity,:application,:message], :multiline => true )
|
187
199
|
end
|
188
200
|
|
189
201
|
it "should find the first row" do
|
@@ -197,8 +209,51 @@ describe 'Indy' do
|
|
197
209
|
results.length.should == 5
|
198
210
|
end
|
199
211
|
|
212
|
+
it "should find using time based search" do
|
213
|
+
results = @indy.before(:time => '2000-09-07 14:07:42', :inclusive => false).for(:all)
|
214
|
+
results.length.should == 2
|
215
|
+
end
|
216
|
+
|
200
217
|
end
|
201
218
|
|
219
|
+
context "support for blocks" do
|
220
|
+
|
221
|
+
def log
|
222
|
+
[ "2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION.",
|
223
|
+
"2000-09-07 14:07:42 DEBUG MyApp - Initializing APPLICATION.",
|
224
|
+
"2000-09-07 14:07:43 INFO MyApp - Exiting APPLICATION."].join("\n")
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should allow a block with :for and yield on each line of the results using :all" do
|
228
|
+
actual_yield_count = 0
|
229
|
+
Indy.search(log).for(:all) do |result|
|
230
|
+
result.should be_kind_of(Struct::Line)
|
231
|
+
actual_yield_count = actual_yield_count + 1
|
232
|
+
end
|
233
|
+
actual_yield_count.should == 3
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should allow a block with :for and yield on each line of the results" do
|
237
|
+
actual_yield_count = 0
|
238
|
+
Indy.search(log).for(:severity => 'INFO') do |result|
|
239
|
+
result.should be_kind_of(Struct::Line)
|
240
|
+
actual_yield_count = actual_yield_count + 1
|
241
|
+
end
|
242
|
+
actual_yield_count.should == 2
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should allow a block with :like and yield on each line of the results" do
|
246
|
+
actual_yield_count = 0
|
247
|
+
Indy.search(log).like(:message => '\be\S+ing') do |result|
|
248
|
+
result.should be_kind_of(Struct::Line)
|
249
|
+
actual_yield_count = actual_yield_count + 1
|
250
|
+
end
|
251
|
+
actual_yield_count.should == 2
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
|
202
257
|
context "instance" do
|
203
258
|
|
204
259
|
before(:each) do
|
@@ -213,11 +268,11 @@ describe 'Indy' do
|
|
213
268
|
end
|
214
269
|
|
215
270
|
it "with() should accept the log4r default pattern const without error" do
|
216
|
-
|
271
|
+
@indy.with(Indy::LOG4R_DEFAULT_FORMAT).class.should == Indy
|
217
272
|
end
|
218
273
|
|
219
274
|
it "with() should accept :default without error" do
|
220
|
-
|
275
|
+
@indy.with(:default).class.should == Indy
|
221
276
|
end
|
222
277
|
|
223
278
|
it "with() should use default log pattern when passed :default" do
|
@@ -225,7 +280,7 @@ describe 'Indy' do
|
|
225
280
|
end
|
226
281
|
|
227
282
|
it "with() should accept no params without error" do
|
228
|
-
|
283
|
+
@indy.with().class.should == Indy
|
229
284
|
end
|
230
285
|
|
231
286
|
it "should return itself" do
|
@@ -238,7 +293,7 @@ describe 'Indy' do
|
|
238
293
|
end
|
239
294
|
|
240
295
|
it "#{method}() should accept a hash of search criteria" do
|
241
|
-
|
296
|
+
@indy.send(method,:severity => "INFO").class.should == Array
|
242
297
|
end
|
243
298
|
|
244
299
|
it "#{method}() should return a set of results" do
|
@@ -300,4 +355,21 @@ describe 'Indy' do
|
|
300
355
|
|
301
356
|
end
|
302
357
|
|
358
|
+
context 'source' do
|
359
|
+
before(:each) do
|
360
|
+
@indy = Indy.search(
|
361
|
+
[ "2000-09-07 14:07:41 INFO MyApp - Entering APPLICATION.",
|
362
|
+
"2000-09-07 14:08:41 INFO MyApp - Initializing APPLICATION.",
|
363
|
+
"2000-09-07 14:09:41 INFO MyApp - Configuring APPLICATION.",
|
364
|
+
"2000-09-07 14:10:50 INFO MyApp - Running APPLICATION.",
|
365
|
+
"2000-09-07 14:11:42 INFO MyApp - Exiting APPLICATION.",
|
366
|
+
"2000-09-07 14:12:15 INFO MyApp - Exiting APPLICATION."
|
367
|
+
].join("\n") )
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should know how many lines it contains" do
|
371
|
+
@indy.source.send(:num_lines).should == 6
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
303
375
|
end
|