airbrake-ruby 6.1.0-java → 6.1.1-java

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  3. data/lib/airbrake-ruby/nested_exception.rb +10 -1
  4. data/lib/airbrake-ruby/notice.rb +5 -3
  5. data/lib/airbrake-ruby/version.rb +1 -1
  6. metadata +4 -122
  7. data/spec/airbrake_spec.rb +0 -522
  8. data/spec/async_sender_spec.rb +0 -65
  9. data/spec/backtrace_spec.rb +0 -430
  10. data/spec/benchmark_spec.rb +0 -35
  11. data/spec/code_hunk_spec.rb +0 -124
  12. data/spec/config/processor_spec.rb +0 -167
  13. data/spec/config/validator_spec.rb +0 -204
  14. data/spec/config_spec.rb +0 -188
  15. data/spec/context_spec.rb +0 -54
  16. data/spec/deploy_notifier_spec.rb +0 -50
  17. data/spec/file_cache_spec.rb +0 -35
  18. data/spec/filter_chain_spec.rb +0 -124
  19. data/spec/filters/context_filter_spec.rb +0 -32
  20. data/spec/filters/dependency_filter_spec.rb +0 -14
  21. data/spec/filters/exception_attributes_filter_spec.rb +0 -52
  22. data/spec/filters/gem_root_filter_spec.rb +0 -44
  23. data/spec/filters/git_last_checkout_filter_spec.rb +0 -61
  24. data/spec/filters/git_repository_filter_spec.rb +0 -72
  25. data/spec/filters/git_revision_filter_spec.rb +0 -126
  26. data/spec/filters/keys_allowlist_spec.rb +0 -204
  27. data/spec/filters/keys_blocklist_spec.rb +0 -242
  28. data/spec/filters/root_directory_filter_spec.rb +0 -39
  29. data/spec/filters/sql_filter_spec.rb +0 -274
  30. data/spec/filters/system_exit_filter_spec.rb +0 -16
  31. data/spec/filters/thread_filter_spec.rb +0 -281
  32. data/spec/fixtures/notroot.txt +0 -7
  33. data/spec/fixtures/project_root/code.rb +0 -221
  34. data/spec/fixtures/project_root/empty_file.rb +0 -0
  35. data/spec/fixtures/project_root/long_line.txt +0 -1
  36. data/spec/fixtures/project_root/short_file.rb +0 -3
  37. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
  38. data/spec/helpers.rb +0 -9
  39. data/spec/ignorable_spec.rb +0 -14
  40. data/spec/inspectable_spec.rb +0 -45
  41. data/spec/loggable_spec.rb +0 -17
  42. data/spec/monotonic_time_spec.rb +0 -25
  43. data/spec/nested_exception_spec.rb +0 -73
  44. data/spec/notice_notifier/options_spec.rb +0 -269
  45. data/spec/notice_notifier_spec.rb +0 -361
  46. data/spec/notice_spec.rb +0 -300
  47. data/spec/performance_breakdown_spec.rb +0 -11
  48. data/spec/performance_notifier_spec.rb +0 -645
  49. data/spec/promise_spec.rb +0 -203
  50. data/spec/query_spec.rb +0 -11
  51. data/spec/queue_spec.rb +0 -18
  52. data/spec/remote_settings/callback_spec.rb +0 -162
  53. data/spec/remote_settings/settings_data_spec.rb +0 -348
  54. data/spec/remote_settings_spec.rb +0 -201
  55. data/spec/request_spec.rb +0 -9
  56. data/spec/response_spec.rb +0 -110
  57. data/spec/spec_helper.rb +0 -100
  58. data/spec/stashable_spec.rb +0 -23
  59. data/spec/stat_spec.rb +0 -39
  60. data/spec/sync_sender_spec.rb +0 -168
  61. data/spec/tdigest_spec.rb +0 -235
  62. data/spec/thread_pool_spec.rb +0 -196
  63. data/spec/time_truncate_spec.rb +0 -30
  64. data/spec/timed_trace_spec.rb +0 -127
  65. data/spec/truncator_spec.rb +0 -267
