inferno_core 0.4.43 → 0.5.0
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 +4 -4
- data/lib/inferno/apps/cli/execute/console_outputter.rb +152 -0
- data/lib/inferno/apps/cli/execute.rb +269 -0
- data/lib/inferno/apps/cli/main.rb +73 -4
- data/lib/inferno/apps/cli/templates/.env.development +2 -1
- data/lib/inferno/apps/cli/templates/.env.production +2 -1
- data/lib/inferno/apps/cli/templates/.env.test +1 -0
- data/lib/inferno/apps/cli/templates/.gitignore +1 -0
- data/lib/inferno/apps/cli/templates/config/nginx.background.conf.tt +15 -0
- data/lib/inferno/apps/cli/templates/docker-compose.background.yml.tt +5 -0
- data/lib/inferno/apps/cli/templates/docker-compose.yml.tt +4 -0
- data/lib/inferno/apps/cli.rb +0 -1
- data/lib/inferno/apps/web/controllers/test_runs/create.rb +7 -32
- data/lib/inferno/apps/web/serializers/serializer.rb +3 -0
- data/lib/inferno/config/boot/executor.rb +14 -0
- data/lib/inferno/dsl/auth_info.rb +77 -72
- data/lib/inferno/dsl/fhir_client_builder.rb +2 -2
- data/lib/inferno/dsl/fhir_resource_validation.rb +4 -0
- data/lib/inferno/dsl/http_client_builder.rb +2 -2
- data/lib/inferno/dsl/links.rb +100 -0
- data/lib/inferno/dsl/runnable.rb +6 -1
- data/lib/inferno/entities/has_runnable.rb +1 -1
- data/lib/inferno/entities/request.rb +2 -2
- data/lib/inferno/entities/test.rb +4 -4
- data/lib/inferno/entities/test_group.rb +2 -2
- data/lib/inferno/entities/test_suite.rb +2 -24
- data/lib/inferno/exceptions.rb +12 -0
- data/lib/inferno/ext/fhir_models.rb +3 -3
- data/lib/inferno/jobs.rb +4 -4
- data/lib/inferno/public/237.bundle.js +1 -0
- data/lib/inferno/public/assets.json +1 -1
- data/lib/inferno/public/bundle.js +42 -63
- data/lib/inferno/public/bundle.js.LICENSE.txt +5 -33
- data/lib/inferno/repositories/in_memory_repository.rb +5 -8
- data/lib/inferno/repositories/repository.rb +1 -1
- data/lib/inferno/result_summarizer.rb +1 -1
- data/lib/inferno/test_runner.rb +2 -2
- data/lib/inferno/utils/middleware/request_logger.rb +1 -1
- data/lib/inferno/utils/persist_inputs.rb +30 -0
- data/lib/inferno/utils/preset_template_generator.rb +1 -1
- data/lib/inferno/utils/verify_runnable.rb +15 -0
- data/lib/inferno/version.rb +1 -1
- data/spec/factories/result.rb +4 -0
- data/spec/fixtures/basic_test_group.rb +2 -1
- data/spec/fixtures/run_as_group_test_group.rb +11 -0
- metadata +24 -171
- data/lib/inferno/public/175.bundle.js +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c6ddae6726754b2036409f6765ffd3746e88a2238226655905332ac9083a907
|
4
|
+
data.tar.gz: a7f8fe7d9eedd5213bd9d825fc32075b00abf69953c29ab550c45b66fc0147b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfbb7ef6d15895b029349446501d739b7e676cff8e0ea369c1f781ee29151187eaba602f4485cee34a19c9a492d1cdbe2e4db3454db5f33a8f7b578586c53685
|
7
|
+
data.tar.gz: 14cb75b1bbaa2dcca319348f9914cf2af5d40d36a23ab7de3d212e43555466dc5f7c6d1af9a570fcca977e16353df80bc76f891616b32f0d91a593cfb9378730
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'pastel'
|
2
|
+
require_relative '../../web/serializers/test_run'
|
3
|
+
require_relative '../../web/serializers/result'
|
4
|
+
|
5
|
+
module Inferno
|
6
|
+
module CLI
|
7
|
+
class Execute
|
8
|
+
# @private
|
9
|
+
class ConsoleOutputter
|
10
|
+
COLOR = Pastel.new
|
11
|
+
CHECKMARK = "\u2713".freeze
|
12
|
+
BAR = ('=' * 80).freeze
|
13
|
+
|
14
|
+
def print_start_message(options)
|
15
|
+
puts ''
|
16
|
+
puts BAR
|
17
|
+
puts "Testing #{options[:suite]}"
|
18
|
+
verbose_puts options, "Running Groups #{options[:groups]}" unless options[:groups].blank?
|
19
|
+
verbose_puts options, "Running Tests #{options[:tests]}" unless options[:tests].blank?
|
20
|
+
verbose_puts options, "Running Entities #{options[:short_ids]}" unless options[:short_ids].blank?
|
21
|
+
puts BAR
|
22
|
+
end
|
23
|
+
|
24
|
+
def print_around_run(_options)
|
25
|
+
puts 'Running tests. This may take a while...'
|
26
|
+
# TODO: spinner/progress bar
|
27
|
+
yield
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_results(options, results)
|
31
|
+
verbose_print_json_results(options, results)
|
32
|
+
|
33
|
+
puts BAR
|
34
|
+
puts 'Test Results:'
|
35
|
+
puts BAR
|
36
|
+
results.each do |result|
|
37
|
+
print format_tag(result), ': ', format_result(result), "\n"
|
38
|
+
verbose_puts(options, "\tsummary: ", result.result_message)
|
39
|
+
verbose_puts(options, "\tmessages: ", format_messages(result))
|
40
|
+
verbose_puts(options, "\trequests: ", format_requests(result))
|
41
|
+
verbose_puts(options, "\tinputs: ", format_inputs(result))
|
42
|
+
verbose_puts(options, "\toutputs: ", format_outputs(result))
|
43
|
+
end
|
44
|
+
puts BAR
|
45
|
+
end
|
46
|
+
|
47
|
+
def print_end_message(options); end
|
48
|
+
|
49
|
+
def print_error(options, exception)
|
50
|
+
puts COLOR.red "Error: #{exception.full_message}"
|
51
|
+
verbose_print(options, exception.backtrace&.join('\n'))
|
52
|
+
end
|
53
|
+
|
54
|
+
# private
|
55
|
+
|
56
|
+
def verbose_print(options, *args)
|
57
|
+
print(COLOR.dim(*args)) if options[:verbose]
|
58
|
+
end
|
59
|
+
|
60
|
+
def verbose_puts(options, *args)
|
61
|
+
args.push("\n")
|
62
|
+
verbose_print(options, *args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def format_tag(result)
|
66
|
+
if result.runnable.respond_to?(:short_id)
|
67
|
+
"#{result.runnable.short_id} #{format_tag_suffix(result)}"
|
68
|
+
else
|
69
|
+
format_tag_suffix(result)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def format_tag_suffix(result)
|
74
|
+
result.runnable.short_title.presence || result.runnable.title.presence || result.runnable.id
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_messages(result)
|
78
|
+
result.messages.map do |message|
|
79
|
+
"\n\t\t#{message.type}: #{message.message}"
|
80
|
+
end.join
|
81
|
+
end
|
82
|
+
|
83
|
+
def format_requests(result)
|
84
|
+
result.requests.map do |req_res|
|
85
|
+
"\n\t\t#{req_res.status} #{req_res.verb.upcase} #{req_res.url}"
|
86
|
+
end.join
|
87
|
+
end
|
88
|
+
|
89
|
+
def format_session_data(result, attr)
|
90
|
+
json = result.send(attr)
|
91
|
+
return '' if json.nil?
|
92
|
+
|
93
|
+
JSON.parse(json).map do |hash|
|
94
|
+
"\n\t\t#{hash['name']}: #{hash['value']}"
|
95
|
+
end.join
|
96
|
+
end
|
97
|
+
|
98
|
+
def format_inputs(result)
|
99
|
+
format_session_data(result, :input_json)
|
100
|
+
end
|
101
|
+
|
102
|
+
def format_outputs(result)
|
103
|
+
format_session_data(result, :output_json)
|
104
|
+
end
|
105
|
+
|
106
|
+
def format_result(result) # rubocop:disable Metrics/CyclomaticComplexity
|
107
|
+
case result.result
|
108
|
+
when 'pass'
|
109
|
+
COLOR.bold.green(CHECKMARK, ' pass')
|
110
|
+
when 'fail'
|
111
|
+
COLOR.bold.red 'X fail'
|
112
|
+
when 'skip'
|
113
|
+
COLOR.yellow '* skip'
|
114
|
+
when 'omit'
|
115
|
+
COLOR.blue '* omit'
|
116
|
+
when 'error'
|
117
|
+
COLOR.magenta 'X error'
|
118
|
+
when 'wait'
|
119
|
+
COLOR.bold '. wait'
|
120
|
+
when 'cancel'
|
121
|
+
COLOR.red 'X cancel'
|
122
|
+
when 'running'
|
123
|
+
COLOR.bold '- running'
|
124
|
+
else
|
125
|
+
raise StandardError.new, "Unrecognized result #{result.result}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def verbose_print_json_results(options, results)
|
130
|
+
verbose_puts(options, BAR)
|
131
|
+
verbose_puts(options, 'JSON Test Results:')
|
132
|
+
verbose_puts(options, BAR)
|
133
|
+
verbose_puts(options, serialize(results))
|
134
|
+
verbose_puts(options, BAR)
|
135
|
+
end
|
136
|
+
|
137
|
+
def serialize(entity)
|
138
|
+
case entity.class.to_s
|
139
|
+
when 'Array'
|
140
|
+
JSON.pretty_generate(entity.map { |item| JSON.parse serialize(item) })
|
141
|
+
when lambda { |x|
|
142
|
+
defined?(x.constantize) && defined?("Inferno::Web::Serializers::#{x.split('::').last}".constantize)
|
143
|
+
}
|
144
|
+
"Inferno::Web::Serializers::#{entity.class.to_s.split('::').last}".constantize.render(entity)
|
145
|
+
else
|
146
|
+
raise StandardError, "CLI does not know how to serialize #{entity.class}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'pastel'
|
2
|
+
require 'active_support'
|
3
|
+
require_relative '../../utils/verify_runnable'
|
4
|
+
require_relative '../../utils/persist_inputs'
|
5
|
+
require_relative 'execute/console_outputter'
|
6
|
+
require_relative '../../result_summarizer'
|
7
|
+
|
8
|
+
module Inferno
|
9
|
+
module CLI
|
10
|
+
class Execute
|
11
|
+
include ::Inferno::Utils::VerifyRunnable
|
12
|
+
include ::Inferno::Utils::PersistInputs
|
13
|
+
|
14
|
+
attr_accessor :options
|
15
|
+
|
16
|
+
def self.suppress_output
|
17
|
+
begin
|
18
|
+
original_stdout = $stdout.clone
|
19
|
+
$stdout.reopen(File.new(File::NULL, 'w+'))
|
20
|
+
retval = yield
|
21
|
+
ensure
|
22
|
+
$stdout.reopen(original_stdout)
|
23
|
+
end
|
24
|
+
retval
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.boot_full_inferno
|
28
|
+
ENV['NO_DB'] = 'false'
|
29
|
+
|
30
|
+
# Inferno boot flow triggers migration and logger outputs it
|
31
|
+
Inferno::CLI::Execute.suppress_output { require_relative '../../../inferno' }
|
32
|
+
|
33
|
+
Inferno::Application.start(:executor)
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(options)
|
37
|
+
print_help_and_exit if options[:help]
|
38
|
+
|
39
|
+
self.options = options
|
40
|
+
|
41
|
+
outputter.print_start_message(options)
|
42
|
+
|
43
|
+
results = []
|
44
|
+
outputter.print_around_run(options) do
|
45
|
+
if all_selected_groups_and_tests.empty?
|
46
|
+
test_run = create_test_run(suite)
|
47
|
+
run_one(suite, test_run)
|
48
|
+
|
49
|
+
results = test_runs_repo.results_for_test_run(test_run.id)
|
50
|
+
results = sort_results(results)
|
51
|
+
else
|
52
|
+
all_selected_groups_and_tests.each do |runnable|
|
53
|
+
test_run = create_test_run(runnable)
|
54
|
+
run_one(runnable, test_run)
|
55
|
+
|
56
|
+
results += sort_results(test_runs_repo.results_for_test_run(test_run.id))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# User may enter duplicate runnables, in which case this prevents a bug of extraneous results
|
62
|
+
results.uniq!(&:id)
|
63
|
+
|
64
|
+
outputter.print_results(options, results)
|
65
|
+
outputter.print_end_message(options)
|
66
|
+
|
67
|
+
# TODO: respect customized rollups
|
68
|
+
exit(0) if Inferno::ResultSummarizer.new(results).summarize == 'pass'
|
69
|
+
|
70
|
+
# exit(1) is for Thor failures
|
71
|
+
# exit(2) is for shell builtin failures
|
72
|
+
exit(3)
|
73
|
+
rescue Sequel::ValidationFailed => e
|
74
|
+
print_error_and_exit(e, 4)
|
75
|
+
rescue Sequel::ForeignKeyConstraintViolation => e
|
76
|
+
print_error_and_exit(e, 5)
|
77
|
+
rescue Inferno::Exceptions::RequiredInputsNotFound => e
|
78
|
+
print_error_and_exit(e, 6)
|
79
|
+
rescue Inferno::Exceptions::NotUserRunnableException => e
|
80
|
+
print_error_and_exit(e, 7)
|
81
|
+
rescue StandardError => e
|
82
|
+
print_error_and_exit(e, 8)
|
83
|
+
end
|
84
|
+
|
85
|
+
def print_help_and_exit
|
86
|
+
puts `NO_DB=true bundle exec inferno help execute`
|
87
|
+
exit(0)
|
88
|
+
end
|
89
|
+
|
90
|
+
def outputter
|
91
|
+
# TODO: swap outputter based on options
|
92
|
+
@outputter ||= Inferno::CLI::Execute::ConsoleOutputter.new
|
93
|
+
end
|
94
|
+
|
95
|
+
def all_selected_groups_and_tests
|
96
|
+
@all_selected_groups_and_tests ||= runnables_by_short_id + groups + tests
|
97
|
+
end
|
98
|
+
|
99
|
+
def run_one(runnable, test_run)
|
100
|
+
verify_runnable(
|
101
|
+
runnable,
|
102
|
+
thor_hash_to_inputs_array(options[:inputs]),
|
103
|
+
test_session.suite_options
|
104
|
+
)
|
105
|
+
|
106
|
+
persist_inputs(session_data_repo, create_params(test_session, suite), test_run)
|
107
|
+
|
108
|
+
dispatch_job(test_run)
|
109
|
+
end
|
110
|
+
|
111
|
+
def suite
|
112
|
+
@suite ||= Inferno::Repositories::TestSuites.new.find(options[:suite])
|
113
|
+
|
114
|
+
raise StandardError, "Test suite #{options[:suite]} not found" if @suite.nil?
|
115
|
+
|
116
|
+
@suite
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_runs_repo
|
120
|
+
@test_runs_repo ||= Inferno::Repositories::TestRuns.new
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_test_run(runnable)
|
124
|
+
test_runs_repo.create(
|
125
|
+
create_params(test_session, runnable).merge({ status: 'queued' })
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def results_repo
|
130
|
+
@results_repo ||= Inferno::Repositories::Results.new
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_groups_repo
|
134
|
+
@test_groups_repo ||= Inferno::Repositories::TestGroups.new
|
135
|
+
end
|
136
|
+
|
137
|
+
def tests_repo
|
138
|
+
@tests_repo ||= Inferno::Repositories::Tests.new
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_sessions_repo
|
142
|
+
@test_sessions_repo ||= Inferno::Repositories::TestSessions.new
|
143
|
+
end
|
144
|
+
|
145
|
+
def session_data_repo
|
146
|
+
@session_data_repo ||= Inferno::Repositories::SessionData.new
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_session
|
150
|
+
@test_session ||= test_sessions_repo.create({
|
151
|
+
test_suite_id: suite.id,
|
152
|
+
suite_options: thor_hash_to_suite_options_array(
|
153
|
+
options[:suite_options]
|
154
|
+
)
|
155
|
+
})
|
156
|
+
end
|
157
|
+
|
158
|
+
def create_params(test_session, runnable)
|
159
|
+
{
|
160
|
+
test_session_id: test_session.id,
|
161
|
+
runnable_id_key(runnable) => runnable.id,
|
162
|
+
inputs: thor_hash_to_inputs_array(options[:inputs])
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
def dispatch_job(test_run)
|
167
|
+
# TODO: move suppression to outputter? better suppression?
|
168
|
+
if options[:verbose]
|
169
|
+
Jobs.perform(Jobs::ExecuteTestRun, test_run.id, force_synchronous: true)
|
170
|
+
else
|
171
|
+
Inferno::CLI::Execute.suppress_output do
|
172
|
+
Jobs.perform(Jobs::ExecuteTestRun, test_run.id, force_synchronous: true)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def runnables_by_short_id
|
178
|
+
return [] if options[:short_ids].blank?
|
179
|
+
|
180
|
+
@runnables_by_short_id ||= options[:short_ids]&.map { |short_id| find_by_short_id(:group_or_test, short_id) }
|
181
|
+
end
|
182
|
+
|
183
|
+
def groups
|
184
|
+
return [] if options[:groups].blank?
|
185
|
+
|
186
|
+
@groups ||= options[:groups]&.map { |short_id| find_by_short_id(:group, short_id) }
|
187
|
+
end
|
188
|
+
|
189
|
+
def tests
|
190
|
+
return [] if options[:tests].blank?
|
191
|
+
|
192
|
+
@tests ||= options[:tests]&.map { |short_id| find_by_short_id(:test, short_id) }
|
193
|
+
end
|
194
|
+
|
195
|
+
def find_by_short_id(repo_symbol, short_id)
|
196
|
+
repo_symbol_to_array(repo_symbol).each do |repo|
|
197
|
+
repo.all.each do |entity|
|
198
|
+
return entity if short_id == entity.short_id && suite.id == entity.suite.id
|
199
|
+
end
|
200
|
+
end
|
201
|
+
raise StandardError, "#{repo_symbol.to_s.humanize} #{short_id} not found."
|
202
|
+
end
|
203
|
+
|
204
|
+
def repo_symbol_to_array(repo_symbol)
|
205
|
+
case repo_symbol
|
206
|
+
when :group
|
207
|
+
[test_groups_repo]
|
208
|
+
when :test
|
209
|
+
[tests_repo]
|
210
|
+
when :group_or_test
|
211
|
+
[test_groups_repo, tests_repo]
|
212
|
+
else
|
213
|
+
raise StandardError, "Unrecognized repo_symbol #{repo_symbol} for `find_by_short_id`"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def thor_hash_to_suite_options_array(hash = {})
|
218
|
+
hash.to_a.map { |pair| Inferno::DSL::SuiteOption.new({ id: pair[0], value: pair[1] }) }
|
219
|
+
end
|
220
|
+
|
221
|
+
def thor_hash_to_inputs_array(hash = {})
|
222
|
+
hash.to_a.map { |pair| { name: pair[0], value: pair[1] } }
|
223
|
+
end
|
224
|
+
|
225
|
+
def print_error_and_exit(err, code)
|
226
|
+
outputter.print_error(options || {}, err)
|
227
|
+
rescue StandardError => e
|
228
|
+
puts "Caught exception #{e} while printing exception #{err}. Exiting."
|
229
|
+
ensure
|
230
|
+
exit(code)
|
231
|
+
end
|
232
|
+
|
233
|
+
def runnable_type(runnable)
|
234
|
+
if runnable < Inferno::TestSuite
|
235
|
+
:suite
|
236
|
+
elsif runnable < Inferno::TestGroup
|
237
|
+
:group
|
238
|
+
elsif runnable < Inferno::Test
|
239
|
+
:test
|
240
|
+
else
|
241
|
+
raise StandardError, "Unidentified runnable #{runnable}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def runnable_id_key(runnable)
|
246
|
+
case runnable_type(runnable)
|
247
|
+
when :suite
|
248
|
+
:test_suite_id
|
249
|
+
when :group
|
250
|
+
:test_group_id
|
251
|
+
else
|
252
|
+
:test_id
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def sort_results(results)
|
257
|
+
results.sort do |result, other|
|
258
|
+
if result.runnable < Inferno::TestSuite
|
259
|
+
-1
|
260
|
+
elsif other.runnable < Inferno::TestSuite
|
261
|
+
1
|
262
|
+
else
|
263
|
+
result.runnable.short_id <=> other.runnable.short_id
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -5,6 +5,7 @@ require_relative 'suite'
|
|
5
5
|
require_relative 'suites'
|
6
6
|
require_relative 'new'
|
7
7
|
require_relative '../../version'
|
8
|
+
require_relative 'execute'
|
8
9
|
|
9
10
|
module Inferno
|
10
11
|
module CLI
|
@@ -65,18 +66,86 @@ module Inferno
|
|
65
66
|
puts "Inferno Core v#{Inferno::VERSION}"
|
66
67
|
end
|
67
68
|
|
69
|
+
EXECUTE_HELP = <<~END_OF_HELP.freeze
|
70
|
+
Run Inferno tests in the command line. Exits with 0 only if test entity passes.
|
71
|
+
Must be run with test kit as working directory.
|
72
|
+
|
73
|
+
You must have background services running: `bundle exec inferno services start`
|
74
|
+
|
75
|
+
You can view suite ids with: `bundle exec inferno suites`
|
76
|
+
|
77
|
+
Examples:
|
78
|
+
|
79
|
+
(These examples only work from within the inferno_core directory).
|
80
|
+
|
81
|
+
`bundle exec inferno execute --suite dev_validator \
|
82
|
+
--inputs "url:https://hapi.fhir.org/baseR4" \
|
83
|
+
patient_id:1234321`
|
84
|
+
=> Outputs test results
|
85
|
+
|
86
|
+
`bundle exec inferno execute --suite dev_validator \
|
87
|
+
--inputs "url:https://hapi.fhir.org/baseR4" \
|
88
|
+
patient_id:1234321 \
|
89
|
+
--tests 1.01 1.02`
|
90
|
+
=> Run specific tests from suite
|
91
|
+
END_OF_HELP
|
92
|
+
desc 'execute', 'Run Inferno tests in command line'
|
93
|
+
long_desc EXECUTE_HELP, wrap: false
|
94
|
+
option :suite,
|
95
|
+
aliases: ['-s'],
|
96
|
+
type: :string,
|
97
|
+
desc: 'Test suite id to run or to select groups and tests from',
|
98
|
+
banner: 'id'
|
99
|
+
option :suite_options,
|
100
|
+
aliases: ['-u'], # NOTE: -o will be for outputter
|
101
|
+
type: :hash,
|
102
|
+
desc: 'Suite options'
|
103
|
+
option :groups,
|
104
|
+
aliases: ['-g'],
|
105
|
+
type: :array,
|
106
|
+
desc: 'Series of test group short ids (AKA sequence number) to run, requires suite'
|
107
|
+
option :tests,
|
108
|
+
aliases: ['-t'],
|
109
|
+
type: :array,
|
110
|
+
desc: 'Series of test short ids (AKA sequence number) to run, requires suite'
|
111
|
+
option :short_ids,
|
112
|
+
aliases: ['-r'],
|
113
|
+
type: :array,
|
114
|
+
desc: 'Series of test or group short ids (AKA sequence number) to run, requires suite'
|
115
|
+
option :inputs,
|
116
|
+
aliases: ['-i'],
|
117
|
+
type: :hash,
|
118
|
+
desc: 'Inputs (i.e: --inputs=foo:bar goo:baz)'
|
119
|
+
option :verbose,
|
120
|
+
aliases: ['-v'],
|
121
|
+
type: :boolean,
|
122
|
+
default: false,
|
123
|
+
desc: 'Output additional information for debugging'
|
124
|
+
option :help,
|
125
|
+
aliases: ['-h'],
|
126
|
+
type: :boolean,
|
127
|
+
default: false,
|
128
|
+
desc: 'Display this message'
|
129
|
+
def execute
|
130
|
+
Execute.boot_full_inferno
|
131
|
+
Execute.new.run(options)
|
132
|
+
end
|
133
|
+
|
134
|
+
# https://github.com/rails/thor/issues/244 - Make Thor exit(1) on Errors/Exceptions
|
135
|
+
def self.exit_on_failure?
|
136
|
+
true
|
137
|
+
end
|
138
|
+
|
68
139
|
private
|
69
140
|
|
70
141
|
# https://github.com/rubocop/rubocop/issues/12571 - still affects Ruby 3.1 upto Rubocop 1.63
|
71
|
-
|
72
|
-
def without_bundler(&block)
|
142
|
+
def without_bundler(&)
|
73
143
|
if defined?(Bundler) && ENV['BUNDLE_GEMFILE']
|
74
|
-
Bundler.with_unbundled_env(&
|
144
|
+
Bundler.with_unbundled_env(&)
|
75
145
|
else
|
76
146
|
yield
|
77
147
|
end
|
78
148
|
end
|
79
|
-
# rubocop:enable Naming/BlockForwarding
|
80
149
|
end
|
81
150
|
end
|
82
151
|
end
|
@@ -98,5 +98,20 @@ http {
|
|
98
98
|
|
99
99
|
proxy_pass http://hl7_validator_service:3500/;
|
100
100
|
}
|
101
|
+
|
102
|
+
location /fhirpath/ {
|
103
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
104
|
+
proxy_set_header Host $http_host;
|
105
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
106
|
+
proxy_set_header X-Forwarded-Port $server_port;
|
107
|
+
proxy_redirect off;
|
108
|
+
proxy_set_header Connection '';
|
109
|
+
proxy_http_version 1.1;
|
110
|
+
chunked_transfer_encoding off;
|
111
|
+
proxy_buffering off;
|
112
|
+
proxy_cache off;
|
113
|
+
|
114
|
+
proxy_pass http://fhirpath:6789/;
|
115
|
+
}
|
101
116
|
}
|
102
117
|
}
|
@@ -23,6 +23,10 @@ services:
|
|
23
23
|
environment:
|
24
24
|
EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi
|
25
25
|
VALIDATOR_BASE_PATH: /validator
|
26
|
+
fhirpath:
|
27
|
+
image: infernocommunity/fhirpath-service
|
28
|
+
ports:
|
29
|
+
- "6789:6789"
|
26
30
|
nginx:
|
27
31
|
image: nginx
|
28
32
|
volumes:
|
@@ -32,6 +36,7 @@ services:
|
|
32
36
|
command: [nginx, '-g', 'daemon off;']
|
33
37
|
depends_on:
|
34
38
|
- fhir_validator_app
|
39
|
+
- fhirpath
|
35
40
|
redis:
|
36
41
|
image: redis
|
37
42
|
ports:
|
data/lib/inferno/apps/cli.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
require_relative '../../../../utils/verify_runnable'
|
2
|
+
require_relative '../../../../utils/persist_inputs'
|
3
|
+
|
1
4
|
module Inferno
|
2
5
|
module Web
|
3
6
|
module Controllers
|
4
7
|
module TestRuns
|
5
8
|
class Create < Controller
|
9
|
+
include ::Inferno::Utils::VerifyRunnable
|
10
|
+
include ::Inferno::Utils::PersistInputs
|
11
|
+
|
6
12
|
include Import[
|
7
13
|
test_sessions_repo: 'inferno.repositories.test_sessions',
|
8
14
|
session_data_repo: 'inferno.repositories.session_data',
|
@@ -11,37 +17,6 @@ module Inferno
|
|
11
17
|
|
12
18
|
PARAMS = [:test_session_id, :test_suite_id, :test_group_id, :test_id].freeze
|
13
19
|
|
14
|
-
def verify_runnable(runnable, inputs, selected_suite_options)
|
15
|
-
missing_inputs = runnable&.missing_inputs(inputs, selected_suite_options)
|
16
|
-
user_runnable = runnable&.user_runnable?
|
17
|
-
raise Inferno::Exceptions::RequiredInputsNotFound, missing_inputs if missing_inputs&.any?
|
18
|
-
raise Inferno::Exceptions::NotUserRunnableException unless user_runnable
|
19
|
-
end
|
20
|
-
|
21
|
-
def persist_inputs(params, test_run)
|
22
|
-
available_inputs = test_run.runnable.available_inputs
|
23
|
-
params[:inputs]&.each do |input_params|
|
24
|
-
input =
|
25
|
-
available_inputs
|
26
|
-
.find { |_, runnable_input| runnable_input.name == input_params[:name] }
|
27
|
-
&.last
|
28
|
-
|
29
|
-
if input.nil?
|
30
|
-
Inferno::Application['logger'].warn(
|
31
|
-
"Unknown input `#{input_params[:name]}` for #{test_run.runnable.id}: #{test_run.runnable.title}"
|
32
|
-
)
|
33
|
-
next
|
34
|
-
end
|
35
|
-
|
36
|
-
session_data_repo.save(
|
37
|
-
test_session_id: test_run.test_session_id,
|
38
|
-
name: input.name,
|
39
|
-
value: input_params[:value],
|
40
|
-
type: input.type
|
41
|
-
)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
20
|
def handle(req, res)
|
46
21
|
test_session = test_sessions_repo.find(req.params[:test_session_id])
|
47
22
|
|
@@ -60,7 +35,7 @@ module Inferno
|
|
60
35
|
|
61
36
|
res.body = serialize(test_run, suite_options: test_session.suite_options)
|
62
37
|
|
63
|
-
persist_inputs(req.params, test_run)
|
38
|
+
persist_inputs(session_data_repo, req.params, test_run)
|
64
39
|
|
65
40
|
Jobs.perform(Jobs::ExecuteTestRun, test_run.id)
|
66
41
|
rescue Sequel::ValidationFailed, Sequel::ForeignKeyConstraintViolation,
|