airbrake-ruby 5.2.0 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby.rb +3 -2
  3. data/lib/airbrake-ruby/async_sender.rb +3 -1
  4. data/lib/airbrake-ruby/context.rb +51 -0
  5. data/lib/airbrake-ruby/filter_chain.rb +2 -0
  6. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  7. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  8. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  9. data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
  10. data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
  11. data/lib/airbrake-ruby/filters/sql_filter.rb +2 -2
  12. data/lib/airbrake-ruby/filters/thread_filter.rb +1 -1
  13. data/lib/airbrake-ruby/ignorable.rb +0 -2
  14. data/lib/airbrake-ruby/notice_notifier.rb +3 -4
  15. data/lib/airbrake-ruby/performance_notifier.rb +1 -2
  16. data/lib/airbrake-ruby/remote_settings/settings_data.rb +1 -1
  17. data/lib/airbrake-ruby/tdigest.rb +7 -6
  18. data/lib/airbrake-ruby/thread_pool.rb +5 -3
  19. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  20. data/lib/airbrake-ruby/version.rb +1 -1
  21. data/spec/airbrake_spec.rb +139 -76
  22. data/spec/async_sender_spec.rb +10 -8
  23. data/spec/backtrace_spec.rb +13 -10
  24. data/spec/benchmark_spec.rb +5 -3
  25. data/spec/code_hunk_spec.rb +24 -15
  26. data/spec/config/processor_spec.rb +12 -4
  27. data/spec/config/validator_spec.rb +5 -2
  28. data/spec/config_spec.rb +24 -16
  29. data/spec/context_spec.rb +54 -0
  30. data/spec/deploy_notifier_spec.rb +6 -4
  31. data/spec/file_cache_spec.rb +1 -0
  32. data/spec/filter_chain_spec.rb +29 -24
  33. data/spec/filters/context_filter_spec.rb +14 -5
  34. data/spec/filters/dependency_filter_spec.rb +3 -1
  35. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  36. data/spec/filters/gem_root_filter_spec.rb +5 -2
  37. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  38. data/spec/filters/git_repository_filter.rb +9 -9
  39. data/spec/filters/git_revision_filter_spec.rb +19 -19
  40. data/spec/filters/keys_allowlist_spec.rb +25 -16
  41. data/spec/filters/keys_blocklist_spec.rb +25 -18
  42. data/spec/filters/root_directory_filter_spec.rb +3 -3
  43. data/spec/filters/sql_filter_spec.rb +26 -26
  44. data/spec/filters/system_exit_filter_spec.rb +4 -2
  45. data/spec/filters/thread_filter_spec.rb +15 -13
  46. data/spec/loggable_spec.rb +2 -2
  47. data/spec/monotonic_time_spec.rb +8 -6
  48. data/spec/nested_exception_spec.rb +46 -46
  49. data/spec/notice_notifier/options_spec.rb +23 -13
  50. data/spec/notice_notifier_spec.rb +52 -47
  51. data/spec/notice_spec.rb +6 -2
  52. data/spec/performance_notifier_spec.rb +67 -60
  53. data/spec/promise_spec.rb +38 -32
  54. data/spec/remote_settings/callback_spec.rb +27 -8
  55. data/spec/remote_settings/settings_data_spec.rb +4 -4
  56. data/spec/remote_settings_spec.rb +18 -8
  57. data/spec/response_spec.rb +34 -12
  58. data/spec/stashable_spec.rb +5 -5
  59. data/spec/stat_spec.rb +7 -5
  60. data/spec/sync_sender_spec.rb +49 -16
  61. data/spec/tdigest_spec.rb +60 -55
  62. data/spec/thread_pool_spec.rb +65 -55
  63. data/spec/time_truncate_spec.rb +4 -2
  64. data/spec/timed_trace_spec.rb +32 -30
  65. data/spec/truncator_spec.rb +72 -43
  66. metadata +51 -48
@@ -1,9 +1,5 @@
1
1
  RSpec.describe Airbrake::ThreadPool do