data/spec/spec_helper.rb DELETED
@@ -1,100 +0,0 @@
1
- require 'simplecov'
2
- SimpleCov.start if ENV['COVERAGE']
3
-
4
- require 'airbrake-ruby'
5
-
6
- require 'rspec/its'
7
-
8
- require 'webmock'
9
- require 'webmock/rspec'
10
- require 'pry'
11
-
12
- require 'pathname'
13
- require 'webrick'
14
- require 'English'
15
- require 'base64'
16
- require 'pp'
17
-
18
- require 'helpers'
19
-
20
- RSpec.configure do |c|
21
- c.order = 'random'
22
- c.color = true
23
- c.disable_monkey_patching!
24
- c.include Helpers
25
- end
26
-
27
- Thread.abort_on_exception = true
28
-
29
- WebMock.disable_net_connect!(allow_localhost: true)
30
-
31
- class AirbrakeTestError < RuntimeError
32
- attr_reader :backtrace
33
-
34
- def initialize(*)
35
- super
36
- # rubocop:disable Layout/LineLength
37
- @backtrace = [
38
- "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb:23:in `<top (required)>'",
39
- "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'",
40
- "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'",
41
- "/home/kyrylo/code/airbrake/ruby/spec/airbrake_spec.rb:1:in `<top (required)>'",
42
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1327:in `load'",
43
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1327:in `block in load_spec_files'",
44
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1325:in `each'",
45
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1325:in `load_spec_files'",
46
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:102:in `setup'",
47
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:88:in `run'",
48
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:73:in `run'",
49
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:41:in `invoke'",
50
- "/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/exe/rspec:4:in `<main>'",
51
- ]
52
- # rubocop:enable Layout/LineLength
53
- end
54
-
55
- # rubocop:disable Naming/AccessorMethodName
56
- def set_backtrace(backtrace)
57
- @backtrace = backtrace
58
- end
59
- # rubocop:enable Naming/AccessorMethodName
60
-
61
- def message
62
- 'App crashed!'
63
- end
64
- end
65
-
66
- class JavaAirbrakeTestError < AirbrakeTestError
67
- def initialize(*)
68
- super
69
- # rubocop:disable Layout/LineLength
70
- @backtrace = [
71
- "org.jruby.java.invokers.InstanceMethodInvoker.call(InstanceMethodInvoker.java:26)",
72
- "org.jruby.ir.interpreter.Interpreter.INTERPRET_EVAL(Interpreter.java:126)",
73
- "org.jruby.RubyKernel$INVOKER$s$0$3$eval19.call(RubyKernel$INVOKER$s$0$3$eval19.gen)",
74
- "org.jruby.RubyKernel$INVOKER$s$0$0$loop.call(RubyKernel$INVOKER$s$0$0$loop.gen)",
75
- "org.jruby.runtime.IRBlockBody.doYield(IRBlockBody.java:139)",
76
- "org.jruby.RubyKernel$INVOKER$s$rbCatch19.call(RubyKernel$INVOKER$s$rbCatch19.gen)",
77
- "opt.rubies.jruby_minus_9_dot_0_dot_0_dot_0.bin.irb.invokeOther4:start(/opt/rubies/jruby-9.0.0.0/bin/irb)",
78
- "opt.rubies.jruby_minus_9_dot_0_dot_0_dot_0.bin.irb.RUBY$script(/opt/rubies/jruby-9.0.0.0/bin/irb:13)",
79
- "org.jruby.ir.Compiler$1.load(Compiler.java:111)",
80
- "org.jruby.Main.run(Main.java:225)",
81
- "org.jruby.Main.main(Main.java:197)",
82
- ]
83
- # rubocop:enable Layout/LineLength
84
- end
85
-
86
- def is_a?(*)
87
- true
88
- end
89
- end
90
-
91
- class Ruby21Error < RuntimeError
92
- attr_accessor :cause
93
-
94
- def self.raise_error(msg)
95
- ex = new(msg)
96
- ex.cause = $ERROR_INFO
97
-
98
- raise ex
99
- end
100
- end
@@ -1,23 +0,0 @@
1
- RSpec.describe Airbrake::Stashable do
2
- let(:klass) do
3
- mod = described_class
4
- Class.new { include(mod) }
5
- end
6
-
7
- describe "#stash" do
8
- subject(:instance) { klass.new }
9
-
10
- it "returns a hash" do
11
- expect(instance.stash).to be_a(Hash)
12
- end
13
-
14
- it "returns an empty hash" do
15
- expect(instance.stash).to be_empty
16
- end
17
-
18
- it "remembers what was put in the stash" do
19
- instance.stash[:foo] = 1
20
- expect(instance.stash[:foo]).to eq(1)
21
- end
22
- end
23
- end
data/spec/stat_spec.rb DELETED
@@ -1,39 +0,0 @@
1
- RSpec.describe Airbrake::Stat do
2
- subject(:stat) { described_class.new }
3
-
4
- describe "#to_h" do
5
- it "converts to a hash" do
6
- expect(stat.to_h).to eq(
7
- 'count' => 0,
8
- 'sum' => 0.0,
9
- 'sumsq' => 0.0,
10
- 'tdigest' => 'AAAAAkA0AAAAAAAAAAAAAA==',
11
- )
12
- end
13
- end
14
-
15
- describe "#increment_ms" do
16
- before { stat.increment_ms(1000) }
17
-
18
- its(:sum) { is_expected.to eq(1000) }
19
- its(:sumsq) { is_expected.to eq(1000000) }
20
-
21
- it "updates tdigest" do
22
- expect(stat.tdigest.size).to eq(1)
23
- end
24
- end
25
-
26
- describe "#inspect" do
27
- it "provides custom inspect output" do
28
- expect(stat.inspect).to eq(
29
- '#<struct Airbrake::Stat count=0, sum=0.0, sumsq=0.0>',
30
- )
31
- end
32
- end
33
-
34
- describe "#pretty_print" do
35
- it "is an alias of #inspect" do
36
- expect(stat.method(:pretty_print)).to eql(stat.method(:inspect))
37
- end
38
- end
39
- end
@@ -1,168 +0,0 @@
1
- RSpec.describe Airbrake::SyncSender do
2
- subject(:sync_sender) { described_class.new }
3
-
4
- before do
5
- Airbrake::Config.instance = Airbrake::Config.new(
6
- project_id: 1, project_key: 'banana',
7
- )
8
- end
9
-
10
- describe "#send" do
11
- let(:promise) { Airbrake::Promise.new }
12
-
13
- let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
14
- let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/1/notices' }
15
-
16
- before { stub_request(:post, endpoint).to_return(body: '{}') }
17
-
18
- it "sets the Content-Type header to JSON" do
19
- sync_sender.send({}, promise)
20
- expect(
21
- a_request(:post, endpoint).with(
22
- headers: { 'Content-Type' => 'application/json' },
23
- ),
24
- ).to have_been_made.once
25
- end
26
-
27
- it "sets the User-Agent header to the notifier slug" do
28
- sync_sender.send({}, promise)
29
- expect(
30
- a_request(:post, endpoint).with(
31
- headers: {
32
- 'User-Agent' => %r{
33
- airbrake-ruby/\d+\.\d+\.\d+(\.rc\.\d+)?\sRuby/\d+\.\d+\.\d+
34
- }x,
35
- },
36
- ),
37
- ).to have_been_made.once
38
- end
39
-
40
- it "sets the Authorization header to the project key" do
41
- sync_sender.send({}, promise)
42
- expect(
43
- a_request(:post, endpoint).with(
44
- headers: { 'Authorization' => 'Bearer banana' },
45
- ),
46
- ).to have_been_made.once
47
- end
48
-
49
- it "catches exceptions raised while sending" do
50
- # rubocop:disable RSpec/VerifiedDoubles
51
- https = double("foo")
52
- # rubocop:enable RSpec/VerifiedDoubles
53
-
54
- # rubocop:disable RSpec/SubjectStub
55
- allow(sync_sender).to receive(:build_https).and_return(https)
56
- # rubocop:enable RSpec/SubjectStub
57
-
58
- allow(https).to receive(:request).and_raise(StandardError.new('foo'))
59
-
60
- expect(sync_sender.send({}, promise)).to be_an(Airbrake::Promise)
61
- expect(promise.value).to eq('error' => '**Airbrake: HTTP error: foo')
62
- end
63
-
64
- it "logs exceptions raised while sending" do
65
- allow(Airbrake::Loggable.instance).to receive(:error)
66
-
67
- # rubocop:disable RSpec/VerifiedDoubles
68
- https = double("foo")
69
- # rubocop:enable RSpec/VerifiedDoubles
70
-
71
- # rubocop:disable RSpec/SubjectStub
72
- allow(sync_sender).to receive(:build_https).and_return(https)
73
- # rubocop:enable RSpec/SubjectStub
74
-
75
- allow(https).to receive(:request).and_raise(StandardError.new('foo'))
76
-
77
- sync_sender.send({}, promise)
78
-
79
- expect(Airbrake::Loggable.instance).to have_received(:error).with(
80
- /HTTP error: foo/,
81
- )
82
- end
83
-
84
- context "when request body is nil" do
85
- # rubocop:disable RSpec/MultipleExpectations
86
- it "doesn't send data" do
87
- allow(Airbrake::Loggable.instance).to receive(:error)
88
-
89
- allow_any_instance_of(Airbrake::Truncator)
90
- .to receive(:reduce_max_size).and_return(0)
91
-
92
- encoded = Base64.encode64("\xD3\xE6\xBC\x9D\xBA").encode!('ASCII-8BIT')
93
- bad_string = Base64.decode64(encoded)
94
-
95
- ex = AirbrakeTestError.new
96
- backtrace = []
97
- 10.times { backtrace << "bin/rails:3:in `<#{bad_string}>'" }
98
- ex.set_backtrace(backtrace)
99
-
100
- notice = Airbrake::Notice.new(ex)
101
-
102
- expect(sync_sender.send(notice, promise)).to be_an(Airbrake::Promise)
103
- expect(promise.value)
104
- .to match('error' => '**Airbrake: data was not sent because of missing body')
105
-
106
- expect(Airbrake::Loggable.instance).to have_received(:error).with(
107
- /data was not sent/,
108
- )
109
- expect(Airbrake::Loggable.instance).to have_received(:error).with(
110
- /truncation failed/,
111
- )
112
- end
113
- # rubocop:enable RSpec/MultipleExpectations
114
- end
115
-
116
- context "when IP is rate limited" do
117
- let(:endpoint) { %r{https://api.airbrake.io/api/v3/projects/1/notices} }
118
-
119
- before do
120
- stub_request(:post, endpoint).to_return(
121
- status: 429,
122
- body: '{"message":"IP is rate limited"}',
123
- headers: { 'X-RateLimit-Delay' => '1' },
124
- )
125
- end
126
-
127
- # rubocop:disable RSpec/MultipleExpectations
128
- it "returns error" do
129
- p1 = Airbrake::Promise.new
130
- sync_sender.send({}, p1)
131
- expect(p1.value).to match('error' => '**Airbrake: IP is rate limited')
132
-
133
- p2 = Airbrake::Promise.new
134
- sync_sender.send({}, p2)
135
- expect(p2.value).to match('error' => '**Airbrake: IP is rate limited')
136
-
137
- # Wait for X-RateLimit-Delay and then make a new request to make sure p2
138
- # was ignored (no request made for it).
139
- sleep 1
140
-
141
- p3 = Airbrake::Promise.new
142
- sync_sender.send({}, p3)
143
- expect(p3.value).to match('error' => '**Airbrake: IP is rate limited')
144
-
145
- expect(a_request(:post, endpoint)).to have_been_made.twice
146
- end
147
- # rubocop:enable RSpec/MultipleExpectations
148
- end
149
-
150
- context "when the provided method is :put" do
151
- before { stub_request(:put, endpoint).to_return(status: 200, body: '') }
152
-
153
- it "PUTs the request" do
154
- sender = described_class.new(:put)
155
- sender.send({}, promise)
156
- expect(a_request(:put, endpoint)).to have_been_made
157
- end
158
- end
159
-
160
- context "when the provided method is :post" do
161
- it "POSTs the request" do
162
- sender = described_class.new(:post)
163
- sender.send({}, promise)
164
- expect(a_request(:post, endpoint)).to have_been_made
165
- end
166
- end
167
- end
168
- end
data/spec/tdigest_spec.rb DELETED
@@ -1,235 +0,0 @@
1
- RSpec.describe Airbrake::TDigest do
2
- subject(:tdigest) { described_class.new }
3
-
4
- describe "byte serialization" do
5
- it "loads serialized data" do
6
- tdigest.push(60, 100)
7
- 10.times { tdigest.push(rand * 100) }
8
- bytes = tdigest.as_bytes
9
- new_tdigest = described_class.from_bytes(bytes)
10
- expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
11
- expect(new_tdigest.as_bytes).to eq(bytes)
12
- end
13
-
14
- it "handles zero size" do
15
- bytes = tdigest.as_bytes
16
- expect(described_class.from_bytes(bytes).size).to be_zero
17
- end
18
-
19
- it "preserves compression" do
20
- td = described_class.new(0.001)
21
- bytes = td.as_bytes
22
- new_tdigest = described_class.from_bytes(bytes)
23
- expect(new_tdigest.compression).to eq(td.compression)
24
- end
25
- end
26
-
27
- describe "small byte serialization" do
28
- it "loads serialized data" do
29
- 10.times { tdigest.push(10) }
30
- bytes = tdigest.as_small_bytes
31
- new_tdigest = described_class.from_bytes(bytes)
32
- # Expect some rounding error due to compression
33
- expect(new_tdigest.percentile(0.9).round(5)).to eq(
34
- tdigest.percentile(0.9).round(5),
35
- )
36
- expect(new_tdigest.as_small_bytes).to eq(bytes)
37
- end
38
-
39
- it "handles zero size" do
40
- bytes = tdigest.as_small_bytes
41
- expect(described_class.from_bytes(bytes).size).to be_zero
42
- end
43
- end
44
-
45
- describe "JSON serialization" do
46
- it "loads serialized data" do
47
- tdigest.push(60, 100)
48
- json = tdigest.as_json
49
- new_tdigest = described_class.from_json(json)
50
- expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
51
- end
52
- end
53
-
54
- describe "#percentile" do
55
- it "returns nil if empty" do
56
- expect(tdigest.percentile(0.90)).to be_nil # This should not crash
57
- end
58
-
59
- it "raises ArgumentError of input not between 0 and 1" do
60
- expect { tdigest.percentile(1.1) }.to raise_error(ArgumentError)
61
- end
62
-
63
- describe "with only single value" do
64
- it "returns the value" do
65
- tdigest.push(60, 100)
66
- expect(tdigest.percentile(0.90)).to eq(60)
67
- end
68
-
69
- it "returns 0 for all percentiles when only 0 present" do
70
- tdigest.push(0)
71
- expect(tdigest.percentile([0.0, 0.5, 1.0])).to eq([0, 0, 0])
72
- end
73
- end
74
-
75
- describe "with alot of uniformly distributed points" do
76
- it "has minimal error" do
77
- seed = srand(1234) # Makes the values a proper fixture
78
- maxerr = 0
79
- values = Array.new(100_000).map { rand }
80
- srand(seed)
81
-
82
- tdigest.push(values)
83
- tdigest.compress!
84
-
85
- 0.step(1, 0.1).each do |i|
86
- q = tdigest.percentile(i)
87
- maxerr = [maxerr, (i - q).abs].max
88
- end
89
-
90
- expect(maxerr).to be < 0.02
91
- end
92
- end
93
- end
94
-
95
- describe "#push" do
96
- it "calls _cumulate so won't crash because of uninitialized mean_cumn" do
97
- tdigest.push(
98
- [
99
- 125000000.0,
100
- 104166666.66666666,
101
- 135416666.66666666,
102
- 104166666.66666666,
103
- 104166666.66666666,
104
- 93750000.0,
105
- 125000000.0,
106
- 62500000.0,
107
- 114583333.33333333,
108
- 156250000.0,
109
- 124909090.90909092,
110
- 104090909.0909091,
111
- 135318181.81818184,
112
- 104090909.0909091,
113
- 104090909.0909091,
114
- 93681818.18181819,
115
- 124909090.90909092,
116
- 62454545.45454546,
117
- 114500000.00000001,
118
- 156136363.63636366,
119
- 123567567.56756756,
120
- 102972972.97297296,
121
- 133864864.86486486,
122
- 102972972.97297296,
123
- 102972972.97297296,
124
- 92675675.67567568,
125
- 123567567.56756756,
126
- 61783783.78378378,
127
- 113270270.27027026,
128
- 154459459.45945945,
129
- 123829787.23404256,
130
- 103191489.36170213,
131
- ],
132
- )
133
- end
134
-
135
- it "does not blow up if data comes in sorted" do
136
- tdigest.push(0..10_000)
137
- expect(tdigest.centroids.size).to be < 5_000
138
- tdigest.compress!
139
- expect(tdigest.centroids.size).to be < 1_000
140
- end
141
- end
142
-
143
- describe "#size" do
144
- it "reports the number of observations" do
145
- n = 10_000
146
- n.times { tdigest.push(rand) }
147
- tdigest.compress!
148
- expect(tdigest.size).to eq(n)
149
- end
150
- end
151
-
152
- describe "#+" do
153
- it "works with empty tdigests" do
154
- other = described_class.new(0.001, 50, 1.2)
155
- expect((tdigest + other).centroids.size).to eq(0)
156
- end
157
-
158
- describe "adding two tdigests" do
159
- let(:other) { described_class.new(0.001, 50, 1.2) }
160
-
161
- before do
162
- [tdigest, other].each do |td|
163
- td.push(60, 100)
164
- 10.times { td.push(rand * 100) }
165
- end
166
- end
167
-
168
- # rubocop:disable RSpec/MultipleExpectations
169
- it "has the parameters of the left argument (the calling tdigest)" do
170
- new_tdigest = tdigest + other
171
- expect(new_tdigest.instance_variable_get(:@delta)).to eq(
172
- tdigest.instance_variable_get(:@delta),
173
- )
174
- expect(new_tdigest.instance_variable_get(:@k)).to eq(
175
- tdigest.instance_variable_get(:@k),
176
- )
177
- expect(new_tdigest.instance_variable_get(:@cx)).to eq(
178
- tdigest.instance_variable_get(:@cx),
179
- )
180
- end
181
- # rubocop:enable RSpec/MultipleExpectations
182
-
183
- it "returns a tdigest with less than or equal centroids" do
184
- new_tdigest = tdigest + other
185
- expect(new_tdigest.centroids.size)
186
- .to be <= tdigest.centroids.size + other.centroids.size
187
- end
188
-
189
- it "has the size of the two digests combined" do
190
- new_tdigest = tdigest + other
191
- expect(new_tdigest.size).to eq(tdigest.size + other.size)
192
- end
193
- end
194
- end
195
-
196
- describe "#merge!" do
197
- it "works with empty tdigests" do
198
- other = described_class.new(0.001, 50, 1.2)
199
- tdigest.merge!(other)
200
- expect(tdigest.centroids.size).to be_zero
201
- end
202
-
203
- describe "with populated tdigests" do
204
- let(:other) { described_class.new(0.001, 50, 1.2) }
205
-
206
- before do
207
- [tdigest, other].each do |td|
208
- td.push(60, 100)
209
- 10.times { td.push(rand * 100) }
210
- end
211
- end
212
-
213
- it "has the parameters of the calling tdigest" do
214
- vars = %i[@delta @k @cx]
215
- expected = vars.map { |v| [v, tdigest.instance_variable_get(v)] }.to_h
216
- tdigest.merge!(other)
217
- vars.each do |v|
218
- expect(tdigest.instance_variable_get(v)).to eq(expected[v])
219
- end
220
- end
221
-
222
- it "returns a tdigest with less than or equal centroids" do
223
- combined_size = tdigest.centroids.size + other.centroids.size
224
- tdigest.merge!(other)
225
- expect(tdigest.centroids.size).to be <= combined_size
226
- end
227
-
228
- it "has the size of the two digests combined" do
229
- combined_size = tdigest.size + other.size
230
- tdigest.merge!(other)
231
- expect(tdigest.size).to eq(combined_size)
232
- end
233
- end
234
- end
235
- end