marty 2.5.2 → 2.5.4
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 +5 -5
- data/.gitignore +4 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +11 -589
- data/Gemfile +9 -9
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -3
- data/app/components/marty/api_auth_view.rb +3 -3
- data/app/components/marty/api_config_view.rb +8 -8
- data/app/components/marty/api_log_view.rb +16 -20
- data/app/components/marty/auth_app.rb +6 -6
- data/app/components/marty/base_rule_view.rb +27 -19
- data/app/components/marty/config_view.rb +12 -9
- data/app/components/marty/data_grid_view.rb +26 -26
- data/app/components/marty/delorean_rule_view.rb +0 -1
- data/app/components/marty/event_view.rb +27 -27
- data/app/components/marty/extras/layout.rb +26 -26
- data/app/components/marty/extras/misc.rb +2 -2
- data/app/components/marty/grid.rb +13 -13
- data/app/components/marty/grid_append_only.rb +0 -1
- data/app/components/marty/import_type_view.rb +13 -13
- data/app/components/marty/import_view.rb +17 -16
- data/app/components/marty/log_view.rb +16 -14
- data/app/components/marty/main_auth_app.rb +59 -59
- data/app/components/marty/main_auth_app/client/main_auth_app.js +3 -3
- data/app/components/marty/mcfly_grid_panel.rb +10 -10
- data/app/components/marty/new_posting_form.rb +11 -11
- data/app/components/marty/new_posting_window.rb +0 -1
- data/app/components/marty/posting_grid.rb +12 -13
- data/app/components/marty/promise_view.rb +6 -6
- data/app/components/marty/report_form.rb +50 -53
- data/app/components/marty/report_select.rb +27 -27
- data/app/components/marty/reporting.rb +4 -4
- data/app/components/marty/script_form.rb +40 -42
- data/app/components/marty/script_grid.rb +24 -24
- data/app/components/marty/script_tester.rb +40 -42
- data/app/components/marty/scripting.rb +25 -27
- data/app/components/marty/simple_app.rb +24 -9
- data/app/components/marty/tag_grid.rb +12 -13
- data/app/components/marty/user_view.rb +35 -35
- data/app/controllers/marty/application_controller.rb +3 -4
- data/app/controllers/marty/components_controller.rb +1 -1
- data/app/controllers/marty/delayed_job_controller.rb +1 -0
- data/app/controllers/marty/diagnostic/controller.rb +4 -6
- data/app/controllers/marty/job_controller.rb +6 -6
- data/app/controllers/marty/report_controller.rb +11 -11
- data/app/controllers/marty/rpc_controller.rb +15 -16
- data/app/helpers/marty/script_set.rb +4 -4
- data/app/models/marty/api_auth.rb +4 -5
- data/app/models/marty/api_config.rb +1 -1
- data/app/models/marty/base.rb +9 -8
- data/app/models/marty/base_rule.rb +18 -13
- data/app/models/marty/config.rb +4 -5
- data/app/models/marty/data_grid.rb +157 -181
- data/app/models/marty/delorean_rule.rb +63 -62
- data/app/models/marty/enum.rb +1 -1
- data/app/models/marty/event.rb +56 -59
- data/app/models/marty/helper.rb +38 -6
- data/app/models/marty/import_type.rb +6 -6
- data/app/models/marty/log.rb +3 -2
- data/app/models/marty/name_validator.rb +3 -2
- data/app/models/marty/pg_enum.rb +3 -4
- data/app/models/marty/posting.rb +20 -24
- data/app/models/marty/promise.rb +28 -30
- data/app/models/marty/script.rb +30 -28
- data/app/models/marty/tag.rb +8 -8
- data/app/models/marty/token.rb +2 -2
- data/app/models/marty/user.rb +24 -23
- data/app/models/marty/vw_promise.rb +10 -11
- data/config/routes.rb +2 -2
- data/delorean/blame_report.dl +268 -0
- data/{spec/dummy/delorean/fields.dl → delorean/marty_fields.dl} +8 -0
- data/delorean/table_report.dl +34 -0
- data/docker-compose.dummy.yml +2 -3
- data/lib/marty/aws/base.rb +8 -8
- data/lib/marty/aws/request.rb +4 -4
- data/lib/marty/cache_adapters/mcfly_ruby_cache.rb +1 -0
- data/lib/marty/content_handler.rb +25 -25
- data/lib/marty/data_change.rb +49 -71
- data/lib/marty/data_conversion.rb +20 -28
- data/lib/marty/data_exporter.rb +25 -28
- data/lib/marty/data_importer.rb +25 -27
- data/lib/marty/engine.rb +1 -2
- data/lib/marty/json_schema.rb +22 -24
- data/lib/marty/logger.rb +6 -9
- data/lib/marty/mcfly_model.rb +20 -24
- data/lib/marty/migrations.rb +37 -35
- data/lib/marty/monkey.rb +33 -33
- data/lib/marty/permissions.rb +18 -18
- data/lib/marty/promise_job.rb +17 -17
- data/lib/marty/promise_proxy.rb +6 -6
- data/lib/marty/relation.rb +6 -7
- data/lib/marty/rpc_call.rb +13 -12
- data/lib/marty/rule_script_set.rb +32 -28
- data/lib/marty/schema_helper.rb +37 -51
- data/lib/marty/util.rb +25 -24
- data/lib/marty/version.rb +1 -1
- data/lib/marty/xl.rb +121 -115
- data/make-dummy.mk +3 -0
- data/marty.gemspec +21 -21
- data/other/marty/api/base.rb +34 -35
- data/other/marty/diagnostic/aws/ec2_instance.rb +8 -8
- data/other/marty/diagnostic/base.rb +13 -14
- data/other/marty/diagnostic/collection.rb +2 -1
- data/other/marty/diagnostic/connections.rb +8 -6
- data/other/marty/diagnostic/database.rb +1 -0
- data/other/marty/diagnostic/delayed_job_version.rb +7 -9
- data/other/marty/diagnostic/delayed_job_worker_total_count.rb +1 -1
- data/other/marty/diagnostic/delayed_job_workers.rb +1 -1
- data/other/marty/diagnostic/environment_variables.rb +17 -15
- data/other/marty/diagnostic/fatal.rb +1 -1
- data/other/marty/diagnostic/node.rb +5 -9
- data/other/marty/diagnostic/nodes.rb +7 -5
- data/other/marty/diagnostic/packer.rb +7 -7
- data/other/marty/diagnostic/reporter.rb +24 -27
- data/other/marty/diagnostic/version.rb +3 -5
- data/script/rails +2 -1
- data/spec/controllers/application_controller_spec.rb +6 -6
- data/spec/controllers/delayed_job_controller_spec.rb +4 -4
- data/spec/controllers/diagnostic/controller_spec.rb +59 -60
- data/spec/controllers/job_controller_spec.rb +68 -69
- data/spec/controllers/rpc_controller_spec.rb +353 -359
- data/spec/controllers/rpc_import_spec.rb +15 -16
- data/spec/dummy/delorean/blame_report.dl +110 -15
- data/spec/dummy/delorean/data_report.dl +4 -4
- data/spec/dummy/delorean/marty_fields.dl +63 -0
- data/spec/dummy/delorean/table_report.dl +34 -0
- data/spec/features/auth_app_spec.rb +1 -2
- data/spec/features/data_import_spec.rb +2 -3
- data/spec/features/enum_spec.rb +42 -46
- data/spec/features/jobs_dashboard_spec.rb +14 -8
- data/spec/features/log_view_spec.rb +40 -43
- data/spec/features/reporting_spec.rb +15 -15
- data/spec/features/rule_spec.rb +195 -190
- data/spec/features/scripting_spec.rb +17 -20
- data/spec/features/scripting_test_spec.rb +32 -33
- data/spec/features/user_view_spec.rb +15 -17
- data/spec/job_helper.rb +11 -11
- data/spec/lib/data_blame_spec.rb +82 -0
- data/spec/lib/data_exporter_spec.rb +31 -32
- data/spec/lib/data_importer_spec.rb +382 -395
- data/spec/lib/delorean_query_spec.rb +117 -119
- data/spec/lib/json_schema_spec.rb +382 -392
- data/spec/lib/logger_spec.rb +23 -24
- data/spec/lib/mcfly_model_spec.rb +112 -109
- data/spec/lib/migrations_spec.rb +10 -10
- data/spec/lib/struct_compare_spec.rb +6 -6
- data/spec/lib/table_report_spec.rb +90 -0
- data/spec/lib/xl_spec.rb +63 -65
- data/spec/lib/xl_styles_spec.rb +16 -19
- data/spec/models/api_auth_spec.rb +30 -30
- data/spec/models/config_spec.rb +32 -32
- data/spec/models/data_grid_spec.rb +642 -655
- data/spec/models/event_spec.rb +96 -88
- data/spec/models/import_type_spec.rb +20 -20
- data/spec/models/posting_spec.rb +35 -35
- data/spec/models/promise_spec.rb +5 -5
- data/spec/models/rule_spec.rb +280 -269
- data/spec/models/script_spec.rb +27 -18
- data/spec/models/user_spec.rb +9 -9
- data/spec/other/diagnostic/base_spec.rb +20 -19
- data/spec/other/diagnostic/collection_spec.rb +6 -5
- data/spec/other/diagnostic/delayed_job_version_spec.rb +1 -1
- data/spec/other/diagnostic/delayed_job_workers_spec.rb +8 -8
- data/spec/other/diagnostic/reporter_spec.rb +31 -33
- data/spec/spec_helper.rb +5 -5
- data/spec/support/chromedriver.rb +3 -5
- data/spec/support/components/netzke_combobox.rb +1 -1
- data/spec/support/components/netzke_grid.rb +17 -17
- data/spec/support/custom_matchers.rb +2 -2
- data/spec/support/download_helper.rb +1 -1
- data/spec/support/helper.rb +1 -2
- data/spec/support/netzke.rb +31 -31
- data/spec/support/performance_helper.rb +8 -8
- data/spec/support/post_run_logger.rb +1 -2
- data/spec/support/setup.rb +1 -4
- data/spec/support/shared_connection.rb +2 -2
- data/spec/support/structure_compare.rb +21 -22
- data/spec/support/suite.rb +1 -2
- data/spec/support/users.rb +5 -6
- metadata +32 -26
|
@@ -34,34 +34,35 @@ describe Marty::JobController, slow: true do
|
|
|
34
34
|
def wait_for_jobs
|
|
35
35
|
60.times do
|
|
36
36
|
break unless Marty::Promise.where(result: {}).exists?
|
|
37
|
+
|
|
37
38
|
sleep 1
|
|
38
39
|
end
|
|
39
40
|
end
|
|
40
41
|
|
|
41
|
-
it
|
|
42
|
+
it 'should be able to evaluate in the foreground ' do
|
|
42
43
|
engine = Marty::ScriptSet.new.get_engine(NAME_A)
|
|
43
44
|
|
|
44
|
-
res = engine.evaluate(
|
|
45
|
+
res = engine.evaluate('Y', 'd')
|
|
45
46
|
expect(res).to eq([
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 0.125 } } },
|
|
48
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 1.125 } } },
|
|
49
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 2.125 } } },
|
|
49
50
|
])
|
|
50
51
|
|
|
51
52
|
expect(Marty::Promise.where(start_dt: nil).count).to eq 0
|
|
52
53
|
|
|
53
|
-
expect
|
|
54
|
-
res = engine.evaluate(
|
|
54
|
+
expect do
|
|
55
|
+
res = engine.evaluate('Y', 'd', 's' => 1)
|
|
55
56
|
# force res to be evaluated
|
|
56
57
|
res.to_s
|
|
57
|
-
|
|
58
|
+
end.to raise_error(RuntimeError)
|
|
58
59
|
|
|
59
60
|
wait_for_jobs
|
|
60
61
|
|
|
61
62
|
expect(Marty::Promise.where(start_dt: nil).count).to eq 0
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
it
|
|
65
|
+
it 'should be able to run long-running tasks in separate jobs' do
|
|
65
66
|
engine = Marty::ScriptSet.new.get_engine(NAME_A)
|
|
66
67
|
|
|
67
68
|
# NOTE: can't make this too small since the default
|
|
@@ -69,45 +70,45 @@ describe Marty::JobController, slow: true do
|
|
|
69
70
|
# However - delayed_job initializer config sets this to 1 for test
|
|
70
71
|
slp = 5
|
|
71
72
|
|
|
72
|
-
exp_res = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
exp_res = { 'd' => [
|
|
74
|
+
{ 'z' => slp, 'a' => { 'b' => { 'e' => 1 - slp } } },
|
|
75
|
+
{ 'z' => slp, 'a' => { 'b' => { 'e' => 2 - slp } } },
|
|
76
|
+
{ 'z' => slp, 'a' => { 'b' => { 'e' => 3 - slp } } },
|
|
77
|
+
] }
|
|
77
78
|
|
|
78
|
-
bench = Benchmark.measure
|
|
79
|
-
res = engine.evaluate(
|
|
79
|
+
bench = Benchmark.measure do
|
|
80
|
+
res = engine.evaluate('Y', 'f', 's' => slp)
|
|
80
81
|
expect(res).to eq exp_res
|
|
81
|
-
|
|
82
|
+
end
|
|
82
83
|
|
|
83
84
|
# If "f" is evaluated in serial fashion, then the process would
|
|
84
85
|
# take slp*3+ seconds. Make sure that we had some parallel
|
|
85
86
|
# behavior.
|
|
86
|
-
expect(bench.real).to be_between(slp, slp*2)
|
|
87
|
+
expect(bench.real).to be_between(slp, slp * 2)
|
|
87
88
|
end
|
|
88
89
|
|
|
89
|
-
it
|
|
90
|
+
it 'should be able to run long-running tasks in separate jobs (2)' do
|
|
90
91
|
engine = Marty::ScriptSet.new.get_engine(NAME_H)
|
|
91
92
|
|
|
92
93
|
slp = 5 # hard-coded in script
|
|
93
|
-
exp_res = {
|
|
94
|
+
exp_res = { 'd' => [{ 'a' => 1 }, { 'a' => 4 }] }
|
|
94
95
|
|
|
95
|
-
bench = Benchmark.measure
|
|
96
|
-
res = engine.background_eval(
|
|
96
|
+
bench = Benchmark.measure do
|
|
97
|
+
res = engine.background_eval('Y', {}, ['d'])
|
|
97
98
|
|
|
98
99
|
expect(res).to eq exp_res
|
|
99
|
-
|
|
100
|
+
end
|
|
100
101
|
|
|
101
|
-
expect(bench.real).to be_between(slp, slp*2)
|
|
102
|
+
expect(bench.real).to be_between(slp, slp * 2)
|
|
102
103
|
end
|
|
103
104
|
|
|
104
|
-
xit
|
|
105
|
+
xit 'should be to handle non-serializable errors' do
|
|
105
106
|
# FIXME: this test is failing now. Object not-serializable isn't
|
|
106
107
|
# the issue. This is caused by the 2nd promise not having been
|
|
107
108
|
# started when it's forced. Not sure this is really an issue.
|
|
108
109
|
|
|
109
110
|
engine = Marty::ScriptSet.new.get_engine(NAME_C)
|
|
110
|
-
res = engine.background_eval(
|
|
111
|
+
res = engine.background_eval('Z', { 'p_title' => NAME_C }, ['result'])
|
|
111
112
|
wait_for_jobs
|
|
112
113
|
|
|
113
114
|
promise = Marty::Promise.find_by_title(NAME_C)
|
|
@@ -117,17 +118,17 @@ describe Marty::JobController, slow: true do
|
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
expect(response.content_type).to eq 'application/json'
|
|
120
|
-
expect(JSON.parse(response.body).keys.member?(
|
|
121
|
+
expect(JSON.parse(response.body).keys.member?('error')).to be true
|
|
121
122
|
end
|
|
122
123
|
|
|
123
|
-
it
|
|
124
|
+
it 'promise proxies should be stored lazily (not expanded)' do
|
|
124
125
|
engine = Marty::ScriptSet.new.get_engine(NAME_E)
|
|
125
|
-
engine.background_eval(
|
|
126
|
+
engine.background_eval('Z', { 'p_title' => NAME_E }, ['result'])
|
|
126
127
|
wait_for_jobs
|
|
127
128
|
|
|
128
129
|
promise = Marty::Promise.find_by_title(NAME_E)
|
|
129
130
|
|
|
130
|
-
res = promise.result[
|
|
131
|
+
res = promise.result['result']
|
|
131
132
|
|
|
132
133
|
expect(res.length).to eq 6
|
|
133
134
|
|
|
@@ -136,43 +137,43 @@ describe Marty::JobController, slow: true do
|
|
|
136
137
|
res.each { |r| expect(r.respond_to?(:__force__)).to be true }
|
|
137
138
|
end
|
|
138
139
|
|
|
139
|
-
it
|
|
140
|
+
it 'should not leave zombie promises when we have exceptions' do
|
|
140
141
|
engine = Marty::ScriptSet.new.get_engine(NAME_D)
|
|
141
|
-
engine.background_eval(
|
|
142
|
+
engine.background_eval('Z', { 'p_title' => NAME_D }, ['result'])
|
|
142
143
|
wait_for_jobs
|
|
143
144
|
|
|
144
145
|
pl = Marty::Promise.all
|
|
145
146
|
|
|
146
147
|
expect(pl.count).to eq 2
|
|
147
148
|
|
|
148
|
-
pl.each
|
|
149
|
-
expect(p.result[
|
|
149
|
+
pl.each do |p|
|
|
150
|
+
expect(p.result['error']).not_to eq nil
|
|
150
151
|
expect(p.end_dt).not_to eq nil
|
|
151
|
-
|
|
152
|
+
end
|
|
152
153
|
end
|
|
153
154
|
|
|
154
|
-
it
|
|
155
|
+
it 'should pass p_title to promise create()' do
|
|
155
156
|
engine = Marty::ScriptSet.new.get_engine(NAME_A)
|
|
156
|
-
res = engine.evaluate(
|
|
157
|
+
res = engine.evaluate('Y', 'a', 'q' => 1)
|
|
157
158
|
wait_for_jobs
|
|
158
159
|
|
|
159
|
-
expect(res).to eq(
|
|
160
|
-
expect(Marty::Promise.all.map(&:title).sort).to eq([
|
|
160
|
+
expect(res).to eq('b' => { 'e' => 0.125 })
|
|
161
|
+
expect(Marty::Promise.all.map(&:title).sort).to eq(['aaa', 'bbb'])
|
|
161
162
|
end
|
|
162
163
|
|
|
163
|
-
it
|
|
164
|
-
title =
|
|
164
|
+
it 'should be able to ask controller for job result' do
|
|
165
|
+
title = 'BG RPC'
|
|
165
166
|
engine = Marty::ScriptSet.new.get_engine(NAME_A)
|
|
166
|
-
engine.background_eval(
|
|
167
|
+
engine.background_eval('Y', { 'p_title' => title }, ['d'])
|
|
167
168
|
sleep 5
|
|
168
169
|
|
|
169
170
|
promise = Marty::Promise.find_by_title(title)
|
|
170
171
|
|
|
171
|
-
res = {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
res = { 'd' => [
|
|
173
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 0.125 } } },
|
|
174
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 1.125 } } },
|
|
175
|
+
{ 'z' => 0.875, 'a' => { 'b' => { 'e' => 2.125 } } },
|
|
176
|
+
] }
|
|
176
177
|
|
|
177
178
|
expect(promise.latest.result).to eq res
|
|
178
179
|
|
|
@@ -184,22 +185,22 @@ describe Marty::JobController, slow: true do
|
|
|
184
185
|
expect(JSON.parse response.body).to eq res
|
|
185
186
|
end
|
|
186
187
|
|
|
187
|
-
it
|
|
188
|
-
title =
|
|
188
|
+
it 'should be able to get zip results' do
|
|
189
|
+
title = 'BG ZIP'
|
|
189
190
|
engine = Marty::ScriptSet.new.get_engine(NAME_B)
|
|
190
|
-
engine.background_eval(
|
|
191
|
+
engine.background_eval('Z',
|
|
191
192
|
{},
|
|
192
|
-
[
|
|
193
|
-
|
|
193
|
+
['result', 'format', 'title'],
|
|
194
|
+
)
|
|
194
195
|
sleep 5
|
|
195
196
|
|
|
196
197
|
promise = Marty::Promise.find_by_title(NAME_B)
|
|
197
198
|
|
|
198
|
-
expect(promise.result).to eq(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
expect(promise.result).to eq(
|
|
200
|
+
'result' => [{ 'a' => 1, 'b' => 1 }, { 'a' => 2, 'b' => 4 }, { 'a' => 3, 'b' => 9 }],
|
|
201
|
+
'format' => 'csv',
|
|
202
|
+
'title' => 'PromiseB',
|
|
203
|
+
)
|
|
203
204
|
|
|
204
205
|
get 'download', params: {
|
|
205
206
|
job_id: promise.id,
|
|
@@ -207,17 +208,15 @@ describe Marty::JobController, slow: true do
|
|
|
207
208
|
|
|
208
209
|
expect_csv = "a,b\r\n1,1\r\n2,4\r\n3,9\r\n"
|
|
209
210
|
expect(response.body).to eq expect_csv
|
|
210
|
-
expect(response.content_type).to eq
|
|
211
|
+
expect(response.content_type).to eq 'text/csv'
|
|
211
212
|
|
|
212
213
|
get 'download', params: {
|
|
213
214
|
job_id: promise.parent_id,
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
expect(response.content_type).to eq
|
|
217
|
-
|
|
218
|
-
Zip::InputStream.open(StringIO.new(response.body)) {
|
|
219
|
-
|io|
|
|
217
|
+
expect(response.content_type).to eq 'application/zip'
|
|
220
218
|
|
|
219
|
+
Zip::InputStream.open(StringIO.new(response.body)) do |io|
|
|
221
220
|
count = 0
|
|
222
221
|
while (entry = io.get_next_entry)
|
|
223
222
|
expect(entry.name).to match /PromiseB.*\.csv/
|
|
@@ -225,20 +224,20 @@ describe Marty::JobController, slow: true do
|
|
|
225
224
|
count += 1
|
|
226
225
|
end
|
|
227
226
|
expect(count).to eq 3
|
|
228
|
-
|
|
227
|
+
end
|
|
229
228
|
end
|
|
230
229
|
|
|
231
|
-
it
|
|
230
|
+
it 'should be able to start promises on imported nodes' do
|
|
232
231
|
engine = Marty::ScriptSet.new.get_engine(NAME_F)
|
|
233
|
-
res = engine.evaluate(
|
|
234
|
-
expect(res).to eq
|
|
232
|
+
res = engine.evaluate('Z', 'result', {})
|
|
233
|
+
expect(res).to eq 'x' * 10
|
|
235
234
|
end
|
|
236
235
|
|
|
237
|
-
it
|
|
236
|
+
it 'promises called from regular node calls should pass parent promise id' do
|
|
238
237
|
engine = Marty::ScriptSet.new.get_engine(NAME_G)
|
|
239
|
-
res = engine.evaluate(
|
|
238
|
+
res = engine.evaluate('V', 'result', {})
|
|
240
239
|
expect(res).to eq [123]
|
|
241
|
-
p1 = Marty::Promise.find_by_title(
|
|
240
|
+
p1 = Marty::Promise.find_by_title(NAME_G.to_s)
|
|
242
241
|
p2 = Marty::Promise.find_by_title("#{NAME_G}2")
|
|
243
242
|
expect(p2.parent_id).to eq p1.id
|
|
244
243
|
end
|
|
@@ -430,55 +430,55 @@ A:
|
|
|
430
430
|
v0 = { "properties": properties}
|
|
431
431
|
eof
|
|
432
432
|
describe Marty::RpcController do
|
|
433
|
-
before(:each)
|
|
433
|
+
before(:each) do
|
|
434
434
|
@routes = Marty::Engine.routes
|
|
435
435
|
|
|
436
436
|
# HACKY: 'params' param is special to the Rails controller test helper (at
|
|
437
437
|
# least as of 4.2). Setting this avoids test framework code that relies on
|
|
438
438
|
# params being a hash.
|
|
439
|
-
@request.env['PATH_INFO'] =
|
|
440
|
-
|
|
439
|
+
@request.env['PATH_INFO'] = '/marty/rpc/evaluate.json'
|
|
440
|
+
end
|
|
441
441
|
|
|
442
|
-
before(:each)
|
|
443
|
-
@p0 = Marty::Posting.do_create(
|
|
442
|
+
before(:each) do
|
|
443
|
+
@p0 = Marty::Posting.do_create('BASE', Date.today, 'a comment')
|
|
444
444
|
|
|
445
445
|
@t1 = Marty::Script.load_script_bodies({
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
446
|
+
'M1' => sample_script,
|
|
447
|
+
'M2' => sample_script.gsub(/a/, 'aa').gsub(/b/, 'bb'),
|
|
448
|
+
'M3' => sample_script3,
|
|
449
|
+
'M3err' => sample_script3err,
|
|
450
|
+
'M4' => sample_script4,
|
|
451
|
+
'M5' => sample_script5,
|
|
452
|
+
'M6' => sample_script6,
|
|
453
|
+
'M7' => sample_script7,
|
|
454
|
+
'M8' => sample_script8,
|
|
455
|
+
'M9' => sample_script9,
|
|
456
|
+
'M10' => sample_script10,
|
|
457
|
+
'M11' => sample_script11,
|
|
458
|
+
'M3Schemas' => script3_schema,
|
|
459
|
+
'M3errSchemas' => script3err_schema,
|
|
460
|
+
'M4Schemas' => script4_schema,
|
|
461
|
+
'M5Schemas' => script5_schema,
|
|
462
|
+
'M6Schemas' => script6_schema,
|
|
463
|
+
'M7Schemas' => script7_schema,
|
|
464
|
+
'M8Schemas' => script8_schema,
|
|
465
|
+
'M9Schemas' => script9_schema,
|
|
466
|
+
'M10Schemas' => script10_schema,
|
|
467
|
+
'M11Schemas' => script11_schema,
|
|
468
468
|
}, Date.today + 1.minute)
|
|
469
469
|
|
|
470
|
-
@p1 = Marty::Posting.do_create(
|
|
470
|
+
@p1 = Marty::Posting.do_create('BASE', Date.today + 2.minute, 'a comment')
|
|
471
471
|
|
|
472
472
|
@t2 = Marty::Script.load_script_bodies({
|
|
473
|
-
|
|
474
|
-
sample_script.gsub(/A/,
|
|
473
|
+
'M1' =>
|
|
474
|
+
sample_script.gsub(/A/, 'AA') + ' e =? "hello"',
|
|
475
475
|
}, Date.today + 3.minute)
|
|
476
476
|
|
|
477
|
-
@p2 = Marty::Posting.do_create(
|
|
478
|
-
@data = [[
|
|
479
|
-
[
|
|
477
|
+
@p2 = Marty::Posting.do_create('BASE', Date.today + 4.minute, 'a comment')
|
|
478
|
+
@data = [['some data', 7, [1, 2, 3], { foo: 'bar', baz: 'quz' }, 5, 'string'],
|
|
479
|
+
['some more data', [1, 2, 3], 5, { foo: 'bar', baz: 'quz' }, 5, 'string']]
|
|
480
480
|
@data_json = @data.to_json
|
|
481
|
-
|
|
481
|
+
end
|
|
482
482
|
|
|
483
483
|
after(:each) do
|
|
484
484
|
Marty::Log.delete_all
|
|
@@ -490,27 +490,27 @@ describe Marty::RpcController do
|
|
|
490
490
|
let(:p1) { @p1 }
|
|
491
491
|
let(:p2) { @p2 }
|
|
492
492
|
|
|
493
|
-
it
|
|
493
|
+
it 'should be able to post' do
|
|
494
494
|
post 'evaluate', params: {
|
|
495
495
|
format: :json,
|
|
496
|
-
script:
|
|
497
|
-
node:
|
|
498
|
-
attrs:
|
|
496
|
+
script: 'M1',
|
|
497
|
+
node: 'B',
|
|
498
|
+
attrs: 'e',
|
|
499
499
|
tag: t1.name,
|
|
500
|
-
params: { a: 333, d: 5}.to_json,
|
|
500
|
+
params: { a: 333, d: 5 }.to_json,
|
|
501
501
|
}
|
|
502
502
|
expect(response.body).to eq(4.to_json)
|
|
503
503
|
end
|
|
504
504
|
|
|
505
|
-
it
|
|
505
|
+
it 'should be able to post background job' do
|
|
506
506
|
Delayed::Worker.delay_jobs = false
|
|
507
507
|
post 'evaluate', params: {
|
|
508
508
|
format: :json,
|
|
509
|
-
script:
|
|
510
|
-
node:
|
|
511
|
-
attrs:
|
|
509
|
+
script: 'M1',
|
|
510
|
+
node: 'B',
|
|
511
|
+
attrs: 'e',
|
|
512
512
|
tag: t1.name,
|
|
513
|
-
params: { a: 333, d: 5}.to_json,
|
|
513
|
+
params: { a: 333, d: 5 }.to_json,
|
|
514
514
|
background: true,
|
|
515
515
|
}
|
|
516
516
|
res = ActiveSupport::JSON.decode response.body
|
|
@@ -519,20 +519,20 @@ describe Marty::RpcController do
|
|
|
519
519
|
|
|
520
520
|
promise = Marty::Promise.find_by_id(job_id)
|
|
521
521
|
|
|
522
|
-
expect(promise.result).to eq(
|
|
522
|
+
expect(promise.result).to eq('e' => 4)
|
|
523
523
|
|
|
524
524
|
Delayed::Worker.delay_jobs = true
|
|
525
525
|
end
|
|
526
526
|
|
|
527
|
-
it
|
|
527
|
+
it 'should be able to post background job with non-array attr' do
|
|
528
528
|
Delayed::Worker.delay_jobs = false
|
|
529
529
|
post 'evaluate', params: {
|
|
530
530
|
format: :json,
|
|
531
|
-
script:
|
|
532
|
-
node:
|
|
533
|
-
attrs:
|
|
531
|
+
script: 'M1',
|
|
532
|
+
node: 'B',
|
|
533
|
+
attrs: 'e',
|
|
534
534
|
tag: t1.name,
|
|
535
|
-
params: { a: 333, d: 5}.to_json,
|
|
535
|
+
params: { a: 333, d: 5 }.to_json,
|
|
536
536
|
background: true,
|
|
537
537
|
}
|
|
538
538
|
res = ActiveSupport::JSON.decode response.body
|
|
@@ -541,45 +541,45 @@ describe Marty::RpcController do
|
|
|
541
541
|
|
|
542
542
|
promise = Marty::Promise.find_by_id(job_id)
|
|
543
543
|
|
|
544
|
-
expect(promise.result).to eq(
|
|
544
|
+
expect(promise.result).to eq('e' => 4)
|
|
545
545
|
|
|
546
546
|
Delayed::Worker.delay_jobs = true
|
|
547
547
|
end
|
|
548
548
|
|
|
549
|
-
it
|
|
549
|
+
it 'should be able to post with complex data' do
|
|
550
550
|
post 'evaluate', params: {
|
|
551
551
|
format: :json,
|
|
552
|
-
script:
|
|
553
|
-
node:
|
|
554
|
-
attrs:
|
|
552
|
+
script: 'M1',
|
|
553
|
+
node: 'D',
|
|
554
|
+
attrs: 'out',
|
|
555
555
|
tag: t1.name,
|
|
556
|
-
params: {in: @data}.to_json
|
|
556
|
+
params: { in: @data }.to_json
|
|
557
557
|
}
|
|
558
558
|
expect(response.body).to eq(@data_json)
|
|
559
559
|
end
|
|
560
560
|
|
|
561
561
|
# content-type: application/json structures the request a little differently
|
|
562
562
|
# so we also test that
|
|
563
|
-
it
|
|
563
|
+
it 'should be able to post (JSON) with complex data' do
|
|
564
564
|
@request.env['CONTENT_TYPE'] = 'application/json'
|
|
565
565
|
@request.env['ACCEPT'] = 'application/json'
|
|
566
566
|
post 'evaluate', params: {
|
|
567
567
|
format: :json,
|
|
568
|
-
script:
|
|
569
|
-
node:
|
|
570
|
-
attrs:
|
|
568
|
+
script: 'M1',
|
|
569
|
+
node: 'D',
|
|
570
|
+
attrs: 'out',
|
|
571
571
|
tag: t1.name,
|
|
572
|
-
params: {in: @data}.to_json
|
|
572
|
+
params: { in: @data }.to_json
|
|
573
573
|
}
|
|
574
574
|
expect(response.body).to eq(@data_json)
|
|
575
575
|
end
|
|
576
576
|
|
|
577
|
-
it
|
|
577
|
+
it 'should be able to run scripts' do
|
|
578
578
|
get 'evaluate', params: {
|
|
579
579
|
format: :json,
|
|
580
|
-
script:
|
|
581
|
-
node:
|
|
582
|
-
attrs:
|
|
580
|
+
script: 'M1',
|
|
581
|
+
node: 'A',
|
|
582
|
+
attrs: 'a',
|
|
583
583
|
tag: t1.name,
|
|
584
584
|
}
|
|
585
585
|
# puts 'Z'*40, request.inspect
|
|
@@ -587,150 +587,150 @@ describe Marty::RpcController do
|
|
|
587
587
|
|
|
588
588
|
get 'evaluate', params: {
|
|
589
589
|
format: :json,
|
|
590
|
-
script:
|
|
591
|
-
node:
|
|
592
|
-
attrs:
|
|
593
|
-
params: {
|
|
590
|
+
script: 'M1',
|
|
591
|
+
node: 'A',
|
|
592
|
+
attrs: 'a',
|
|
593
|
+
params: { 'a' => 4.5 }.to_json,
|
|
594
594
|
tag: t1.name,
|
|
595
595
|
}
|
|
596
596
|
expect(response.body).to eq(4.5.to_json)
|
|
597
597
|
|
|
598
598
|
get 'evaluate', params: {
|
|
599
599
|
format: :json,
|
|
600
|
-
script:
|
|
601
|
-
node:
|
|
602
|
-
attrs:
|
|
603
|
-
params: {
|
|
600
|
+
script: 'M1',
|
|
601
|
+
node: 'B',
|
|
602
|
+
attrs: 'a',
|
|
603
|
+
params: { 'a' => 4.5 }.to_json,
|
|
604
604
|
tag: t1.name,
|
|
605
605
|
}
|
|
606
606
|
expect(response.body).to eq(4.5.to_json)
|
|
607
607
|
|
|
608
608
|
get 'evaluate', params: {
|
|
609
609
|
format: :json,
|
|
610
|
-
script:
|
|
611
|
-
tag:
|
|
612
|
-
node:
|
|
613
|
-
attrs:
|
|
614
|
-
params: {
|
|
610
|
+
script: 'M1',
|
|
611
|
+
tag: 'DEV',
|
|
612
|
+
node: 'AA',
|
|
613
|
+
attrs: 'a',
|
|
614
|
+
params: { 'a' => 3.3 }.to_json,
|
|
615
615
|
}
|
|
616
616
|
expect(response.body).to eq(3.3.to_json)
|
|
617
617
|
end
|
|
618
618
|
|
|
619
|
-
it
|
|
619
|
+
it 'should be able to use posting name for tags' do
|
|
620
620
|
get 'evaluate', params: {
|
|
621
621
|
format: :json,
|
|
622
|
-
script:
|
|
623
|
-
node:
|
|
624
|
-
attrs:
|
|
622
|
+
script: 'M1',
|
|
623
|
+
node: 'A',
|
|
624
|
+
attrs: 'a',
|
|
625
625
|
tag: p0.name,
|
|
626
626
|
}
|
|
627
|
-
expect(response.body[
|
|
627
|
+
expect(response.body['error']).to_not be_nil
|
|
628
628
|
|
|
629
629
|
get 'evaluate', params: {
|
|
630
630
|
format: :json,
|
|
631
|
-
script:
|
|
632
|
-
node:
|
|
633
|
-
attrs:
|
|
634
|
-
params: {
|
|
631
|
+
script: 'M1',
|
|
632
|
+
node: 'A',
|
|
633
|
+
attrs: 'a',
|
|
634
|
+
params: { 'a' => 4.5 }.to_json,
|
|
635
635
|
tag: p1.name,
|
|
636
636
|
}
|
|
637
637
|
expect(response.body).to eq(4.5.to_json)
|
|
638
638
|
|
|
639
639
|
get 'evaluate', params: {
|
|
640
640
|
format: :json,
|
|
641
|
-
script:
|
|
642
|
-
node:
|
|
643
|
-
attrs:
|
|
644
|
-
params: {
|
|
641
|
+
script: 'M1',
|
|
642
|
+
node: 'B',
|
|
643
|
+
attrs: 'a',
|
|
644
|
+
params: { 'a' => 4.5 }.to_json,
|
|
645
645
|
tag: p2.name,
|
|
646
646
|
}
|
|
647
647
|
expect(response.body).to eq(4.5.to_json)
|
|
648
648
|
|
|
649
649
|
get 'evaluate', params: {
|
|
650
650
|
format: :json,
|
|
651
|
-
script:
|
|
652
|
-
tag:
|
|
653
|
-
node:
|
|
654
|
-
attrs:
|
|
655
|
-
params: {
|
|
651
|
+
script: 'M1',
|
|
652
|
+
tag: 'NOW',
|
|
653
|
+
node: 'AA',
|
|
654
|
+
attrs: 'a',
|
|
655
|
+
params: { 'a' => 3.3 }.to_json,
|
|
656
656
|
}
|
|
657
657
|
expect(response.body).to eq(3.3.to_json)
|
|
658
658
|
end
|
|
659
659
|
|
|
660
|
-
it
|
|
660
|
+
it 'should be able to run scripts 2' do
|
|
661
661
|
get 'evaluate', params: {
|
|
662
662
|
format: :json,
|
|
663
|
-
script:
|
|
664
|
-
node:
|
|
665
|
-
attrs:
|
|
663
|
+
script: 'M3',
|
|
664
|
+
node: 'C',
|
|
665
|
+
attrs: 'pc',
|
|
666
666
|
}
|
|
667
667
|
# puts 'Z'*40, request.inspect
|
|
668
668
|
expect(response.body).to eq(7.to_json)
|
|
669
669
|
|
|
670
670
|
get 'evaluate', params: {
|
|
671
671
|
format: :json,
|
|
672
|
-
script:
|
|
673
|
-
node:
|
|
674
|
-
attrs:
|
|
672
|
+
script: 'M3',
|
|
673
|
+
node: 'B',
|
|
674
|
+
attrs: 'pc',
|
|
675
675
|
}
|
|
676
676
|
# puts 'Z'*40, request.inspect
|
|
677
677
|
expect(response.body).to eq(9.to_json)
|
|
678
678
|
|
|
679
679
|
get 'evaluate', params: {
|
|
680
680
|
format: :json,
|
|
681
|
-
script:
|
|
682
|
-
node:
|
|
683
|
-
attrs:
|
|
681
|
+
script: 'M3',
|
|
682
|
+
node: 'A',
|
|
683
|
+
attrs: 'pc',
|
|
684
684
|
}
|
|
685
685
|
# puts 'Z'*40, request.inspect
|
|
686
686
|
expect(response.body).to match(/"error":"undefined parameter p"/)
|
|
687
687
|
end
|
|
688
688
|
|
|
689
|
-
it
|
|
689
|
+
it 'should be able to handle imports' do
|
|
690
690
|
get 'evaluate', params: {
|
|
691
691
|
format: :json,
|
|
692
|
-
script:
|
|
693
|
-
node:
|
|
694
|
-
attrs:
|
|
692
|
+
script: 'M4',
|
|
693
|
+
node: 'A',
|
|
694
|
+
attrs: 'a',
|
|
695
695
|
}
|
|
696
696
|
# puts 'Z'*40, request.inspect
|
|
697
697
|
expect(response.body).to eq(2.to_json)
|
|
698
698
|
end
|
|
699
699
|
|
|
700
|
-
it
|
|
700
|
+
it 'should support CSV' do
|
|
701
701
|
get 'evaluate', params: {
|
|
702
702
|
format: :csv,
|
|
703
|
-
script:
|
|
704
|
-
node:
|
|
705
|
-
attrs:
|
|
703
|
+
script: 'M4',
|
|
704
|
+
node: 'A',
|
|
705
|
+
attrs: 'a',
|
|
706
706
|
}
|
|
707
707
|
# puts 'Z'*40, request.inspect
|
|
708
708
|
expect(response.body).to eq("2\r\n")
|
|
709
709
|
end
|
|
710
710
|
|
|
711
|
-
it
|
|
711
|
+
it 'should support CSV (2)' do
|
|
712
712
|
get 'evaluate', params: {
|
|
713
713
|
format: :csv,
|
|
714
|
-
script:
|
|
715
|
-
node:
|
|
716
|
-
attrs:
|
|
714
|
+
script: 'M4',
|
|
715
|
+
node: 'A',
|
|
716
|
+
attrs: 'result',
|
|
717
717
|
}
|
|
718
718
|
# puts 'Z'*40, request.inspect
|
|
719
719
|
expect(response.body).to eq("a,b\r\n10,456\r\n789,10\r\n")
|
|
720
720
|
end
|
|
721
721
|
|
|
722
|
-
it
|
|
723
|
-
Marty::ApiConfig.create!(script:
|
|
724
|
-
node:
|
|
722
|
+
it 'returns an error message on missing schema script (csv)' do
|
|
723
|
+
Marty::ApiConfig.create!(script: 'M1',
|
|
724
|
+
node: 'A',
|
|
725
725
|
attr: nil,
|
|
726
726
|
logged: false,
|
|
727
727
|
input_validated: true)
|
|
728
|
-
attr =
|
|
729
|
-
params = {
|
|
728
|
+
attr = 'b'
|
|
729
|
+
params = { 'a' => 5 }.to_json
|
|
730
730
|
get 'evaluate', params: {
|
|
731
731
|
format: :csv,
|
|
732
|
-
script:
|
|
733
|
-
node:
|
|
732
|
+
script: 'M1',
|
|
733
|
+
node: 'A',
|
|
734
734
|
attrs: attr,
|
|
735
735
|
params: params
|
|
736
736
|
}
|
|
@@ -738,79 +738,79 @@ describe Marty::RpcController do
|
|
|
738
738
|
expect(response.body).to eq("error,#{expect}")
|
|
739
739
|
end
|
|
740
740
|
|
|
741
|
-
it
|
|
742
|
-
Marty::ApiConfig.create!(script:
|
|
743
|
-
node:
|
|
741
|
+
it 'returns an error message on missing schema script (json)' do
|
|
742
|
+
Marty::ApiConfig.create!(script: 'M1',
|
|
743
|
+
node: 'A',
|
|
744
744
|
attr: nil,
|
|
745
745
|
logged: false,
|
|
746
746
|
input_validated: true)
|
|
747
|
-
attr =
|
|
748
|
-
params = {
|
|
747
|
+
attr = 'b'
|
|
748
|
+
params = { 'a' => 5 }.to_json
|
|
749
749
|
get 'evaluate', params: {
|
|
750
750
|
format: :json,
|
|
751
|
-
script:
|
|
752
|
-
node:
|
|
751
|
+
script: 'M1',
|
|
752
|
+
node: 'A',
|
|
753
753
|
attrs: attr,
|
|
754
754
|
params: params
|
|
755
755
|
}
|
|
756
|
-
expect =
|
|
756
|
+
expect = 'Schema error for M1/A attrs=b: Schema not defined'
|
|
757
757
|
res = JSON.parse(response.body)
|
|
758
758
|
expect(res.keys.size).to eq(1)
|
|
759
|
-
expect(res.keys[0]).to eq(
|
|
759
|
+
expect(res.keys[0]).to eq('error')
|
|
760
760
|
expect(res.values[0]).to eq(expect)
|
|
761
761
|
end
|
|
762
762
|
|
|
763
|
-
it
|
|
764
|
-
Marty::ApiConfig.create!(script:
|
|
765
|
-
node:
|
|
763
|
+
it 'returns an error message on missing attributes in schema script' do
|
|
764
|
+
Marty::ApiConfig.create!(script: 'M4',
|
|
765
|
+
node: 'A',
|
|
766
766
|
attr: nil,
|
|
767
767
|
logged: false,
|
|
768
768
|
input_validated: true)
|
|
769
|
-
attr =
|
|
770
|
-
params = {
|
|
769
|
+
attr = 'h'
|
|
770
|
+
params = { 'f' => 5 }.to_json
|
|
771
771
|
get 'evaluate', params: {
|
|
772
772
|
format: :csv,
|
|
773
|
-
script:
|
|
774
|
-
node:
|
|
773
|
+
script: 'M4',
|
|
774
|
+
node: 'A',
|
|
775
775
|
attrs: attr,
|
|
776
776
|
params: params
|
|
777
777
|
}
|
|
778
|
-
expect =
|
|
778
|
+
expect = 'error,Schema error for M4/A attrs=h: Schema not defined'
|
|
779
779
|
expect(response.body).to include(expect)
|
|
780
780
|
end
|
|
781
781
|
|
|
782
|
-
it
|
|
783
|
-
Marty::ApiConfig.create!(script:
|
|
784
|
-
node:
|
|
782
|
+
it 'returns an error message on invalid schema' do
|
|
783
|
+
Marty::ApiConfig.create!(script: 'M3err',
|
|
784
|
+
node: 'A',
|
|
785
785
|
attr: nil,
|
|
786
786
|
logged: false,
|
|
787
787
|
input_validated: true)
|
|
788
|
-
attr =
|
|
789
|
-
params = {
|
|
788
|
+
attr = 'pc'
|
|
789
|
+
params = { 'p' => 5 }.to_json
|
|
790
790
|
get 'evaluate', params: {
|
|
791
791
|
format: :csv,
|
|
792
|
-
script:
|
|
793
|
-
node:
|
|
792
|
+
script: 'M3err',
|
|
793
|
+
node: 'A',
|
|
794
794
|
attrs: attr,
|
|
795
795
|
params: params
|
|
796
796
|
}
|
|
797
|
-
expect =
|
|
797
|
+
expect = 'Schema error for M3err/A attrs=pc: Problem with schema: '\
|
|
798
798
|
"syntax error M3errSchemas:2\r\n"
|
|
799
799
|
expect(response.body).to eq("error,#{expect}")
|
|
800
800
|
end
|
|
801
801
|
|
|
802
|
-
it
|
|
803
|
-
Marty::ApiConfig.create!(script:
|
|
804
|
-
node:
|
|
802
|
+
it 'returns a validation error when validating a single attribute' do
|
|
803
|
+
Marty::ApiConfig.create!(script: 'M4',
|
|
804
|
+
node: 'A',
|
|
805
805
|
attr: nil,
|
|
806
806
|
logged: false,
|
|
807
807
|
input_validated: true)
|
|
808
|
-
attr =
|
|
809
|
-
params = {
|
|
808
|
+
attr = 'd'
|
|
809
|
+
params = { 'p' => '132' }.to_json
|
|
810
810
|
get 'evaluate', params: {
|
|
811
811
|
format: :csv,
|
|
812
|
-
script:
|
|
813
|
-
node:
|
|
812
|
+
script: 'M4',
|
|
813
|
+
node: 'A',
|
|
814
814
|
attrs: attr,
|
|
815
815
|
params: params
|
|
816
816
|
}
|
|
@@ -819,163 +819,163 @@ describe Marty::RpcController do
|
|
|
819
819
|
expect(response.body).to include(expect)
|
|
820
820
|
end
|
|
821
821
|
|
|
822
|
-
context
|
|
823
|
-
it
|
|
824
|
-
Marty::ApiConfig.create!(script:
|
|
825
|
-
node:
|
|
822
|
+
context 'output_validation' do
|
|
823
|
+
it 'validates output' do
|
|
824
|
+
Marty::ApiConfig.create!(script: 'M4',
|
|
825
|
+
node: 'A',
|
|
826
826
|
attr: nil,
|
|
827
827
|
logged: false,
|
|
828
828
|
input_validated: true,
|
|
829
829
|
output_validated: true,
|
|
830
830
|
strict_validate: true)
|
|
831
|
-
attr =
|
|
832
|
-
params = {
|
|
831
|
+
attr = 'ii'
|
|
832
|
+
params = { 'p' => 132, 'e' => 55, 'f' => 16, 'i' => 'string' }.to_json
|
|
833
833
|
get 'evaluate', params: {
|
|
834
834
|
format: :json,
|
|
835
|
-
script:
|
|
836
|
-
node:
|
|
835
|
+
script: 'M4',
|
|
836
|
+
node: 'A',
|
|
837
837
|
attrs: attr,
|
|
838
838
|
params: params
|
|
839
839
|
}
|
|
840
840
|
res = JSON.parse(response.body)
|
|
841
|
-
errpart =
|
|
841
|
+
errpart = 'of type string did not match the following type: integer'
|
|
842
842
|
expect(res['error']).to include(errpart)
|
|
843
843
|
logs = Marty::Log.all
|
|
844
844
|
expect(logs.count).to eq(1)
|
|
845
|
-
expect(logs[0].details[
|
|
845
|
+
expect(logs[0].details['error'][0]).to include(errpart)
|
|
846
846
|
end
|
|
847
847
|
|
|
848
|
-
it
|
|
849
|
-
Marty::ApiConfig.create!(script:
|
|
850
|
-
node:
|
|
848
|
+
it 'validates output (bad type, with strict errors)' do
|
|
849
|
+
Marty::ApiConfig.create!(script: 'M5',
|
|
850
|
+
node: 'A',
|
|
851
851
|
attr: nil,
|
|
852
852
|
logged: false,
|
|
853
853
|
input_validated: true,
|
|
854
854
|
output_validated: true,
|
|
855
855
|
strict_validate: true)
|
|
856
856
|
|
|
857
|
-
attr =
|
|
858
|
-
params = {
|
|
857
|
+
attr = 'result'
|
|
858
|
+
params = { 'f' => 'Banana' }.to_json
|
|
859
859
|
get 'evaluate', params: {
|
|
860
860
|
format: :json,
|
|
861
|
-
script:
|
|
862
|
-
node:
|
|
861
|
+
script: 'M5',
|
|
862
|
+
node: 'A',
|
|
863
863
|
attrs: attr,
|
|
864
864
|
params: params
|
|
865
865
|
}
|
|
866
866
|
res = JSON.parse(response.body)
|
|
867
|
-
expect(res).to include(
|
|
867
|
+
expect(res).to include('error')
|
|
868
868
|
expect1 = "The property '#/0/b' of type integer did not match the "\
|
|
869
|
-
|
|
869
|
+
'following type: string'
|
|
870
870
|
expect2 = "The property '#/0/a' of type string did not match the "\
|
|
871
|
-
|
|
872
|
-
expect(res[
|
|
873
|
-
expect(res[
|
|
871
|
+
'following type: integer'
|
|
872
|
+
expect(res['error']).to include(expect1)
|
|
873
|
+
expect(res['error']).to include(expect2)
|
|
874
874
|
|
|
875
875
|
logs = Marty::Log.all
|
|
876
876
|
expect(logs.count).to eq(1)
|
|
877
|
-
expect(logs[0].message).to eq(
|
|
878
|
-
expect(logs[0].details[
|
|
879
|
-
expect(logs[0].details[
|
|
880
|
-
expect(logs[0].details[
|
|
881
|
-
{
|
|
877
|
+
expect(logs[0].message).to eq('API M5:A.result')
|
|
878
|
+
expect(logs[0].details['error'].join).to include(expect1)
|
|
879
|
+
expect(logs[0].details['error'].join).to include(expect2)
|
|
880
|
+
expect(logs[0].details['data']).to eq([{ 'a' => 'str', 'b' => 456 },
|
|
881
|
+
{ 'a' => 789, 'b' => 'str' }])
|
|
882
882
|
end
|
|
883
883
|
|
|
884
|
-
it
|
|
885
|
-
Marty::ApiConfig.create!(script:
|
|
886
|
-
node:
|
|
887
|
-
attr:
|
|
884
|
+
it 'validates output (bad type, with non strict errors)' do
|
|
885
|
+
Marty::ApiConfig.create!(script: 'M5',
|
|
886
|
+
node: 'A',
|
|
887
|
+
attr: 'result2',
|
|
888
888
|
logged: false,
|
|
889
889
|
input_validated: true,
|
|
890
890
|
output_validated: true,
|
|
891
891
|
strict_validate: false)
|
|
892
|
-
attr =
|
|
893
|
-
params = {
|
|
892
|
+
attr = 'result2'
|
|
893
|
+
params = { 'f' => 'Banana' }.to_json
|
|
894
894
|
get 'evaluate', params: {
|
|
895
895
|
format: :json,
|
|
896
|
-
script:
|
|
897
|
-
node:
|
|
896
|
+
script: 'M5',
|
|
897
|
+
node: 'A',
|
|
898
898
|
attrs: attr,
|
|
899
899
|
params: params
|
|
900
900
|
}
|
|
901
901
|
expect1 = "The property '#/0/b' of type integer did not match the "\
|
|
902
|
-
|
|
902
|
+
'following type: string'
|
|
903
903
|
expect2 = "The property '#/0/a' of type string did not match the "\
|
|
904
|
-
|
|
904
|
+
'following type: integer'
|
|
905
905
|
logs = Marty::Log.all
|
|
906
906
|
expect(logs.count).to eq(1)
|
|
907
|
-
expect(logs[0].message).to eq(
|
|
908
|
-
expect(logs[0].details[
|
|
909
|
-
expect(logs[0].details[
|
|
910
|
-
expect(logs[0].details[
|
|
911
|
-
{
|
|
907
|
+
expect(logs[0].message).to eq('API M5:A.result2')
|
|
908
|
+
expect(logs[0].details['error'].join).to include(expect1)
|
|
909
|
+
expect(logs[0].details['error'].join).to include(expect2)
|
|
910
|
+
expect(logs[0].details['data']).to eq([{ 'a' => 'str', 'b' => 456 },
|
|
911
|
+
{ 'a' => 789, 'b' => 'str' }])
|
|
912
912
|
end
|
|
913
913
|
|
|
914
|
-
it
|
|
915
|
-
Marty::ApiConfig.create!(script:
|
|
916
|
-
node:
|
|
914
|
+
it 'validates output (missing item)' do
|
|
915
|
+
Marty::ApiConfig.create!(script: 'M9',
|
|
916
|
+
node: 'A',
|
|
917
917
|
attr: nil,
|
|
918
918
|
logged: false,
|
|
919
919
|
input_validated: true,
|
|
920
920
|
output_validated: true,
|
|
921
921
|
strict_validate: true)
|
|
922
|
-
attr =
|
|
923
|
-
params = {
|
|
922
|
+
attr = 'result'
|
|
923
|
+
params = { 'b' => 122 }.to_json
|
|
924
924
|
get 'evaluate', params: {
|
|
925
925
|
format: :json,
|
|
926
|
-
script:
|
|
927
|
-
node:
|
|
926
|
+
script: 'M9',
|
|
927
|
+
node: 'A',
|
|
928
928
|
attrs: attr,
|
|
929
929
|
params: params
|
|
930
930
|
}
|
|
931
931
|
|
|
932
932
|
res = JSON.parse(response.body)
|
|
933
|
-
expect(res).to include(
|
|
933
|
+
expect(res).to include('error')
|
|
934
934
|
expect1 = "The property '#/0' did not contain a required property of 'c'"
|
|
935
935
|
expect2 = "The property '#/1' did not contain a required property of 'c'"
|
|
936
|
-
expect(res[
|
|
937
|
-
expect(res[
|
|
936
|
+
expect(res['error']).to include(expect1)
|
|
937
|
+
expect(res['error']).to include(expect2)
|
|
938
938
|
|
|
939
939
|
logs = Marty::Log.all
|
|
940
940
|
expect(logs.count).to eq(1)
|
|
941
|
-
expect(logs[0].message).to eq(
|
|
942
|
-
expect(logs[0].details[
|
|
943
|
-
expect(logs[0].details[
|
|
944
|
-
expect(logs[0].details[
|
|
945
|
-
{
|
|
941
|
+
expect(logs[0].message).to eq('API M9:A.result')
|
|
942
|
+
expect(logs[0].details['error'].join).to include(expect1)
|
|
943
|
+
expect(logs[0].details['error'].join).to include(expect2)
|
|
944
|
+
expect(logs[0].details['data']).to eq([{ 'a' => 1, 'b' => 123 },
|
|
945
|
+
{ 'a' => 789, 'b' => 123 }])
|
|
946
946
|
end
|
|
947
947
|
end
|
|
948
948
|
|
|
949
|
-
it
|
|
950
|
-
Marty::ApiConfig.create!(script:
|
|
951
|
-
node:
|
|
949
|
+
it 'validates schema' do
|
|
950
|
+
Marty::ApiConfig.create!(script: 'M4',
|
|
951
|
+
node: 'A',
|
|
952
952
|
attr: nil,
|
|
953
953
|
logged: false,
|
|
954
954
|
input_validated: true)
|
|
955
|
-
attr =
|
|
956
|
-
params = {
|
|
955
|
+
attr = 'lc'
|
|
956
|
+
params = { 'p' => 5 }.to_json
|
|
957
957
|
get 'evaluate', params: {
|
|
958
958
|
format: :csv,
|
|
959
|
-
script:
|
|
960
|
-
node:
|
|
959
|
+
script: 'M4',
|
|
960
|
+
node: 'A',
|
|
961
961
|
attrs: attr,
|
|
962
962
|
params: params
|
|
963
963
|
}
|
|
964
964
|
expect(response.body).to eq("9\r\n9\r\n")
|
|
965
965
|
end
|
|
966
966
|
|
|
967
|
-
it
|
|
968
|
-
Marty::ApiConfig.create!(script:
|
|
969
|
-
node:
|
|
967
|
+
it 'catches JSON::Validator exceptions' do
|
|
968
|
+
Marty::ApiConfig.create!(script: 'M6',
|
|
969
|
+
node: 'A',
|
|
970
970
|
attr: nil,
|
|
971
971
|
logged: false,
|
|
972
972
|
input_validated: true)
|
|
973
|
-
attr =
|
|
974
|
-
params = {
|
|
973
|
+
attr = 'res'
|
|
974
|
+
params = { 'b' => 5.22 }.to_json
|
|
975
975
|
get 'evaluate', params: {
|
|
976
976
|
format: :json,
|
|
977
|
-
script:
|
|
978
|
-
node:
|
|
977
|
+
script: 'M6',
|
|
978
|
+
node: 'A',
|
|
979
979
|
attrs: attr,
|
|
980
980
|
params: params
|
|
981
981
|
}
|
|
@@ -983,48 +983,47 @@ describe Marty::RpcController do
|
|
|
983
983
|
'did not match one or more of the required schemas'
|
|
984
984
|
res = JSON.parse(response.body)
|
|
985
985
|
expect(res.keys.size).to eq(1)
|
|
986
|
-
expect(res.keys[0]).to eq(
|
|
986
|
+
expect(res.keys[0]).to eq('error')
|
|
987
987
|
expect(res.values[0]).to eq(expect)
|
|
988
988
|
end
|
|
989
989
|
|
|
990
|
-
|
|
991
990
|
class FruitsEnum
|
|
992
|
-
VALUES=Set['Apple', 'Banana', 'Orange']
|
|
991
|
+
VALUES = Set['Apple', 'Banana', 'Orange']
|
|
993
992
|
end
|
|
994
993
|
class CondEnum
|
|
995
|
-
VALUES=Set['no opts','opt1','opt2','opttf']
|
|
994
|
+
VALUES = Set['no opts', 'opt1', 'opt2', 'opttf']
|
|
996
995
|
end
|
|
997
996
|
|
|
998
|
-
it
|
|
999
|
-
Marty::ApiConfig.create!(script:
|
|
1000
|
-
node:
|
|
997
|
+
it 'validates schema with a pg_enum (Positive)' do
|
|
998
|
+
Marty::ApiConfig.create!(script: 'M5',
|
|
999
|
+
node: 'A',
|
|
1001
1000
|
attr: nil,
|
|
1002
1001
|
logged: false,
|
|
1003
1002
|
input_validated: true)
|
|
1004
|
-
attr =
|
|
1005
|
-
params = {
|
|
1003
|
+
attr = 'res'
|
|
1004
|
+
params = { 'f' => 'Banana' }.to_json
|
|
1006
1005
|
get 'evaluate', params: {
|
|
1007
1006
|
format: :csv,
|
|
1008
|
-
script:
|
|
1009
|
-
node:
|
|
1007
|
+
script: 'M5',
|
|
1008
|
+
node: 'A',
|
|
1010
1009
|
attrs: attr,
|
|
1011
1010
|
params: params
|
|
1012
1011
|
}
|
|
1013
1012
|
expect(response.body).to eq("1\r\n")
|
|
1014
1013
|
end
|
|
1015
1014
|
|
|
1016
|
-
it
|
|
1017
|
-
Marty::ApiConfig.create!(script:
|
|
1018
|
-
node:
|
|
1015
|
+
it 'validates schema with a pg_enum (Negative)' do
|
|
1016
|
+
Marty::ApiConfig.create!(script: 'M5',
|
|
1017
|
+
node: 'A',
|
|
1019
1018
|
attr: nil,
|
|
1020
1019
|
logged: false,
|
|
1021
1020
|
input_validated: true)
|
|
1022
|
-
attr =
|
|
1023
|
-
params = {
|
|
1021
|
+
attr = 'res'
|
|
1022
|
+
params = { 'f' => 'Beans' }.to_json
|
|
1024
1023
|
get 'evaluate', params: {
|
|
1025
1024
|
format: :csv,
|
|
1026
|
-
script:
|
|
1027
|
-
node:
|
|
1025
|
+
script: 'M5',
|
|
1026
|
+
node: 'A',
|
|
1028
1027
|
attrs: attr,
|
|
1029
1028
|
params: params
|
|
1030
1029
|
}
|
|
@@ -1032,132 +1031,129 @@ describe Marty::RpcController do
|
|
|
1032
1031
|
expect(response.body).to include(expect)
|
|
1033
1032
|
end
|
|
1034
1033
|
|
|
1035
|
-
it
|
|
1036
|
-
Marty::ApiConfig.create!(script:
|
|
1037
|
-
node:
|
|
1034
|
+
it 'validates schema with a non-existant enum' do
|
|
1035
|
+
Marty::ApiConfig.create!(script: 'M7',
|
|
1036
|
+
node: 'A',
|
|
1038
1037
|
attr: nil,
|
|
1039
1038
|
logged: false,
|
|
1040
1039
|
input_validated: true)
|
|
1041
|
-
attr =
|
|
1042
|
-
params = {
|
|
1040
|
+
attr = 'res'
|
|
1041
|
+
params = { 'b' => 'MemberOfANonExistantEnum' }.to_json
|
|
1043
1042
|
get 'evaluate', params: {
|
|
1044
1043
|
format: :json,
|
|
1045
|
-
script:
|
|
1046
|
-
node:
|
|
1044
|
+
script: 'M7',
|
|
1045
|
+
node: 'A',
|
|
1047
1046
|
attrs: attr,
|
|
1048
1047
|
params: params
|
|
1049
1048
|
}
|
|
1050
1049
|
expect = "property '#/b': 'NonExistantEnum' is not a pg_enum"
|
|
1051
1050
|
res = JSON.parse(response.body)
|
|
1052
1051
|
expect(res.keys.size).to eq(1)
|
|
1053
|
-
expect(res.keys[0]).to eq(
|
|
1052
|
+
expect(res.keys[0]).to eq('error')
|
|
1054
1053
|
expect(res.values[0]).to include(expect)
|
|
1055
1054
|
end
|
|
1056
1055
|
|
|
1057
|
-
it
|
|
1058
|
-
Marty::ApiConfig.create!(script:
|
|
1059
|
-
node:
|
|
1056
|
+
it 'validates pgenum with capitalization issues' do
|
|
1057
|
+
Marty::ApiConfig.create!(script: 'M8',
|
|
1058
|
+
node: 'A',
|
|
1060
1059
|
attr: nil,
|
|
1061
1060
|
logged: false,
|
|
1062
1061
|
input_validated: true)
|
|
1063
|
-
skip
|
|
1064
|
-
|
|
1065
|
-
attr =
|
|
1066
|
-
params = {
|
|
1062
|
+
skip 'pending until a solution is found that handles '\
|
|
1063
|
+
'autoload issues involving constantize'
|
|
1064
|
+
attr = 'res'
|
|
1065
|
+
params = { 'b' => 'Annual' }.to_json
|
|
1067
1066
|
get 'evaluate', params: {
|
|
1068
1067
|
format: :json,
|
|
1069
|
-
script:
|
|
1070
|
-
node:
|
|
1068
|
+
script: 'M8',
|
|
1069
|
+
node: 'A',
|
|
1071
1070
|
attrs: attr,
|
|
1072
1071
|
params: params
|
|
1073
1072
|
}
|
|
1074
1073
|
end
|
|
1075
1074
|
|
|
1076
|
-
it
|
|
1077
|
-
Marty::ApiConfig.create!(script:
|
|
1078
|
-
node:
|
|
1075
|
+
it 'should log good req' do
|
|
1076
|
+
Marty::ApiConfig.create!(script: 'M3',
|
|
1077
|
+
node: 'A',
|
|
1079
1078
|
attr: nil,
|
|
1080
1079
|
logged: true)
|
|
1081
|
-
attr =
|
|
1082
|
-
params = {
|
|
1080
|
+
attr = 'lc'
|
|
1081
|
+
params = { 'p' => 5 }
|
|
1083
1082
|
get 'evaluate', params: {
|
|
1084
1083
|
format: :csv,
|
|
1085
|
-
script:
|
|
1086
|
-
node:
|
|
1084
|
+
script: 'M3',
|
|
1085
|
+
node: 'A',
|
|
1087
1086
|
attrs: attr,
|
|
1088
1087
|
params: params.to_json
|
|
1089
1088
|
}
|
|
1090
1089
|
expect(response.body).to eq("9\r\n9\r\n")
|
|
1091
1090
|
log = Marty::Log.order(id: :desc).first
|
|
1092
1091
|
|
|
1093
|
-
expect(log.details['script']).to eq(
|
|
1094
|
-
expect(log.details['node']).to eq(
|
|
1092
|
+
expect(log.details['script']).to eq('M3')
|
|
1093
|
+
expect(log.details['node']).to eq('A')
|
|
1095
1094
|
expect(log.details['attrs']).to eq(attr)
|
|
1096
1095
|
expect(log.details['input']).to eq(params)
|
|
1097
1096
|
expect(log.details['output']).to eq([9, 9])
|
|
1098
|
-
expect(log.details['remote_ip']).to eq(
|
|
1097
|
+
expect(log.details['remote_ip']).to eq('0.0.0.0')
|
|
1099
1098
|
expect(log.details['error']).to eq(nil)
|
|
1100
|
-
|
|
1101
1099
|
end
|
|
1102
1100
|
|
|
1103
|
-
it
|
|
1104
|
-
Marty::ApiConfig.create!(script:
|
|
1105
|
-
node:
|
|
1101
|
+
it 'should log good req [background]' do
|
|
1102
|
+
Marty::ApiConfig.create!(script: 'M3',
|
|
1103
|
+
node: 'A',
|
|
1106
1104
|
attr: nil,
|
|
1107
1105
|
logged: true)
|
|
1108
|
-
attr =
|
|
1109
|
-
params = {
|
|
1106
|
+
attr = 'lc'
|
|
1107
|
+
params = { 'p' => 5 }
|
|
1110
1108
|
get 'evaluate', params: {
|
|
1111
1109
|
format: :csv,
|
|
1112
|
-
script:
|
|
1113
|
-
node:
|
|
1110
|
+
script: 'M3',
|
|
1111
|
+
node: 'A',
|
|
1114
1112
|
attrs: attr,
|
|
1115
1113
|
params: params.to_json,
|
|
1116
1114
|
background: true
|
|
1117
1115
|
}
|
|
1118
1116
|
expect(response.body).to match(/job_id,/)
|
|
1119
1117
|
log = Marty::Log.order(id: :desc).first
|
|
1120
|
-
|
|
1121
1118
|
end
|
|
1122
1119
|
|
|
1123
|
-
it
|
|
1120
|
+
it 'should not log if it should not log' do
|
|
1124
1121
|
get 'evaluate', params: {
|
|
1125
1122
|
format: :json,
|
|
1126
|
-
script:
|
|
1127
|
-
node:
|
|
1128
|
-
attrs:
|
|
1123
|
+
script: 'M1',
|
|
1124
|
+
node: 'A',
|
|
1125
|
+
attrs: 'a',
|
|
1129
1126
|
tag: t1.name,
|
|
1130
1127
|
}
|
|
1131
1128
|
expect(Marty::Log.count).to eq(0)
|
|
1132
1129
|
end
|
|
1133
1130
|
|
|
1134
|
-
it
|
|
1135
|
-
Marty::ApiConfig.create!(script:
|
|
1136
|
-
node:
|
|
1131
|
+
it 'should handle atom attribute' do
|
|
1132
|
+
Marty::ApiConfig.create!(script: 'M3',
|
|
1133
|
+
node: 'A',
|
|
1137
1134
|
attr: nil,
|
|
1138
1135
|
logged: true)
|
|
1139
|
-
params = {
|
|
1136
|
+
params = { 'p' => 5 }
|
|
1140
1137
|
get 'evaluate', params: {
|
|
1141
1138
|
format: :csv,
|
|
1142
|
-
script:
|
|
1143
|
-
node:
|
|
1144
|
-
attrs:
|
|
1139
|
+
script: 'M3',
|
|
1140
|
+
node: 'A',
|
|
1141
|
+
attrs: 'lc',
|
|
1145
1142
|
params: params.to_json
|
|
1146
1143
|
}
|
|
1147
1144
|
expect(response.body).to eq("9\r\n9\r\n")
|
|
1148
1145
|
log = Marty::Log.order(id: :desc).first
|
|
1149
1146
|
|
|
1150
|
-
expect(log.details['script']).to eq(
|
|
1151
|
-
expect(log.details['node']).to eq(
|
|
1152
|
-
expect(log.details['attrs']).to eq(
|
|
1147
|
+
expect(log.details['script']).to eq('M3')
|
|
1148
|
+
expect(log.details['node']).to eq('A')
|
|
1149
|
+
expect(log.details['attrs']).to eq('lc')
|
|
1153
1150
|
expect(log.details['input']).to eq(params)
|
|
1154
1151
|
expect(log.details['output']).to eq([9, 9])
|
|
1155
|
-
expect(log.details['remote_ip']).to eq(
|
|
1152
|
+
expect(log.details['remote_ip']).to eq('0.0.0.0')
|
|
1156
1153
|
expect(log.details['error']).to eq(nil)
|
|
1157
|
-
|
|
1158
1154
|
end
|
|
1159
1155
|
|
|
1160
|
-
it
|
|
1156
|
+
it 'should support api authorization - api_key not required' do
|
|
1161
1157
|
api = Marty::ApiAuth.new
|
|
1162
1158
|
api.app_name = 'TestApp'
|
|
1163
1159
|
api.script_name = 'M2'
|
|
@@ -1165,14 +1161,14 @@ describe Marty::RpcController do
|
|
|
1165
1161
|
|
|
1166
1162
|
get 'evaluate', params: {
|
|
1167
1163
|
format: :json,
|
|
1168
|
-
script:
|
|
1169
|
-
node:
|
|
1170
|
-
attrs:
|
|
1164
|
+
script: 'M3',
|
|
1165
|
+
node: 'C',
|
|
1166
|
+
attrs: 'pc',
|
|
1171
1167
|
}
|
|
1172
1168
|
expect(response.body).to eq(7.to_json)
|
|
1173
1169
|
end
|
|
1174
1170
|
|
|
1175
|
-
it
|
|
1171
|
+
it 'should support api authorization - api_key required but missing' do
|
|
1176
1172
|
api = Marty::ApiAuth.new
|
|
1177
1173
|
api.app_name = 'TestApp'
|
|
1178
1174
|
api.script_name = 'M3'
|
|
@@ -1180,14 +1176,14 @@ describe Marty::RpcController do
|
|
|
1180
1176
|
|
|
1181
1177
|
get 'evaluate', params: {
|
|
1182
1178
|
format: :json,
|
|
1183
|
-
script:
|
|
1184
|
-
node:
|
|
1185
|
-
attrs:
|
|
1179
|
+
script: 'M3',
|
|
1180
|
+
node: 'C',
|
|
1181
|
+
attrs: 'pc',
|
|
1186
1182
|
}
|
|
1187
1183
|
expect(response.body).to match(/"error":"Permission denied"/)
|
|
1188
1184
|
end
|
|
1189
1185
|
|
|
1190
|
-
it
|
|
1186
|
+
it 'should support api authorization - api_key required and supplied' do
|
|
1191
1187
|
api = Marty::ApiAuth.new
|
|
1192
1188
|
api.app_name = 'TestApp'
|
|
1193
1189
|
api.script_name = 'M3'
|
|
@@ -1196,26 +1192,26 @@ describe Marty::RpcController do
|
|
|
1196
1192
|
apic = Marty::ApiConfig.create!(script: 'M3',
|
|
1197
1193
|
logged: true)
|
|
1198
1194
|
|
|
1199
|
-
attr =
|
|
1195
|
+
attr = 'pc'
|
|
1200
1196
|
get 'evaluate', params: {
|
|
1201
1197
|
format: :json,
|
|
1202
|
-
script:
|
|
1203
|
-
node:
|
|
1198
|
+
script: 'M3',
|
|
1199
|
+
node: 'C',
|
|
1204
1200
|
attrs: attr,
|
|
1205
1201
|
api_key: api.api_key,
|
|
1206
1202
|
}
|
|
1207
1203
|
expect(response.body).to eq(7.to_json)
|
|
1208
1204
|
log = Marty::Log.order(id: :desc).first
|
|
1209
1205
|
|
|
1210
|
-
expect(log.details['script']).to eq(
|
|
1211
|
-
expect(log.details['node']).to eq(
|
|
1206
|
+
expect(log.details['script']).to eq('M3')
|
|
1207
|
+
expect(log.details['node']).to eq('C')
|
|
1212
1208
|
expect(log.details['attrs']).to eq(attr)
|
|
1213
1209
|
expect(log.details['output']).to eq(7)
|
|
1214
|
-
expect(log.details['remote_ip']).to eq(
|
|
1215
|
-
expect(log.details['auth_name']).to eq(
|
|
1210
|
+
expect(log.details['remote_ip']).to eq('0.0.0.0')
|
|
1211
|
+
expect(log.details['auth_name']).to eq('TestApp')
|
|
1216
1212
|
end
|
|
1217
1213
|
|
|
1218
|
-
it
|
|
1214
|
+
it 'should support api authorization - api_key required but incorrect' do
|
|
1219
1215
|
api = Marty::ApiAuth.new
|
|
1220
1216
|
api.app_name = 'TestApp'
|
|
1221
1217
|
api.script_name = 'M3'
|
|
@@ -1223,39 +1219,39 @@ describe Marty::RpcController do
|
|
|
1223
1219
|
|
|
1224
1220
|
get 'evaluate', params: {
|
|
1225
1221
|
format: :json,
|
|
1226
|
-
script:
|
|
1227
|
-
node:
|
|
1228
|
-
attrs:
|
|
1222
|
+
script: 'M3',
|
|
1223
|
+
node: 'C',
|
|
1224
|
+
attrs: 'pc',
|
|
1229
1225
|
api_key: api.api_key + 'x',
|
|
1230
1226
|
}
|
|
1231
1227
|
expect(response.body).to match(/"error":"Permission denied"/)
|
|
1232
1228
|
end
|
|
1233
1229
|
|
|
1234
|
-
it
|
|
1230
|
+
it 'should convert incoming ints in number fields to float' do
|
|
1235
1231
|
api = Marty::ApiAuth.new
|
|
1236
1232
|
api.app_name = 'TestApp'
|
|
1237
1233
|
api.script_name = 'M11'
|
|
1238
1234
|
api.save!
|
|
1239
1235
|
p = File.expand_path('../../fixtures/json', __FILE__)
|
|
1240
|
-
f =
|
|
1236
|
+
f = '%s/%s' % [p, 'rpc_controller.json']
|
|
1241
1237
|
begin
|
|
1242
1238
|
tests = JSON.parse(File.read(f))
|
|
1243
|
-
rescue => e
|
|
1239
|
+
rescue StandardError => e
|
|
1244
1240
|
puts "Error parsing #{f}: #{e.message}"
|
|
1245
1241
|
raise
|
|
1246
1242
|
end
|
|
1247
|
-
aggregate_failures
|
|
1243
|
+
aggregate_failures 'input coercing' do
|
|
1248
1244
|
tests.each_with_index do |t, idx|
|
|
1249
1245
|
get 'evaluate', params: {
|
|
1250
1246
|
format: :json,
|
|
1251
|
-
script:
|
|
1252
|
-
node:
|
|
1247
|
+
script: 'M11',
|
|
1248
|
+
node: 'A',
|
|
1253
1249
|
attrs: t['attr'],
|
|
1254
1250
|
api_key: api.api_key,
|
|
1255
1251
|
params: t['request'].to_json
|
|
1256
1252
|
}
|
|
1257
1253
|
resp = JSON.parse(response.body)
|
|
1258
|
-
comp = struct_compare(resp, t['result'],
|
|
1254
|
+
comp = struct_compare(resp, t['result'], 'float_int_nomatch' => true)
|
|
1259
1255
|
(puts "TEST=#{idx}\n#{comp}"; binding.pry) if comp &&
|
|
1260
1256
|
ENV['PRY'] == 'true'
|
|
1261
1257
|
|
|
@@ -1264,21 +1260,21 @@ describe Marty::RpcController do
|
|
|
1264
1260
|
end
|
|
1265
1261
|
end
|
|
1266
1262
|
|
|
1267
|
-
context
|
|
1263
|
+
context 'conditional validation' do
|
|
1268
1264
|
before(:all) do
|
|
1269
|
-
Marty::ApiConfig.create!(script:
|
|
1270
|
-
node:
|
|
1265
|
+
Marty::ApiConfig.create!(script: 'M10',
|
|
1266
|
+
node: 'A',
|
|
1271
1267
|
attr: nil,
|
|
1272
1268
|
logged: false,
|
|
1273
1269
|
input_validated: true,
|
|
1274
1270
|
output_validated: false,
|
|
1275
1271
|
strict_validate: false)
|
|
1276
1272
|
end
|
|
1277
|
-
def do_call(req1, req2, req3, optionals={})
|
|
1278
|
-
attr =
|
|
1279
|
-
params = optionals.merge(
|
|
1280
|
-
|
|
1281
|
-
|
|
1273
|
+
def do_call(req1, req2, req3, optionals = {})
|
|
1274
|
+
attr = 'v1'
|
|
1275
|
+
params = optionals.merge('req1' => req1,
|
|
1276
|
+
'req2' => req2,
|
|
1277
|
+
'req3' => req3).to_json
|
|
1282
1278
|
|
|
1283
1279
|
# to see what the schema helpers generated:
|
|
1284
1280
|
# engine = Marty::ScriptSet.new(nil).get_engine("M10Schemas")
|
|
@@ -1287,20 +1283,19 @@ describe Marty::RpcController do
|
|
|
1287
1283
|
|
|
1288
1284
|
get 'evaluate', params: {
|
|
1289
1285
|
format: :json,
|
|
1290
|
-
script:
|
|
1291
|
-
node:
|
|
1286
|
+
script: 'M10',
|
|
1287
|
+
node: 'A',
|
|
1292
1288
|
attrs: attr,
|
|
1293
1289
|
params: params
|
|
1294
1290
|
}
|
|
1295
|
-
|
|
1296
1291
|
end
|
|
1297
1292
|
|
|
1298
|
-
it
|
|
1299
|
-
aggregate_failures
|
|
1293
|
+
it 'does conditional' do
|
|
1294
|
+
aggregate_failures 'conditionals' do
|
|
1300
1295
|
[
|
|
1301
1296
|
# first group has all required fields
|
|
1302
|
-
[['opt1', 'no opts', 'no opts', opt1: 'hi mom'],
|
|
1303
|
-
[['no opts', 'no opts', 'no opts', opt1: 'hi mom'],
|
|
1297
|
+
[['opt1', 'no opts', 'no opts', opt1: 'hi mom'], 'hi mom'],
|
|
1298
|
+
[['no opts', 'no opts', 'no opts', opt1: 'hi mom'], 'no opts'],
|
|
1304
1299
|
[['opt2', 'opt2', 'no opts', optn: 'foo'], 'foo'],
|
|
1305
1300
|
[['opt2', 'no opts', 'opt2'], 'req3'],
|
|
1306
1301
|
[['opt2', 'no opts', 'opttf', opttf: true, opttrue: 'bar'], 'bar'],
|
|
@@ -1317,19 +1312,18 @@ describe Marty::RpcController do
|
|
|
1317
1312
|
"did not contain a required property of 'opttrue'"],
|
|
1318
1313
|
[['opt2', 'no opts', 'opttf', opttf: false],
|
|
1319
1314
|
"did not contain a required property of 'optfalse'"],
|
|
1320
|
-
[['opt2', 'no opts', 'opttf', opttf: false, optfalse:
|
|
1321
|
-
optdisallow:
|
|
1315
|
+
[['opt2', 'no opts', 'opttf', opttf: false, optfalse: 'val',
|
|
1316
|
+
optdisallow: 'hi mom'],
|
|
1322
1317
|
"disallowed parameter 'optdisallow' of type string was received"],
|
|
1323
|
-
[['opt2', 'no opts', 'opttf', opttf: false, optfalse:
|
|
1324
|
-
opt3:
|
|
1318
|
+
[['opt2', 'no opts', 'opttf', opttf: false, optfalse: 'val',
|
|
1319
|
+
opt3: 'hi'],
|
|
1325
1320
|
"disallowed parameter 'opt3' of type string was received"],
|
|
1326
|
-
[['opt2', 'no opts', 'opttf', opttf: true, opttrue:
|
|
1327
|
-
opt4:
|
|
1321
|
+
[['opt2', 'no opts', 'opttf', opttf: true, opttrue: 'val',
|
|
1322
|
+
opt4: 'mom'],
|
|
1328
1323
|
"disallowed parameter 'opt4' of type string was received"],
|
|
1329
|
-
[['opt2', 'no opts', 'xyz', opt5:
|
|
1324
|
+
[['opt2', 'no opts', 'xyz', opt5: 'hi'],
|
|
1330
1325
|
"disallowed parameter 'opt5' of type string was received"],
|
|
1331
|
-
].each do
|
|
1332
|
-
|a, exp|
|
|
1326
|
+
].each do |a, exp|
|
|
1333
1327
|
do_call(*a)
|
|
1334
1328
|
res = JSON.parse(response.body) rescue response.body
|
|
1335
1329
|
expect(res.is_a?(Hash) ? res['error'] : res).to include(exp)
|
|
@@ -1338,44 +1332,44 @@ describe Marty::RpcController do
|
|
|
1338
1332
|
end
|
|
1339
1333
|
end
|
|
1340
1334
|
|
|
1341
|
-
context
|
|
1335
|
+
context 'error handling' do
|
|
1342
1336
|
it 'returns bad attrs if attr is not a string' do
|
|
1343
|
-
get :evaluate, params: {format: :json, attrs: 0}
|
|
1337
|
+
get :evaluate, params: { format: :json, attrs: 0 }
|
|
1344
1338
|
expect(response.body).to match(/"error":"Malformed attrs"/)
|
|
1345
1339
|
end
|
|
1346
1340
|
|
|
1347
1341
|
it 'returns malformed attrs for improperly formatted json' do
|
|
1348
|
-
get :evaluate, params: { format: :json, attrs:
|
|
1342
|
+
get :evaluate, params: { format: :json, attrs: '{' }
|
|
1349
1343
|
expect(response.body).to match(/"error":"Malformed attrs"/)
|
|
1350
1344
|
end
|
|
1351
1345
|
|
|
1352
1346
|
it 'returns malformed attrs if attr is not an array of strings' do
|
|
1353
|
-
get :evaluate, params: {format: :json, attrs:
|
|
1347
|
+
get :evaluate, params: { format: :json, attrs: '{}' }
|
|
1354
1348
|
expect(response.body).to match(/"error":"Malformed attrs"/)
|
|
1355
1349
|
|
|
1356
|
-
get :evaluate, params: { format: :json, attrs:
|
|
1350
|
+
get :evaluate, params: { format: :json, attrs: '[0]' }
|
|
1357
1351
|
expect(response.body).to match(/"error":"Malformed attrs"/)
|
|
1358
1352
|
end
|
|
1359
1353
|
|
|
1360
1354
|
it 'returns malformed params for improperly formatted json' do
|
|
1361
|
-
get :evaluate, params: {format: :json, attrs:
|
|
1355
|
+
get :evaluate, params: { format: :json, attrs: 'e', params: '{' }
|
|
1362
1356
|
expect(response.body).to match(/"error":"Malformed params"/)
|
|
1363
1357
|
end
|
|
1364
1358
|
|
|
1365
1359
|
it 'returns malformed params if params is not a hash' do
|
|
1366
|
-
get :evaluate, params: {format: :json, attrs:
|
|
1360
|
+
get :evaluate, params: { format: :json, attrs: 'e', params: '[0]' }
|
|
1367
1361
|
expect(response.body).to match(/"error":"Malformed params"/)
|
|
1368
1362
|
end
|
|
1369
1363
|
|
|
1370
1364
|
it 'returns engine/tag lookup error if script not found' do
|
|
1371
|
-
get :evaluate, params: {format: :json, script: 'M1', attrs:
|
|
1365
|
+
get :evaluate, params: { format: :json, script: 'M1', attrs: 'e', tag: 'invalid' }
|
|
1372
1366
|
expect(response.body).to match(/bad tag identifier.*invalid/)
|
|
1373
|
-
get :evaluate, params: {format: :json, script: 'Invalid', attrs:
|
|
1367
|
+
get :evaluate, params: { format: :json, script: 'Invalid', attrs: 'e', tag: t1.name }
|
|
1374
1368
|
expect(response.body).to match(/"error":"Can't get engine:/)
|
|
1375
1369
|
end
|
|
1376
1370
|
|
|
1377
1371
|
it 'returns the script runtime error (no node specified)' do
|
|
1378
|
-
get :evaluate, params: {format: :json, script: 'M1', attrs:
|
|
1372
|
+
get :evaluate, params: { format: :json, script: 'M1', attrs: 'e', tag: t1.name }
|
|
1379
1373
|
expect(response.body).to match(/"error":"bad node/)
|
|
1380
1374
|
end
|
|
1381
1375
|
end
|