inferno_core 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno.rb +4 -0
  3. data/lib/inferno/apps/web/controllers/test_runs/create.rb +17 -10
  4. data/lib/inferno/apps/web/controllers/test_runs/show.rb +10 -0
  5. data/lib/inferno/apps/web/controllers/test_sessions/create.rb +1 -0
  6. data/lib/inferno/apps/web/controllers/test_sessions/last_test_run.rb +22 -0
  7. data/lib/inferno/apps/web/controllers/test_sessions/results/index.rb +6 -1
  8. data/lib/inferno/apps/web/controllers/test_sessions/session_data/index.rb +21 -0
  9. data/lib/inferno/apps/web/index.html.erb +44 -0
  10. data/lib/inferno/apps/web/router.rb +15 -0
  11. data/lib/inferno/apps/web/serializers/request.rb +1 -0
  12. data/lib/inferno/apps/web/serializers/result.rb +8 -0
  13. data/lib/inferno/apps/web/serializers/session_data.rb +10 -0
  14. data/lib/inferno/apps/web/serializers/test.rb +1 -3
  15. data/lib/inferno/apps/web/serializers/test_group.rb +2 -3
  16. data/lib/inferno/apps/web/serializers/test_run.rb +1 -0
  17. data/lib/inferno/apps/web/serializers/test_session.rb +1 -1
  18. data/lib/inferno/apps/web/serializers/test_suite.rb +1 -0
  19. data/lib/inferno/config/application.rb +4 -2
  20. data/lib/inferno/config/boot.rb +2 -0
  21. data/lib/inferno/config/boot/db.rb +10 -1
  22. data/lib/inferno/config/boot/sidekiq.rb +11 -0
  23. data/lib/inferno/db/migrations/001_create_initial_structure.rb +0 -21
  24. data/lib/inferno/db/migrations/002_add_wait_support.rb +7 -0
  25. data/lib/inferno/db/migrations/003_update_session_data.rb +18 -0
  26. data/lib/inferno/db/migrations/004_add_request_results_table.rb +9 -0
  27. data/lib/inferno/db/migrations/005_add_updated_at_index_to_results.rb +5 -0
  28. data/lib/inferno/db/schema.rb +154 -0
  29. data/lib/inferno/dsl.rb +1 -3
  30. data/lib/inferno/dsl/fhir_client_builder.rb +16 -0
  31. data/lib/inferno/dsl/request_storage.rb +12 -0
  32. data/lib/inferno/dsl/results.rb +49 -0
  33. data/lib/inferno/dsl/resume_test_route.rb +89 -0
  34. data/lib/inferno/dsl/runnable.rb +96 -7
  35. data/lib/inferno/entities.rb +1 -1
  36. data/lib/inferno/entities/header.rb +7 -7
  37. data/lib/inferno/entities/message.rb +8 -6
  38. data/lib/inferno/entities/request.rb +40 -14
  39. data/lib/inferno/entities/result.rb +34 -18
  40. data/lib/inferno/entities/session_data.rb +33 -0
  41. data/lib/inferno/entities/test.rb +20 -7
  42. data/lib/inferno/entities/test_run.rb +13 -6
  43. data/lib/inferno/entities/test_session.rb +8 -8
  44. data/lib/inferno/exceptions.rb +12 -0
  45. data/lib/inferno/jobs.rb +16 -0
  46. data/lib/inferno/jobs/execute_test_run.rb +14 -0
  47. data/lib/inferno/jobs/resume_test_run.rb +14 -0
  48. data/lib/inferno/public/bundle.js +1 -1
  49. data/lib/inferno/repositories/repository.rb +13 -0
  50. data/lib/inferno/repositories/requests.rb +5 -4
  51. data/lib/inferno/repositories/results.rb +151 -3
  52. data/lib/inferno/repositories/session_data.rb +47 -0
  53. data/lib/inferno/repositories/test_runs.rb +66 -0
  54. data/lib/inferno/test_runner.rb +121 -29
  55. data/lib/inferno/utils/middleware/request_logger.rb +16 -3
  56. data/lib/inferno/version.rb +1 -1
  57. data/spec/factories/header.rb +19 -0
  58. data/spec/factories/message.rb +17 -0
  59. data/spec/factories/request.rb +35 -0
  60. data/spec/factories/result.rb +45 -0
  61. data/spec/factories/test_run.rb +24 -0
  62. data/spec/factories/test_session.rb +11 -0
  63. data/spec/fixtures/basic_test_group.rb +9 -0
  64. data/spec/fixtures/basic_test_suite.rb +8 -0
  65. metadata +139 -89
  66. data/lib/inferno/dsl/fhir_manipulation.rb +0 -25
  67. data/lib/inferno/entities/test_input.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e46c84421bcf3279ee20f3dcd6a9e390473233a95db1ad889c16cd823f2d879