2
- let(:tasks) { [] }
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 = subject << 1
17
- subject.close
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
- subject << 2
23
- subject << 1
24
- subject.close
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
- before do
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,34 @@ 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 = subject << 1
44
- subject.close
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 { subject << 1 }
50
- subject.close
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
- expect(Airbrake::Loggable.instance).to receive(:error).with(
58
+ allow(Airbrake::Loggable.instance).to receive(:error)
59
+
60
+ 15.times { full_thread_pool << 1 }
61
+ full_thread_pool.close
62
+
63
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
57
64
  /reached its capacity/,
58
65
  ).exactly(15).times
59
-
60
- 15.times { subject << 1 }
61
- subject.close
62
66
  end
63
67
  end
64
68
  end
@@ -67,22 +71,22 @@ RSpec.describe Airbrake::ThreadPool do
67
71
  let(:worker_size) { 0 }
68
72
 
69
73
  it "returns the size of the queue" do
70
- subject << 1
71
- expect(subject.backlog).to eq(1)
74
+ thread_pool << 1
75
+ expect(thread_pool.backlog).to eq(1)
72
76
  end
73
77
  end
74
78
 
75
79
  describe "#has_workers?" do
76
80
  it "returns false when the thread pool is not closed, but has 0 workers" do
77
- subject.workers.list.each do |worker|
81
+ thread_pool.workers.list.each do |worker|
78
82
  worker.kill.join
79
83
  end
80
- expect(subject).not_to have_workers
84
+ expect(thread_pool).not_to have_workers
81
85
  end
82
86
 
83
87
  it "returns false when the thread pool is closed" do
84
- subject.close
85
- expect(subject).not_to have_workers
88
+ thread_pool.close
89
+ expect(thread_pool).not_to have_workers
86
90
  end
87
91
 
88
92
  describe "forking behavior" do
@@ -93,20 +97,22 @@ RSpec.describe Airbrake::ThreadPool do
93
97
  end
94
98
  end
95
99
 
100
+ # rubocop:disable RSpec/MultipleExpectations
96
101
  it "respawns workers on fork()" do
97
- pid = fork { expect(subject).to have_workers }
102
+ pid = fork { expect(thread_pool).to have_workers }
98
103
  Process.wait(pid)
99
- subject.close
104
+ thread_pool.close
100
105
 
101
106
  expect(Process.last_status).to be_success
102
- expect(subject).not_to have_workers
107
+ expect(thread_pool).not_to have_workers
103
108
  end
109
+ # rubocop:enable RSpec/MultipleExpectations
104
110
 
105
111
  it "ensures that a new thread group is created per process" do
106
- subject << 1
107
- pid = fork { subject.has_workers? }
112
+ thread_pool << 1
113
+ pid = fork { thread_pool.has_workers? }
108
114
  Process.wait(pid)
109
- subject.close
115
+ thread_pool.close
110
116
 
111
117
  expect(Process.last_status).to be_success
112
118
  end
@@ -116,27 +122,29 @@ RSpec.describe Airbrake::ThreadPool do
116
122
  describe "#close" do
117
123
  context "when there's no work to do" do
118
124
  it "joins the spawned thread" do
119
- workers = subject.workers.list
125
+ workers = thread_pool.workers.list
120
126
  expect(workers).to all(be_alive)
121
127
 
122
- subject.close
128
+ thread_pool.close
123
129
  expect(workers).to all(be_stop)
124
130
  end
125
131
  end
126
132
 
127
133
  context "when there's some work to do" do
128
134
  it "logs how many tasks are left to process" do
129
- thread_pool = described_class.new(
130
- worker_size: 0, queue_size: 2, block: proc {},
131
- )
135
+ allow(Airbrake::Loggable.instance).to receive(:debug)
132
136
 
