-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FI-2431 inferno new IG loading (#454)
* implement load_igs * use https://packages.fhir.org registry * factorize into Inferno::Utils::IgDownloader * rspec, rubocop, and clean * update CLI "--help" docs * replace "test suite app" with test kit" --------- Co-authored-by: Stephen MacVicar <Jammjammjamm@users.noreply.github.com>
- Loading branch information
1 parent
21b7aef
commit 123ab58
Showing
4 changed files
with
278 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
module Inferno | ||
module Utils | ||
module IgDownloader | ||
FHIR_PACKAGE_NAME_REG_EX = /^[a-z][a-zA-Z0-9-]*\.([a-z][a-zA-Z0-9-]*\.?)*/ | ||
HTTP_URI_REG_EX = %r{^https?://[^/?#]+[^?#]*} | ||
FILE_URI_REG_EX = %r{^file://(.+)} | ||
HTTP_URI_END_REG_EX = %r{[^/]*\.x?html?$} | ||
|
||
def ig_path | ||
File.join('lib', library_name, 'igs') | ||
end | ||
|
||
def ig_file(suffix = nil) | ||
File.join(ig_path, suffix ? "package_#{suffix}.tgz" : 'package.tgz') | ||
end | ||
|
||
def load_ig(ig_input, idx = nil, thor_config = { verbose: true }) | ||
case ig_input | ||
when FHIR_PACKAGE_NAME_REG_EX | ||
uri = ig_registry_url(ig_input) | ||
when HTTP_URI_REG_EX | ||
uri = ig_http_url(ig_input) | ||
when FILE_URI_REG_EX | ||
uri = ig_input[7..] | ||
else | ||
raise StandardError, <<~FAILED_TO_LOAD | ||
Could not find implementation guide: #{ig_input} | ||
Put its package.tgz file directly in #{ig_path} | ||
FAILED_TO_LOAD | ||
end | ||
|
||
# use Thor's get to support CLI options config | ||
get(uri, ig_file(idx), thor_config) | ||
uri | ||
end | ||
|
||
def ig_registry_url(ig_npm_style) | ||
unless ig_npm_style.include? '@' | ||
raise StandardError, <<~NO_VERSION | ||
No IG version specified for #{ig_npm_style}; you must specify one with '@'. I.e: hl7.fhir.us.core@6.1.0 | ||
NO_VERSION | ||
end | ||
|
||
package_name, version = ig_npm_style.split('@') | ||
"https://packages.fhir.org/#{package_name}/-/#{package_name}-#{version}.tgz" | ||
end | ||
|
||
def ig_http_url(ig_page_url) | ||
return ig_page_url if ig_page_url.end_with? 'package.tgz' | ||
|
||
return "#{ig_page_url}package.tgz" if ig_page_url.end_with? '/' | ||
|
||
ig_page_url.gsub(HTTP_URI_END_REG_EX, 'package.tgz') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
require 'open-uri' | ||
require 'thor' | ||
require_relative '../../../lib/inferno/utils/ig_downloader' | ||
|
||
def with_temp_path(name) | ||
path = File.join(Inferno::Application.root, 'tmp', "rspec-#{name.sum}.tmp") | ||
yield(path) | ||
File.delete(path) if File.exist?(path) | ||
end | ||
|
||
RSpec.describe Inferno::Utils::IgDownloader do | ||
let(:ig_downloader_class) do | ||
Class.new do | ||
include Thor::Base | ||
include Thor::Actions | ||
include Inferno::Utils::IgDownloader | ||
attr_accessor :library_name | ||
|
||
source_root Inferno::Application.root | ||
end | ||
end | ||
let(:ig_downloader) do | ||
ig_downloader_instance = ig_downloader_class.new | ||
ig_downloader_instance.library_name = 'udap' | ||
ig_downloader_instance | ||
end | ||
let(:package_fixture) { File.expand_path('../../fixtures/small_package.tgz', __dir__) } | ||
let(:package_binary) { File.read(package_fixture) } | ||
|
||
describe '#ig_path' do | ||
it 'builds correct path to IGs' do | ||
expect(ig_downloader.ig_path).to eq('lib/udap/igs') | ||
end | ||
end | ||
|
||
describe '#ig_file' do | ||
it 'builds correct IG file path' do | ||
expect(ig_downloader.ig_file).to eq('lib/udap/igs/package.tgz') | ||
end | ||
|
||
it 'suffixes IG file path' do | ||
expect(ig_downloader.ig_file(99)).to eq('lib/udap/igs/package_99.tgz') | ||
end | ||
end | ||
|
||
context 'with IG by canonical name' do | ||
let(:canonical) { 'hl7.fhir.us.udap-security@1.0.0' } | ||
let(:resolved_url) do | ||
'https://packages.fhir.org/hl7.fhir.us.udap-security/-/hl7.fhir.us.udap-security-1.0.0.tgz' | ||
end | ||
|
||
describe 'FHIR_PACKAGE_NAME_REG_EX' do | ||
it 'matches given canonical name' do | ||
expect(canonical).to match(Inferno::Utils::IgDownloader::FHIR_PACKAGE_NAME_REG_EX) | ||
end | ||
end | ||
|
||
describe '#ig_registry_url' do | ||
it 'returns correct registry url' do | ||
expect(ig_downloader.ig_registry_url(canonical)).to eq(resolved_url) | ||
end | ||
|
||
it 'raises standard error if missing version' do | ||
expect { ig_downloader.ig_registry_url('hl7.fhir.us.udap-security') }.to raise_error(StandardError) | ||
end | ||
end | ||
|
||
describe '#load_ig' do | ||
it 'successfully downloads package' do | ||
stub_request(:get, 'https://packages.fhir.org/hl7.fhir.us.udap-security/-/hl7.fhir.us.udap-security-1.0.0.tgz') | ||
.to_return(body: package_binary) | ||
|
||
with_temp_path('ig-downloader-canonical') do |temp_path| | ||
allow(ig_downloader).to receive(:ig_file).and_return(temp_path) | ||
ig_downloader.load_ig(canonical, nil, { verbose: false }) | ||
expect(File.read(temp_path)).to eq(package_binary) | ||
end | ||
end | ||
end | ||
end | ||
|
||
%w[ | ||
https://build.fhir.org/ig/HL7/fhir-udap-security-ig/package.tgz | ||
https://build.fhir.org/ig/HL7/fhir-udap-security-ig/ | ||
https://build.fhir.org/ig/HL7/fhir-udap-security-ig/index.html | ||
https://build.fhir.org/ig/HL7/fhir-udap-security-ig/downloads.html | ||
http://build.fhir.org/ig/HL7/fhir-udap-security-ig/ | ||
].each do |url| | ||
context "with IG by http URL #{url}" do | ||
describe 'HTTP_URI_REG_EX' do | ||
it 'matches given url' do | ||
expect(url).to match(Inferno::Utils::IgDownloader::HTTP_URI_REG_EX) | ||
end | ||
end | ||
|
||
describe 'FHIR_PACKAGE_NAME_REG_EX' do | ||
it 'does not match given url' do | ||
expect(url).to_not match(Inferno::Utils::IgDownloader::FHIR_PACKAGE_NAME_REG_EX) | ||
end | ||
end | ||
|
||
describe '#ig_http_url' do | ||
it 'normalizes to a package.tgz url' do | ||
expect(ig_downloader.ig_http_url(url)) | ||
.to match(%r{https?://build.fhir.org/ig/HL7/fhir-udap-security-ig/package.tgz}) | ||
end | ||
end | ||
|
||
describe '#load_ig' do | ||
it 'successfully downloads package' do | ||
stub_request(:get, %r{https?://build.fhir.org}).to_return(body: package_binary) | ||
with_temp_path("ig-downloader-#{url}") do |temp_path| | ||
allow(ig_downloader).to receive(:ig_file).and_return(temp_path) | ||
ig_downloader.load_ig(url, nil, { verbose: false }) | ||
expect(File.read(temp_path)).to eq(package_binary) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
context 'with IG by absolute file path' do | ||
let(:absolute_path) { "file://#{PACKAGE_FIXTURE}" } | ||
|
||
describe 'FILE_URI_REG_EX' do | ||
it 'matches given file uri' do | ||
expect(absolute_path).to match(Inferno::Utils::IgDownloader::FILE_URI_REG_EX) | ||
end | ||
end | ||
|
||
describe 'HTTP_URI_REG_EX' do | ||
it 'does not match given file uri' do | ||
expect(absolute_path).to_not match(Inferno::Utils::IgDownloader::HTTP_URI_REG_EX) | ||
end | ||
end | ||
|
||
describe 'FHIR_PACKAGE_NAME_REG_EX' do | ||
it 'does not match given file uri' do | ||
expect(absolute_path).to_not match(Inferno::Utils::IgDownloader::FHIR_PACKAGE_NAME_REG_EX) | ||
end | ||
end | ||
|
||
describe '#load_ig' do | ||
it 'successfully downloads package' do | ||
with_temp_path('ig-downloader-file') do |temp_path| | ||
allow(ig_downloader).to receive(:ig_file).and_return(temp_path) | ||
ig_downloader.load_ig(absolute_path, nil, { verbose: false }) | ||
expect(File.read(temp_path)).to eq(package_binary) | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe '#load_ig' do | ||
it 'with bad input raises standard error' do | ||
expect { ig_downloader.load_ig('bad') }.to raise_error(StandardError) | ||
end | ||
|
||
it 'with bad url raises http error' do | ||
bad_url = 'http://bad.example.com/package.tgz' | ||
stub_request(:get, bad_url).to_return(status: 404) | ||
expect { ig_downloader.load_ig(bad_url) }.to raise_error(OpenURI::HTTPError) | ||
end | ||
end | ||
end |