4
- data.tar.gz: '08fd84f83d463edf9e5822c38084a379da6089bb92e8552e7bd79caa285ec3e7'
3
+ metadata.gz: 9b643b7c720a9c79df5f329a9947110971076db80fe29f0b57928230cf348d1b
4
+ data.tar.gz: e03d93994e7ad33e6e131969af5e31449390d36670d256a7d4bf43c1a9f80e4d
5
5
  SHA512:
6
- metadata.gz: 3f8f32c53c9e1946ea9bd986df6c423d4877b39865887a2abe316ba973dba23979b2638684b290041507a4ce5f40f3e6d3c013b89d3207762461817124ed7f9c
7
- data.tar.gz: f2f2c2886be27e7d76e84cb1fe8cd67402890488aa46aa1db41de8b5a20fdffc67f4e566aa43199975a43166ce244e0de3c847f3d926ca303c97e15960f6d481
6
+ metadata.gz: 4767e5dfd7f469a6eb70892fb9e5402f2a46708655810b91be0b3d1d9d1dfa839c3502678156f763f5e9a7999948a31013fb68e3a1d1605306d5297639f3b3c3
7
+ data.tar.gz: 3adbce3ebb0786095826a114e4c6bc6a3ced2f9e560e2eaa6f6e6f6784bbf44c10ef25734f67bb097ee384b4cd6ab3296dc156e2c14cd5085bc64cb4fb27f575
data/lib/inferno.rb CHANGED
@@ -6,10 +6,14 @@ require_relative 'inferno/config/application'
6
6
  require_relative 'inferno/dsl'
7
7
  require_relative 'inferno/entities'
8
8
  require_relative 'inferno/exceptions'
9
+ require_relative 'inferno/jobs'
9
10
  require_relative 'inferno/repositories'
10
11
  require_relative 'inferno/spec_support'
11
12
  require_relative 'inferno/test_runner'
12
13
  require_relative 'inferno/version'
13
14
 
14
15
  module Inferno
16
+ def self.routes
17
+ @routes ||= []
18
+ end
15
19
  end
@@ -3,28 +3,35 @@ module Inferno
3
3
  module Controllers
4
4
  module TestRuns
5
5
  class Create < Controller
6
- include Import[test_sessions_repo: 'repositories.test_sessions']
6
+ include Import[
7
+ test_sessions_repo: 'repositories.test_sessions',
8
+ session_data_repo: 'repositories.session_data'
9
+ ]
7
10
 
8
11
  PARAMS = [:test_session_id, :test_suite_id, :test_group_id, :test_id].freeze
9
12
 
10
13
  def call(params)
11
- test_run = repo.create(create_params(params))
12
- inputs = (params[:inputs] || {}).each_with_object({}) do |input, new_inputs|
13
- new_inputs[input[:name].to_sym] = input[:value]
14
- end
14
+ test_session = test_sessions_repo.find(params[:test_session_id])
15
15
 
16
- test_session = test_sessions_repo.find(test_run.test_session_id)
17
16
  # if testsession.nil?
18
17
 
19
- TestRunner
20
- .new(test_session: test_session, test_run: test_run)
21
- .run(test_run.runnable, inputs)
22
-
18
+ test_run = repo.create(create_params(params).merge(status: 'queued'))
23
19
  self.body = serialize(test_run)
20
+
21
+ params[:inputs]&.each do |input|
22
+ session_data_repo.save(
23
+ test_session_id: test_session.id,
24
+ name: input[:name],
25
+ value: input[:value]
26
+ )
27
+ end
28
+
29
+ Jobs.perform(Jobs::ExecuteTestRun, test_run.id)
24
30
  rescue Sequel::ValidationFailed, Sequel::ForeignKeyConstraintViolation => e
25
31
  self.body = { errors: e.message }.to_json
