logbox 0.2.10

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.
Files changed (46) hide show
  1. data/.bundle/config +3 -0
  2. data/.rvmrc +2 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +30 -0
  5. data/README +14 -0
  6. data/Rakefile +74 -0
  7. data/VERSION +1 -0
  8. data/bin/download_logs +20 -0
  9. data/bin/obsstats +39 -0
  10. data/bin/rotate +17 -0
  11. data/bin/viewobs +198 -0
  12. data/lib/logbox.rb +9 -0
  13. data/lib/logbox/ansi_colors.rb +28 -0
  14. data/lib/logbox/log_parser.rb +79 -0
  15. data/lib/logbox/mockup_log.rb +44 -0
  16. data/lib/logbox/observation.rb +162 -0
  17. data/lib/logbox/observation_compiler.rb +311 -0
  18. data/lib/logbox/observation_mover.rb +142 -0
  19. data/lib/logbox/stream_wrapper.rb +20 -0
  20. data/lib/logbox/stream_wrapper/gzip_multi_file.rb +90 -0
  21. data/lib/logbox/stream_wrapper/observation_filter.rb +113 -0
  22. data/lib/logbox/stream_wrapper/order_blob_splitter.rb +96 -0
  23. data/lib/setup_environment.rb +15 -0
  24. data/logbox.gemspec +110 -0
  25. data/test/bin_viewobs_test.rb +42 -0
  26. data/test/fixtures/aws_keys_yaml.txt +3 -0
  27. data/test/fixtures/double-obs.log +1 -0
  28. data/test/fixtures/error_line.log +1 -0
  29. data/test/fixtures/log-for-md5.log +1 -0
  30. data/test/fixtures/log0.log +0 -0
  31. data/test/fixtures/log1.log +1 -0
  32. data/test/fixtures/log1.log.gz +0 -0
  33. data/test/fixtures/log2.log +2 -0
  34. data/test/fixtures/log2.log.gz +0 -0
  35. data/test/fixtures/log_invalid_mixed_encoding.log +1 -0
  36. data/test/fixtures/observation_filter.log +5 -0
  37. data/test/fixtures/unquoted_ugliness.log +2 -0
  38. data/test/log_parser_test.rb +84 -0
  39. data/test/observation_compiler_test.rb +216 -0
  40. data/test/observation_mover_test.rb +135 -0
  41. data/test/observation_test.rb +114 -0
  42. data/test/stream_wrapper/gzip_multi_file_test.rb +147 -0
  43. data/test/stream_wrapper/observation_filter_test.rb +171 -0
  44. data/test/stream_wrapper/order_blob_splitter_test.rb +129 -0
  45. data/test/test_helper.rb +23 -0
  46. metadata +177 -0