133
- expect(Airbrake::Loggable.instance).to receive(:debug).with(
134
- /waiting to process \d+ task\(s\)/,
137
+ thread_pool = described_class.new(
138
+ name: 'foo', worker_size: 0, queue_size: 2, block: proc {},
135
139
  )
136
- expect(Airbrake::Loggable.instance).to receive(:debug).with(/closed/)
137
140
 
138
141
  2.times { thread_pool << 1 }
139
142
  thread_pool.close
143
+
144
+ expect(Airbrake::Loggable.instance).to have_received(:debug).with(
145
+ /waiting to process \d+ task\(s\)/,
146
+ )
147
+ expect(Airbrake::Loggable.instance).to have_received(:debug).with(/foo.+closed/)
140
148
  end
141
149
 
142
150
  it "waits until the queue gets empty" do
@@ -144,7 +152,7 @@ RSpec.describe Airbrake::ThreadPool do
144
152
  worker_size: 1, queue_size: 2, block: proc {},
145
153
  )
146
154
 
147
- 10.times { subject << 1 }
155
+ 10.times { thread_pool << 1 }
148
156
  thread_pool.close
149
157
  expect(thread_pool.backlog).to be_zero
150
158
  end
@@ -153,17 +161,17 @@ RSpec.describe Airbrake::ThreadPool do
153
161
  context "when it was already closed" do
154
162
  it "doesn't increase the queue size" do
155
163
  begin
156
- subject.close
164
+ thread_pool.close
157
165
  rescue Airbrake::Error
158
166
  nil
159
167
  end
160
168
 
161
- expect(subject.backlog).to be_zero
169
+ expect(thread_pool.backlog).to be_zero
162
170
  end
163
171
 
164
172
  it "raises error" do
