bidu-mercy 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +88 -0
- data/LICENSE +22 -0
- data/README.md +100 -0
- data/Rakefile +7 -0
- data/circle.yml +16 -0
- data/lib/bidu.rb +3 -0
- data/lib/bidu/mercy.rb +18 -0
- data/lib/bidu/mercy/class_methods.rb +19 -0
- data/lib/bidu/mercy/concern.rb +10 -0
- data/lib/bidu/mercy/report.rb +44 -0
- data/lib/bidu/mercy/report/active_record.rb +28 -0
- data/lib/bidu/mercy/report/error.rb +62 -0
- data/lib/bidu/mercy/report/multiple.rb +29 -0
- data/lib/bidu/mercy/report/range.rb +54 -0
- data/lib/bidu/mercy/report_builder.rb +24 -0
- data/lib/bidu/mercy/report_config.rb +37 -0
- data/lib/bidu/mercy/status.rb +27 -0
- data/lib/bidu/mercy/status_builder.rb +35 -0
- data/lib/bidu/mercy/version.rb +5 -0
- data/lib/bidu/period_parser.rb +32 -0
- data/lib/json_parser/type_cast_ext.rb +7 -0
- data/mercy.gemspec +33 -0
- data/spec/lib/bidu/mercy/report/error_spec.rb +385 -0
- data/spec/lib/bidu/mercy/report/multiple_spec.rb +122 -0
- data/spec/lib/bidu/mercy/report/range_spec.rb +302 -0
- data/spec/lib/bidu/mercy/report/report_config_spec.rb +39 -0
- data/spec/lib/bidu/mercy/report_builder_spec.rb +72 -0
- data/spec/lib/bidu/mercy/report_spec.rb +44 -0
- data/spec/lib/bidu/mercy/status_builder_spec.rb +84 -0
- data/spec/lib/bidu/mercy/status_spec.rb +135 -0
- data/spec/lib/bidu/period_parser_spec.rb +27 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/fixture_helpers.rb +19 -0
- data/spec/support/models/document.rb +6 -0
- data/spec/support/report/dummy.rb +17 -0
- data/spec/support/schema.rb +11 -0
- metadata +236 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bidu::Mercy::ReportBuilder do
|
4
|
+
let(:errors) { 1 }
|
5
|
+
let(:successes) { 3 }
|
6
|
+
let(:old_errors) { 2 }
|
7
|
+
let(:key) { :errors }
|
8
|
+
let(:threshold) { 0.02 }
|
9
|
+
let(:period) { 1.day }
|
10
|
+
let(:external_key) { :external_id }
|
11
|
+
let(:config) do
|
12
|
+
{
|
13
|
+
period: period,
|
14
|
+
threshold: threshold,
|
15
|
+
external_key: :external_id,
|
16
|
+
scope: :with_error,
|
17
|
+
id: key,
|
18
|
+
clazz: Document
|
19
|
+
}
|
20
|
+
end
|
21
|
+
let(:parameters) { {} }
|
22
|
+
let(:report) { subject.build(key, parameters) }
|
23
|
+
before do
|
24
|
+
subject.add_config(key, config)
|
25
|
+
Document.all.each(&:destroy)
|
26
|
+
successes.times { |i| Document.create status: :success, external_id: 30+i }
|
27
|
+
errors.times { |i| Document.create status: :error, external_id: 10+i }
|
28
|
+
old_errors.times do |i|
|
29
|
+
Document.create status: :error, external_id: 20+i, created_at: 2.days.ago, updated_at: 2.days.ago
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#build' do
|
34
|
+
let(:ids) { [ 10 ] }
|
35
|
+
it do
|
36
|
+
expect(report).to be_a(Bidu::Mercy::Report::Error)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'builds the report using the given configuration' do
|
40
|
+
expect(report.as_json).to eq( ids: ids, percentage: 0.25, status: :error )
|
41
|
+
expect(report.error?).to be_truthy
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when passing a custom threshold parameter' do
|
45
|
+
let(:parameters) { { threshold: 1 } }
|
46
|
+
|
47
|
+
it 'uses custom threshold parameter' do
|
48
|
+
expect(report.error?).to be_falsey
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when passing a custom period parameter' do
|
53
|
+
let(:parameters) { { threshold: 0.4, period: 10.days, status: :error } }
|
54
|
+
|
55
|
+
it 'uses custom period parameter' do
|
56
|
+
expect(report.error?).to be_truthy
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when passing a custom other parameters' do
|
61
|
+
let(:parameters) do
|
62
|
+
{ scope: :with_success, clazz: Bidu::Mercy::Report::Error, external_key: :id, id: :failures }
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'ignores the non customizable parameters' do
|
66
|
+
expect(report.as_json).to eq( ids: ids, percentage: 0.25, status: :error )
|
67
|
+
expect(report.error?).to be_truthy
|
68
|
+
expect(report.id).to eq(:errors)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bidu::Mercy::Report do
|
4
|
+
class Bidu::Mercy::Report::Dummy1 < Bidu::Mercy::Report
|
5
|
+
DEFAULT_OPTION = {
|
6
|
+
option_value: 1,
|
7
|
+
other_option: 10
|
8
|
+
}
|
9
|
+
json_parse :option_value, :other_option, case: :snake
|
10
|
+
end
|
11
|
+
class Bidu::Mercy::Report::Dummy2 < Bidu::Mercy::Report::Dummy1; end
|
12
|
+
class Bidu::Mercy::Report::Dummy3 < Bidu::Mercy::Report::Dummy1
|
13
|
+
DEFAULT_OPTION = { option_value: 5 }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'default_options' do
|
17
|
+
let(:report_class) { described_class::Dummy1 }
|
18
|
+
let(:subject) { report_class.new }
|
19
|
+
|
20
|
+
it 'setup the attributes using class default options' do
|
21
|
+
expect(subject.option_value).to eq(1)
|
22
|
+
expect(subject.other_option).to eq(10)
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when class inherit options' do
|
26
|
+
let(:report_class) { described_class::Dummy2 }
|
27
|
+
|
28
|
+
it 'setup the attributes using superclass default options' do
|
29
|
+
expect(subject.option_value).to eq(1)
|
30
|
+
expect(subject.other_option).to eq(10)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when class inherit options but overrides some' do
|
35
|
+
let(:report_class) { described_class::Dummy3 }
|
36
|
+
|
37
|
+
it 'setup the attributes using superclass default options' do
|
38
|
+
expect(subject.option_value).to eq(5)
|
39
|
+
expect(subject.other_option).to eq(10)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bidu::Mercy::StatusBuilder do
|
4
|
+
let(:errors) { 1 }
|
5
|
+
let(:successes) { 3 }
|
6
|
+
let(:old_errors) { 2 }
|
7
|
+
let(:key) { :errors }
|
8
|
+
let(:threshold) { 0.02 }
|
9
|
+
let(:period) { 1.day }
|
10
|
+
let(:external_key) { :external_id }
|
11
|
+
let(:config) do
|
12
|
+
{
|
13
|
+
period: period,
|
14
|
+
threshold: threshold,
|
15
|
+
scope: :with_error,
|
16
|
+
clazz: Document,
|
17
|
+
id: :failures,
|
18
|
+
external_key: :external_id,
|
19
|
+
on: key
|
20
|
+
}
|
21
|
+
end
|
22
|
+
let(:parameters) { {} }
|
23
|
+
let(:status) { subject.build(key, parameters) }
|
24
|
+
before do
|
25
|
+
subject.add_report_config(key, config)
|
26
|
+
Document.all.each(&:destroy)
|
27
|
+
successes.times { |i| Document.create status: :success, external_id: 30+i }
|
28
|
+
errors.times { |i| Document.create status: :error, external_id: 10+i }
|
29
|
+
old_errors.times do |i|
|
30
|
+
Document.create status: :error, external_id: 20+i, created_at: 2.days.ago, updated_at: 2.days.ago
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#build' do
|
35
|
+
let(:ids) { [ 10 ] }
|
36
|
+
let(:status_expected) { :error }
|
37
|
+
let(:percentage) { 0.25 }
|
38
|
+
let(:json_expected) do
|
39
|
+
{
|
40
|
+
status: status_expected,
|
41
|
+
failures: {
|
42
|
+
ids: ids,
|
43
|
+
percentage: percentage,
|
44
|
+
status: status_expected
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
it do
|
50
|
+
expect(status).to be_a(Bidu::Mercy::Status)
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when not specifying where to report' do
|
54
|
+
let(:key) {}
|
55
|
+
|
56
|
+
it 'register report under default' do
|
57
|
+
expect(subject.build(:default).as_json).to eq(json_expected)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'builds the report using the given configuration' do
|
62
|
+
expect(status.as_json).to eq(json_expected)
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when passing a custom threshold parameter' do
|
66
|
+
let(:parameters) { { threshold: 1 } }
|
67
|
+
let(:status_expected) { :ok }
|
68
|
+
|
69
|
+
it 'uses custom threshold parameter' do
|
70
|
+
expect(status.as_json).to eq(json_expected)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when passing a custom period parameter' do
|
75
|
+
let(:ids) { [ 10, 20, 21 ] }
|
76
|
+
let(:percentage) { 0.5 }
|
77
|
+
let(:parameters) { { threshold: 0.4, period: 10.days } }
|
78
|
+
|
79
|
+
it 'uses custom period parameter' do
|
80
|
+
expect(status.as_json).to eq(json_expected)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bidu::Mercy::Status do
|
4
|
+
let(:threshold) { 0.02 }
|
5
|
+
let(:period) { 1.day }
|
6
|
+
let(:report_options) do
|
7
|
+
{
|
8
|
+
period: period,
|
9
|
+
threshold: threshold,
|
10
|
+
scope: :with_error,
|
11
|
+
clazz: Document,
|
12
|
+
id: :errors
|
13
|
+
}
|
14
|
+
end
|
15
|
+
let(:success_options) do
|
16
|
+
report_options.merge(
|
17
|
+
scope: :with_success,
|
18
|
+
id: :success
|
19
|
+
)
|
20
|
+
end
|
21
|
+
let(:errors) { 0 }
|
22
|
+
let(:successes) { 1 }
|
23
|
+
let(:error_report) { Bidu::Mercy::Report::Error.new(report_options) }
|
24
|
+
let(:success_report) do
|
25
|
+
Bidu::Mercy::Report::Error.new(success_options)
|
26
|
+
end
|
27
|
+
let(:reports) { [ error_report ] }
|
28
|
+
let(:subject) { described_class.new(reports) }
|
29
|
+
before do
|
30
|
+
Document.all.each(&:destroy)
|
31
|
+
errors.times { Document.create status: :error }
|
32
|
+
successes.times { Document.create status: :success }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#as_json' do
|
36
|
+
let(:status_json) { subject.as_json }
|
37
|
+
let(:status) { status_json[:status] }
|
38
|
+
|
39
|
+
context 'when report is ok' do
|
40
|
+
it 'returns a json with ok' do
|
41
|
+
expect(status).to eq(:ok)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns the report json' do
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when report is not ok' do
|
50
|
+
let(:errors) { 1 }
|
51
|
+
|
52
|
+
it 'returns a json with error' do
|
53
|
+
expect(status).to eq(:error)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when there are both success and error reports' do
|
58
|
+
let(:success_report) do
|
59
|
+
Bidu::Mercy::Report::Error.new(report_options.merge(scope: :with_success))
|
60
|
+
end
|
61
|
+
let(:reports) { [ success_report, error_report ] }
|
62
|
+
|
63
|
+
it 'returns a json with error' do
|
64
|
+
expect(status).to eq(:error)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#status' do
|
70
|
+
context 'when report is ok' do
|
71
|
+
it do
|
72
|
+
expect(subject.status).to eq(:ok)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when report is not ok' do
|
77
|
+
let(:errors) { 1 }
|
78
|
+
|
79
|
+
it do
|
80
|
+
expect(subject.status).to eq(:error)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when there are both success and error reports' do
|
85
|
+
let(:reports) { [ success_report, error_report ] }
|
86
|
+
|
87
|
+
it do
|
88
|
+
expect(subject.status).to eq(:error)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#as_json' do
|
94
|
+
let(:errors) { 3 }
|
95
|
+
let(:ids) { Document.with_error.map(&:id) }
|
96
|
+
let(:expected) do
|
97
|
+
{
|
98
|
+
status: :error,
|
99
|
+
errors: {
|
100
|
+
ids: ids,
|
101
|
+
percentage: 0.75,
|
102
|
+
status: :error
|
103
|
+
}
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'creates a summary of the reports' do
|
108
|
+
expect(subject.as_json).to eq(expected)
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when there are both success and error reports' do
|
112
|
+
let(:success_ids) { Document.with_success.map(&:id) }
|
113
|
+
let(:expected) do
|
114
|
+
{
|
115
|
+
status: :error,
|
116
|
+
errors: {
|
117
|
+
ids: ids,
|
118
|
+
percentage: 0.75,
|
119
|
+
status: :error
|
120
|
+
},
|
121
|
+
success: {
|
122
|
+
ids: success_ids,
|
123
|
+
percentage: 0.25,
|
124
|
+
status: :error
|
125
|
+
}
|
126
|
+
}
|
127
|
+
end
|
128
|
+
let(:reports) { [ success_report, error_report ] }
|
129
|
+
|
130
|
+
it 'creates a summary of all the reports' do
|
131
|
+
expect(subject.as_json).to eq(expected)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bidu::PeriodParser do
|
4
|
+
shared_examples 'a class who knows how to parse time' do |tests|
|
5
|
+
tests.each do |string, expected|
|
6
|
+
it "parses #{string} into #{expected} seconds" do
|
7
|
+
expect(described_class.parse(string)).to eq(expected)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it_behaves_like 'a class who knows how to parse time', {
|
13
|
+
'3' => 3.seconds,
|
14
|
+
'3seconds' => 3.seconds,
|
15
|
+
'3minutes' => 3.minutes,
|
16
|
+
'3hours' => 3.hours,
|
17
|
+
'3days' => 3.days,
|
18
|
+
'3months' => 3.months,
|
19
|
+
'3years' => 3.years
|
20
|
+
}
|
21
|
+
|
22
|
+
context 'when value is already a period' do
|
23
|
+
it 'returns the value itself' do
|
24
|
+
expect(described_class.parse(3.minutes)).to eq(3.minutes)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.profiles.define 'gem' do
|
3
|
+
add_filter '/spec/'
|
4
|
+
end
|
5
|
+
|
6
|
+
if ENV['CODECLIMATE_REPO_TOKEN']
|
7
|
+
require "codeclimate-test-reporter"
|
8
|
+
CodeClimate::TestReporter.start
|
9
|
+
end
|
10
|
+
|
11
|
+
SimpleCov.start 'gem'
|
12
|
+
|
13
|
+
require 'pry-nav'
|
14
|
+
require 'bidu/mercy'
|
15
|
+
|
16
|
+
require 'active_record'
|
17
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
18
|
+
|
19
|
+
support_files = File.expand_path("spec/support/**/*.rb")
|
20
|
+
Dir[support_files].each { |file| require file }
|
21
|
+
|
22
|
+
RSpec.configure do |config|
|
23
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
24
|
+
config.run_all_when_everything_filtered = true
|
25
|
+
config.filter_run :focus
|
26
|
+
config.filter_run_excluding :integration unless ENV['ALL']
|
27
|
+
|
28
|
+
config.order = 'random'
|
29
|
+
|
30
|
+
config.before do
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module FixtureHelpers
|
4
|
+
def load_fixture_file(filename)
|
5
|
+
File.read (['./spec/', 'fixtures', filename].join('/'))
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_json_fixture_file(filename)
|
9
|
+
cached_json_fixture_file(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def cached_json_fixture_file(filename)
|
15
|
+
ActiveSupport::JSON.decode(load_fixture_file(filename))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configuration.include FixtureHelpers
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Bidu
|
2
|
+
module Mercy
|
3
|
+
class Report
|
4
|
+
class Dummy < Report
|
5
|
+
ALLOWED_PARAMETERS=[:period, :threshold]
|
6
|
+
def initialize(options)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Dummy
|
14
|
+
ALLOWED_PARAMETERS=[:period, :threshold]
|
15
|
+
def initialize(options)
|
16
|
+
end
|
17
|
+
end
|