26
32
  self.status = 422
27
33
  rescue StandardError => e
34
+ Application['logger'].error(e.full_message)
28
35
  self.body = { errors: e.message }.to_json
29
36
  self.status = 500
30
37
  end
@@ -7,6 +7,16 @@ module Inferno
7
7
  test_run = repo.find(params[:id])
8
8
  halt 404 if test_run.nil?
9
9
 
10
+ if params[:include_results] == 'true'
11
+ results_repo = Inferno::Repositories::Results.new
12
+ test_run.results =
13
+ if params[:after].present?
14
+ results_repo.test_run_results_after(test_run_id: test_run.id, after: Time.parse(params[:after]))
15
+ else
16
+ repo.results_for_test_run(test_run.id)
17
+ end
18
+ end
19
+
10
20
  self.body = serialize(test_run)
11
21
  end
12
22
  end
@@ -12,6 +12,7 @@ module Inferno
12
12
  self.body = { errors: e.message }.to_json
13
13
  self.status = 422
14
14
  rescue StandardError => e
15
+ Application['logger'].error(e.full_message)
15
16
  self.body = { errors: e.message }.to_json
16
17
  self.status = 500
17
18
  end
@@ -0,0 +1,22 @@
1
+ module Inferno
2
+ module Web
3
+ module Controllers
4
+ module TestSessions
5
+ class LastTestRun < Controller
6
+ include Import[test_runs_repo: 'repositories.test_runs']
7
+
8
+ def call(params)
9
+ test_run = test_runs_repo.last_test_run(params[:test_session_id])
10
+
11
+ self.body =
12
+ if test_run.nil?
13
+ nil
14
+ else
15
+ Inferno::Web::Serializers::TestRun.render(test_run)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -7,7 +7,12 @@ module Inferno
7
7
  include Import[test_sessions_repo: 'repositories.test_sessions']
8
8
 
9
9
  def call(params)
10
- self.body = serialize(test_sessions_repo.results_for_test_session(params[:test_session_id]))
10
+ self.body =
11
+ if params[:all] == 'true'
12
+ serialize(test_sessions_repo.results_for_test_session(params[:test_session_id]))
13
+ else
14
+ serialize(repo.current_results_for_test_session(params[:test_session_id]))
15
+ end
11
16
  end
12
17
  end
13
18
  end
@@ -0,0 +1,21 @@
1
+ module Inferno
2
+ module Web
3
+ module Controllers
4
+ module TestSessions
5
+ module SessionData
6
+ class Index < Controller
7
+ include Import[session_data_repo: 'repositories.session_data']
8
+
9
+ def self.resource_class
10
+ 'SessionData'
11
+ end
12
+
13
+ def call(params)
14
+ self.body = serialize(session_data_repo.get_all_from_session(params[:test_session_id]))
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="/public/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta
9
+ name="description"
10
+ content="FHIR Testing"
11
+ />
12
+ <link rel="apple-touch-icon" href="/public/logo192.png" />
13
+ <!--
14
+ manifest.json provides metadata used when your web app is installed on a
15
+ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16
+ -->
17
+ <link rel="manifest" href="/public/manifest.json" />
18
+ <!--
19
+ Notice the use of %PUBLIC_URL% in the tags above.
20
+ It will be replaced with the URL of the `public` folder during the build.
21
+ Only files inside the `public` folder can be referenced from the HTML.
22
+
23
+ Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24
+ work correctly both with client-side routing and a non-root public URL.
25
+ Learn how to configure a non-root public URL by running `npm run build`.
26
+ -->
27
+ <title>Inferno</title>
28
+ </head>
29
+ <body>
30
+ <noscript>You need to enable JavaScript to run this app.</noscript>
31
+ <div id="root"></div>
32
+ <!--
33
+ This HTML file is a template.
34
+ If you open it directly in the browser, you will see an empty page.
35
+
36
+ You can add webfonts, meta tags, or analytics to this file.
37
+ The build step will place the bundled scripts into the <body> tag.
38
+
39
+ To begin the development, run `npm start` or `yarn start`.
40
+ To create a production bundle, use `npm run build` or `yarn build`.
41
+ -->
42
+ <script src='<%= Inferno::Application['js_host'] %>/public/bundle.js'></script>
43
+ </body>
44
+ </html>
@@ -13,7 +13,11 @@ module Inferno
13
13
 
