marty 2.5.2 → 2.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|