indy 0.2.0 → 0.3.0
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.
- 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
|