airbrake-ruby 3.1.0 → 3.2.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.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +197 -43
- data/lib/airbrake-ruby/config.rb +43 -11
- data/lib/airbrake-ruby/deploy_notifier.rb +47 -0
- data/lib/airbrake-ruby/filter_chain.rb +32 -50
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +9 -1
- data/lib/airbrake-ruby/filters/sql_filter.rb +104 -0
- data/lib/airbrake-ruby/hash_keyable.rb +37 -0
- data/lib/airbrake-ruby/ignorable.rb +44 -0
- data/lib/airbrake-ruby/notice.rb +2 -22
- data/lib/airbrake-ruby/{notifier.rb → notice_notifier.rb} +66 -46
- data/lib/airbrake-ruby/performance_notifier.rb +161 -0
- data/lib/airbrake-ruby/stat.rb +56 -0
- data/lib/airbrake-ruby/tdigest.rb +393 -0
- data/lib/airbrake-ruby/time_truncate.rb +17 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +57 -13
- data/spec/async_sender_spec.rb +0 -2
- data/spec/backtrace_spec.rb +0 -2
- data/spec/code_hunk_spec.rb +0 -2
- data/spec/config/validator_spec.rb +0 -2
- data/spec/config_spec.rb +16 -4
- data/spec/deploy_notifier_spec.rb +41 -0
- data/spec/file_cache.rb +0 -2
- data/spec/filter_chain_spec.rb +1 -7
- data/spec/filters/context_filter_spec.rb +0 -2
- data/spec/filters/dependency_filter_spec.rb +0 -2
- data/spec/filters/exception_attributes_filter_spec.rb +0 -2
- data/spec/filters/gem_root_filter_spec.rb +0 -2
- data/spec/filters/git_last_checkout_filter_spec.rb +0 -2
- data/spec/filters/git_repository_filter.rb +0 -2
- data/spec/filters/git_revision_filter_spec.rb +0 -2
- data/spec/filters/keys_blacklist_spec.rb +0 -2
- data/spec/filters/keys_whitelist_spec.rb +0 -2
- data/spec/filters/root_directory_filter_spec.rb +0 -2
- data/spec/filters/sql_filter_spec.rb +219 -0
- data/spec/filters/system_exit_filter_spec.rb +0 -2
- data/spec/filters/thread_filter_spec.rb +0 -2
- data/spec/ignorable_spec.rb +14 -0
- data/spec/nested_exception_spec.rb +0 -2
- data/spec/{notifier_spec.rb → notice_notifier_spec.rb} +24 -114
- data/spec/{notifier_spec → notice_notifier_spec}/options_spec.rb +40 -39
- data/spec/notice_spec.rb +2 -4
- data/spec/performance_notifier_spec.rb +287 -0
- data/spec/promise_spec.rb +0 -2
- data/spec/response_spec.rb +0 -2
- data/spec/stat_spec.rb +35 -0
- data/spec/sync_sender_spec.rb +0 -2
- data/spec/tdigest_spec.rb +230 -0
- data/spec/time_truncate_spec.rb +13 -0
- data/spec/truncator_spec.rb +0 -2
- metadata +34 -15
- data/lib/airbrake-ruby/route_sender.rb +0 -175
- data/spec/route_sender_spec.rb +0 -130
@@ -0,0 +1,17 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# TimeTruncate contains methods for truncating time.
|
3
|
+
#
|
4
|
+
# @api private
|
5
|
+
# @since v3.2.0
|
6
|
+
module TimeTruncate
|
7
|
+
# Truncate +time+ to floor minute and turn it into an RFC3339 timestamp.
|
8
|
+
#
|
9
|
+
# @param [Time] time
|
10
|
+
# @return [String]
|
11
|
+
def self.utc_truncate_minutes(time)
|
12
|
+
tm = time.getutc
|
13
|
+
|
14
|
+
Time.utc(tm.year, tm.month, tm.day, tm.hour, tm.min).to_datetime.rfc3339
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/airbrake_spec.rb
CHANGED
@@ -1,20 +1,30 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
RSpec.describe Airbrake do
|
4
2
|
describe ".[]" do
|
5
3
|
it "returns a NilNotifier" do
|
6
|
-
expect(described_class[:test]).to be_an(Airbrake::
|
4
|
+
expect(described_class[:test]).to be_an(Airbrake::NilNoticeNotifier)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".notifiers" do
|
9
|
+
it "returns a Hash of notifiers" do
|
10
|
+
expect(described_class.notifiers).to eq(
|
11
|
+
notice: {}, performance: {}, deploy: {}
|
12
|
+
)
|
7
13
|
end
|
8
14
|
end
|
9
15
|
|
10
16
|
let(:default_notifier) do
|
11
|
-
described_class
|
17
|
+
described_class[:default]
|
12
18
|
end
|
13
19
|
|
14
20
|
describe ".configure" do
|
15
21
|
let(:config_params) { { project_id: 1, project_key: 'abc' } }
|
16
22
|
|
17
|
-
after
|
23
|
+
after do
|
24
|
+
described_class.instance_variable_get(:@notice_notifiers).clear
|
25
|
+
described_class.instance_variable_get(:@performance_notifiers).clear
|
26
|
+
described_class.instance_variable_get(:@deploy_notifiers).clear
|
27
|
+
end
|
18
28
|
|
19
29
|
it "yields the config" do
|
20
30
|
expect do |b|
|
@@ -26,17 +36,17 @@ RSpec.describe Airbrake do
|
|
26
36
|
end.to yield_with_args(Airbrake::Config)
|
27
37
|
end
|
28
38
|
|
29
|
-
context "when invoked with a notifier name" do
|
30
|
-
it "sets notifier name to the provided name" do
|
39
|
+
context "when invoked with a notice notifier name" do
|
40
|
+
it "sets notice notifier name to the provided name" do
|
31
41
|
described_class.configure(:test) { |c| c.merge(config_params) }
|
32
|
-
expect(described_class[:test]).to be_an(Airbrake::
|
42
|
+
expect(described_class[:test]).to be_an(Airbrake::NoticeNotifier)
|
33
43
|
end
|
34
44
|
end
|
35
45
|
|
36
46
|
context "when invoked without a notifier name" do
|
37
47
|
it "defaults to the :default notifier name" do
|
38
48
|
described_class.configure { |c| c.merge(config_params) }
|
39
|
-
expect(described_class[:default]).to be_an(Airbrake::
|
49
|
+
expect(described_class[:default]).to be_an(Airbrake::NoticeNotifier)
|
40
50
|
end
|
41
51
|
end
|
42
52
|
|
@@ -50,6 +60,20 @@ RSpec.describe Airbrake do
|
|
50
60
|
)
|
51
61
|
end
|
52
62
|
end
|
63
|
+
|
64
|
+
context "when user config doesn't contain a project id" do
|
65
|
+
it "raises error" do
|
66
|
+
expect { described_class.configure { |c| c.project_key = '1' } }.
|
67
|
+
to raise_error(Airbrake::Error, ':project_id is required')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when user config doesn't contain a project key" do
|
72
|
+
it "raises error" do
|
73
|
+
expect { described_class.configure { |c| c.project_id = 1 } }.
|
74
|
+
to raise_error(Airbrake::Error, ':project_key is required')
|
75
|
+
end
|
76
|
+
end
|
53
77
|
end
|
54
78
|
|
55
79
|
describe ".configured?" do
|
@@ -98,8 +122,10 @@ RSpec.describe Airbrake do
|
|
98
122
|
end
|
99
123
|
|
100
124
|
describe ".create_deploy" do
|
101
|
-
|
102
|
-
|
125
|
+
let(:default_notifier) { described_class.notifiers[:deploy][:default] }
|
126
|
+
|
127
|
+
it "calls 'notify' on the deploy notifier" do
|
128
|
+
expect(default_notifier).to receive(:notify).with(foo: 'bar')
|
103
129
|
described_class.create_deploy(foo: 'bar')
|
104
130
|
end
|
105
131
|
end
|
@@ -112,7 +138,9 @@ RSpec.describe Airbrake do
|
|
112
138
|
end
|
113
139
|
|
114
140
|
describe ".notify_request" do
|
115
|
-
|
141
|
+
let(:default_notifier) { described_class.notifiers[:performance][:default] }
|
142
|
+
|
143
|
+
it "calls 'notify' on the route notifier" do
|
116
144
|
params = {
|
117
145
|
method: 'GET',
|
118
146
|
route: '/foo',
|
@@ -120,8 +148,24 @@ RSpec.describe Airbrake do
|
|
120
148
|
start_time: Time.new(2018, 1, 1, 0, 20, 0, 0),
|
121
149
|
end_time: Time.new(2018, 1, 1, 0, 19, 0, 0)
|
122
150
|
}
|
123
|
-
expect(default_notifier).to receive(:
|
151
|
+
expect(default_notifier).to receive(:notify).with(Airbrake::Request.new(params))
|
124
152
|
described_class.notify_request(params)
|
125
153
|
end
|
126
154
|
end
|
155
|
+
|
156
|
+
describe ".notify_query" do
|
157
|
+
let(:default_notifier) { described_class.notifiers[:performance][:default] }
|
158
|
+
|
159
|
+
it "calls 'notify' on the query notifier" do
|
160
|
+
params = {
|
161
|
+
method: 'GET',
|
162
|
+
route: '/foo',
|
163
|
+
query: 'SELECT * FROM foos',
|
164
|
+
start_time: Time.new(2018, 1, 1, 0, 20, 0, 0),
|
165
|
+
end_time: Time.new(2018, 1, 1, 0, 19, 0, 0)
|
166
|
+
}
|
167
|
+
expect(default_notifier).to receive(:notify).with(Airbrake::Query.new(params))
|
168
|
+
described_class.notify_query(params)
|
169
|
+
end
|
170
|
+
end
|
127
171
|
end
|
data/spec/async_sender_spec.rb
CHANGED
data/spec/backtrace_spec.rb
CHANGED
data/spec/code_hunk_spec.rb
CHANGED
data/spec/config_spec.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
RSpec.describe Airbrake::Config do
|
4
2
|
let(:config) { described_class.new }
|
5
3
|
|
@@ -79,12 +77,26 @@ RSpec.describe Airbrake::Config do
|
|
79
77
|
expect(config.whitelist_keys).to be_empty
|
80
78
|
end
|
81
79
|
|
82
|
-
it "
|
80
|
+
it "disables route stats by default (deprecated)" do
|
81
|
+
out = StringIO.new
|
82
|
+
config.logger = Logger.new(out)
|
83
83
|
expect(config.route_stats).to be_falsey
|
84
|
+
expect(out.string).to match(/'route_stats'.+is deprecated/)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "disables performance stats by default" do
|
88
|
+
expect(config.performance_stats).to be_falsey
|
84
89
|
end
|
85
90
|
|
86
|
-
it "sets the default route_stats_flush_period" do
|
91
|
+
it "sets the default route_stats_flush_period (deprecated)" do
|
92
|
+
out = StringIO.new
|
93
|
+
config.logger = Logger.new(out)
|
87
94
|
expect(config.route_stats_flush_period).to eq(15)
|
95
|
+
expect(out.string).to match(/'route_stats_flush_period'.+is deprecated/)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "sets the default performance_stats_flush_period" do
|
99
|
+
expect(config.performance_stats_flush_period).to eq(15)
|
88
100
|
end
|
89
101
|
end
|
90
102
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
RSpec.describe Airbrake::DeployNotifier do
|
2
|
+
let(:user_params) { { project_id: 1, project_key: 'banana' } }
|
3
|
+
let(:params) { {} }
|
4
|
+
let(:config) { Airbrake::Config.new(user_params.merge(params)) }
|
5
|
+
|
6
|
+
subject { described_class.new(config) }
|
7
|
+
|
8
|
+
describe "#notify" do
|
9
|
+
it "returns a promise" do
|
10
|
+
stub_request(:post, 'https://api.airbrake.io/api/v4/projects/1/deploys').
|
11
|
+
to_return(status: 201, body: '{}')
|
12
|
+
expect(subject.notify({})).to be_an(Airbrake::Promise)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when environment is configured" do
|
16
|
+
let(:params) { { environment: 'fooenv' } }
|
17
|
+
|
18
|
+
it "prefers the passed environment to the config env" do
|
19
|
+
expect_any_instance_of(Airbrake::SyncSender).to receive(:send).with(
|
20
|
+
{ environment: 'barenv' },
|
21
|
+
instance_of(Airbrake::Promise),
|
22
|
+
URI('https://api.airbrake.io/api/v4/projects/1/deploys')
|
23
|
+
)
|
24
|
+
subject.notify(environment: 'barenv')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when environment is not configured" do
|
29
|
+
let(:params) { { environment: 'fooenv' } }
|
30
|
+
|
31
|
+
it "sets the environment from the config" do
|
32
|
+
expect_any_instance_of(Airbrake::SyncSender).to receive(:send).with(
|
33
|
+
{ environment: 'fooenv' },
|
34
|
+
instance_of(Airbrake::Promise),
|
35
|
+
URI('https://api.airbrake.io/api/v4/projects/1/deploys')
|
36
|
+
)
|
37
|
+
subject.notify({})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/file_cache.rb
CHANGED
data/spec/filter_chain_spec.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
RSpec.describe Airbrake::FilterChain do
|
4
|
-
subject { described_class.new(config, {}) }
|
5
|
-
|
6
|
-
let(:config) { Airbrake::Config.new }
|
7
|
-
|
8
2
|
let(:notice) do
|
9
|
-
Airbrake::Notice.new(
|
3
|
+
Airbrake::Notice.new(Airbrake::Config.new, AirbrakeTestError.new)
|
10
4
|
end
|
11
5
|
|
12
6
|
describe "#refine" do
|
@@ -0,0 +1,219 @@
|
|
1
|
+
RSpec.describe Airbrake::Filters::SqlFilter do
|
2
|
+
shared_examples "query filtering" do |test|
|
3
|
+
test[:dialects].each do |dialect|
|
4
|
+
it "correctly filters SQL like `#{test[:input]}' (#{dialect} dialect)" do
|
5
|
+
filter = described_class.new(dialect)
|
6
|
+
q = OpenStruct.new(query: test[:input])
|
7
|
+
filter.call(q)
|
8
|
+
expect(q.query).to eq(test[:output])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
ALL_DIALECTS = %i[mysql postgres sqlite cassandra oracle].freeze
|
14
|
+
|
15
|
+
# rubocop:disable Metrics/LineLength
|
16
|
+
[
|
17
|
+
{
|
18
|
+
input: 'SELECT * FROM things;',
|
19
|
+
output: 'SELECT * FROM things;',
|
20
|
+
dialects: ALL_DIALECTS
|
21
|
+
}, {
|
22
|
+
input: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = 'value' AND c3=\"othervalue\" LIMIT ?",
|
23
|
+
output: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = ? AND c3=? LIMIT ?",
|
24
|
+
dialects: %i[mysql]
|
25
|
+
}, {
|
26
|
+
input: "SELECT * FROM t WHERE foo=\"bar/*\" AND baz=\"whatever */qux\"",
|
27
|
+
output: "SELECT * FROM t WHERE foo=? AND baz=?",
|
28
|
+
dialects: %i[mysql]
|
29
|
+
}, {
|
30
|
+
input: "SELECT * FROM t WHERE foo='bar/*' AND baz='whatever */qux'",
|
31
|
+
output: "SELECT * FROM t WHERE foo=? AND baz=?",
|
32
|
+
dialects: ALL_DIALECTS
|
33
|
+
}, {
|
34
|
+
input: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = 'value' AND c3=1234 LIMIT 1",
|
35
|
+
output: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = ? AND c3=? LIMIT ?",
|
36
|
+
dialects: %i[postgres oracle]
|
37
|
+
}, {
|
38
|
+
input: "SELECT * FROM t WHERE foo=\"bar--\" AND\n baz=\"qux--\"",
|
39
|
+
output: "SELECT * FROM t WHERE foo=? AND\n baz=?",
|
40
|
+
dialects: %i[mysql]
|
41
|
+
}, {
|
42
|
+
input: "SELECT * FROM t WHERE foo='bar--' AND\n baz='qux--'",
|
43
|
+
output: "SELECT * FROM t WHERE foo=? AND\n baz=?",
|
44
|
+
dialects: ALL_DIALECTS
|
45
|
+
}, {
|
46
|
+
input: "SELECT * FROM foo WHERE bar='baz' /* Hide Me */",
|
47
|
+
output: "SELECT * FROM foo WHERE bar=? ?",
|
48
|
+
dialects: ALL_DIALECTS
|
49
|
+
}, {
|
50
|
+
input: "SELECT * FROM foobar WHERE password='hunter2'\n-- No peeking!",
|
51
|
+
output: "SELECT * FROM foobar WHERE password=?\n?",
|
52
|
+
dialects: ALL_DIALECTS
|
53
|
+
}, {
|
54
|
+
input: "SELECT foo, bar FROM baz WHERE password='hunter2' # Secret",
|
55
|
+
output: "SELECT foo, bar FROM baz WHERE password=? ?",
|
56
|
+
dialects: ALL_DIALECTS
|
57
|
+
}, {
|
58
|
+
input: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E'foo\\'bar\\\\baz' AND country=e'foo\\'bar\\\\baz'",
|
59
|
+
output: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E?",
|
60
|
+
dialects: %i[postgres]
|
61
|
+
}, {
|
62
|
+
input: "INSERT INTO `X` values(\"test\",0, 1 , 2, 'test')",
|
63
|
+
output: "INSERT INTO `X` values(?,?, ? , ?, ?)",
|
64
|
+
dialects: %i[mysql]
|
65
|
+
}, {
|
66
|
+
input: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value='nothing'",
|
67
|
+
output: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value=?",
|
68
|
+
dialects: ALL_DIALECTS
|
69
|
+
}, {
|
70
|
+
input: "INSERT INTO X VALUES(1, 23456, 123.456, 99+100)",
|
71
|
+
output: "INSERT INTO X VALUES(?, ?, ?, ?+?)",
|
72
|
+
dialects: ALL_DIALECTS
|
73
|
+
}, {
|
74
|
+
input: "SELECT * FROM table WHERE name=\"foo\" AND value=\"don't\"",
|
75
|
+
output: "SELECT * FROM table WHERE name=? AND value=?",
|
76
|
+
dialects: %i[mysql]
|
77
|
+
}, {
|
78
|
+
input: "SELECT * FROM table WHERE name='foo' AND value = 'bar'",
|
79
|
+
output: "SELECT * FROM table WHERE name=? AND value = ?",
|
80
|
+
dialects: ALL_DIALECTS
|
81
|
+
}, {
|
82
|
+
input: "SELECT * FROM table WHERE col='foo\\''bar'",
|
83
|
+
output: "SELECT * FROM table WHERE col=?",
|
84
|
+
dialects: ALL_DIALECTS
|
85
|
+
}, {
|
86
|
+
input: "SELECT * FROM table WHERE col1='foo\"bar' AND col2='what\"ever'",
|
87
|
+
output: "SELECT * FROM table WHERE col1=? AND col2=?",
|
88
|
+
dialects: ALL_DIALECTS
|
89
|
+
}, {
|
90
|
+
input: "select * from accounts where accounts.name != 'dude\n newline' order by accounts.name",
|
91
|
+
output: "select * from accounts where accounts.name != ? order by accounts.name",
|
92
|
+
dialects: ALL_DIALECTS
|
93
|
+
}, {
|
94
|
+
input: "SELECT * FROM table WHERE col1=\"don't\" AND col2=\"won't\"",
|
95
|
+
output: "SELECT * FROM table WHERE col1=? AND col2=?",
|
96
|
+
dialects: %i[mysql]
|
97
|
+
}, {
|
98
|
+
input: "INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son', \"\"\"jim''s\"\" hat\", \"\\\"jim''s secret\\\"\")",
|
99
|
+
output: "INSERT INTO X values(?, ?,?, ? , ?, ?, ?",
|
100
|
+
dialects: %i[mysql]
|
101
|
+
}, {
|
102
|
+
input: "SELECT * FROM table WHERE name='foo\\' AND color='blue'",
|
103
|
+
output: "SELECT * FROM table WHERE name=?",
|
104
|
+
dialects: ALL_DIALECTS
|
105
|
+
}, {
|
106
|
+
input: "SELECT * FROM table WHERE foo=\"this string ends with a backslash\\\\\"",
|
107
|
+
output: "SELECT * FROM table WHERE foo=?",
|
108
|
+
dialects: %i[mysql]
|
109
|
+
}, {
|
110
|
+
input: "SELECT * FROM table WHERE foo='this string ends with a backslash\\\\'",
|
111
|
+
output: "SELECT * FROM table WHERE foo=?",
|
112
|
+
dialects: ALL_DIALECTS
|
113
|
+
}, {
|
114
|
+
# TODO: fix this example.
|
115
|
+
input: "SELECT * FROM table WHERE name='foo\'' AND color='blue'",
|
116
|
+
output: "Error: Airbrake::Query was not filtered",
|
117
|
+
dialects: ALL_DIALECTS
|
118
|
+
}, {
|
119
|
+
input: "INSERT INTO X values('', 'a''b c',0, 1 , 'd''e f''s h')",
|
120
|
+
output: "INSERT INTO X values(?, ?,?, ? , ?)",
|
121
|
+
dialects: ALL_DIALECTS
|
122
|
+
}, {
|
123
|
+
input: "SELECT * FROM t WHERE -- '\n bar='baz' -- '",
|
124
|
+
output: "SELECT * FROM t WHERE ?\n bar=? ?",
|
125
|
+
dialects: ALL_DIALECTS
|
126
|
+
}, {
|
127
|
+
input: "SELECT * FROM t WHERE /* ' */\n bar='baz' -- '",
|
128
|
+
output: "SELECT * FROM t WHERE ?\n bar=? ?",
|
129
|
+
dialects: ALL_DIALECTS
|
130
|
+
}, {
|
131
|
+
input: "SELECT * FROM t WHERE -- '\n /* ' */ c2='xxx' /* ' */\n c='x\n xx' -- '",
|
132
|
+
output: "SELECT * FROM t WHERE ?\n ? c2=? ?\n c=? ?",
|
133
|
+
dialects: ALL_DIALECTS
|
134
|
+
}, {
|
135
|
+
input: "SELECT * FROM t WHERE -- '\n c='x\n xx' -- '",
|
136
|
+
output: "SELECT * FROM t WHERE ?\n c=? ?",
|
137
|
+
dialects: ALL_DIALECTS
|
138
|
+
}, {
|
139
|
+
input: "SELECT * FROM foo WHERE col='value1' AND /* don't */ col2='value1' /* won't */",
|
140
|
+
output: "SELECT * FROM foo WHERE col=? AND ? col2=? ?",
|
141
|
+
dialects: ALL_DIALECTS
|
142
|
+
}, {
|
143
|
+
input: "SELECT * FROM table WHERE foo='bar' AND baz=\"nothing to see here'",
|
144
|
+
output: "Error: Airbrake::Query was not filtered",
|
145
|
+
dialects: %i[mysql]
|
146
|
+
}, {
|
147
|
+
input: "SELECT * FROM table WHERE foo='bar' AND baz='nothing to see here",
|
148
|
+
output: "Error: Airbrake::Query was not filtered",
|
149
|
+
dialects: ALL_DIALECTS
|
150
|
+
}, {
|
151
|
+
input: "SELECT * FROM \"foo\" WHERE \"foo\" = $a$dollar quotes can be $b$nested$b$$a$ and bar = 'baz'",
|
152
|
+
output: "SELECT * FROM \"foo\" WHERE \"foo\" = ? and bar = ?",
|
153
|
+
dialects: %i[postgres]
|
154
|
+
}, {
|
155
|
+
input: "INSERT INTO \"foo\" (\"bar\", \"baz\", \"qux\") VALUES ($1, $2, $3) RETURNING \"id\"",
|
156
|
+
output: "INSERT INTO \"foo\" (\"bar\", \"baz\", \"qux\") VALUES ($?, $?, $?) RETURNING \"id\"",
|
157
|
+
dialects: %i[postgres]
|
158
|
+
}, {
|
159
|
+
input: "select * from foo where bar = 'some\\tthing' and baz = 10",
|
160
|
+
output: "select * from foo where bar = ? and baz = ?",
|
161
|
+
dialects: ALL_DIALECTS
|
162
|
+
}, {
|
163
|
+
input: "select * from users where user = 'user1\\' password = 'hunter 2' -- ->don't count this quote",
|
164
|
+
output: "select * from users where user = ?",
|
165
|
+
dialects: ALL_DIALECTS
|
166
|
+
}, {
|
167
|
+
input: "select * from foo where bar=q'[baz's]' and x=5",
|
168
|
+
output: "select * from foo where bar=? and x=?",
|
169
|
+
dialects: %i[oracle]
|
170
|
+
}, {
|
171
|
+
input: "select * from foo where bar=q'{baz's}' and x=5",
|
172
|
+
output: "select * from foo where bar=? and x=?",
|
173
|
+
dialects: %i[oracle]
|
174
|
+
}, {
|
175
|
+
input: "select * from foo where bar=q'<baz's>' and x=5",
|
176
|
+
output: "select * from foo where bar=? and x=?",
|
177
|
+
dialects: %i[oracle]
|
178
|
+
}, {
|
179
|
+
input: "select * from foo where bar=q'(baz's)' and x=5",
|
180
|
+
output: "select * from foo where bar=? and x=?",
|
181
|
+
dialects: %i[oracle]
|
182
|
+
}, {
|
183
|
+
input: "select * from foo where bar=0xabcdef123 and x=5",
|
184
|
+
output: "select * from foo where bar=? and x=?",
|
185
|
+
dialects: %i[cassandra sqlite]
|
186
|
+
}, {
|
187
|
+
input: "select * from foo where bar=0x2F and x=5",
|
188
|
+
output: "select * from foo where bar=? and x=?",
|
189
|
+
dialects: %i[mysql cassandra sqlite]
|
190
|
+
}, {
|
191
|
+
input: "select * from foo where bar=1.234e-5 and x=5",
|
192
|
+
output: "select * from foo where bar=? and x=?",
|
193
|
+
dialects: ALL_DIALECTS
|
194
|
+
}, {
|
195
|
+
input: "select * from foo where bar=01234567-89ab-cdef-0123-456789abcdef and x=5",
|
196
|
+
output: "select * from foo where bar=? and x=?",
|
197
|
+
dialects: %i[postgres cassandra]
|
198
|
+
}, {
|
199
|
+
input: "select * from foo where bar={01234567-89ab-cdef-0123-456789abcdef} and x=5",
|
200
|
+
output: "select * from foo where bar=? and x=?",
|
201
|
+
dialects: %i[postgres]
|
202
|
+
}, {
|
203
|
+
input: "select * from foo where bar=0123456789abcdef0123456789abcdef and x=5",
|
204
|
+
output: "select * from foo where bar=? and x=?",
|
205
|
+
dialects: %i[postgtes]
|
206
|
+
}, {
|
207
|
+
input: "select * from foo where bar={012-345678-9abc-def012345678-9abcdef} and x=5",
|
208
|
+
output: "select * from foo where bar=? and x=?",
|
209
|
+
dialects: %i[postgres]
|
210
|
+
}, {
|
211
|
+
input: "select * from foo where bar=true and x=FALSE",
|
212
|
+
output: "select * from foo where bar=? and x=?",
|
213
|
+
dialects: %i[mysql postgres cassandra sqlite]
|
214
|
+
}
|
215
|
+
].each do |test|
|
216
|
+
include_examples 'query filtering', test
|
217
|
+
end
|
218
|
+
# rubocop:enable Metrics/LineLength
|
219
|
+
end
|