spec/functional/fetchers/net_fetcher_spec.rb (269 lines of code) (raw):
require "spec_helper"
module Omnibus
module RSpec
module OhaiHelpers
# Turn off the mandatory Ohai helper.
def stub_ohai(options = {}, &block); end
end
end
describe NetFetcher do
include_examples "a software", "zlib"
let(:source_url) { "http://chef-releng.s3.amazonaws.com/omnibus/integration_test/zlib-1.2.8.tar.gz" }
let(:source_md5) { "44d667c142d7cda120332623eab69f40" }
let(:source_sha1) { "a4d316c404ff54ca545ea71a27af7dbc29817088" }
let(:source_sha256) { "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d" }
let(:source_sha512) { "ece209d4c7ec0cb58ede791444dc754e0d10811cbbdebe3df61c0fd9f9f9867c1c3ccd5f1827f847c005e24eef34fb5bf87b5d3f894d75da04f1797538290e4a" }
let(:source) do
{ url: source_url, md5: source_md5 }
end
let(:downloaded_file) { subject.send(:downloaded_file) }
let(:extracted) { File.join(source_dir, "zlib-1.2.8") }
let(:fetch!) { capture_stdout { subject.fetch } }
let(:manifest_entry) do
double(ManifestEntry,
name: "software",
locked_version: "1.2.8",
described_version: "1.2.8",
locked_source: source)
end
subject { described_class.new(manifest_entry, project_dir, build_dir) }
describe "#fetch_required?" do
context "when the file is not downloaded" do
it "return true" do
expect(subject.fetch_required?).to be_truthy
end
end
context "when the file is downloaded" do
before { fetch! }
context "when the checksum is different" do
it "return true" do
allow(subject).to receive(:checksum).and_return("abcd1234")
expect(subject.fetch_required?).to be_truthy
end
end
context "when the checksum is the same" do
it "return false" do
expect(subject.fetch_required?).to be(false)
end
end
end
end
describe "#version_guid" do
context "source with md5" do
it "includes the md5 digest" do
expect(subject.version_guid).to eq("md5:#{source_md5}")
end
end
context "source with sha1" do
let(:source) do
{ url: source_url, sha1: source_sha1 }
end
it "includes the sha1 digest" do
expect(subject.version_guid).to eq("sha1:#{source_sha1}")
end
end
context "source with sha256" do
let(:source) do
{ url: source_url, sha256: source_sha256 }
end
it "includes the sha256 digest" do
expect(subject.version_guid).to eq("sha256:#{source_sha256}")
end
end
context "source with sha512" do
let(:source) do
{ url: source_url, sha512: source_sha512 }
end
it "includes the sha512 digest" do
expect(subject.version_guid).to eq("sha512:#{source_sha512}")
end
end
end
describe "#clean" do
before { fetch! }
context "when the project directory exists" do
before do
create_file("#{project_dir}/file_a")
end
it "extracts the asset" do
subject.clean
expect(extracted).to_not be_a_file
end
it "returns true" do
expect(subject.clean).to be_truthy
end
end
context "when the project directory does not exist" do
before do
remove_directory(project_dir)
end
it "returns false" do
expect(subject.clean).to be(false)
end
end
# we need to find a new test fixture because this one no longer exists
# context "when the source has read-only files"
context "when the source has broken symlinks" do
let(:source_url) { "http://www.openssl.org/source/openssl-1.0.1q.tar.gz" }
let(:source_md5) { "54538d0cdcb912f9bc2b36268388205e" }
let(:source) do
{ url: source_url, md5: source_md5, extract: :lax_tar }
end
it "extracts the asset without crashing" do
subject.clean
expect(extracted).to_not be_a_file
subject.clean
expect(extracted).to_not be_a_file
end
end
end
describe "#fetch" do
context "source with md5" do
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
context "when the checksum is invalid" do
let(:source_md5) { "bad01234checksum" }
it "raises an exception" do
expect { fetch! }.to raise_error(ChecksumMismatch)
end
end
end
context "source with no checksum" do
let(:source) do
{ url: source_url }
end
it "raises an exception" do
expect { fetch! }.to raise_error(ChecksumMissing)
end
end
context "when use_internal_sources is true and no internal source url" do
before { Omnibus::Config.use_internal_sources(true) }
it "raises an exception" do
expect { fetch! }.to raise_error(InternalSourceMissing)
end
end
context "when use_internal_sources is true and internal source url given" do
before { Omnibus::Config.use_internal_sources(true) }
let(:source) do
{ url: source_url, md5: source_md5, internal: true }
end
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
end
context "source with sha1" do
let(:source) do
{ url: source_url, sha1: source_sha1 }
end
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
context "when the checksum is invalid" do
let(:source_sha1) { "bad01234checksum" }
it "raises an exception" do
expect { fetch! }.to raise_error(ChecksumMismatch)
end
end
end
context "source with sha256" do
let(:source) do
{ url: source_url, sha256: source_sha256 }
end
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
context "when the checksum is invalid" do
let(:source_sha256) { "bad01234checksum" }
it "raises an exception" do
expect { fetch! }.to raise_error(ChecksumMismatch)
end
end
end
context "source with sha512" do
let(:source) do
{ url: source_url, sha512: source_sha512 }
end
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
context "when the checksum is invalid" do
let(:source_sha512) { "bad01234checksum" }
it "raises an exception" do
expect { fetch! }.to raise_error(ChecksumMismatch)
end
end
end
it "when the download times out" do
# Mock the Timeout::Error for this particular test only
WebMock.disable_net_connect!
stub_request(:get, "http://chef-releng.s3.amazonaws.com/omnibus/integration_test/zlib-1.2.8.tar.gz").to_timeout
output = capture_logging do
expect { subject.send(:download) }.to raise_error(Timeout::Error)
end
expect(output).to include("Retrying failed download")
expect(output).to include("Download failed")
retry_count = output.scan("Retrying failed download").count
expect(retry_count).to eq(Omnibus::Config.fetcher_retries)
end
context "when network unstable" do
context "when download failed and the checksum is invalid" do
let(:source_md5) { "invalid_md5_checksum" }
it "raises an exception" do
output = capture_logging do
expect { fetch! }.to raise_error(ChecksumMismatch)
end
expect(output).to include("Retry(1)")
expect(output).to include("Retry(2)")
expect(output).not_to include("Retry(3)")
end
end
end
context "when the file is less than 10240 bytes" do
let(:source_url) { "https://downloads.chef.io/packages-chef-io-public.key" }
let(:source_md5) { "369efc3a19b9118cdf51c7e87a34f266" }
it "downloads the file" do
fetch!
expect(downloaded_file).to be_a_file
end
end
end
describe "#version_for_cache" do
before do
create_file("#{project_dir}/file_a")
create_file("#{project_dir}/file_b")
create_file("#{project_dir}/.file_c")
end
context "source with md5" do
it "includes the download_url and checksum" do
expect(subject.version_for_cache).to eq("download_url:#{source_url}|md5:#{source_md5}")
end
end
context "source with sha1" do
let(:source) do
{ url: source_url, sha1: source_sha1 }
end
it "includes the download_url and checksum" do
expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha1:#{source_sha1}")
end
end
context "source with sha256" do
let(:source) do
{ url: source_url, sha256: source_sha256 }
end
it "includes the download_url and checksum" do
expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha256:#{source_sha256}")
end
end
context "source with sha512" do
let(:source) do
{ url: source_url, sha512: source_sha512 }
end
it "includes the download_url and checksum" do
expect(subject.version_for_cache).to eq("download_url:#{source_url}|sha512:#{source_sha512}")
end
end
end
end
end