165
- subject.close
166
- expect { subject.close }.to raise_error(
173
+ thread_pool.close
174
+ expect { thread_pool.close }.to raise_error(
167
175
  Airbrake::Error, 'this thread pool is closed already'
168
176
  )
169
177
  end
@@ -171,17 +179,19 @@ RSpec.describe Airbrake::ThreadPool do
171
179
  end
172
180
 
173
181
  describe "#spawn_workers" do
174
- it "spawns alive threads in an enclosed ThreadGroup" do
175
- expect(subject.workers).to be_a(ThreadGroup)
176
- expect(subject.workers.list).to all(be_alive)
177
- expect(subject.workers).to be_enclosed
182
+ after { thread_pool.close }
183
+
184
+ it "spawns an enclosed thread group" do
185
+ expect(thread_pool.workers).to be_a(ThreadGroup)
186
+ expect(thread_pool.workers).to be_enclosed
187
+ end
178
188
 
179
- subject.close
189
+ it "spawns threads that are alive" do
190
+ expect(thread_pool.workers.list).to all(be_alive)
180
191
  end
181
192
 
182
193
  it "spawns exactly `workers_size` workers" do
183
- expect(subject.workers.list.size).to eq(worker_size)
184
- subject.close
194
+ expect(thread_pool.workers.list.size).to eq(worker_size)
185
195
  end
186
196
  end
187
197
  end
@@ -2,12 +2,14 @@ RSpec.describe Airbrake::TimeTruncate do
2
2
  describe "#utc_truncate_minutes" do
3
3
  it "truncates time to the floor minute and returns an RFC3339 timestamp" do
4
4
  time = Time.new(2018, 1, 1, 0, 0, 20, 0)
5
- expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T00:00:00+00:00')
5
+ expect(described_class.utc_truncate_minutes(time))
6
+ .to eq('2018-01-01T00:00:00+00:00')
6
7
  end
7
8
 
8
9
  it "converts time with zone to UTC" do
9
10
  time = Time.new(2018, 1, 1, 0, 0, 20, '-05:00')
10
- expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T05:00:00+00:00')
11
+ expect(described_class.utc_truncate_minutes(time))
12
+ .to eq('2018-01-01T05:00:00+00:00')
11
13
  end
12
14
  end
13
15
  end
@@ -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
- subject.span('operation') {}
16
- expect(subject.spans).to match('operation' => be > 0)
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(subject.start_span('operation')).to eq(true)
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 { subject.start_span('operation') }
30
+ before { timed_trace.start_span('operation') }
29
31
 
30
32
  it "returns false" do
31
- expect(subject.start_span('operation')).to eq(false)
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 { subject.start_span('operation') }
38
+ before { timed_trace.start_span('operation') }
37
39
 
38
40
  it "returns true" do
39
- expect(subject.start_span('another operation')).to eq(true)
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 { subject.start_span('operation') }
46
+ before { timed_trace.start_span('operation') }
45
47
 
46
48
  it "returns spans with zero values" do
47
- expect(subject.spans).to eq('operation' => 0.0)
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(subject.stop_span('operation')).to eq(false)
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 { subject.start_span('operation') }
62
+ before { timed_trace.start_span('operation') }
61
63
 
62
64
  it "returns true" do
63
- expect(subject.stop_span('operation')).to eq(true)
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
- subject.start_span('operation')
70
- subject.start_span('another operation')
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(subject.stop_span('another operation')).to eq(true)
76
- expect(subject.stop_span('operation')).to eq(true)
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(subject.stop_span('operation')).to eq(true)
83
- expect(subject.stop_span('another operation')).to eq(true)
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(subject.spans).to eq({})
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
- subject.start_span('operation')
99
- subject.stop_span('operation')
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
- subject.stop_span('operation')
104
- expect(subject.spans).to match('operation' => be > 0)
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
- subject.start_span('operation')
111
- subject.stop_span('operation')
112
+ timed_trace.start_span('operation')
113
+ timed_trace.stop_span('operation')
112
114
 
113
- subject.start_span('another operation')
114
- subject.stop_span('another operation')
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(subject.spans).to match(
120
+ expect(timed_trace.spans).to match(
119
121
  'operation' => be > 0,
120
122
  'another operation' => be > 0,
121
123
  )
@@ -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(subject.length).to eq(max_len)
18
- expect(subject).to be_frozen
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 new truncated frozen hash" do
33
- expect(subject.size).to eq(max_size)
34
- expect(subject).to be_frozen
32
+ it "returns a hash of the same size" do
33
+ expect(truncator.size).to eq(max_size)
34
+ end
35
35
 
36
- expect(subject).to eq(
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
- expect(subject[:banana]).to be_frozen
40
- expect(subject[:kiwi]).to be_frozen
41
- expect(subject[:strawberry]).not_to be_frozen
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 a new truncated frozen array" do
56
- expect(subject.size).to eq(max_size)
57
- expect(subject).to be_frozen
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
- expect(subject).to eq(['aaa[Truncated]', 'b', 'ccc[Truncated]'])
60
- expect(subject[0]).to be_frozen
61
- expect(subject[1]).not_to be_frozen
62
- expect(subject[2]).to be_frozen
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 new truncated frozen array" do
77
- expect(subject.size).to eq(max_size)
78
- expect(subject).to be_frozen
98
+ it "returns a set of the same size" do
99
+ expect(truncator.size).to eq(max_size)
100
+ end
79
101
 
80
- expect(subject).to eq(
81
- Set.new(['aaa[Truncated]', 'b', 'ccc[Truncated]']),
82
- )
83
- expect(subject).to be_frozen
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 "converts the object to truncated JSON" do
97
- expect(subject.length).to eq(max_len)
98
- expect(subject).to be_frozen
120
+ it "returns a string of a max len size" do
121
+ expect(truncator.length).to eq(max_len)
122
+ end
99
123
 
100
- expect(subject).to eq('{"o[Truncated]')
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(subject.length).to eq(max_len)
114
- expect(subject).to eq('#<O[Truncated]')
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(subject).to eq(['aaa[Truncated]', 'bb', '[Circular]'])
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(subject).to eq(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]'])
153
- expect(subject).to be_frozen
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(subject).to eq(
197
+ expect(truncator).to eq(
169
198
  Set.new(['[Circular]', { k: '[Circular]' }, 'aaa[Truncated]']),
170
199
  )
171
- expect(subject).to be_frozen
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(subject).to eq(
214
+ expect(truncator).to eq(
186
215
  a: 'aaa[Truncated]', b: 'bbb[Truncated]', c: { d: 'ddd[Truncated]', e: 'e' },
187
216
  )
188
- expect(subject).to be_frozen
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(subject).to eq("€€€[Truncated]")
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(subject).to eq("���[Truncated]")
209
- expect(subject).to be_frozen
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(subject).to eq(
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(subject).to be_frozen
263
+ expect(truncator).to be_frozen
235
264
  end
236
265
  end
237
266
  end