airbrake-ruby 4.15.0 → 6.0.2
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/async_sender.rb +4 -2
- data/lib/airbrake-ruby/backtrace.rb +6 -5
- data/lib/airbrake-ruby/config/processor.rb +71 -0
- data/lib/airbrake-ruby/config/validator.rb +6 -0
- data/lib/airbrake-ruby/config.rb +44 -35
- data/lib/airbrake-ruby/context.rb +51 -0
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +3 -0
- data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +3 -4
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +4 -1
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
- data/lib/airbrake-ruby/filters/keys_filter.rb +23 -15
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +11 -11
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +4 -3
- data/lib/airbrake-ruby/grouppable.rb +1 -1
- data/lib/airbrake-ruby/ignorable.rb +1 -2
- data/lib/airbrake-ruby/mergeable.rb +1 -1
- data/lib/airbrake-ruby/monotonic_time.rb +1 -1
- data/lib/airbrake-ruby/notice.rb +1 -8
- data/lib/airbrake-ruby/notice_notifier.rb +4 -4
- data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
- data/lib/airbrake-ruby/performance_notifier.rb +40 -54
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +1 -6
- data/lib/airbrake-ruby/queue.rb +1 -8
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/remote_settings.rb +128 -0
- data/lib/airbrake-ruby/request.rb +1 -8
- data/lib/airbrake-ruby/stat.rb +2 -13
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +12 -9
- data/lib/airbrake-ruby/thread_pool.rb +9 -6
- data/lib/airbrake-ruby/time_truncate.rb +2 -2
- data/lib/airbrake-ruby/timed_trace.rb +1 -3
- data/lib/airbrake-ruby/truncator.rb +8 -2
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +44 -54
- data/spec/airbrake_spec.rb +178 -92
- data/spec/async_sender_spec.rb +10 -8
- data/spec/backtrace_spec.rb +39 -36
- data/spec/benchmark_spec.rb +5 -3
- data/spec/code_hunk_spec.rb +26 -17
- data/spec/config/processor_spec.rb +151 -0
- data/spec/config/validator_spec.rb +23 -3
- data/spec/config_spec.rb +40 -52
- data/spec/context_spec.rb +54 -0
- data/spec/deploy_notifier_spec.rb +6 -4
- data/spec/file_cache_spec.rb +1 -0
- data/spec/filter_chain_spec.rb +29 -24
- data/spec/filters/context_filter_spec.rb +14 -5
- data/spec/filters/dependency_filter_spec.rb +3 -1
- data/spec/filters/exception_attributes_filter_spec.rb +5 -3
- data/spec/filters/gem_root_filter_spec.rb +9 -6
- data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
- data/spec/filters/git_repository_filter.rb +9 -9
- data/spec/filters/git_revision_filter_spec.rb +20 -20
- data/spec/filters/keys_allowlist_spec.rb +26 -16
- data/spec/filters/keys_blocklist_spec.rb +35 -18
- data/spec/filters/root_directory_filter_spec.rb +7 -7
- data/spec/filters/sql_filter_spec.rb +28 -28
- data/spec/filters/system_exit_filter_spec.rb +4 -2
- data/spec/filters/thread_filter_spec.rb +16 -14
- data/spec/loggable_spec.rb +2 -2
- data/spec/monotonic_time_spec.rb +8 -6
- data/spec/nested_exception_spec.rb +46 -46
- data/spec/notice_notifier/options_spec.rb +25 -15
- data/spec/notice_notifier_spec.rb +54 -49
- data/spec/notice_spec.rb +7 -3
- data/spec/performance_breakdown_spec.rb +0 -12
- data/spec/performance_notifier_spec.rb +69 -87
- data/spec/promise_spec.rb +38 -32
- data/spec/query_spec.rb +1 -11
- data/spec/queue_spec.rb +1 -13
- data/spec/remote_settings/callback_spec.rb +162 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +201 -0
- data/spec/request_spec.rb +1 -13
- data/spec/response_spec.rb +34 -12
- data/spec/spec_helper.rb +4 -4
- data/spec/stashable_spec.rb +5 -5
- data/spec/stat_spec.rb +7 -14
- data/spec/sync_sender_spec.rb +52 -17
- data/spec/tdigest_spec.rb +61 -56
- data/spec/thread_pool_spec.rb +65 -56
- data/spec/time_truncate_spec.rb +23 -6
- data/spec/timed_trace_spec.rb +32 -30
- data/spec/truncator_spec.rb +72 -43
- metadata +66 -50
data/spec/thread_pool_spec.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
RSpec.describe Airbrake::ThreadPool do
|
2
|
-
|
3
|
-
let(:worker_size) { 1 }
|
4
|
-
let(:queue_size) { 2 }
|
5
|
-
|
6
|
-
subject do
|
2
|
+
subject(:thread_pool) do
|
7
3
|
described_class.new(
|
8
4
|
worker_size: worker_size,
|
9
5
|
queue_size: queue_size,
|
@@ -11,27 +7,27 @@ RSpec.describe Airbrake::ThreadPool do
|
|
11
7
|
)
|
12
8
|
end
|
13
9
|
|
10
|
+
let(:tasks) { [] }
|
11
|
+
let(:worker_size) { 1 }
|
12
|
+
let(:queue_size) { 2 }
|
13
|
+
|
14
14
|
describe "#<<" do
|
15
15
|
it "returns true" do
|
16
|
-
retval =
|
17
|
-
|
16
|
+
retval = thread_pool << 1
|
17
|
+
thread_pool.close
|
18
18
|
expect(retval).to eq(true)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "performs work in background" do
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
thread_pool << 2
|
23
|
+
thread_pool << 1
|
24
|
+
thread_pool.close
|
25
25
|
|
26
26
|
expect(tasks).to eq([2, 1])
|
27
27
|
end
|
28
28
|
|
29
29
|
context "when the queue is full" do
|
30
|
-
|
31
|
-
allow(subject).to receive(:backlog).and_return(queue_size)
|
32
|
-
end
|
33
|
-
|
34
|
-
subject do
|
30
|
+
subject(:full_thread_pool) do
|
35
31
|
described_class.new(
|
36
32
|
worker_size: 1,
|
37
33
|
queue_size: 1,
|
@@ -39,26 +35,33 @@ RSpec.describe Airbrake::ThreadPool do
|
|
39
35
|
)
|
40
36
|
end
|
41
37
|
|
38
|
+
before do
|
39
|
+
# rubocop:disable RSpec/SubjectStub
|
40
|
+
allow(full_thread_pool).to receive(:backlog).and_return(queue_size)
|
41
|
+
# rubocop:enable RSpec/SubjectStub
|
42
|
+
end
|
43
|
+
|
42
44
|
it "returns false" do
|
43
|
-
retval =
|
44
|
-
|
45
|
+
retval = full_thread_pool << 1
|
46
|
+
full_thread_pool.close
|
45
47
|
expect(retval).to eq(false)
|
46
48
|
end
|
47
49
|
|
48
50
|
it "discards tasks" do
|
49
|
-
200.times {
|
50
|
-
|
51
|
+
200.times { full_thread_pool << 1 }
|
52
|
+
full_thread_pool.close
|
51
53
|
|
52
54
|
expect(tasks.size).to be_zero
|
53
55
|
end
|
54
56
|
|
55
57
|
it "logs discarded tasks" do
|
56
|
-
|
57
|
-
|
58
|
-
|
58
|
+
allow(Airbrake::Loggable.instance).to receive(:info)
|
59
|
+
|
60
|
+
15.times { full_thread_pool << 1 }
|
61
|
+
full_thread_pool.close
|
59
62
|
|
60
|
-
|
61
|
-
|
63
|
+
expect(Airbrake::Loggable.instance)
|
64
|
+
.to have_received(:info).exactly(15).times
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
@@ -67,22 +70,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
67
70
|
let(:worker_size) { 0 }
|
68
71
|
|
69
72
|
it "returns the size of the queue" do
|
70
|
-
|
71
|
-
expect(
|
73
|
+
thread_pool << 1
|
74
|
+
expect(thread_pool.backlog).to eq(1)
|
72
75
|
end
|
73
76
|
end
|
74
77
|
|
75
78
|
describe "#has_workers?" do
|
76
79
|
it "returns false when the thread pool is not closed, but has 0 workers" do
|
77
|
-
|
80
|
+
thread_pool.workers.list.each do |worker|
|
78
81
|
worker.kill.join
|
79
82
|
end
|
80
|
-
expect(
|
83
|
+
expect(thread_pool).not_to have_workers
|
81
84
|
end
|
82
85
|
|
83
86
|
it "returns false when the thread pool is closed" do
|
84
|
-
|
85
|
-
expect(
|
87
|
+
thread_pool.close
|
88
|
+
expect(thread_pool).not_to have_workers
|
86
89
|
end
|
87
90
|
|
88
91
|
describe "forking behavior" do
|
@@ -93,20 +96,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
93
96
|
end
|
94
97
|
end
|
95
98
|
|
99
|
+
# rubocop:disable RSpec/MultipleExpectations
|
96
100
|
it "respawns workers on fork()" do
|
97
|
-
pid = fork { expect(
|
101
|
+
pid = fork { expect(thread_pool).to have_workers }
|
98
102
|
Process.wait(pid)
|
99
|
-
|
103
|
+
thread_pool.close
|
100
104
|
|
101
105
|
expect(Process.last_status).to be_success
|
102
|
-
expect(
|
106
|
+
expect(thread_pool).not_to have_workers
|
103
107
|
end
|
108
|
+
# rubocop:enable RSpec/MultipleExpectations
|
104
109
|
|
105
110
|
it "ensures that a new thread group is created per process" do
|
106
|
-
|
107
|
-
pid = fork {
|
111
|
+
thread_pool << 1
|
112
|
+
pid = fork { thread_pool.has_workers? }
|
108
113
|
Process.wait(pid)
|
109
|
-
|
114
|
+
thread_pool.close
|
110
115
|
|
111
116
|
expect(Process.last_status).to be_success
|
112
117
|
end
|
@@ -116,27 +121,29 @@ RSpec.describe Airbrake::ThreadPool do
|
|
116
121
|
describe "#close" do
|
117
122
|
context "when there's no work to do" do
|
118
123
|
it "joins the spawned thread" do
|
119
|
-
workers =
|
124
|
+
workers = thread_pool.workers.list
|
120
125
|
expect(workers).to all(be_alive)
|
121
126
|
|
122
|
-
|
127
|
+
thread_pool.close
|
123
128
|
expect(workers).to all(be_stop)
|
124
129
|
end
|
125
130
|
end
|
126
131
|
|
127
132
|
context "when there's some work to do" do
|
128
133
|
it "logs how many tasks are left to process" do
|
129
|
-
|
130
|
-
worker_size: 0, queue_size: 2, block: proc {},
|
131
|
-
)
|
134
|
+
allow(Airbrake::Loggable.instance).to receive(:debug)
|
132
135
|
|
133
|
-
|
134
|
-
|
136
|
+
thread_pool = described_class.new(
|
137
|
+
name: 'foo', worker_size: 0, queue_size: 2, block: proc {},
|
135
138
|
)
|
136
|
-
expect(Airbrake::Loggable.instance).to receive(:debug).with(/closed/)
|
137
139
|
|
138
140
|
2.times { thread_pool << 1 }
|
139
141
|
thread_pool.close
|
142
|
+
|
143
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(
|
144
|
+
/waiting to process \d+ task\(s\)/,
|
145
|
+
)
|
146
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(/foo.+closed/)
|
140
147
|
end
|
141
148
|
|
142
149
|
it "waits until the queue gets empty" do
|
@@ -144,7 +151,7 @@ RSpec.describe Airbrake::ThreadPool do
|
|
144
151
|
worker_size: 1, queue_size: 2, block: proc {},
|
145
152
|
)
|
146
153
|
|
147
|
-
10.times {
|
154
|
+
10.times { thread_pool << 1 }
|
148
155
|
thread_pool.close
|
149
156
|
expect(thread_pool.backlog).to be_zero
|
150
157
|
end
|
@@ -153,17 +160,17 @@ RSpec.describe Airbrake::ThreadPool do
|
|
153
160
|
context "when it was already closed" do
|
154
161
|
it "doesn't increase the queue size" do
|
155
162
|
begin
|
156
|
-
|
163
|
+
thread_pool.close
|
157
164
|
rescue Airbrake::Error
|
158
165
|
nil
|
159
166
|
end
|
160
167
|
|
161
|
-
expect(
|
168
|
+
expect(thread_pool.backlog).to be_zero
|
162
169
|
end
|
163
170
|
|
164
171
|
it "raises error" do
|
165
|
-
|
166
|
-
expect {
|
172
|
+
thread_pool.close
|
173
|
+
expect { thread_pool.close }.to raise_error(
|
167
174
|
Airbrake::Error, 'this thread pool is closed already'
|
168
175
|
)
|
169
176
|
end
|
@@ -171,17 +178,19 @@ RSpec.describe Airbrake::ThreadPool do
|
|
171
178
|
end
|
172
179
|
|
173
180
|
describe "#spawn_workers" do
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
expect(
|
181
|
+
after { thread_pool.close }
|
182
|
+
|
183
|
+
it "spawns an enclosed thread group" do
|
184
|
+
expect(thread_pool.workers).to be_a(ThreadGroup)
|
185
|
+
expect(thread_pool.workers).to be_enclosed
|
186
|
+
end
|
178
187
|
|
179
|
-
|
188
|
+
it "spawns threads that are alive" do
|
189
|
+
expect(thread_pool.workers.list).to all(be_alive)
|
180
190
|
end
|
181
191
|
|
182
192
|
it "spawns exactly `workers_size` workers" do
|
183
|
-
expect(
|
184
|
-
subject.close
|
193
|
+
expect(thread_pool.workers.list.size).to eq(worker_size)
|
185
194
|
end
|
186
195
|
end
|
187
196
|
end
|
data/spec/time_truncate_spec.rb
CHANGED
@@ -1,13 +1,30 @@
|
|
1
1
|
RSpec.describe Airbrake::TimeTruncate do
|
2
|
+
time = Time.new(2018, 1, 1, 0, 0, 20, 0)
|
3
|
+
time_with_zone = Time.new(2018, 1, 1, 0, 0, 20, '-05:00')
|
4
|
+
|
2
5
|
describe "#utc_truncate_minutes" do
|
3
|
-
|
4
|
-
time
|
5
|
-
|
6
|
+
shared_examples 'time conversion' do |t|
|
7
|
+
it "truncates the time to the floor minute and returns an RFC3339 timestamp" do
|
8
|
+
expect(described_class.utc_truncate_minutes(t))
|
9
|
+
.to eq('2018-01-01T00:00:00+00:00')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "converts time with zone to UTC" do
|
13
|
+
expect(described_class.utc_truncate_minutes(time_with_zone))
|
14
|
+
.to eq('2018-01-01T05:00:00+00:00')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the time argument is a Time object" do
|
19
|
+
include_examples 'time conversion', time
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when the time argument is a Float" do
|
23
|
+
include_examples 'time conversion', time.to_f
|
6
24
|
end
|
7
25
|
|
8
|
-
|
9
|
-
time
|
10
|
-
expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T05:00:00+00:00')
|
26
|
+
context "when the time argument is an Integer" do
|
27
|
+
include_examples 'time conversion', time.to_i
|
11
28
|
end
|
12
29
|
end
|
13
30
|
end
|
data/spec/timed_trace_spec.rb
CHANGED
@@ -1,50 +1,52 @@
|
|
1
1
|
RSpec.describe Airbrake::TimedTrace do
|
2
|
+
subject(:timed_trace) { described_class.new }
|
3
|
+
|
2
4
|
describe ".span" do
|
3
5
|
it "returns a timed trace" do
|
4
|
-
expect(described_class.span('operation') {}).to be_a(described_class)
|
6
|
+
expect(described_class.span('operation') { anything }).to be_a(described_class)
|
5
7
|
end
|
6
8
|
|
7
9
|
it "returns a timed trace with a stopped span" do
|
8
|
-
timed_trace = described_class.span('operation') {}
|
10
|
+
timed_trace = described_class.span('operation') { anything }
|
9
11
|
expect(timed_trace.spans).to match('operation' => be > 0)
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
15
|
describe "#span" do
|
14
16
|
it "captures a span" do
|
15
|
-
|
16
|
-
expect(
|
17
|
+
timed_trace.span('operation') { anything }
|
18
|
+
expect(timed_trace.spans).to match('operation' => be > 0)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
describe "#start_span" do
|
21
23
|
context "when called once" do
|
22
24
|
it "returns true" do
|
23
|
-
expect(
|
25
|
+
expect(timed_trace.start_span('operation')).to eq(true)
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
29
|
context "when called multiple times" do
|
28
|
-
before {
|
30
|
+
before { timed_trace.start_span('operation') }
|
29
31
|
|
30
32
|
it "returns false" do
|
31
|
-
expect(
|
33
|
+
expect(timed_trace.start_span('operation')).to eq(false)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
context "when another span was started" do
|
36
|
-
before {
|
38
|
+
before { timed_trace.start_span('operation') }
|
37
39
|
|
38
40
|
it "returns true" do
|
39
|
-
expect(
|
41
|
+
expect(timed_trace.start_span('another operation')).to eq(true)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
context "when #spans was called" do
|
44
|
-
before {
|
46
|
+
before { timed_trace.start_span('operation') }
|
45
47
|
|
46
48
|
it "returns spans with zero values" do
|
47
|
-
expect(
|
49
|
+
expect(timed_trace.spans).to eq('operation' => 0.0)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -52,35 +54,35 @@ RSpec.describe Airbrake::TimedTrace do
|
|
52
54
|
describe "#stop_span" do
|
53
55
|
context "when #start_span wasn't invoked" do
|
54
56
|
it "returns false" do
|
55
|
-
expect(
|
57
|
+
expect(timed_trace.stop_span('operation')).to eq(false)
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
context "when #start_span was invoked" do
|
60
|
-
before {
|
62
|
+
before { timed_trace.start_span('operation') }
|
61
63
|
|
62
64
|
it "returns true" do
|
63
|
-
expect(
|
65
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
67
69
|
context "when multiple spans were started" do
|
68
70
|
before do
|
69
|
-
|
70
|
-
|
71
|
+
timed_trace.start_span('operation')
|
72
|
+
timed_trace.start_span('another operation')
|
71
73
|
end
|
72
74
|
|
73
75
|
context "and when stopping in LIFO order" do
|
74
76
|
it "returns true for all spans" do
|
75
|
-
expect(
|
76
|
-
expect(
|
77
|
+
expect(timed_trace.stop_span('another operation')).to eq(true)
|
78
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
80
82
|
context "and when stopping in FIFO order" do
|
81
83
|
it "returns true for all spans" do
|
82
|
-
expect(
|
83
|
-
expect(
|
84
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
85
|
+
expect(timed_trace.stop_span('another operation')).to eq(true)
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
@@ -89,33 +91,33 @@ RSpec.describe Airbrake::TimedTrace do
|
|
89
91
|
describe "#spans" do
|
90
92
|
context "when no spans were captured" do
|
91
93
|
it "returns an empty hash" do
|
92
|
-
expect(
|
94
|
+
expect(timed_trace.spans).to eq({})
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
96
98
|
context "when a span was captured" do
|
97
99
|
before do
|
98
|
-
|
99
|
-
|
100
|
+
timed_trace.start_span('operation')
|
101
|
+
timed_trace.stop_span('operation')
|
100
102
|
end
|
101
103
|
|
102
104
|
it "returns a Hash with the corresponding span" do
|
103
|
-
|
104
|
-
expect(
|
105
|
+
timed_trace.stop_span('operation')
|
106
|
+
expect(timed_trace.spans).to match('operation' => be > 0)
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
110
|
context "when multiple spans were captured" do
|
109
111
|
before do
|
110
|
-
|
111
|
-
|
112
|
+
timed_trace.start_span('operation')
|
113
|
+
timed_trace.stop_span('operation')
|
112
114
|
|
113
|
-
|
114
|
-
|
115
|
+
timed_trace.start_span('another operation')
|
116
|
+
timed_trace.stop_span('another operation')
|
115
117
|
end
|
116
118
|
|
117
119
|
it "returns a Hash with all spans" do
|
118
|
-
expect(
|
120
|
+
expect(timed_trace.spans).to match(
|
119
121
|
'operation' => be > 0,
|
120
122
|
'another operation' => be > 0,
|
121
123
|
)
|
data/spec/truncator_spec.rb
CHANGED
@@ -4,18 +4,18 @@ RSpec.describe Airbrake::Truncator do
|
|
4
4
|
end
|
5
5
|
|
6
6
|
describe "#truncate" do
|
7
|
+
subject(:truncator) { described_class.new(max_size).truncate(object) }
|
8
|
+
|
7
9
|
let(:max_size) { 3 }
|
8
10
|
let(:truncated) { '[Truncated]' }
|
9
11
|
let(:max_len) { max_size + truncated.length }
|
10
12
|
|
11
|
-
subject { described_class.new(max_size).truncate(object) }
|
12
|
-
|
13
13
|
context "given a frozen string" do
|
14
14
|
let(:object) { multiply_by_2_max_len('a') }
|
15
15
|
|
16
16
|
it "returns a new truncated frozen string" do
|
17
|
-
expect(
|
18
|
-
expect(
|
17
|
+
expect(truncator.length).to eq(max_len)
|
18
|
+
expect(truncator).to be_frozen
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -29,16 +29,27 @@ RSpec.describe Airbrake::Truncator do
|
|
29
29
|
}.freeze
|
30
30
|
end
|
31
31
|
|
32
|
-
it "returns a
|
33
|
-
expect(
|
34
|
-
|
32
|
+
it "returns a hash of the same size" do
|
33
|
+
expect(truncator.size).to eq(max_size)
|
34
|
+
end
|
35
35
|
|
36
|
-
|
36
|
+
it "returns a frozen hash" do
|
37
|
+
expect(truncator).to be_frozen
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns a hash with truncated values" do
|
41
|
+
expect(truncator).to eq(
|
37
42
|
banana: 'aaa[Truncated]', kiwi: 'bbb[Truncated]', strawberry: 'c',
|
38
43
|
)
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns a hash with truncated strings that are frozen" do
|
47
|
+
expect(truncator[:banana]).to be_frozen
|
48
|
+
expect(truncator[:kiwi]).to be_frozen
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns a hash unfrozen untruncated strings" do
|
52
|
+
expect(truncator[:strawberry]).not_to be_frozen
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
@@ -52,14 +63,25 @@ RSpec.describe Airbrake::Truncator do
|
|
52
63
|
].freeze
|
53
64
|
end
|
54
65
|
|
55
|
-
it "returns
|
56
|
-
expect(
|
57
|
-
|
66
|
+
it "returns an array of the same size" do
|
67
|
+
expect(truncator.size).to eq(max_size)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns a frozen array" do
|
71
|
+
expect(truncator).to be_frozen
|
72
|
+
end
|
58
73
|
|
59
|
-
|
60
|
-
expect(
|
61
|
-
|
62
|
-
|
74
|
+
it "returns an array with truncated values" do
|
75
|
+
expect(truncator).to eq(['aaa[Truncated]', 'b', 'ccc[Truncated]'])
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns an array with truncated strings that are frozen" do
|
79
|
+
expect(truncator[0]).to be_frozen
|
80
|
+
expect(truncator[2]).to be_frozen
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns an array with unfrozen untruncated strings" do
|
84
|
+
expect(truncator[1]).not_to be_frozen
|
63
85
|
end
|
64
86
|
end
|
65
87
|
|
@@ -73,14 +95,16 @@ RSpec.describe Airbrake::Truncator do
|
|
73
95
|
]).freeze
|
74
96
|
end
|
75
97
|
|
76
|
-
it "returns a
|
77
|
-
expect(
|
78
|
-
|
98
|
+
it "returns a set of the same size" do
|
99
|
+
expect(truncator.size).to eq(max_size)
|
100
|
+
end
|
79
101
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
102
|
+
it "returns a frozen set" do
|
103
|
+
expect(truncator).to be_frozen
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns a set with truncated values" do
|
107
|
+
expect(truncator).to eq(Set.new(['aaa[Truncated]', 'b', 'ccc[Truncated]']))
|
84
108
|
end
|
85
109
|
end
|
86
110
|
|
@@ -93,11 +117,16 @@ RSpec.describe Airbrake::Truncator do
|
|
93
117
|
obj.freeze
|
94
118
|
end
|
95
119
|
|
96
|
-
it "
|
97
|
-
expect(
|
98
|
-
|
120
|
+
it "returns a string of a max len size" do
|
121
|
+
expect(truncator.length).to eq(max_len)
|
122
|
+
end
|
99
123
|
|
100
|
-
|
124
|
+
it "returns a frozen object" do
|
125
|
+
expect(truncator).to be_frozen
|
126
|
+
end
|
127
|
+
|
128
|
+
it "converts the object to truncated JSON" do
|
129
|
+
expect(truncator).to eq('{"o[Truncated]')
|
101
130
|
end
|
102
131
|
end
|
103
132
|
|
@@ -110,8 +139,8 @@ RSpec.describe Airbrake::Truncator do
|
|
110
139
|
end
|
111
140
|
|
112
141
|
it "converts the object to a truncated string" do
|
113
|
-
expect(
|
114
|
-
expect(
|
142
|
+
expect(truncator.length).to eq(max_len)
|
143
|
+
expect(truncator).to eq('#<O[Truncated]')
|
115
144
|
end
|
116
145
|
end
|
117
146
|
|
@@ -134,7 +163,7 @@ RSpec.describe Airbrake::Truncator do
|
|
134
163
|
end
|
135
164
|
|
136
165
|
it "prevents recursion" do
|
137
|
-
expect(
|
166
|
+
expect(truncator).to eq(['aaa[Truncated]', 'bb', '[Circular]'])
|
138
167
|
end
|
139
168
|
end
|
140
169
|
|
@@ -149,8 +178,8 @@ RSpec.describe Airbrake::Truncator do
|
|
149
178
|
end
|
150
179
|
|
151
180
|
it "prevents recursion" do
|
152
|
-
expect(
|
153
|
-
expect(
|
181
|
+
expect(truncator).to eq(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]'])
|
182
|
+
expect(truncator).to be_frozen
|
154
183
|
end
|
155
184
|
end
|
156
185
|
|
@@ -165,10 +194,10 @@ RSpec.describe Airbrake::Truncator do
|
|
165
194
|
end
|
166
195
|
|
167
196
|
it "prevents recursion" do
|
168
|
-
expect(
|
197
|
+
expect(truncator).to eq(
|
169
198
|
Set.new(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]']),
|
170
199
|
)
|
171
|
-
expect(
|
200
|
+
expect(truncator).to be_frozen
|
172
201
|
end
|
173
202
|
end
|
174
203
|
|
@@ -182,10 +211,10 @@ RSpec.describe Airbrake::Truncator do
|
|
182
211
|
end
|
183
212
|
|
184
213
|
it "truncates the long strings" do
|
185
|
-
expect(
|
214
|
+
expect(truncator).to eq(
|
186
215
|
a: 'aaa[Truncated]', b: 'bbb[Truncated]', c: { d: 'ddd[Truncated]', e: 'e' },
|
187
216
|
)
|
188
|
-
expect(
|
217
|
+
expect(truncator).to be_frozen
|
189
218
|
end
|
190
219
|
end
|
191
220
|
|
@@ -193,7 +222,7 @@ RSpec.describe Airbrake::Truncator do
|
|
193
222
|
let(:object) { "€€€€€" }
|
194
223
|
|
195
224
|
it "truncates the string" do
|
196
|
-
expect(
|
225
|
+
expect(truncator).to eq("€€€[Truncated]")
|
197
226
|
end
|
198
227
|
end
|
199
228
|
|
@@ -205,8 +234,8 @@ RSpec.describe Airbrake::Truncator do
|
|
205
234
|
end
|
206
235
|
|
207
236
|
it "converts and truncates the string to UTF-8" do
|
208
|
-
expect(
|
209
|
-
expect(
|
237
|
+
expect(truncator).to eq("���[Truncated]")
|
238
|
+
expect(truncator).to be_frozen
|
210
239
|
end
|
211
240
|
end
|
212
241
|
|
@@ -224,14 +253,14 @@ RSpec.describe Airbrake::Truncator do
|
|
224
253
|
end
|
225
254
|
|
226
255
|
it "truncates values" do
|
227
|
-
expect(
|
256
|
+
expect(truncator).to eq(
|
228
257
|
errors: [
|
229
258
|
{ file: 'a' },
|
230
259
|
{ file: 'a' },
|
231
260
|
hashie.new.merge(file: 'bcd[Truncated]'),
|
232
261
|
],
|
233
262
|
)
|
234
|
-
expect(
|
263
|
+
expect(truncator).to be_frozen
|
235
264
|
end
|
236
265
|
end
|
237
266
|
end
|