14
14
  resources 'test_sessions', only: [:create, :show] do
15
15
  resources 'results', only: [:index]
16
+ resources 'session_data', only: [:index]
16
17
  end
18
+ get 'test_sessions/:test_session_id/last_test_run',
19
+ to: Inferno::Web::Controllers::TestSessions::LastTestRun,
20
+ as: :last_test_run
17
21
 
18
22
  resources 'test_suites', only: [:index, :show]
19
23
 
@@ -22,6 +26,17 @@ module Inferno
22
26
 
23
27
  get '/', to: ->(_env) { [200, {}, [client_page]] }
24
28
  get '/test_sessions/:id', to: ->(_env) { [200, {}, [client_page]] }
29
+
30
+ Inferno.routes.each do |route|
31
+ cleaned_id = route[:suite].id.gsub(/[^a-zA-Z\d\-._~]/, '_')
32
+ path = "/custom/#{cleaned_id}#{route[:path]}"
33
+ Application['logger'].info("Registering custom route: #{path}")
34
+ if route[:method] == :all
35
+ mount route[:handler], at: path
36
+ else
37
+ send(route[:method], path, to: route[:handler])
38
+ end
39
+ end
25
40
  end
26
41
  end
27
42
  end
@@ -9,6 +9,7 @@ module Inferno
9
9
  field :url
10
10
  field :direction
11
11
  field :status
12
+ field :result_id
12
13
  end
13
14
 
14
15
  view :full do
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Inferno
2
4
  module Web
3
5
  module Serializers
@@ -12,6 +14,12 @@ module Inferno
12
14
  field :test_session_id
13
15
  field :result
14
16
  field :result_message, if: :field_present?
17
+ field :created_at
18
+ field :updated_at
19
+
20
+ field :outputs do |result, _options|
21
+ result.output_json.present? ? JSON.parse(result.output_json) : []
22
+ end
15
23
 
16
24
  association :messages, blueprint: Message, if: :field_present?
17
25
  association :requests, blueprint: Request, view: :summary, if: :field_present?
@@ -0,0 +1,10 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class SessionData < Serializer
5
+ field :name
6
+ field :value
7
+ end
8
+ end
9
+ end
10
+ end
@@ -4,9 +4,7 @@ module Inferno
4
4
  class Test < Serializer
5
5
  identifier :id
6
6
  field :title
7
- field :inputs do |test, _options|
8
- test.inputs.map { |input| { name: input } }
9
- end
7
+ field :inputs
10
8
  field :outputs do |test, _options|
11
9
  test.outputs.map { |output| { name: output } }
12
10
  end
@@ -7,13 +7,12 @@ module Inferno
7
7
  # TODO: fill out test group
8
8
  field :title
9
9
  field :description
10
+ field :test_count
10
11
  # field :run_as_group
11
12
 
12
13
  association :groups, name: :test_groups, blueprint: TestGroup
13
14
  association :tests, blueprint: Test
14
- field :inputs do |group, _options|
15
- group.inputs.map { |input| { name: input } }
16
- end
15
+ field :inputs
17
16
  field :outputs do |group, _options|
18
17
  group.outputs.map { |input| { name: input } }
19
18
  end
@@ -6,6 +6,7 @@ module Inferno
6
6
  field :test_session_id
7
7
 
8
8
  field :status
9
+ field :test_count
9
10
 
10
11
  field :test_group_id, if: :field_present?
11
12
  field :test_suite_id, if: :field_present?
@@ -9,7 +9,7 @@ module Inferno
9
9
  field :test_suite_id
10
10
 
11
11
  association :test_suite, blueprint: TestSuite, view: :full
12
- # association :test_run, blueprint: TestRun
12
+ # association :test_runs, blueprint: TestRun
13
13
  # association :results, blueprint: Result
14
14
  end
15
15
  end
@@ -6,6 +6,7 @@ module Inferno
6
6
  identifier :id
7
7
  field :title
8
8
  field :description
9
+ field :test_count
9
10
  end
10
11
 
11
12
  view :full do
@@ -1,3 +1,4 @@
1
+ require 'dry/system/container'
1
2
  require_relative 'boot'
2
3
 
3
4
  module Inferno
@@ -6,6 +7,9 @@ module Inferno
6
7
 
