appsignal 1.1.0.beta.6 → 1.1.0.beta.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/agent.yml +7 -7
- data/ext/appsignal_extension.c +7 -5
- data/ext/extconf.rb +9 -2
- data/lib/appsignal/config.rb +5 -2
- data/lib/appsignal/event_formatter.rb +2 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +1 -47
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +88 -0
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +6 -7
- data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +13 -0
- data/lib/appsignal/hooks/sequel.rb +4 -7
- data/lib/appsignal/integrations/capistrano/appsignal.cap +1 -1
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +9 -5
- data/lib/appsignal/js_exception_transaction.rb +2 -2
- data/lib/appsignal/subscriber.rb +3 -2
- data/lib/appsignal/transaction.rb +8 -2
- data/lib/appsignal/transmitter.rb +1 -1
- data/lib/appsignal/utils.rb +38 -4
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/capistrano3_spec.rb +21 -1
- data/spec/lib/appsignal/config_spec.rb +12 -0
- data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +1 -1
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +14 -186
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +115 -0
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +4 -4
- data/spec/lib/appsignal/event_formatter/sequel/sql_formatter_spec.rb +22 -0
- data/spec/lib/appsignal/extension_spec.rb +1 -1
- data/spec/lib/appsignal/hooks/sequel_spec.rb +1 -1
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +8 -5
- data/spec/lib/appsignal/subscriber_spec.rb +23 -5
- data/spec/lib/appsignal/transaction_spec.rb +21 -0
- data/spec/lib/appsignal/utils_spec.rb +48 -0
- data/spec/support/helpers/env_helpers.rb +1 -0
- metadata +8 -2
@@ -28,7 +28,7 @@ module Appsignal
|
|
28
28
|
@transaction_index,
|
29
29
|
@data['name'],
|
30
30
|
@data['message'],
|
31
|
-
|
31
|
+
Appsignal::Utils.json_generate(@data['backtrace'])
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
@@ -43,7 +43,7 @@ module Appsignal
|
|
43
43
|
Appsignal::Extension.set_transaction_sample_data(
|
44
44
|
@transaction_index,
|
45
45
|
key.to_s,
|
46
|
-
|
46
|
+
Appsignal::Utils.json_generate(data)
|
47
47
|
)
|
48
48
|
rescue JSON::GeneratorError=>e
|
49
49
|
Appsignal.logger.error("JSON generate error (#{e.message}) for '#{data.inspect}'")
|
data/lib/appsignal/subscriber.rb
CHANGED
@@ -45,12 +45,13 @@ module Appsignal
|
|
45
45
|
return unless transaction = Appsignal::Transaction.current
|
46
46
|
return if transaction.nil_transaction? || transaction.paused?
|
47
47
|
|
48
|
-
title, body = Appsignal::EventFormatter.format(name, payload)
|
48
|
+
title, body, body_format = Appsignal::EventFormatter.format(name, payload)
|
49
49
|
Appsignal::Extension.finish_event(
|
50
50
|
transaction.transaction_index,
|
51
51
|
name,
|
52
52
|
title || BLANK,
|
53
|
-
body || BLANK
|
53
|
+
body || BLANK,
|
54
|
+
body_format || 0
|
54
55
|
)
|
55
56
|
end
|
56
57
|
end
|
@@ -113,7 +113,7 @@ module Appsignal
|
|
113
113
|
Appsignal::Extension.set_transaction_sample_data(
|
114
114
|
transaction_index,
|
115
115
|
key.to_s,
|
116
|
-
|
116
|
+
Appsignal::Utils.json_generate(data)
|
117
117
|
)
|
118
118
|
rescue JSON::GeneratorError=>e
|
119
119
|
Appsignal.logger.error("JSON generate error (#{e.message}) for '#{data.inspect}'")
|
@@ -124,6 +124,7 @@ module Appsignal
|
|
124
124
|
:params => sanitized_params,
|
125
125
|
:environment => sanitized_environment,
|
126
126
|
:session_data => sanitized_session_data,
|
127
|
+
:metadata => metadata,
|
127
128
|
:tags => sanitized_tags
|
128
129
|
}.each do |key, data|
|
129
130
|
set_sample_data(key, data)
|
@@ -141,7 +142,7 @@ module Appsignal
|
|
141
142
|
transaction_index,
|
142
143
|
error.class.name,
|
143
144
|
error.message,
|
144
|
-
backtrace ?
|
145
|
+
backtrace ? Appsignal::Utils.json_generate(backtrace) : ''
|
145
146
|
)
|
146
147
|
rescue JSON::GeneratorError=>e
|
147
148
|
Appsignal.logger.error("JSON generate error (#{e.message}) for '#{backtrace.inspect}'")
|
@@ -212,6 +213,11 @@ module Appsignal
|
|
212
213
|
Appsignal::ParamsSanitizer.sanitize(session.to_hash)
|
213
214
|
end
|
214
215
|
|
216
|
+
def metadata
|
217
|
+
return unless request.env
|
218
|
+
request.env[:metadata]
|
219
|
+
end
|
220
|
+
|
215
221
|
# Only keep tags if they meet the following criteria:
|
216
222
|
# * Key is a symbol or string with less then 100 chars
|
217
223
|
# * Value is a symbol or string with less then 100 chars
|
@@ -53,7 +53,7 @@ module Appsignal
|
|
53
53
|
request['Content-Type'] = CONTENT_TYPE
|
54
54
|
request['Content-Encoding'] = CONTENT_ENCODING
|
55
55
|
request.body = Zlib::Deflate.deflate(
|
56
|
-
|
56
|
+
Appsignal::Utils.json_generate(payload),
|
57
57
|
Zlib::BEST_SPEED
|
58
58
|
)
|
59
59
|
end
|
data/lib/appsignal/utils.rb
CHANGED
@@ -1,25 +1,59 @@
|
|
1
1
|
module Appsignal
|
2
2
|
module Utils
|
3
|
-
def self.sanitize(params, only_top_level=false)
|
3
|
+
def self.sanitize(params, only_top_level=false, key_sanitizer=nil)
|
4
4
|
if params.is_a?(Hash)
|
5
5
|
{}.tap do |hsh|
|
6
6
|
params.each do |key, val|
|
7
|
-
hsh[key] =
|
7
|
+
hsh[self.sanitize_key(key, key_sanitizer)] = if only_top_level
|
8
|
+
'?'
|
9
|
+
else
|
10
|
+
sanitize(val, only_top_level, key_sanitizer=nil)
|
11
|
+
end
|
8
12
|
end
|
9
13
|
end
|
10
14
|
elsif params.is_a?(Array)
|
11
15
|
if only_top_level
|
12
|
-
sanitize(params[0], only_top_level)
|
16
|
+
sanitize(params[0], only_top_level, key_sanitizer=nil)
|
13
17
|
elsif params.first.is_a?(String)
|
14
18
|
['?']
|
15
19
|
else
|
16
20
|
params.map do |item|
|
17
|
-
sanitize(item, only_top_level)
|
21
|
+
sanitize(item, only_top_level, key_sanitizer=nil)
|
18
22
|
end
|
19
23
|
end
|
20
24
|
else
|
21
25
|
'?'
|
22
26
|
end
|
23
27
|
end
|
28
|
+
|
29
|
+
def self.sanitize_key(key, sanitizer)
|
30
|
+
case sanitizer
|
31
|
+
when :mongodb then key.to_s.gsub(/(\..+)/, '.?')
|
32
|
+
else key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.json_generate(body)
|
37
|
+
JSON.generate(jsonify(body))
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.jsonify(value)
|
41
|
+
case value
|
42
|
+
when String
|
43
|
+
value.encode(
|
44
|
+
'utf-8',
|
45
|
+
:invalid => :replace,
|
46
|
+
:undef => :replace
|
47
|
+
)
|
48
|
+
when Numeric, NilClass, TrueClass, FalseClass
|
49
|
+
value
|
50
|
+
when Hash
|
51
|
+
Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
|
52
|
+
when Array
|
53
|
+
value.map { |v| jsonify(v) }
|
54
|
+
else
|
55
|
+
jsonify(value.to_s)
|
56
|
+
end
|
57
|
+
end
|
24
58
|
end
|
25
59
|
end
|
data/lib/appsignal/version.rb
CHANGED
@@ -80,9 +80,29 @@ if capistrano3_present?
|
|
80
80
|
)
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
context "when stage is used instead of rack_env / rails_env" do
|
85
|
+
before do
|
86
|
+
@capistrano_config.delete(:rails_env)
|
87
|
+
@capistrano_config.set(:stage, 'stage_production')
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be instantiated with the right params" do
|
91
|
+
Appsignal::Config.should_receive(:new).with(
|
92
|
+
project_fixture_path,
|
93
|
+
'stage_production',
|
94
|
+
{:name => 'AppName'},
|
95
|
+
kind_of(Logger)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
83
99
|
end
|
84
100
|
|
85
|
-
after
|
101
|
+
after do
|
102
|
+
invoke('appsignal:deploy')
|
103
|
+
@capistrano_config.delete(:stage)
|
104
|
+
@capistrano_config.delete(:rack_env)
|
105
|
+
end
|
86
106
|
end
|
87
107
|
|
88
108
|
context "send marker" do
|
@@ -98,6 +98,18 @@ describe Appsignal::Config do
|
|
98
98
|
ENV['APPSIGNAL_HTTP_PROXY'].should == 'http://localhost'
|
99
99
|
ENV['APPSIGNAL_IGNORE_ACTIONS'].should == 'action1,action2'
|
100
100
|
ENV['APPSIGNAL_RUNNING_IN_CONTAINER'].should == 'false'
|
101
|
+
ENV['APPSIGNAL_WORKING_DIR_PATH'].should be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
context "if working_dir_path is set" do
|
105
|
+
before do
|
106
|
+
subject.config_hash[:working_dir_path] = '/tmp/appsignal2'
|
107
|
+
subject.write_to_environment
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should write the current config to env vars" do
|
111
|
+
ENV['APPSIGNAL_WORKING_DIR_PATH'].should == '/tmp/appsignal2'
|
112
|
+
end
|
101
113
|
end
|
102
114
|
end
|
103
115
|
|
@@ -4,7 +4,7 @@ describe Appsignal::EventFormatter::ActiveRecord::InstantiationFormatter do
|
|
4
4
|
let(:klass) { Appsignal::EventFormatter::ActiveRecord::InstantiationFormatter }
|
5
5
|
let(:formatter) { klass.new }
|
6
6
|
|
7
|
-
it "should register
|
7
|
+
it "should register instantiation.active_record" do
|
8
8
|
Appsignal::EventFormatter.registered?('instantiation.active_record', klass).should be_true
|
9
9
|
end
|
10
10
|
|
@@ -1,195 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe Appsignal::EventFormatter::ActiveRecord::InstantiationFormatter do
|
4
|
+
let(:klass) { Appsignal::EventFormatter::ActiveRecord::SqlFormatter }
|
5
|
+
let(:formatter) { klass.new }
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
let(:connection_config) { {} }
|
10
|
-
before do
|
11
|
-
if ActiveRecord::Base.respond_to?(:connection_config)
|
12
|
-
# Rails 3.1+
|
13
|
-
ActiveRecord::Base.stub(
|
14
|
-
:connection_config => connection_config
|
15
|
-
)
|
16
|
-
else
|
17
|
-
# Rails 3.0
|
18
|
-
spec = double(:config => connection_config)
|
19
|
-
ActiveRecord::Base.stub(
|
20
|
-
:connection_pool => double(:spec => spec)
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
pending "should register sql.activerecord" do
|
26
|
-
Appsignal::EventFormatter.registered?('sql.active_record', klass).should be_true
|
27
|
-
end
|
28
|
-
|
29
|
-
context "if a connection cannot be established" do
|
30
|
-
before do
|
31
|
-
ActiveRecord::Base.stub(:connection_config).and_raise(ActiveRecord::ConnectionNotEstablished)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should log the error and unregister the formatter" do
|
35
|
-
Appsignal.logger.should_receive(:error).with(
|
36
|
-
'Error while getting ActiveRecord connection info, unregistering sql.active_record event formatter'
|
37
|
-
)
|
38
|
-
|
39
|
-
lambda {
|
40
|
-
formatter
|
41
|
-
}.should_not raise_error
|
42
|
-
|
43
|
-
Appsignal::EventFormatter.registered?('sql.active_record').should be_false
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "#format" do
|
48
|
-
let(:name) { 'Model load' }
|
49
|
-
let(:payload) { {:sql => sql, :name => name} }
|
50
|
-
subject { formatter.format(payload) }
|
51
|
-
|
52
|
-
context "with backtick table names" do
|
53
|
-
before { formatter.stub(:adapter_uses_double_quoted_table_names => false) }
|
54
|
-
|
55
|
-
context "single quoted data value" do
|
56
|
-
let(:sql) { "SELECT `table`.* FROM `table` WHERE `id` = 'secret' ORDER BY `table`.`id` ASC LIMIT 1" }
|
57
|
-
|
58
|
-
it { should == ['Model load', "SELECT `table`.* FROM `table` WHERE `id` = ? ORDER BY `table`.`id` ASC LIMIT ?"] }
|
59
|
-
|
60
|
-
context "with escaped single quotes in the string" do
|
61
|
-
let(:sql) { "`id` = 'this is a \'big\' secret'" }
|
62
|
-
|
63
|
-
it { should == ['Model load', "`id` = ?"] }
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context "double quoted data value" do
|
68
|
-
let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` = "secret"' }
|
69
|
-
|
70
|
-
it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` = ?'] }
|
71
|
-
|
72
|
-
context "with escaped double quotes in the string" do
|
73
|
-
let(:sql) { '`id` = "this is a \"big\" secret"' }
|
74
|
-
|
75
|
-
it { should == ['Model load', "`id` = ?"] }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
context "numeric parameter" do
|
80
|
-
context "integer" do
|
81
|
-
let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` = 1' }
|
82
|
-
|
83
|
-
it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` = ?'] }
|
84
|
-
end
|
85
|
-
|
86
|
-
context "float" do
|
87
|
-
let(:sql) { 'SELECT `table`.* FROM `table` WHERE `value` = 10.0' }
|
88
|
-
|
89
|
-
it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `value` = ?'] }
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "in operator with values" do
|
94
|
-
let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` IN (1, 2)' }
|
95
|
-
|
96
|
-
it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` IN (?)'] }
|
97
|
-
end
|
98
|
-
|
99
|
-
context "in operator with inner query" do
|
100
|
-
let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` IN (SELECT `id` from `other_table` WHERE `value` = 10.0)' }
|
101
|
-
|
102
|
-
it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` IN (SELECT `id` from `other_table` WHERE `value` = ?)'] }
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "with double quote style table names" do
|
107
|
-
let(:connection_config) { {:adapter => 'postgresql'} }
|
108
|
-
|
109
|
-
context "single quoted data value" do
|
110
|
-
let(:sql) { "SELECT \"table\".* FROM \"table\" WHERE \"id\" = 'secret' ORDER BY \"table\".\"id\" ASC LIMIT 1" }
|
111
|
-
|
112
|
-
it { should == ['Model load', "SELECT \"table\".* FROM \"table\" WHERE \"id\" = ? ORDER BY \"table\".\"id\" ASC LIMIT ?"] }
|
113
|
-
|
114
|
-
context "with an escaped single quote" do
|
115
|
-
let(:sql) { "\"id\" = 'this is a \'big\' secret'" }
|
116
|
-
|
117
|
-
it { should == ['Model load', "\"id\" = ?"] }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context "numeric parameter" do
|
122
|
-
context "integer" do
|
123
|
-
let(:sql) { 'SELECT "table".* FROM "table" WHERE "id"=1' }
|
124
|
-
|
125
|
-
it { should == ['Model load', 'SELECT "table".* FROM "table" WHERE "id"=?'] }
|
126
|
-
end
|
127
|
-
|
128
|
-
context "float" do
|
129
|
-
let(:sql) { 'SELECT "table".* FROM "table" WHERE "value"=10.0' }
|
130
|
-
|
131
|
-
it { should == ['Model load', 'SELECT "table".* FROM "table" WHERE "value"=?'] }
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "return nil for schema queries" do
|
137
|
-
let(:name) { 'SCHEMA' }
|
138
|
-
let(:sql) { 'SET client_min_messages TO 22' }
|
139
|
-
|
140
|
-
it { should be_nil }
|
141
|
-
end
|
142
|
-
|
143
|
-
context "with a a frozen sql string" do
|
144
|
-
let(:sql) { "SELECT `table`.* FROM `table` WHERE `id` = 'secret'".freeze }
|
145
|
-
|
146
|
-
it { should == ['Model load', "SELECT `table`.* FROM `table` WHERE `id` = ?"] }
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
describe "#schema_query?" do
|
151
|
-
let(:payload) { {} }
|
152
|
-
subject { formatter.send(:schema_query?, payload) }
|
153
|
-
|
154
|
-
it { should be_false }
|
155
|
-
|
156
|
-
context "when name is schema" do
|
157
|
-
let(:payload) { {:name => 'SCHEMA'} }
|
7
|
+
it "should register sql.active_record" do
|
8
|
+
Appsignal::EventFormatter.registered?('sql.active_record', klass).should be_true
|
9
|
+
end
|
158
10
|
|
159
|
-
|
160
|
-
|
11
|
+
describe "#format" do
|
12
|
+
let(:payload) do
|
13
|
+
{
|
14
|
+
name: 'User load',
|
15
|
+
sql: 'SELECT * FROM users'
|
16
|
+
}
|
161
17
|
end
|
162
18
|
|
163
|
-
|
164
|
-
describe "#connection_config" do
|
165
|
-
let(:connection_config) { {:adapter => 'adapter'} }
|
166
|
-
|
167
|
-
subject { formatter.send(:connection_config) }
|
168
|
-
|
169
|
-
it { should == {:adapter => 'adapter'} }
|
170
|
-
end
|
171
|
-
|
172
|
-
describe "#adapter_uses_double_quoted_table_names" do
|
173
|
-
subject { formatter.adapter_uses_double_quoted_table_names }
|
19
|
+
subject { formatter.format(payload) }
|
174
20
|
|
175
|
-
|
176
|
-
let(:connection_config) { {:adapter => 'mysql'} }
|
177
|
-
|
178
|
-
it { should be_false }
|
179
|
-
end
|
180
|
-
|
181
|
-
context "when using postgresql" do
|
182
|
-
let(:connection_config) { {:adapter => 'postgresql'} }
|
183
|
-
|
184
|
-
it { should be_true }
|
185
|
-
end
|
186
|
-
|
187
|
-
context "when using sqlite" do
|
188
|
-
let(:connection_config) { {:adapter => 'sqlite'} }
|
189
|
-
|
190
|
-
it { should be_true }
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
21
|
+
it { should == ['User load', 'SELECT * FROM users', 1] }
|
194
22
|
end
|
195
23
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Appsignal::EventFormatter::MongoRubyDriver::QueryFormatter do
|
4
|
+
let(:formatter) { Appsignal::EventFormatter::MongoRubyDriver::QueryFormatter }
|
5
|
+
|
6
|
+
describe ".format" do
|
7
|
+
let(:strategy) { :find }
|
8
|
+
let(:command) do
|
9
|
+
{
|
10
|
+
"find" => "users",
|
11
|
+
"filter" => {"_id" => 1}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should apply a strategy for each key" do
|
16
|
+
expect( formatter ).to receive(:apply_strategy)
|
17
|
+
.with(:sanitize_document, {"_id" => 1})
|
18
|
+
|
19
|
+
expect( formatter ).to receive(:apply_strategy)
|
20
|
+
.with(:allow, "users")
|
21
|
+
|
22
|
+
formatter.format(strategy, command)
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when strategy is unkown" do
|
26
|
+
let(:strategy) { :bananas }
|
27
|
+
|
28
|
+
it "should return an empty hash" do
|
29
|
+
expect( formatter.format(strategy, command) ).to eql({})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when command is not a hash " do
|
34
|
+
let(:command) { :bananas }
|
35
|
+
|
36
|
+
it "should return an empty hash" do
|
37
|
+
expect( formatter.format(strategy, command) ).to eql({})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ".apply_strategy" do
|
43
|
+
context "when strategy is allow" do
|
44
|
+
let(:strategy) { :allow }
|
45
|
+
let(:value) { {"_id" => 1} }
|
46
|
+
|
47
|
+
it "should return the given value" do
|
48
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when strategy is deny" do
|
53
|
+
let(:strategy) { :deny }
|
54
|
+
let(:value) { {"_id" => 1} }
|
55
|
+
|
56
|
+
it "should return a '?'" do
|
57
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql('?')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when strategy is deny_array" do
|
62
|
+
let(:strategy) { :deny_array }
|
63
|
+
let(:value) { {"_id" => 1} }
|
64
|
+
|
65
|
+
it "should return a sanitized array string" do
|
66
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql("[?]")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when strategy is sanitize_document" do
|
71
|
+
let(:strategy) { :sanitize_document }
|
72
|
+
let(:value) { {"_id" => 1} }
|
73
|
+
|
74
|
+
it "should return a sanitized document" do
|
75
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql({"_id" => '?'})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when strategy is sanitize_bulk" do
|
80
|
+
let(:strategy) { :sanitize_bulk }
|
81
|
+
let(:value) { [{"q" => {"_id" => 1}, "u" => [{"foo" => "bar"}]}] }
|
82
|
+
|
83
|
+
it "should return an array of sanitized bulk documents" do
|
84
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql([
|
85
|
+
{"q" => {"_id" => '?'}, "u" => '[?]'}
|
86
|
+
])
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when bulk has more than one update" do
|
90
|
+
let(:value) do
|
91
|
+
[
|
92
|
+
{"q" => {"_id" => 1}, "u" => [{"foo" => "bar"}]},
|
93
|
+
{"q" => {"_id" => 2}, "u" => [{"foo" => "baz"}]},
|
94
|
+
]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should return only the first value of sanitized bulk documents" do
|
98
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql([
|
99
|
+
{"q" => {"_id" => '?'}, "u" => '[?]'},
|
100
|
+
"[...]"
|
101
|
+
])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when strategy is missing" do
|
107
|
+
let(:strategy) { nil }
|
108
|
+
let(:value) { {"_id" => 1} }
|
109
|
+
|
110
|
+
it "should return a '?'" do
|
111
|
+
expect( formatter.apply_strategy(strategy, value) ).to eql('?')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|