@@ -0,0 +1,135 @@
1
+ require 'test_helper'
2
+ require 'observation_mover'
3
+
4
+ class ObservationMoverTest < Test::Unit::TestCase
5
+ context "ObservationMover" do
6
+ setup do
7
+ setup_log_dir
8
+ @mover = ObservationMover.new(log_file_path)
9
+ end
10
+
11
+ context "#rotate" do
12
+ context "with a non-empty log file" do
13
+ should "move the log file" do
14
+ @mover.rotate_current
15
+ rotated = rotated_path!
16
+ assert_not_nil rotated
17
+ assert_equal "loggy\n", File.read(rotated)
18
+ end
19
+ should "create a new, empty log file" do
20
+ @mover.rotate_current
21
+ assert File.exists?(log_file_path)
22
+ assert ! File.size?(log_file_path)
23
+ end
24
+ should "return true" do
25
+ assert @mover.rotate_current
26
+ end
27
+ end
28
+
29
+ context "with an empty log file" do
30
+ setup do
31
+ File.open(log_file_path, "w").close
32
+ end
33
+ should "not rename the log file" do
34
+ @mover.rotate_current
35
+ assert_equal [log_file_path], Dir[log_file_path('*')]
36
+ end
37
+ should "return false" do
38
+ assert ! @mover.rotate_current
39
+ end
40
+ end
41
+ end
42
+
43
+ context "#prepare_rotated_for_archiving" do
44
+ setup do
45
+ @mover.rotate_current
46
+ end
47
+ should "rename a rotated file" do
48
+ rotated = rotated_path!
49
+ @mover.prepare_rotated_for_archiving
50
+ assert ! File.exists?(rotated), "#{rotated} exists!"
51
+ end
52
+ should "compress a rotated file" do
53
+ rotated = rotated_path!
54
+ @mover.prepare_rotated_for_archiving
55
+ assert ! Dir[rotated + '*.gz'].empty?
56
+ end
57
+ end
58
+
59
+ context '#move_prepared_to_archive' do
60
+ context "with one file with a sha" do
61
+ setup do
62
+ @shad_name = log_file_path('observer-log-2010-01-05-21-13-11-1234567890abcdef.gz')
63
+ File.open(@shad_name, 'w') { |f| f << "logline\n" }
64
+ end
65
+ should "move that file to s3" do
66
+ @mover.expects(:store_file_on_s3).with(@shad_name).returns(true)
67
+ @mover.move_prepared_to_archive
68
+ end
69
+ should "delete the file if the move succeeds" do
70
+ @mover.expects(:store_file_on_s3).with(@shad_name).returns(true)
71
+ @mover.move_prepared_to_archive
72
+ assert ! File.exists?(@shad_name)
73
+ end
74
+ should "not delete the file if the move fails" do
75
+ @mover.expects(:store_file_on_s3).with(@shad_name).returns(false)
76
+ @mover.move_prepared_to_archive
77
+ assert File.exists?(@shad_name)
78
+ end
79
+ # should "talk to s3" do
80
+ # #WebMock.disable_net_connect!
81
+ # #WebMock.allow_net_connect!
82
+ # # stub_request(:put, %r'https://rwdata-logs.s3.amazonaws.com/.*').to_return do |request|
83
+ # # raise request.inspect
84
+ # # end
85
+ # # PUT https://rwdata-logs.s3.amazonaws.com/observer-log-2010-01-05-21-13-11-1234567890abcdef with body 'logline\n' with headers {'Accept'=>'*/*', 'Authorization'=>'AWS AAAAAAAAAA:4aYODn+8Yx7nIGnGf1coqWbEjWY=', 'Content-Length'=>'8', 'Content-Md5'=>'2ee0c171dab3e30627525ff535355eba', 'Content-Type'=>'', 'Date'=>'Thu, 'User-Agent'=>'', 22 Apr 2010 12:11:09 GMT'}
86
+ # @mover.move_prepared_to_archive
87
+ # end
88
+ # should "talk to s3" do
89
+ # WebMock.disable_net_connect!
90
+ # #WebMock.allow_net_connect!
91
+ # stub_request(:any, 'https://rwdata-logs.s3.amazonaws.com/?location').to_return(:status => [500, 'Internal Server knas'])
92
+ # @mover.s3.bucket_location('rwdata-logs')
93
+ # end
94
+ end
95
+ end
96
+
97
+ context '#aws_keys' do
98
+ should "read from a yaml file and return a list" do
99
+ file = fixture_file('aws_keys_yaml.txt')
100
+ key, secret = @mover.aws_keys(file)
101
+ assert_equal 'PUBLICKEY', key
102
+ assert_equal 'SECRET/KEY', secret
103
+ end
104
+ end
105
+
106
+ context '#md5' do
107
+ should "return a Base64-coded string" do
108
+ file = fixture_file('../fixtures/log-for-md5.log')
109
+ assert_equal 'X301NTIE25GbZGzT7u7cog==', @mover.md5(file)
110
+ end
111
+ end
112
+ end
113
+
114
+ def log_file_path (file_name = 'observer.log')
115
+ File.join(log_dir, file_name)
116
+ end
117
+
118
+ def log_dir
119
+ '/tmp/test/logs'
120
+ end
121
+
122
+ def setup_log_dir
123
+ FileUtils.mkdir_p log_dir
124
+ FileUtils.rm_r log_dir
125
+ FileUtils.mkdir log_dir
126
+ File.open(log_file_path, "w") { |f| f.puts "loggy" }
127
+ end
128
+
129
+ def rotated_path!
130
+ paths = Dir[log_file_path('*')] - [log_file_path]
131
+ assert_equal 1, paths.size, "Not exactly one path in #{paths.inspect}"
132
+ paths.first
133
+ end
134
+
135
+ end
@@ -0,0 +1,114 @@
1
+ require 'test_helper'
2
+ require 'observation'
3
+
4
+ class ObservationTest < Test::Unit::TestCase
5
+
6
+ context "The Observation when initialized" do
7
+
8
+ should "copy and rename attributes" do
9
+ log_attr = {:r => "referrer", :_item_id => "id", :_user1 => "custom", :ip => "ip"}
10
+ o = Observation.new(log_attr)
11
+ assert_equal 0, o.unknown_attributes.size
12
+ assert_equal 4, o.attributes.size
13
+ assert_equal "referrer", o.attributes[:referrer]
14
+ assert_equal "id", o.attributes[:item_id]
15
+ assert_equal "custom", o.attributes[:user1]
16
+ assert_equal "ip", o.attributes[:ip]
17
+ end
18
+
19
+ should "convert local urls to absolute urls" do
20
+ log_attr = {
21
+ :_url => "../index.html",
22
+ :_thumbnail => 'http://www.test.com/te st.html#debug',
23
+ :_image => 'http://www.test.com/te%st.html#debugon',
24
+ :_basket_url => 'http://www.test.com/te%20st.html#debugoff',
25
+ :u => 'http://www.test.com/f1/f2/index.html#debugon'
26
+ }
27
+ o = Observation.new(log_attr)
28
+ assert_equal 0, o.unknown_attributes.size
29
+ assert_equal 5, o.attributes.size
30
+ assert_equal "http://www.test.com/f1/index.html", o.attributes[:url]
31
+ assert_equal "http://www.test.com/te%20st.html", o.attributes[:thumbnail]
32
+ assert_equal "http://www.test.com/te%25st.html", o.attributes[:image]
33
+ assert_equal "http://www.test.com/te%20st.html", o.attributes[:basket_url]
34
+ end
35
+
36
+ should "convert not tamper with javascript urls" do
37
+ log_attr = {
38
+ :_basket_url => "javascript:alert('basket')",
39
+ :u => 'http://www.test.com/'
40
+ }
41
+ o = Observation.new(log_attr)
42
+ assert_equal "javascript:alert('basket')", o.attributes[:basket_url]
43
+ end
44
+
45
+ should "report error for invalid urls" do
46
+ log_attr = {
47
+ :_url => "../index.html",
48
+ :u => 'index.html#anchor2'
49
+ }
50
+ o = Observation.new(log_attr)
51
+ assert o.errors.include?(:url_error_on_url)
52
+ end
53
+
54
+ should "validate that status is ok (200)" do
55
+ log_attr = { :status => '200' }
56
+ o = Observation.new(log_attr)
57
+ assert !o.errors.include?(:status_not_ok)
58
+
59
+ log_attr = { :status => '404' }
60
+ o = Observation.new(log_attr)
61
+ assert o.errors.include?(:status_not_ok)
62
+ end
63
+
64
+ should "validate type attribute" do
65
+ log_attr = { :o => "view_item", :status => "200" }
66
+ o = Observation.new(log_attr)
67
+ assert !o.errors.include?(:unknown_type)
68
+ assert_equal :view_item, o.type
69
+
70
+ log_attr = { :o => "pick_item", :status => "200" }
71
+ o = Observation.new(log_attr)
72
+ assert !o.errors.include?(:unknown_type)
73
+ assert_equal :pick_item, o.type
74
+
75
+ log_attr = { :o => "visit_page", :status => "200" }
76
+ o = Observation.new(log_attr)
77
+ assert !o.errors.include?(:unknown_type)
78
+ assert_equal :visit_page, o.type
79
+
80
+ log_attr = { :o => "apa", :status => "200" }
81
+ o = Observation.new(log_attr)
82
+ assert o.errors.include?(:unknown_type)
83
+ assert_equal :unknown, o.type
84
+ end
85
+
86
+ should "validate required attributes" do
87
+ other_names = Observation::BASIC_ATTRIBUTES_NAMES.merge(Observation::OBSERVATION_ATTRIBUTES_NAMES)
88
+ [ :uid, :sid, :aid, :_item_id ].each do |name|
89
+ error_message = "missing_#{other_names[name]}".to_sym
90
+
91
+ log_attr = { :o => "view_item", :status => "200", name => "1000" }
92
+ o = Observation.new(log_attr)
93
+ assert !o.errors.include?(error_message)
94
+
95
+ log_attr = { :o => "view_item", :status => "200" }
96
+ o = Observation.new(log_attr)
97
+ assert o.errors.include?(error_message), "'#{error_message}' not found in #{o.errors.inspect}"
98
+ end
99
+ end
100
+
101
+ should "validate visit_page with shop, account and user id" do
102
+ assert Observation.new({ :o => "visit_page", :aid => "jshop", :sid => "shirtstore", :uid => "1234", :status => "200" }).valid?
103
+ assert !Observation.new({ :o => "visit_page", :sid => "shirtstore", :uid => "1234", :status => "200" }).valid?
104
+ assert !Observation.new({ :o => "visit_page", :aid => "jshop", :uid => "1234", :status => "200" }).valid?
105
+ assert !Observation.new({ :o => "visit_page", :aid => "jshop", :sid => "shirtstore", :status => "200" }).valid?
106
+ end
107
+ should "accept visit_page without item_id as a valid observation" do
108
+ assert Observation.new({ :o => "visit_page", :status => "200", :uid => '1' * 16, :sid => 'shoop', :aid => 'act'}).valid?
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+
@@ -0,0 +1,147 @@
1
+ require 'test_helper'
2
+ require 'stream_wrapper'
3
+ include StreamWrapper
4
+
5
+ class StreamWrapper::GzipMultiFileTest < Test::Unit::TestCase
6
+ context "A GzipMultiFile with one file" do
7
+ setup { @sw = GzipMultiFile.new fixture_file("log1.log") }
8
+
9
+ should "read from that file with #gets" do
10
+ assert_equal("Log 1 line 1\n", @sw.gets)
11
+ end
12
+
13
+ should "return nil from #gets after the last line" do
14
+ @sw.gets
15
+ assert_equal(nil, @sw.gets)
16
+ end
17
+ end
18
+
19
+ context "A GzipMultiFile with data to read" do
20
+ setup { @sw = GzipMultiFile.new fixture_file("log1.log") }
21
+
22
+ should "not be #eof?" do
23
+ assert ! @sw.eof?
24
+ end
25
+ end
26
+
27
+ context "A GzipMultiFile with no data left to read" do
28
+ setup do
29
+ @sw = GzipMultiFile.new fixture_file("log1.log")
30
+ @sw.gets
31
+ end
32
+
33
+ should "be #eof?" do
34
+ assert @sw.eof?
35
+ end
36
+ end
37
+
38
+ context "A GzipMultiFile with two files" do
39
+ setup do
40
+ @sw = GzipMultiFile.new [fixture_file("log1.log"), fixture_file("log2.log")]
41
+ end
42
+
43
+ should "read the line from file 1 first" do
44
+ assert_equal("Log 1 line 1\n", @sw.gets)
45
+ end
46
+
47
+ should "read the lines from file 2 after file 1" do
48
+ @sw.gets
49
+ assert_equal("Log 2 line 1\n", @sw.gets)
50
+ assert_equal("Log 2 line 2\n", @sw.gets)
51
+ assert_equal(nil, @sw.gets)
52
+ end
53
+
54
+ should "return nil when file 2 is empty" do
55
+ 3.times { @sw.gets }
56
+ assert_equal(nil, @sw.gets)
57
+ end
58
+ end
59
+
60
+ context "A GzipMultiFile without files" do
61
+ setup do
62
+ @stdin = $stdin
63
+ $stdin = StringIO.new "Line 1\nLine 2\n"
64
+ @sw = GzipMultiFile.new
65
+ end
66
+ teardown do
67
+ $stdin = @stdin
68
+ end
69
+
70
+ should "read from STDIN" do
71
+ assert_equal("Line 1\n", @sw.gets)
72
+ assert_equal("Line 2\n", @sw.gets)
73
+ assert_equal(nil, @sw.gets)
74
+ end
75
+ end
76
+
77
+ context "A GzipMultiFile with one gzipped file" do
78
+ setup do
79
+ @sw = GzipMultiFile.new fixture_file("log1.log.gz")
80
+ end
81
+
82
+ should "read the unzipped data with #gets" do
83
+ assert_equal("Log 1 line 1\n", @sw.gets)
84
+ end
85
+
86
+ should "return nil from #gets after the last line" do
87
+ @sw.gets
88
+ assert_equal(nil, @sw.gets)
89
+ end
90
+ end
91
+
92
+ context "A GzipMultiFile with two gzipped files" do
93
+ setup do
94
+ @sw = GzipMultiFile.new [fixture_file("log1.log.gz"), fixture_file("log2.log.gz")]
95
+ end
96
+
97
+ should "read the line from file 1 first" do
98
+ assert_equal("Log 1 line 1\n", @sw.gets)
99
+ end
100
+
101
+ should "read the lines from file 2 after file 1" do
102
+ @sw.gets
103
+ assert_equal("Log 2 line 1\n", @sw.gets)
104
+ assert_equal("Log 2 line 2\n", @sw.gets)
105
+ assert_equal(nil, @sw.gets)
106
+ end
107
+
108
+ should "return nil when file 2 is empty" do
109
+ 3.times { @sw.gets }
110
+ assert_equal(nil, @sw.gets)
111
+ end
112
+ end
113
+
114
+ context "If one of the files is empty, the GzipMultiFile" do
115
+ setup do
116
+ @sw = GzipMultiFile.new [fixture_file("log0.log"), fixture_file("log2.log")]
117
+ end
118
+
119
+ should "ignore that file without a glitch" do
120
+ assert_equal("Log 2 line 1\n", @sw.gets)
121
+ end
122
+ end
123
+
124
+ context "#shell_command" do
125
+ should "cat regular files" do
126
+ command = GzipMultiFile.new.send :shell_command, "file.log"
127
+ assert_match /^cat file.log/, command
128
+ end
129
+ should "unzip zipped files" do
130
+ command = GzipMultiFile.new.send :shell_command, "file.gz"
131
+ assert_match /^gunzip -c file.gz/, command
132
+ end
133
+ should "add filter for shop" do
134
+ command = GzipMultiFile.new("", {:shop_id => "www.24.se"}).send :shell_command, "file.gz"
135
+ assert_match /grep -F sid=www\.24\.se/, command
136
+ end
137
+ should "add filter for account" do
138
+ command = GzipMultiFile.new("", {:account_id => "jetshop"}).send :shell_command, "file.gz"
139
+ assert_match /grep -F aid=jetshop/, command
140
+ end
141
+ should "add filter for type" do
142
+ command = GzipMultiFile.new("", {:observation_type => "view_item"}).send :shell_command, "file.gz"
143
+ assert_match /grep -F o=view_item/, command
144
+ end
145
+ end
146
+
147
+ end
@@ -0,0 +1,171 @@
1
+ require 'test_helper'
2
+ require 'stream_wrapper'
3
+ include StreamWrapper
4
+
5
+ class StreamWrapper::ObservationFilterTest < Test::Unit::TestCase
6
+
7
+ context "An ObservationFilter (regardless of filter options)" do
8
+ setup do
9
+ @of = ObservationFilter.new "line 1\nline 2", {}
10
+ end
11
+
12
+ should "read from from a stream with #gets" do
13
+ assert_equal("line 1\n", @of.gets)
14
+ assert_equal("line 2", @of.gets)
15
+ end
16
+
17
+ should "return nil from #gets after the last line" do
18
+ @of.gets
19
+ @of.gets
20
+ assert_equal(nil, @of.gets)
21
+ end
22
+
23
+ should "know if the stream is eof" do
24
+ assert_equal(false, @of.eof?)
25
+ @of.gets
26
+ assert_equal(false, @of.eof?)
27
+ @of.gets
28
+ assert_equal(true, @of.eof?)
29
+ end
30
+ end
31
+
32
+ context "An ObservationFilter" do
33
+ should "be able to handle empty lines" do
34
+ assert_nothing_raised{ObservationFilter.new("\n", {}).to_a}
35
+ end
36
+
37
+ should "filter case insensitive" do
38
+ File.open(fixture_file("observation_filter.log")) do |file|
39
+ of = ObservationFilter.new(file, {:account_id => "xRoAdS"})
40
+ assert_not_nil(of.gets);
41
+ end
42
+ end
43
+
44
+ should "match escaped strings" do
45
+ file = "aid=Trygg%20Hansa\n"
46
+ of = ObservationFilter.new(file, {:account_id => "Trygg Hansa"})
47
+ assert_not_nil(of.gets);
48
+ end
49
+
50
+ should "only return rows with matching account id" do
51
+ File.open(fixture_file("observation_filter.log")) do |file|
52
+ of = ObservationFilter.new(file, {:account_id => "xroads"})
53
+ assert_not_nil(of.gets);
54
+ end
55
+ File.open(fixture_file("observation_filter.log")) do |file|
56
+ of = ObservationFilter.new(file, {:account_id => "apa"})
57
+ assert_nil(of.gets);
58
+ assert(of.eof?)
59
+ end
60
+ end
61
+
62
+ should "only return rows with matching shop id" do
63
+ File.open(fixture_file("observation_filter.log")) do |file|
64
+ of = ObservationFilter.new(file, {:shop_id => "Fortum"})
65
+ assert_not_nil(of.gets);
66
+ end
67
+ File.open(fixture_file("observation_filter.log")) do |file|
68
+ of = ObservationFilter.new(file, {:account_id => "apa"})
69
+ assert_nil(of.gets);
70
+ assert(of.eof?)
71
+ end
72
+ end
73
+
74
+ should "only return rows with matching account id AND shop id" do
75
+ File.open(fixture_file("observation_filter.log")) do |file|
76
+ of = ObservationFilter.new file, {:account_id => "xroads", :shop_id => "fortum"}
77
+ assert(!(of.gets =~ /fortum/));
78
+ end
79
+ File.open(fixture_file("observation_filter.log")) do |file|
80
+ of = ObservationFilter.new file, {:account_id => "apa", :shop_id => "fortum"}
81
+ assert_nil(of.gets);
82
+ end
83
+ File.open(fixture_file("observation_filter.log")) do |file|
84
+ of = ObservationFilter.new file, {:account_id => "xroads", :shop_id => "apa"}
85
+ assert_nil(of.gets);
86
+ end
87
+ end
88
+
89
+ should "skip shops" do
90
+ File.open(fixture_file("observation_filter.log")) do |file|
91
+ of = ObservationFilter.new file, {:skip_shop_id => "fortum"}
92
+ assert(!(of.gets =~ /fortum/i));
93
+ assert(!(of.gets =~ /fortum/i));
94
+ assert_nil(of.gets);
95
+ end
96
+ File.open(fixture_file("observation_filter.log")) do |file|
97
+ of = ObservationFilter.new file, {:skip_shop_id => "trygg\shansa"}
98
+ assert(!(of.gets =~ /trygg\shansa/i));
99
+ assert(!(of.gets =~ /trygg\shansa/i));
100
+ assert(!(of.gets =~ /trygg\shansa/i));
101
+ assert(!(of.gets =~ /trygg\shansa/i));
102
+ assert(!(of.gets =~ /trygg\shansa/i));
103
+ assert_nil(of.gets);
104
+ end
105
+ end
106
+
107
+ should "only return rows with matching observation type" do
108
+ File.open(fixture_file("observation_filter.log")) do |file|
109
+ of = ObservationFilter.new file, {:observation_type => "view_item"}
110
+ assert(of.gets =~ /o=view_item/);
111
+ end
112
+ File.open(fixture_file("observation_filter.log")) do |file|
113
+ of = ObservationFilter.new file, {:observation_type => "pick_item"}
114
+ assert(of.gets =~ /o=pick_item/);
115
+ end
116
+ File.open(fixture_file("observation_filter.log")) do |file|
117
+ of = ObservationFilter.new file, {:observation_type => "apa"}
118
+ assert_nil(of.gets);
119
+ end
120
+ end
121
+
122
+ should "ignore inhouse and debug rows" do
123
+ File.open(fixture_file("observation_filter.log")) do |file|
124
+ of = ObservationFilter.new file, {:skip_debug_observations => true}
125
+ assert_not_nil(of.gets);
126
+ assert_not_nil(of.gets);
127
+ assert_nil(of.gets);
128
+ end
129
+ end
130
+
131
+ if RUBY_VERSION > "1.9"
132
+ should "ignore invalide byte sequence" do
133
+ File.open(fixture_file('log_invalid_mixed_encoding.log'), :encoding => "utf-8") do |file|
134
+ of = ObservationFilter.new file, {:skip_debug_observations => true}
135
+ assert_nothing_raised{of.gets}
136
+ end
137
+ end
138
+ end
139
+
140
+ should "iterate over observations" do
141
+ File.open(fixture_file("observation_filter.log")) do |file|
142
+ of = ObservationFilter.new file, {:observation_type => "view_item"}
143
+ of.each do |o|
144
+ assert(o.kind_of?(Observation))
145
+ end
146
+ assert_equal(4, of.observation_count)
147
+ end
148
+ end
149
+
150
+ should "filter valid observations" do
151
+ file = File.open(fixture_file("observation_filter.log")).readlines.join
152
+ of = ObservationFilter.new file, {:valid => true}
153
+ assert_equal(5, of.count)
154
+ file += '81.233.91.34 - - [16/Feb/2009:08:36:36 +0100] "GET /log.gif?Intesahimlavaliddirekt& HTTP/1.1" 200 35 "http://www.xroads.se/trygghansa/Products/Product.asp?itemId=6971" "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6"\n'
155
+ of = ObservationFilter.new file, {:valid => true}
156
+ assert_equal(5, of.count)
157
+ of = ObservationFilter.new file, {:skip_valid => true}
158
+ assert_equal(1, of.count)
159
+ end
160
+
161
+ should "not accept false values for any options" do
162
+ File.open(fixture_file("observation_filter.log")) do |file|
163
+ assert_raise RuntimeError do
164
+ of = ObservationFilter.new file, {:valid => false}
165
+ end
166
+ end
167
+ end
168
+
169
+ end
170
+
171
+ end