7
8
  use :env, inferrer: -> { ENV.fetch('APP_ENV', :development).to_sym }
8
9
 
10
+ Application.register('js_host', ENV.fetch('JS_HOST', ''))
11
+ Application.register('async_jobs', ENV['ASYNC_JOBS'] != 'false')
12
+
9
13
  configure do |config|
10
14
  config.root = File.expand_path('../../..', __dir__)
11
15
  config.default_namespace = 'inferno'
@@ -15,8 +19,6 @@ module Inferno
15
19
  config.auto_register = 'lib'
16
20
  end
17
21
 
18
- Application.register('js_host', ENV.fetch('JS_HOST', ''))
19
-
20
22
  load_paths!('lib')
21
23
  end
22
24
  end
@@ -1,3 +1,5 @@
1
+ require 'dotenv'
2
+
1
3
  ENV['APP_ENV'] ||= 'development'
2
4
 
3
5
  root_path = Dir.pwd
@@ -1,3 +1,5 @@
1
+ require 'sequel'
2
+
1
3
  Inferno::Application.boot(:db) do
2
4
  init do
3
5
  use :logging
@@ -17,7 +19,14 @@ Inferno::Application.boot(:db) do
17
19
 
18
20
  start do
19
21
  Sequel.extension :migration
22
+ db = Inferno::Application['db.connection']
20
23
  migration_path = File.join(Inferno::Application.root, 'lib', 'inferno', 'db', 'migrations')
21
- Sequel::Migrator.run(Inferno::Application['db.connection'], migration_path)
24
+ Sequel::Migrator.run(db, migration_path)
25
+
26
+ if ENV['APP_ENV'] == 'development'
27
+ schema_path = File.join(Inferno::Application.root, 'lib', 'inferno', 'db', 'schema.rb')
28
+ db.extension :schema_dumper
29
+ File.open(schema_path, 'w') { |f| f.print(db.dump_schema_migration) }
30
+ end
22
31
  end
23
32
  end
@@ -0,0 +1,11 @@
1
+ require 'sidekiq'
2
+
3
+ Inferno::Application.boot(:sidekiq) do
4
+ init do
5
+ if Inferno::Application['async_jobs']
6
+ Sidekiq.configure_server do |config|
7
+ config.redis = { url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379/0') }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,26 +1,5 @@
1
1
  Sequel.migration do
2
2
  change do
3
- #
4
- # NOT NEEDED BECUASE THEY ARE DEFINED WITHIN TEST SUITE.
5
- # MUST BE REFERENCED USING SOME KIND OF GLOBALLY UNIQUE KEY
6
- # THAT IS REPRESENTED AS A STRING
7
- #
8
-
9
- # create_table :test_suites do
10
- # end
11
-
12
- # create_table :test_groups do
13
- # end
14
-
15
- # create_table :tests do
16
- # end
17
-
18
- # create_table :test_inputs do
19
- # end
20
-
21
- # create_table :test_outputs do
22
- # end
23
-
24
3
  # A way for the test to signal that it requires some kind of action by the
25
4
  # app that is invoking the test (e.g. SMART Launch, perhaps mid-test manual verification)
26
5
  # create_table :test_prompts do
@@ -0,0 +1,7 @@
1
+ Sequel.migration do
2
+ change do
3
+ add_column :test_runs, :identifier, String, text: true
4
+ add_column :test_runs, :wait_timeout, DateTime
5
+ add_index :test_runs, [:status, :identifier, :wait_timeout, :updated_at], concurrently: true
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ Sequel.migration do
2
+ change do
3
+ drop_table :test_run_inputs
4
+ drop_table :result_inputs
5
+
6
+ set_column_type :session_data, :value, String, text: true
7
+ drop_index :session_data, [:test_session_id, :name], concurrently: true
8
+ add_index :session_data, [:test_session_id, :name], unique: true, concurrently: true
9
+ drop_index :session_data, :id, concurrently: true
10
+ add_index :session_data, :id, unique: true, concurrently: true
11
+
12
+ add_column :results, :input_json, String, text: true
13
+ add_column :results, :output_json, String, text: true
14
+ add_index :results, [:test_session_id, :test_id], concurrently: true
15
+ add_index :results, [:test_session_id, :test_group_id], concurrently: true
16
+ add_index :results, [:test_session_id, :test_suite_id], concurrently: true
17
+ end
18
+ end