diff options
author | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-22 23:08:05 +0000 |
---|---|---|
committer | hsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-22 23:08:05 +0000 |
commit | 7825e8363d4b2ccad8e2d3f5eeba9e26f6656911 (patch) | |
tree | 83cbcf419e0feeb2ab0fd063ed85e0776eb0081b /spec/bundler/bundler | |
parent | 73bed0312895322e0fd18310e840356c8e6af812 (diff) |
Postponing the Bundler merge.
I faced a big issue about Bundler with ruby core.
I have no time to resolve it issue before 2.5 final release.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61416 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/bundler/bundler')
55 files changed, 0 insertions, 8309 deletions
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb deleted file mode 100644 index 19e3f0336f..0000000000 --- a/spec/bundler/bundler/bundler_spec.rb +++ /dev/null @@ -1,230 +0,0 @@ -# encoding: utf-8 -# frozen_string_literal: true - -require "bundler" - -RSpec.describe Bundler do - describe "#load_gemspec_uncached" do - let(:app_gemspec_path) { tmp("test.gemspec") } - subject { Bundler.load_gemspec_uncached(app_gemspec_path) } - - context "with incorrect YAML file" do - before do - File.open(app_gemspec_path, "wb") do |f| - f.write strip_whitespace(<<-GEMSPEC) - --- - {:!00 ao=gu\g1= 7~f - GEMSPEC - end - end - - it "catches YAML syntax errors" do - expect { subject }.to raise_error(Bundler::GemspecError, /error while loading `test.gemspec`/) - end - - context "on Rubies with a settable YAML engine", :if => defined?(YAML::ENGINE) do - context "with Syck as YAML::Engine" do - it "raises a GemspecError after YAML load throws ArgumentError" do - orig_yamler = YAML::ENGINE.yamler - YAML::ENGINE.yamler = "syck" - - expect { subject }.to raise_error(Bundler::GemspecError) - - YAML::ENGINE.yamler = orig_yamler - end - end - - context "with Psych as YAML::Engine" do - it "raises a GemspecError after YAML load throws Psych::SyntaxError" do - orig_yamler = YAML::ENGINE.yamler - YAML::ENGINE.yamler = "psych" - - expect { subject }.to raise_error(Bundler::GemspecError) - - YAML::ENGINE.yamler = orig_yamler - end - end - end - end - - context "with correct YAML file", :if => defined?(Encoding) do - it "can load a gemspec with unicode characters with default ruby encoding" do - # spec_helper forces the external encoding to UTF-8 but that's not the - # default until Ruby 2.0 - verbose = $VERBOSE - $VERBOSE = false - encoding = Encoding.default_external - Encoding.default_external = "ASCII" - $VERBOSE = verbose - - File.open(app_gemspec_path, "wb") do |file| - file.puts <<-GEMSPEC.gsub(/^\s+/, "") - # -*- encoding: utf-8 -*- - Gem::Specification.new do |gem| - gem.author = "André the Giant" - end - GEMSPEC - end - - expect(subject.author).to eq("André the Giant") - - verbose = $VERBOSE - $VERBOSE = false - Encoding.default_external = encoding - $VERBOSE = verbose - end - end - - it "sets loaded_from" do - app_gemspec_path.open("w") do |f| - f.puts <<-GEMSPEC - Gem::Specification.new do |gem| - gem.name = "validated" - end - GEMSPEC - end - - expect(subject.loaded_from).to eq(app_gemspec_path.expand_path.to_s) - end - - context "validate is true" do - subject { Bundler.load_gemspec_uncached(app_gemspec_path, true) } - - it "validates the specification" do - app_gemspec_path.open("w") do |f| - f.puts <<-GEMSPEC - Gem::Specification.new do |gem| - gem.name = "validated" - end - GEMSPEC - end - expect(Bundler.rubygems).to receive(:validate).with have_attributes(:name => "validated") - subject - end - end - - context "with gemspec containing local variables" do - before do - File.open(app_gemspec_path, "wb") do |f| - f.write strip_whitespace(<<-GEMSPEC) - must_not_leak = true - Gem::Specification.new do |gem| - gem.name = "leak check" - end - GEMSPEC - end - end - - it "should not pollute the TOPLEVEL_BINDING" do - subject - expect(TOPLEVEL_BINDING.eval("local_variables")).to_not include(:must_not_leak) - end - end - end - - describe "#which" do - let(:executable) { "executable" } - let(:path) { %w[/a /b c ../d /e] } - let(:expected) { "executable" } - - before do - ENV["PATH"] = path.join(File::PATH_SEPARATOR) - - allow(File).to receive(:file?).and_return(false) - allow(File).to receive(:executable?).and_return(false) - if expected - expect(File).to receive(:file?).with(expected).and_return(true) - expect(File).to receive(:executable?).with(expected).and_return(true) - end - end - - subject { described_class.which(executable) } - - shared_examples_for "it returns the correct executable" do - it "returns the expected file" do - expect(subject).to eq(expected) - end - end - - it_behaves_like "it returns the correct executable" - - context "when the executable in inside a quoted path" do - let(:expected) { "/e/executable" } - it_behaves_like "it returns the correct executable" - end - - context "when the executable is not found" do - let(:expected) { nil } - it_behaves_like "it returns the correct executable" - end - end - - describe "configuration" do - context "disable_shared_gems" do - it "should unset GEM_PATH with empty string" do - env = {} - expect(Bundler).to receive(:use_system_gems?).and_return(false) - Bundler.send(:configure_gem_path, env) - expect(env.keys).to include("GEM_PATH") - expect(env["GEM_PATH"]).to eq "" - end - end - end - - describe "#rm_rf" do - context "the directory is world writable" do - let(:bundler_ui) { Bundler.ui } - it "should raise a friendly error" do - allow(File).to receive(:exist?).and_return(true) - allow(bundler_fileutils).to receive(:remove_entry_secure).and_raise(ArgumentError) - allow(File).to receive(:world_writable?).and_return(true) - message = <<EOF -It is a security vulnerability to allow your home directory to be world-writable, and bundler can not continue. -You should probably consider fixing this issue by running `chmod o-w ~` on *nix. -Please refer to http://ruby-doc.org/stdlib-2.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details. -EOF - expect(bundler_ui).to receive(:warn).with(message) - expect { Bundler.send(:rm_rf, bundled_app) }.to raise_error(Bundler::PathError) - end - end - end - - describe "#user_home" do - context "home directory is set" do - it "should return the user home" do - path = "/home/oggy" - allow(Bundler.rubygems).to receive(:user_home).and_return(path) - allow(File).to receive(:directory?).with(path).and_return true - allow(File).to receive(:writable?).with(path).and_return true - expect(Bundler.user_home).to eq(Pathname(path)) - end - end - - context "home directory is not set" do - it "should issue warning and return a temporary user home" do - allow(Bundler.rubygems).to receive(:user_home).and_return(nil) - allow(Etc).to receive(:getlogin).and_return("USER") - allow(Dir).to receive(:tmpdir).and_return("/TMP") - allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true) - expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER") - message = <<EOF -Your home directory is not set. -Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily. -EOF - expect(Bundler.ui).to receive(:warn).with(message) - expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER")) - end - end - end - - describe "#tmp_home_path" do - it "should create temporary user home" do - allow(Dir).to receive(:tmpdir).and_return("/TMP") - allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(false) - expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home") - expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home/USER") - expect(File).to receive(:chmod).with(0o777, "/TMP/bundler/home") - expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER")) - end - end -end diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb deleted file mode 100644 index ace4e8a625..0000000000 --- a/spec/bundler/bundler/cli_spec.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: true - -require "bundler/cli" - -RSpec.describe "bundle executable" do - it "returns non-zero exit status when passed unrecognized options" do - bundle "--invalid_argument" - expect(exitstatus).to_not be_zero if exitstatus - end - - it "returns non-zero exit status when passed unrecognized task" do - bundle "unrecognized-task" - expect(exitstatus).to_not be_zero if exitstatus - end - - it "looks for a binary and executes it if it's named bundler-<task>" do - File.open(tmp("bundler-testtasks"), "w", 0o755) do |f| - ruby = ENV['BUNDLE_RUBY'] || "/usr/bin/env ruby" - f.puts "#!#{ruby}\nputs 'Hello, world'\n" - end - - with_path_added(tmp) do - bundle "testtasks" - end - - expect(exitstatus).to be_zero if exitstatus - expect(out).to eq("Hello, world") - end - - context "with no arguments" do - it "prints a concise help message", :bundler => "2" do - bundle! "" - expect(last_command.stderr).to be_empty - expect(last_command.stdout).to include("Bundler version #{Bundler::VERSION}"). - and include("\n\nBundler commands:\n\n"). - and include("\n\n Primary commands:\n"). - and include("\n\n Utilities:\n"). - and include("\n\nOptions:\n") - end - end - - context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do - it "ignores it" do - gemfile bundled_app("Gemfile"), <<-G - source "file://#{gem_repo1}" - gem 'rack' - G - - bundle :install, :env => { "BUNDLE_GEMFILE" => "" } - - expect(the_bundle).to include_gems "rack 1.0.0" - end - end - - context "when ENV['RUBYGEMS_GEMDEPS'] is set" do - it "displays a warning" do - gemfile bundled_app("Gemfile"), <<-G - source "file://#{gem_repo1}" - gem 'rack' - G - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" } - expect(out).to include("RUBYGEMS_GEMDEPS") - expect(out).to include("conflict with Bundler") - - bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" } - expect(out).not_to include("RUBYGEMS_GEMDEPS") - end - end - - context "with --verbose" do - it "prints the running command" do - gemfile "" - bundle! "info bundler", :verbose => true - expect(last_command.stdout).to start_with("Running `bundle info bundler --no-color --verbose` with bundler #{Bundler::VERSION}") - end - - it "doesn't print defaults" do - install_gemfile! "", :verbose => true - expect(last_command.stdout).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") - end - - it "doesn't print defaults" do - install_gemfile! "", :verbose => true - expect(last_command.stdout).to start_with("Running `bundle install --no-color --retry 0 --verbose` with bundler #{Bundler::VERSION}") - end - end - - describe "printing the outdated warning" do - shared_examples_for "no warning" do - it "prints no warning" do - bundle "fail" - expect(last_command.stdboth).to eq("Could not find command \"fail\".") - end - end - - let(:bundler_version) { "1.1" } - let(:latest_version) { nil } - before do - bundle! "config --global disable_version_check false" - - simulate_bundler_version(bundler_version) - if latest_version - info_path = home(".bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/bundler") - info_path.parent.mkpath - info_path.open("w") {|f| f.write "#{latest_version}\n" } - end - end - - context "when there is no latest version" do - include_examples "no warning" - end - - context "when the latest version is equal to the current version" do - let(:latest_version) { bundler_version } - include_examples "no warning" - end - - context "when the latest version is less than the current version" do - let(:latest_version) { "0.9" } - include_examples "no warning" - end - - context "when the latest version is greater than the current version" do - let(:latest_version) { "222.0" } - it "prints the version warning" do - bundle "fail" - expect(last_command.stdout).to start_with(<<-EOS.strip) -The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To install the latest version, run `gem install bundler` - EOS - end - - context "and disable_version_check is set" do - before { bundle! "config disable_version_check true" } - include_examples "no warning" - end - - context "running a parseable command" do - it "prints no warning" do - bundle! "config --parseable foo" - expect(last_command.stdboth).to eq "" - - bundle "platform --ruby" - expect(last_command.stdboth).to eq "Could not locate Gemfile" - end - end - - context "and is a pre-release" do - let(:latest_version) { "222.0.0.pre.4" } - it "prints the version warning" do - bundle "fail" - expect(last_command.stdout).to start_with(<<-EOS.strip) -The latest bundler is #{latest_version}, but you are currently running #{bundler_version}. -To install the latest version, run `gem install bundler --pre` - EOS - end - end - end - end -end - -RSpec.describe "bundler executable" do - it "shows the bundler version just as the `bundle` executable does", :bundler => "< 2" do - bundler "--version" - expect(out).to eq("Bundler version #{Bundler::VERSION}") - end - - it "shows the bundler version just as the `bundle` executable does", :bundler => "2" do - bundler "--version" - expect(out).to eq(Bundler::VERSION) - end -end diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb deleted file mode 100644 index 3c4f212b60..0000000000 --- a/spec/bundler/bundler/compact_index_client/updater_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require "net/http" -require "bundler/compact_index_client" -require "bundler/compact_index_client/updater" - -RSpec.describe Bundler::CompactIndexClient::Updater do - subject(:updater) { described_class.new(fetcher) } - - let(:fetcher) { double(:fetcher) } - - context "when the ETag header is missing" do - # Regression test for https://github.com/bundler/bundler/issues/5463 - - let(:response) { double(:response, :body => "") } - let(:local_path) { Pathname("/tmp/localpath") } - let(:remote_path) { double(:remote_path) } - - it "MisMatchedChecksumError is raised" do - # Twice: #update retries on failure - expect(response).to receive(:[]).with("Content-Encoding").twice { "" } - expect(response).to receive(:[]).with("ETag").twice { nil } - expect(fetcher).to receive(:call).twice { response } - - expect do - updater.update(local_path, remote_path) - end.to raise_error(Bundler::CompactIndexClient::Updater::MisMatchedChecksumError) - end - end -end diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb deleted file mode 100644 index 3ca0dc0f79..0000000000 --- a/spec/bundler/bundler/definition_spec.rb +++ /dev/null @@ -1,358 +0,0 @@ -# frozen_string_literal: true - -require "bundler/definition" - -RSpec.describe Bundler::Definition do - describe "#lock" do - before do - allow(Bundler).to receive(:settings) { Bundler::Settings.new(".") } - allow(Bundler::SharedHelpers).to receive(:find_gemfile) { Pathname.new("Gemfile") } - allow(Bundler).to receive(:ui) { double("UI", :info => "", :debug => "") } - end - context "when it's not possible to write to the file" do - subject { Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) } - - it "raises an PermissionError with explanation" do - expect(File).to receive(:open).with("Gemfile.lock", "wb"). - and_raise(Errno::EACCES) - expect { subject.lock("Gemfile.lock") }. - to raise_error(Bundler::PermissionError, /Gemfile\.lock/) - end - end - context "when a temporary resource access issue occurs" do - subject { Bundler::Definition.new(nil, [], Bundler::SourceList.new, []) } - - it "raises a TemporaryResourceError with explanation" do - expect(File).to receive(:open).with("Gemfile.lock", "wb"). - and_raise(Errno::EAGAIN) - expect { subject.lock("Gemfile.lock") }. - to raise_error(Bundler::TemporaryResourceError, /temporarily unavailable/) - end - end - end - - describe "detects changes" do - it "for a path gem with changes", :bundler => "< 2" do - build_lib "foo", "1.0", :path => lib_path("foo") - - install_gemfile <<-G - source "file://localhost#{gem_repo1}" - gem "foo", :path => "#{lib_path("foo")}" - G - - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" - end - - bundle :install, :env => { "DEBUG" => 1 } - - expect(out).to match(/re-resolving dependencies/) - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - GEM - remote: file://localhost#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "for a path gem with changes", :bundler => "2" do - build_lib "foo", "1.0", :path => lib_path("foo") - - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "foo", :path => "#{lib_path("foo")}" - G - - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" - end - - bundle :install, :env => { "DEBUG" => 1 } - - expect(out).to match(/re-resolving dependencies/) - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "for a path gem with deps and no changes", :bundler => "< 2" do - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" - s.add_development_dependency "net-ssh", "1.0" - end - - install_gemfile <<-G - source "file://localhost#{gem_repo1}" - gem "foo", :path => "#{lib_path("foo")}" - G - - bundle :check, :env => { "DEBUG" => 1 } - - expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - GEM - remote: file://localhost#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "for a path gem with deps and no changes", :bundler => "2" do - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" - s.add_development_dependency "net-ssh", "1.0" - end - - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "foo", :path => "#{lib_path("foo")}" - G - - bundle :check, :env => { "DEBUG" => 1 } - - expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "for a rubygems gem" do - install_gemfile <<-G - source "file://localhost#{gem_repo1}" - gem "foo" - G - - bundle :check, :env => { "DEBUG" => 1 } - - expect(out).to match(/using resolution from the lockfile/) - lockfile_should_be <<-G - GEM - remote: file://localhost#{gem_repo1}/ - specs: - foo (1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo - - BUNDLED WITH - #{Bundler::VERSION} - G - end - end - - describe "initialize" do - context "gem version promoter" do - context "with lockfile" do - before do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "foo" - G - end - - it "should get a locked specs list when updating all" do - definition = Bundler::Definition.new(bundled_app("Gemfile.lock"), [], Bundler::SourceList.new, true) - locked_specs = definition.gem_version_promoter.locked_specs - expect(locked_specs.to_a.map(&:name)).to eq ["foo"] - expect(definition.instance_variable_get("@locked_specs").empty?).to eq true - end - end - - context "without gemfile or lockfile" do - it "should not attempt to parse empty lockfile contents" do - definition = Bundler::Definition.new(nil, [], mock_source_list, true) - expect(definition.gem_version_promoter.locked_specs.to_a).to eq [] - end - end - - context "eager unlock" do - let(:source_list) do - Bundler::SourceList.new.tap do |source_list| - source_list.global_rubygems_source = "file://#{gem_repo4}" - end - end - - before do - gemfile <<-G - source "file://#{gem_repo4}" - gem 'isolated_owner' - - gem 'shared_owner_a' - gem 'shared_owner_b' - G - - lockfile <<-L - GEM - remote: file://#{gem_repo4} - specs: - isolated_dep (2.0.1) - isolated_owner (1.0.1) - isolated_dep (~> 2.0) - shared_dep (5.0.1) - shared_owner_a (3.0.1) - shared_dep (~> 5.0) - shared_owner_b (4.0.1) - shared_dep (~> 5.0) - - PLATFORMS - ruby - - DEPENDENCIES - shared_owner_a - shared_owner_b - isolated_owner - - BUNDLED WITH - 1.13.0 - L - end - - it "should not eagerly unlock shared dependency with bundle install conservative updating behavior" do - updated_deps_in_gemfile = [Bundler::Dependency.new("isolated_owner", ">= 0"), - Bundler::Dependency.new("shared_owner_a", "3.0.2"), - Bundler::Dependency.new("shared_owner_b", ">= 0")] - unlock_hash_for_bundle_install = {} - definition = Bundler::Definition.new( - bundled_app("Gemfile.lock"), - updated_deps_in_gemfile, - source_list, - unlock_hash_for_bundle_install - ) - locked = definition.send(:converge_locked_specs).map(&:name) - expect(locked).to include "shared_dep" - end - - it "should not eagerly unlock shared dependency with bundle update conservative updating behavior" do - updated_deps_in_gemfile = [Bundler::Dependency.new("isolated_owner", ">= 0"), - Bundler::Dependency.new("shared_owner_a", ">= 0"), - Bundler::Dependency.new("shared_owner_b", ">= 0")] - definition = Bundler::Definition.new( - bundled_app("Gemfile.lock"), - updated_deps_in_gemfile, - source_list, - :gems => ["shared_owner_a"], :lock_shared_dependencies => true - ) - locked = definition.send(:converge_locked_specs).map(&:name) - expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b] - expect(locked.include?("shared_dep")).to be_truthy - end - end - end - end - - describe "find_resolved_spec" do - it "with no platform set in SpecSet" do - ss = Bundler::SpecSet.new([build_stub_spec("a", "1.0"), build_stub_spec("b", "1.0")]) - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@specs", ss) - found = dfn.find_resolved_spec(build_spec("a", "0.9", "ruby").first) - expect(found.name).to eq "a" - expect(found.version.to_s).to eq "1.0" - end - end - - describe "find_indexed_specs" do - it "with no platform set in indexed specs" do - index = Bundler::Index.new - %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) } - - dfn = Bundler::Definition.new(nil, [], mock_source_list, true) - dfn.instance_variable_set("@index", index) - found = dfn.find_indexed_specs(build_spec("foo", "0.9", "ruby").first) - expect(found.length).to eq 3 - end - end - - def build_stub_spec(name, version) - Bundler::StubSpecification.new(name, version, nil, nil) - end - - def mock_source_list - Class.new do - def all_sources - [] - end - - def path_sources - [] - end - - def rubygems_remotes - [] - end - - def replace_sources!(arg) - nil - end - end.new - end -end diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb deleted file mode 100644 index f706e1b9ad..0000000000 --- a/spec/bundler/bundler/dsl_spec.rb +++ /dev/null @@ -1,289 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Dsl do - before do - @rubygems = double("rubygems") - allow(Bundler::Source::Rubygems).to receive(:new) { @rubygems } - end - - describe "#git_source" do - it "registers custom hosts" do - subject.git_source(:example) {|repo_name| "git@git.example.com:#{repo_name}.git" } - subject.git_source(:foobar) {|repo_name| "git@foobar.com:#{repo_name}.git" } - subject.gem("dobry-pies", :example => "strzalek/dobry-pies") - example_uri = "git@git.example.com:strzalek/dobry-pies.git" - expect(subject.dependencies.first.source.uri).to eq(example_uri) - end - - it "raises exception on invalid hostname" do - expect do - subject.git_source(:group) {|repo_name| "git@git.example.com:#{repo_name}.git" } - end.to raise_error(Bundler::InvalidOption) - end - - it "expects block passed" do - expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption) - end - - context "default hosts (git, gist)", :bundler => "< 2" do - it "converts :github to :git" do - subject.gem("sparks", :github => "indirect/sparks") - github_uri = "git://github.com/indirect/sparks.git" - expect(subject.dependencies.first.source.uri).to eq(github_uri) - end - - it "converts numeric :gist to :git" do - subject.gem("not-really-a-gem", :gist => 2_859_988) - github_uri = "https://gist.github.com/2859988.git" - expect(subject.dependencies.first.source.uri).to eq(github_uri) - end - - it "converts :gist to :git" do - subject.gem("not-really-a-gem", :gist => "2859988") - github_uri = "https://gist.github.com/2859988.git" - expect(subject.dependencies.first.source.uri).to eq(github_uri) - end - - it "converts 'rails' to 'rails/rails'" do - subject.gem("rails", :github => "rails") - github_uri = "git://github.com/rails/rails.git" - expect(subject.dependencies.first.source.uri).to eq(github_uri) - end - - it "converts :bitbucket to :git" do - subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails") - bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/flatlab-rails.git" - expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri) - end - - it "converts 'mcorp' to 'mcorp/mcorp'" do - subject.gem("not-really-a-gem", :bitbucket => "mcorp") - bitbucket_uri = "https://mcorp@bitbucket.org/mcorp/mcorp.git" - expect(subject.dependencies.first.source.uri).to eq(bitbucket_uri) - end - end - - context "default git sources", :bundler => "2" do - it "has none" do - expect(subject.instance_variable_get(:@git_sources)).to eq({}) - end - end - end - - describe "#method_missing" do - it "raises an error for unknown DSL methods" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s). - and_return("unknown") - - error_msg = "There was an error parsing `Gemfile`: Undefined local variable or method `unknown' for Gemfile. Bundler cannot continue." - expect { subject.eval_gemfile("Gemfile") }. - to raise_error(Bundler::GemfileError, Regexp.new(error_msg)) - end - end - - describe "#eval_gemfile" do - it "handles syntax errors with a useful message" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return("}") - expect { subject.eval_gemfile("Gemfile") }. - to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'). Bundler cannot continue./) - end - - it "distinguishes syntax errors from evaluation errors" do - expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return( - "ruby '2.1.5', :engine => 'ruby', :engine_version => '1.2.4'" - ) - expect { subject.eval_gemfile("Gemfile") }. - to raise_error(Bundler::GemfileError, /There was an error evaluating `Gemfile`: ruby_version must match the :engine_version for MRI/) - end - end - - describe "#gem" do - [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :mri, :mri_18, :mri_19, - :mri_20, :mri_21, :mri_22, :mri_23, :mri_24, :mri_25, :jruby, :rbx].each do |platform| - it "allows #{platform} as a valid platform" do - subject.gem("foo", :platform => platform) - end - end - - it "rejects invalid platforms" do - expect { subject.gem("foo", :platform => :bogus) }. - to raise_error(Bundler::GemfileError, /is not a valid platform/) - end - - it "rejects empty gem name" do - expect { subject.gem("") }. - to raise_error(Bundler::GemfileError, /an empty gem name is not valid/) - end - - it "rejects with a leading space in the name" do - expect { subject.gem(" foo") }. - to raise_error(Bundler::GemfileError, /' foo' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a trailing space in the name" do - expect { subject.gem("foo ") }. - to raise_error(Bundler::GemfileError, /'foo ' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a space in the gem name" do - expect { subject.gem("fo o") }. - to raise_error(Bundler::GemfileError, /'fo o' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a tab in the gem name" do - expect { subject.gem("fo\to") }. - to raise_error(Bundler::GemfileError, /'fo\to' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a newline in the gem name" do - expect { subject.gem("fo\no") }. - to raise_error(Bundler::GemfileError, /'fo\no' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a carriage return in the gem name" do - expect { subject.gem("fo\ro") }. - to raise_error(Bundler::GemfileError, /'fo\ro' is not a valid gem name because it contains whitespace/) - end - - it "rejects with a form feed in the gem name" do - expect { subject.gem("fo\fo") }. - to raise_error(Bundler::GemfileError, /'fo\fo' is not a valid gem name because it contains whitespace/) - end - - it "rejects symbols as gem name" do - expect { subject.gem(:foo) }. - to raise_error(Bundler::GemfileError, /You need to specify gem names as Strings. Use 'gem "foo"' instead/) - end - - it "rejects branch option on non-git gems" do - expect { subject.gem("foo", :branch => "test") }. - to raise_error(Bundler::GemfileError, /The `branch` option for `gem 'foo'` is not allowed. Only gems with a git source can specify a branch/) - end - - it "allows specifying a branch on git gems" do - subject.gem("foo", :branch => "test", :git => "http://mytestrepo") - dep = subject.dependencies.last - expect(dep.name).to eq "foo" - end - - it "allows specifying a branch on git gems with a git_source" do - subject.git_source(:test_source) {|n| "https://github.com/#{n}" } - subject.gem("foo", :branch => "test", :test_source => "bundler/bundler") - dep = subject.dependencies.last - expect(dep.name).to eq "foo" - end - end - - describe "#gemspec" do - let(:spec) do - Gem::Specification.new do |gem| - gem.name = "example" - gem.platform = platform - end - end - - before do - allow(Dir).to receive(:[]).and_return(["spec_path"]) - allow(Bundler).to receive(:load_gemspec).with("spec_path").and_return(spec) - allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile")) - end - - context "with a ruby platform" do - let(:platform) { "ruby" } - - it "keeps track of the ruby platforms in the dependency" do - subject.gemspec - expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::RUBY]) - end - end - - context "with a jruby platform" do - let(:platform) { "java" } - - it "keeps track of the jruby platforms in the dependency" do - allow(Gem::Platform).to receive(:local).and_return(java) - subject.gemspec - expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::JAVA]) - end - end - end - - context "can bundle groups of gems with" do - # git "https://github.com/rails/rails.git" do - # gem "railties" - # gem "action_pack" - # gem "active_model" - # end - describe "#git" do - it "from a single repo" do - rails_gems = %w[railties action_pack active_model] - subject.git "https://github.com/rails/rails.git" do - rails_gems.each {|rails_gem| subject.send :gem, rails_gem } - end - expect(subject.dependencies.map(&:name)).to match_array rails_gems - end - end - - # github 'spree' do - # gem 'spree_core' - # gem 'spree_api' - # gem 'spree_backend' - # end - describe "#github", :bundler => "< 2" do - it "from github" do - spree_gems = %w[spree_core spree_api spree_backend] - subject.github "spree" do - spree_gems.each {|spree_gem| subject.send :gem, spree_gem } - end - - subject.dependencies.each do |d| - expect(d.source.uri).to eq("git://github.com/spree/spree.git") - end - end - end - - describe "#github", :bundler => "2" do - it "from github" do - expect do - spree_gems = %w[spree_core spree_api spree_backend] - subject.github "spree" do - spree_gems.each {|spree_gem| subject.send :gem, spree_gem } - end - end.to raise_error(Bundler::DeprecatedError, /github method has been removed/) - end - end - end - - describe "syntax errors" do - it "will raise a Bundler::GemfileError" do - gemfile "gem 'foo', :path => /unquoted/string/syntax/error" - expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }. - to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)? unknown regexp options - trg. Bundler cannot continue./) - end - end - - describe "Runtime errors", :unless => Bundler.current_ruby.on_18? do - it "will raise a Bundler::GemfileError" do - gemfile "s = 'foo'.freeze; s.strip!" - expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }. - to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: can't modify frozen String. Bundler cannot continue./i) - end - end - - describe "#with_source" do - context "if there was a rubygem source already defined" do - it "restores it after it's done" do - other_source = double("other-source") - allow(Bundler::Source::Rubygems).to receive(:new).and_return(other_source) - allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile")) - - subject.source("https://other-source.org") do - subject.gem("dobry-pies", :path => "foo") - subject.gem("foo") - end - - expect(subject.dependencies.last.source).to eq(other_source) - end - end - end -end diff --git a/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb deleted file mode 100644 index a9371f6617..0000000000 --- a/spec/bundler/bundler/endpoint_specification_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::EndpointSpecification do - let(:name) { "foo" } - let(:version) { "1.0.0" } - let(:platform) { Gem::Platform::RUBY } - let(:dependencies) { [] } - let(:metadata) { nil } - - subject(:spec) { described_class.new(name, version, platform, dependencies, metadata) } - - describe "#build_dependency" do - let(:name) { "foo" } - let(:requirement1) { "~> 1.1" } - let(:requirement2) { ">= 1.1.7" } - - it "should return a Gem::Dependency" do - expect(subject.send(:build_dependency, name, [requirement1, requirement2])). - to eq(Gem::Dependency.new(name, requirement1, requirement2)) - end - - context "when an ArgumentError occurs" do - before do - allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) { - raise ArgumentError.new("Some error occurred") - } - end - - it "should raise the original error" do - expect { subject.send(:build_dependency, name, [requirement1, requirement2]) }.to raise_error( - ArgumentError, "Some error occurred" - ) - end - end - - context "when there is an ill formed requirement" do - before do - allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) { - raise ArgumentError.new("Ill-formed requirement [\"#<YAML::Syck::DefaultKey") - } - # Eliminate extra line break in rspec output due to `puts` in `#build_dependency` - allow(subject).to receive(:puts) {} - end - - it "should raise a Bundler::GemspecError with invalid gemspec message" do - expect { subject.send(:build_dependency, name, [requirement1, requirement2]) }.to raise_error( - Bundler::GemspecError, /Unfortunately, the gem foo \(1\.0\.0\) has an invalid gemspec/ - ) - end - end - end - - describe "#parse_metadata" do - context "when the metadata has malformed requirements" do - let(:metadata) { { "rubygems" => ">\n" } } - it "raises a helpful error message" do - expect { subject }.to raise_error( - Bundler::GemspecError, - a_string_including("There was an error parsing the metadata for the gem foo (1.0.0)"). - and(a_string_including('The metadata was {"rubygems"=>">\n"}')) - ) - end - end - end - - it "supports equality comparison" do - other_spec = described_class.new("bar", version, platform, dependencies, metadata) - expect(spec).to eql(spec) - expect(spec).to_not eql(other_spec) - end -end diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb deleted file mode 100644 index 83c03e67d5..0000000000 --- a/spec/bundler/bundler/env_spec.rb +++ /dev/null @@ -1,143 +0,0 @@ -# frozen_string_literal: true - -require "bundler/settings" - -RSpec.describe Bundler::Env do - let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil, nil) } - - describe "#report" do - it "prints the environment" do - out = described_class.report - - expect(out).to include("Environment") - expect(out).to include(Bundler::VERSION) - expect(out).to include(Gem::VERSION) - expect(out).to include(described_class.send(:ruby_version)) - expect(out).to include(described_class.send(:git_version)) - expect(out).to include(OpenSSL::OPENSSL_VERSION) - end - - context "when there is a Gemfile and a lockfile and print_gemfile is true" do - before do - gemfile "gem 'rack', '1.0.0'" - - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - DEPENDENCIES - rack - - BUNDLED WITH - 1.10.0 - L - end - - let(:output) { described_class.report(:print_gemfile => true) } - - it "prints the Gemfile" do - expect(output).to include("Gemfile") - expect(output).to include("'rack', '1.0.0'") - end - - it "prints the lockfile" do - expect(output).to include("Gemfile.lock") - expect(output).to include("rack (1.0.0)") - end - end - - context "when there no Gemfile and print_gemfile is true" do - let(:output) { described_class.report(:print_gemfile => true) } - - it "prints the environment" do - expect(output).to start_with("## Environment") - end - end - - context "when Gemfile contains a gemspec and print_gemspecs is true" do - let(:gemspec) do - strip_whitespace(<<-GEMSPEC) - Gem::Specification.new do |gem| - gem.name = "foo" - gem.author = "Fumofu" - end - GEMSPEC - end - - before do - gemfile("gemspec") - - File.open(bundled_app.join("foo.gemspec"), "wb") do |f| - f.write(gemspec) - end - end - - it "prints the gemspec" do - output = described_class.report(:print_gemspecs => true) - - expect(output).to include("foo.gemspec") - expect(output).to include(gemspec) - end - end - - context "when eval_gemfile is used" do - it "prints all gemfiles" do - create_file "other/Gemfile-other", "gem 'rack'" - create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'" - create_file "Gemfile-alt", <<-G - source "file:#{gem_repo1}" - eval_gemfile "other/Gemfile" - G - gemfile "eval_gemfile #{File.expand_path("Gemfile-alt").dump}" - - output = described_class.report(:print_gemspecs => true) - expect(output).to include(strip_whitespace(<<-ENV)) - ## Gemfile - - ### Gemfile - - ```ruby - eval_gemfile #{File.expand_path("Gemfile-alt").dump} - ``` - - ### Gemfile-alt - - ```ruby - source "file:#{gem_repo1}" - eval_gemfile "other/Gemfile" - ``` - - ### other/Gemfile - - ```ruby - eval_gemfile 'Gemfile-other' - ``` - - ### other/Gemfile-other - - ```ruby - gem 'rack' - ``` - - ### Gemfile.lock - - ``` - <No #{bundled_app("Gemfile.lock")} found> - ``` - ENV - end - end - - context "when the git version is OS specific" do - it "includes OS specific information with the version number" do - expect(git_proxy_stub).to receive(:git).with("--version"). - and_return("git version 1.2.3 (Apple Git-BS)") - expect(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub) - - expect(described_class.report).to include("Git 1.2.3 (Apple Git-BS)") - end - end - end -end diff --git a/spec/bundler/bundler/environment_preserver_spec.rb b/spec/bundler/bundler/environment_preserver_spec.rb deleted file mode 100644 index 530ca6f835..0000000000 --- a/spec/bundler/bundler/environment_preserver_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::EnvironmentPreserver do - let(:preserver) { described_class.new(env, ["foo"]) } - - describe "#backup" do - let(:env) { { "foo" => "my-foo", "bar" => "my-bar" } } - subject { preserver.backup } - - it "should create backup entries" do - expect(subject["BUNDLER_ORIG_foo"]).to eq("my-foo") - end - - it "should keep the original entry" do - expect(subject["foo"]).to eq("my-foo") - end - - it "should not create backup entries for unspecified keys" do - expect(subject.key?("BUNDLER_ORIG_bar")).to eq(false) - end - - it "should not affect the original env" do - subject - expect(env.keys.sort).to eq(%w[bar foo]) - end - - context "when a key is empty" do - let(:env) { { "foo" => "" } } - - it "should not create backup entries" do - expect(subject).not_to have_key "BUNDLER_ORIG_foo" - end - end - - context "when an original key is set" do - let(:env) { { "foo" => "my-foo", "BUNDLER_ORIG_foo" => "orig-foo" } } - - it "should keep the original value in the BUNDLER_ORIG_ variable" do - expect(subject["BUNDLER_ORIG_foo"]).to eq("orig-foo") - end - - it "should keep the variable" do - expect(subject["foo"]).to eq("my-foo") - end - end - end - - describe "#restore" do - subject { preserver.restore } - - context "when an original key is set" do - let(:env) { { "foo" => "my-foo", "BUNDLER_ORIG_foo" => "orig-foo" } } - - it "should restore the original value" do - expect(subject["foo"]).to eq("orig-foo") - end - - it "should delete the backup value" do - expect(subject.key?("BUNDLER_ORIG_foo")).to eq(false) - end - end - - context "when no original key is set" do - let(:env) { { "foo" => "my-foo" } } - - it "should keep the current value" do - expect(subject["foo"]).to eq("my-foo") - end - end - - context "when the original key is empty" do - let(:env) { { "foo" => "my-foo", "BUNDLER_ORIG_foo" => "" } } - - it "should keep the current value" do - expect(subject["foo"]).to eq("my-foo") - end - end - end -end diff --git a/spec/bundler/bundler/fetcher/base_spec.rb b/spec/bundler/bundler/fetcher/base_spec.rb deleted file mode 100644 index df1245d44d..0000000000 --- a/spec/bundler/bundler/fetcher/base_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Fetcher::Base do - let(:downloader) { double(:downloader) } - let(:remote) { double(:remote) } - let(:display_uri) { "http://sample_uri.com" } - - class TestClass < described_class; end - - subject { TestClass.new(downloader, remote, display_uri) } - - describe "#initialize" do - context "with the abstract Base class" do - it "should raise an error" do - expect { described_class.new(downloader, remote, display_uri) }.to raise_error(RuntimeError, "Abstract class") - end - end - - context "with a class that inherits the Base class" do - it "should set the passed attributes" do - expect(subject.downloader).to eq(downloader) - expect(subject.remote).to eq(remote) - expect(subject.display_uri).to eq("http://sample_uri.com") - end - end - end - - describe "#remote_uri" do - let(:remote_uri_obj) { double(:remote_uri_obj) } - - before { allow(remote).to receive(:uri).and_return(remote_uri_obj) } - - it "should return the remote's uri" do - expect(subject.remote_uri).to eq(remote_uri_obj) - end - end - - describe "#fetch_uri" do - let(:remote_uri_obj) { URI("http://rubygems.org") } - - before { allow(subject).to receive(:remote_uri).and_return(remote_uri_obj) } - - context "when the remote uri's host is rubygems.org" do - it "should create a copy of the remote uri with index.rubygems.org as the host" do - fetched_uri = subject.fetch_uri - expect(fetched_uri.host).to eq("index.rubygems.org") - expect(fetched_uri).to_not be(remote_uri_obj) - end - end - - context "when the remote uri's host is not rubygems.org" do - let(:remote_uri_obj) { URI("http://otherhost.org") } - - it "should return the remote uri" do - expect(subject.fetch_uri).to eq(URI("http://otherhost.org")) - end - end - - it "memoizes the fetched uri" do - expect(remote_uri_obj).to receive(:host).once - 2.times { subject.fetch_uri } - end - end - - describe "#available?" do - it "should return whether the api is available" do - expect(subject.available?).to be_truthy - end - end - - describe "#api_fetcher?" do - it "should return false" do - expect(subject.api_fetcher?).to be_falsey - end - end -end diff --git a/spec/bundler/bundler/fetcher/compact_index_spec.rb b/spec/bundler/bundler/fetcher/compact_index_spec.rb deleted file mode 100644 index e0f58766ea..0000000000 --- a/spec/bundler/bundler/fetcher/compact_index_spec.rb +++ /dev/null @@ -1,103 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Fetcher::CompactIndex do - let(:downloader) { double(:downloader) } - let(:display_uri) { URI("http://sampleuri.com") } - let(:remote) { double(:remote, :cache_slug => "lsjdf", :uri => display_uri) } - let(:compact_index) { described_class.new(downloader, remote, display_uri) } - - before do - allow(compact_index).to receive(:log_specs) {} - end - - describe "#specs_for_names" do - it "has only one thread open at the end of the run" do - compact_index.specs_for_names(["lskdjf"]) - - thread_count = Thread.list.count {|thread| thread.status == "run" } - expect(thread_count).to eq 1 - end - - it "calls worker#stop during the run" do - expect_any_instance_of(Bundler::Worker).to receive(:stop).at_least(:once) - - compact_index.specs_for_names(["lskdjf"]) - end - - describe "#available?" do - before do - allow(compact_index).to receive(:compact_index_client). - and_return(double(:compact_index_client, :update_and_parse_checksums! => true)) - end - - it "returns true" do - expect(compact_index).to be_available - end - - context "when OpenSSL is not available" do - before do - allow(compact_index).to receive(:require).with("openssl").and_raise(LoadError) - end - - it "returns true" do - expect(compact_index).to be_available - end - end - - context "when OpenSSL is FIPS-enabled", :ruby => ">= 2.0.0" do - def remove_cached_md5_availability - return unless Bundler::SharedHelpers.instance_variable_defined?(:@md5_available) - Bundler::SharedHelpers.remove_instance_variable(:@md5_available) - end - - before do - remove_cached_md5_availability - stub_const("OpenSSL::OPENSSL_FIPS", true) - end - - after { remove_cached_md5_availability } - - context "when FIPS-mode is active" do - before do - allow(OpenSSL::Digest::MD5).to receive(:digest). - and_raise(OpenSSL::Digest::DigestError) - end - - it "returns false" do - expect(compact_index).to_not be_available - end - end - - it "returns true" do - expect(compact_index).to be_available - end - end - end - - context "logging" do - before { allow(compact_index).to receive(:log_specs).and_call_original } - - context "with debug on" do - before do - allow(Bundler).to receive_message_chain(:ui, :debug?).and_return(true) - end - - it "should log at info level" do - expect(Bundler).to receive_message_chain(:ui, :debug).with('Looking up gems ["lskdjf"]') - compact_index.specs_for_names(["lskdjf"]) - end - end - - context "with debug off" do - before do - allow(Bundler).to receive_message_chain(:ui, :debug?).and_return(false) - end - - it "should log at info level" do - expect(Bundler).to receive_message_chain(:ui, :info).with(".", false) - compact_index.specs_for_names(["lskdjf"]) - end - end - end - end -end diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb deleted file mode 100644 index 081fdff34d..0000000000 --- a/spec/bundler/bundler/fetcher/dependency_spec.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Fetcher::Dependency do - let(:downloader) { double(:downloader) } - let(:remote) { double(:remote, :uri => URI("http://localhost:5000")) } - let(:display_uri) { "http://sample_uri.com" } - - subject { described_class.new(downloader, remote, display_uri) } - - describe "#available?" do - let(:dependency_api_uri) { double(:dependency_api_uri) } - let(:fetched_spec) { double(:fetched_spec) } - - before do - allow(subject).to receive(:dependency_api_uri).and_return(dependency_api_uri) - allow(downloader).to receive(:fetch).with(dependency_api_uri).and_return(fetched_spec) - end - - it "should be truthy" do - expect(subject.available?).to be_truthy - end - - context "when there is no network access" do - before do - allow(downloader).to receive(:fetch).with(dependency_api_uri) { - raise Bundler::Fetcher::NetworkDownError.new("Network Down Message") - } - end - - it "should raise an HTTPError with the original message" do - expect { subject.available? }.to raise_error(Bundler::HTTPError, "Network Down Message") - end - end - - context "when authentication is required" do - let(:remote_uri) { "http://remote_uri.org" } - - before do - allow(downloader).to receive(:fetch).with(dependency_api_uri) { - raise Bundler::Fetcher::AuthenticationRequiredError.new(remote_uri) - } - end - - it "should raise the original error" do - expect { subject.available? }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote_uri.org}) - end - end - - context "when there is an http error" do - before { allow(downloader).to receive(:fetch).with(dependency_api_uri) { raise Bundler::HTTPError.new } } - - it "should be falsey" do - expect(subject.available?).to be_falsey - end - end - end - - describe "#api_fetcher?" do - it "should return true" do - expect(subject.api_fetcher?).to be_truthy - end - end - - describe "#specs" do - let(:gem_names) { %w[foo bar] } - let(:full_dependency_list) { ["bar"] } - let(:last_spec_list) { [["boulder", gem_version1, "ruby", resque]] } - let(:fail_errors) { double(:fail_errors) } - let(:bundler_retry) { double(:bundler_retry) } - let(:gem_version1) { double(:gem_version1) } - let(:resque) { double(:resque) } - let(:remote_uri) { "http://remote-uri.org" } - - before do - stub_const("Bundler::Fetcher::FAIL_ERRORS", fail_errors) - allow(Bundler::Retry).to receive(:new).with("dependency api", fail_errors).and_return(bundler_retry) - allow(bundler_retry).to receive(:attempts) {|&block| block.call } - allow(subject).to receive(:log_specs) {} - allow(subject).to receive(:remote_uri).and_return(remote_uri) - allow(Bundler).to receive_message_chain(:ui, :debug?) - allow(Bundler).to receive_message_chain(:ui, :info) - allow(Bundler).to receive_message_chain(:ui, :debug) - end - - context "when there are given gem names that are not in the full dependency list" do - let(:spec_list) { [["top", gem_version2, "ruby", faraday]] } - let(:deps_list) { [] } - let(:dependency_specs) { [spec_list, deps_list] } - let(:gem_version2) { double(:gem_version2) } - let(:faraday) { double(:faraday) } - - before { allow(subject).to receive(:dependency_specs).with(["foo"]).and_return(dependency_specs) } - - it "should return a hash with the remote_uri and the list of specs" do - expect(subject.specs(gem_names, full_dependency_list, last_spec_list)).to eq([ - ["top", gem_version2, "ruby", faraday], - ["boulder", gem_version1, "ruby", resque], - ]) - end - end - - context "when all given gem names are in the full dependency list" do - let(:gem_names) { ["foo"] } - let(:full_dependency_list) { %w[foo bar] } - let(:last_spec_list) { ["boulder"] } - - it "should return a hash with the remote_uri and the last spec list" do - expect(subject.specs(gem_names, full_dependency_list, last_spec_list)).to eq(["boulder"]) - end - end - - context "logging" do - before { allow(subject).to receive(:log_specs).and_call_original } - - context "with debug on" do - before do - allow(Bundler).to receive_message_chain(:ui, :debug?).and_return(true) - allow(subject).to receive(:dependency_specs).with(["foo"]).and_return([[], []]) - end - - it "should log the query list at debug level" do - expect(Bundler).to receive_message_chain(:ui, :debug).with("Query List: [\"foo\"]") - expect(Bundler).to receive_message_chain(:ui, :debug).with("Query List: []") - subject.specs(gem_names, full_dependency_list, last_spec_list) - end - end - - context "with debug off" do - before do - allow(Bundler).to receive_message_chain(:ui, :debug?).and_return(false) - allow(subject).to receive(:dependency_specs).with(["foo"]).and_return([[], []]) - end - - it "should log at info level" do - expect(Bundler).to receive_message_chain(:ui, :info).with(".", false) - expect(Bundler).to receive_message_chain(:ui, :info).with(".", false) - subject.specs(gem_names, full_dependency_list, last_spec_list) - end - end - end - - shared_examples_for "the error is properly handled" do - it "should return nil" do - expect(subject.specs(gem_names, full_dependency_list, last_spec_list)).to be_nil - end - - context "debug logging is not on" do - before { allow(Bundler).to receive_message_chain(:ui, :debug?).and_return(false) } - - it "should log a new line to info" do - expect(Bundler).to receive_message_chain(:ui, :info).with("") - subject.specs(gem_names, full_dependency_list, last_spec_list) - end - end - end - - shared_examples_for "the error suggests retrying with the full index" do - it "should log the inability to fetch from API at debug level" do - expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`") - subject.specs(gem_names, full_dependency_list, last_spec_list) - end - end - - context "when an HTTPError occurs" do - before { allow(subject).to receive(:dependency_specs) { raise Bundler::HTTPError.new } } - - it_behaves_like "the error is properly handled" - it_behaves_like "the error suggests retrying with the full index" - end - - context "when a GemspecError occurs" do - before { allow(subject).to receive(:dependency_specs) { raise Bundler::GemspecError.new } } - - it_behaves_like "the error is properly handled" - it_behaves_like "the error suggests retrying with the full index" - end - - context "when a MarshalError occurs" do - before { allow(subject).to receive(:dependency_specs) { raise Bundler::MarshalError.new } } - - it_behaves_like "the error is properly handled" - - it "should log the inability to fetch from API and mention retrying" do - expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API, trying the full index") - subject.specs(gem_names, full_dependency_list, last_spec_list) - end - end - end - - describe "#dependency_specs" do - let(:gem_names) { [%w[foo bar], %w[bundler rubocop]] } - let(:gem_list) { double(:gem_list) } - let(:formatted_specs_and_deps) { double(:formatted_specs_and_deps) } - - before do - allow(subject).to receive(:unmarshalled_dep_gems).with(gem_names).and_return(gem_list) - allow(subject).to receive(:get_formatted_specs_and_deps).with(gem_list).and_return(formatted_specs_and_deps) - end - - it "should log the query list at debug level" do - expect(Bundler).to receive_message_chain(:ui, :debug).with( - "Query Gemcutter Dependency Endpoint API: foo,bar,bundler,rubocop" - ) - subject.dependency_specs(gem_names) - end - - it "should return formatted specs and a unique list of dependencies" do - expect(subject.dependency_specs(gem_names)).to eq(formatted_specs_and_deps) - end - end - - describe "#unmarshalled_dep_gems" do - let(:gem_names) { [%w[foo bar], %w[bundler rubocop]] } - let(:dep_api_uri) { double(:dep_api_uri) } - let(:unmarshalled_gems) { double(:unmarshalled_gems) } - let(:fetch_response) { double(:fetch_response, :body => double(:body)) } - let(:rubygems_limit) { 50 } - - before { allow(subject).to receive(:dependency_api_uri).with(gem_names).and_return(dep_api_uri) } - - it "should fetch dependencies from RubyGems and unmarshal them" do - expect(gem_names).to receive(:each_slice).with(rubygems_limit).and_call_original - expect(downloader).to receive(:fetch).with(dep_api_uri).and_return(fetch_response) - expect(Bundler).to receive(:load_marshal).with(fetch_response.body).and_return([unmarshalled_gems]) - expect(subject.unmarshalled_dep_gems(gem_names)).to eq([unmarshalled_gems]) - end - end - - describe "#get_formatted_specs_and_deps" do - let(:gem_list) do - [ - { - :dependencies => { - "resque" => "req3,req4", - }, - :name => "typhoeus", - :number => "1.0.1", - :platform => "ruby", - }, - { - :dependencies => { - "faraday" => "req1,req2", - }, - :name => "grape", - :number => "2.0.2", - :platform => "jruby", - }, - ] - end - - it "should return formatted specs and a unique list of dependencies" do - spec_list, deps_list = subject.get_formatted_specs_and_deps(gem_list) - expect(spec_list).to eq([["typhoeus", "1.0.1", "ruby", [["resque", ["req3,req4"]]]], - ["grape", "2.0.2", "jruby", [["faraday", ["req1,req2"]]]]]) - expect(deps_list).to eq(%w[resque faraday]) - end - end - - describe "#dependency_api_uri" do - let(:uri) { URI("http://gem-api.com") } - - context "with gem names" do - let(:gem_names) { %w[foo bar bundler rubocop] } - - before { allow(subject).to receive(:fetch_uri).and_return(uri) } - - it "should return an api calling uri with the gems in the query" do - expect(subject.dependency_api_uri(gem_names).to_s).to eq( - "http://gem-api.com/api/v1/dependencies?gems=bar%2Cbundler%2Cfoo%2Crubocop" - ) - end - end - - context "with no gem names" do - let(:gem_names) { [] } - - before { allow(subject).to receive(:fetch_uri).and_return(uri) } - - it "should return an api calling uri with no query" do - expect(subject.dependency_api_uri(gem_names).to_s).to eq( - "http://gem-api.com/api/v1/dependencies" - ) - end - end - end -end diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb deleted file mode 100644 index c9b4fa662a..0000000000 --- a/spec/bundler/bundler/fetcher/downloader_spec.rb +++ /dev/null @@ -1,250 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Fetcher::Downloader do - let(:connection) { double(:connection) } - let(:redirect_limit) { 5 } - let(:uri) { URI("http://www.uri-to-fetch.com/api/v2/endpoint") } - let(:options) { double(:options) } - - subject { described_class.new(connection, redirect_limit) } - - describe "fetch" do - let(:counter) { 0 } - let(:httpv) { "1.1" } - let(:http_response) { double(:response) } - - before do - allow(subject).to receive(:request).with(uri, options).and_return(http_response) - allow(http_response).to receive(:body).and_return("Body with info") - end - - context "when the # requests counter is greater than the redirect limit" do - let(:counter) { redirect_limit + 1 } - - it "should raise a Bundler::HTTPError specifying too many redirects" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::HTTPError, "Too many redirects") - end - end - - context "logging" do - let(:http_response) { Net::HTTPSuccess.new("1.1", 200, "Success") } - - it "should log the HTTP response code and message to debug" do - expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP 200 Success #{uri}") - subject.fetch(uri, options, counter) - end - end - - context "when the request response is a Net::HTTPRedirection" do - let(:http_response) { Net::HTTPRedirection.new(httpv, 308, "Moved") } - - before { http_response["location"] = "http://www.redirect-uri.com/api/v2/endpoint" } - - it "should try to fetch the redirect uri and iterate the # requests counter" do - expect(subject).to receive(:fetch).with(URI("http://www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original - expect(subject).to receive(:fetch).with(URI("http://www.redirect-uri.com/api/v2/endpoint"), options, 1) - subject.fetch(uri, options, counter) - end - - context "when the redirect uri and original uri are the same" do - let(:uri) { URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint") } - - before { http_response["location"] = "ssh://www.uri-to-fetch.com/api/v1/endpoint" } - - it "should set the same user and password for the redirect uri" do - expect(subject).to receive(:fetch).with(URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original - expect(subject).to receive(:fetch).with(URI("ssh://username:password@www.uri-to-fetch.com/api/v1/endpoint"), options, 1) - subject.fetch(uri, options, counter) - end - end - end - - context "when the request response is a Net::HTTPSuccess" do - let(:http_response) { Net::HTTPSuccess.new("1.1", 200, "Success") } - - it "should return the response body" do - expect(subject.fetch(uri, options, counter)).to eq(http_response) - end - end - - context "when the request response is a Net::HTTPRequestEntityTooLarge" do - let(:http_response) { Net::HTTPRequestEntityTooLarge.new("1.1", 413, "Too Big") } - - it "should raise a Bundler::Fetcher::FallbackError with the response body" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Body with info") - end - end - - context "when the request response is a Net::HTTPUnauthorized" do - let(:http_response) { Net::HTTPUnauthorized.new("1.1", 401, "Unauthorized") } - - it "should raise a Bundler::Fetcher::AuthenticationRequiredError with the uri host" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - /Authentication is required for www.uri-to-fetch.com/) - end - end - - context "when the request response is a Net::HTTPNotFound" do - let(:http_response) { Net::HTTPNotFound.new("1.1", 404, "Not Found") } - - it "should raise a Bundler::Fetcher::FallbackError with Net::HTTPNotFound" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::FallbackError, "Net::HTTPNotFound") - end - end - - context "when the request response is some other type" do - let(:http_response) { Net::HTTPBadGateway.new("1.1", 500, "Fatal Error") } - - it "should raise a Bundler::HTTPError with the response class and body" do - expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::HTTPError, "Net::HTTPBadGateway: Body with info") - end - end - end - - describe "request" do - let(:net_http_get) { double(:net_http_get) } - let(:response) { double(:response) } - - before do - allow(Net::HTTP::Get).to receive(:new).with("/api/v2/endpoint", options).and_return(net_http_get) - allow(connection).to receive(:request).with(uri, net_http_get).and_return(response) - end - - it "should log the HTTP GET request to debug" do - expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://www.uri-to-fetch.com/api/v2/endpoint") - subject.request(uri, options) - end - - context "when there is a user provided in the request" do - context "and there is also a password provided" do - context "that contains cgi escaped characters" do - let(:uri) { URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") } - - it "should request basic authentication with the username and password" do - expect(net_http_get).to receive(:basic_auth).with("username", "password$") - subject.request(uri, options) - end - end - - context "that is all unescaped characters" do - let(:uri) { URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } - it "should request basic authentication with the username and proper cgi compliant password" do - expect(net_http_get).to receive(:basic_auth).with("username", "password") - subject.request(uri, options) - end - end - end - - context "and there is no password provided" do - let(:uri) { URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") } - - it "should request basic authentication with just the user" do - expect(net_http_get).to receive(:basic_auth).with("username", nil) - subject.request(uri, options) - end - end - - context "that contains cgi escaped characters" do - let(:uri) { URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") } - - it "should request basic authentication with the proper cgi compliant password user" do - expect(net_http_get).to receive(:basic_auth).with("username$", nil) - subject.request(uri, options) - end - end - end - - context "when the request response causes a NoMethodError" do - before { allow(connection).to receive(:request).with(uri, net_http_get) { raise NoMethodError.new(message) } } - - context "and the error message is about use_ssl=" do - let(:message) { "undefined method 'use_ssl='" } - - it "should raise a LoadError about openssl" do - expect { subject.request(uri, options) }.to raise_error(LoadError, "cannot load such file -- openssl") - end - end - - context "and the error message is not about use_ssl=" do - let(:message) { "undefined method 'undefined_method_call'" } - - it "should raise the original NoMethodError" do - expect { subject.request(uri, options) }.to raise_error(NoMethodError, "undefined method 'undefined_method_call'") - end - end - end - - context "when the request response causes a OpenSSL::SSL::SSLError" do - before { allow(connection).to receive(:request).with(uri, net_http_get) { raise OpenSSL::SSL::SSLError.new } } - - it "should raise a LoadError about openssl" do - expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::CertificateFailureError, - %r{Could not verify the SSL certificate for http://www.uri-to-fetch.com/api/v2/endpoint}) - end - end - - context "when the request response causes an error included in HTTP_ERRORS" do - let(:message) { nil } - let(:error) { RuntimeError.new(message) } - - before do - stub_const("Bundler::Fetcher::HTTP_ERRORS", [RuntimeError]) - allow(connection).to receive(:request).with(uri, net_http_get) { raise error } - end - - it "should trace log the error" do - allow(Bundler).to receive_message_chain(:ui, :debug) - expect(Bundler).to receive_message_chain(:ui, :trace).with(error) - expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError) - end - - context "when error message is about the host being down" do - let(:message) { "host down: http://www.uri-to-fetch.com" } - - it "should raise a Bundler::Fetcher::NetworkDownError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError, - /Could not reach host www.uri-to-fetch.com/) - end - end - - context "when error message is about getaddrinfo issues" do - let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" } - - it "should raise a Bundler::Fetcher::NetworkDownError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError, - /Could not reach host www.uri-to-fetch.com/) - end - end - - context "when error message is about neither host down or getaddrinfo" do - let(:message) { "other error about network" } - - it "should raise a Bundler::HTTPError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError, - "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (other error about network)") - end - - context "when the there are credentials provided in the request" do - let(:uri) { URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } - before do - allow(net_http_get).to receive(:basic_auth).with("username", "password") - end - - it "should raise a Bundler::HTTPError that doesn't contain the password" do - expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError, - "Network error while fetching http://username@www.uri-to-fetch.com/api/v2/endpoint (other error about network)") - end - end - end - - context "when error message is about no route to host" do - let(:message) { "Failed to open TCP connection to www.uri-to-fetch.com:443 " } - - it "should raise a Bundler::Fetcher::HTTPError" do - expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError, - "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (#{message})") - end - end - end - end -end diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb deleted file mode 100644 index 0cf0ae764e..0000000000 --- a/spec/bundler/bundler/fetcher/index_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Fetcher::Index do - let(:downloader) { nil } - let(:remote) { nil } - let(:display_uri) { "http://sample_uri.com" } - let(:rubygems) { double(:rubygems) } - let(:gem_names) { %w[foo bar] } - - subject { described_class.new(downloader, remote, display_uri) } - - before { allow(Bundler).to receive(:rubygems).and_return(rubygems) } - - it "fetches and returns the list of remote specs" do - expect(rubygems).to receive(:fetch_all_remote_specs) { nil } - subject.specs(gem_names) - end - - context "error handling" do - shared_examples_for "the error is properly handled" do - let(:remote_uri) { URI("http://remote-uri.org") } - before do - allow(subject).to receive(:remote_uri).and_return(remote_uri) - end - - context "when certificate verify failed" do - let(:error_message) { "certificate verify failed" } - - it "should raise a Bundler::Fetcher::CertificateFailureError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError, - %r{Could not verify the SSL certificate for http://sample_uri.com}) - end - end - - context "when a 401 response occurs" do - let(:error_message) { "401" } - - it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote-uri.org}) - end - end - - context "when a 403 response occurs" do - let(:error_message) { "403" } - - before do - allow(remote_uri).to receive(:userinfo).and_return(userinfo) - end - - context "and there was userinfo" do - let(:userinfo) { double(:userinfo) } - - it "should raise a Bundler::Fetcher::BadAuthenticationError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, - %r{Bad username or password for http://remote-uri.org}) - end - end - - context "and there was no userinfo" do - let(:userinfo) { nil } - - it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote-uri.org}) - end - end - end - - context "any other message is returned" do - let(:error_message) { "You get an error, you get an error!" } - - before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) } - - it "should raise a Bundler::HTTPError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com") - end - end - end - - context "when a Gem::RemoteFetcher::FetchError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, nil) } } - - it_behaves_like "the error is properly handled" - end - - context "when a OpenSSL::SSL::SSLError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise OpenSSL::SSL::SSLError.new(error_message) } } - - it_behaves_like "the error is properly handled" - end - - context "when a Net::HTTPFatalError occurs" do - before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Net::HTTPFatalError.new(error_message, 404) } } - - it_behaves_like "the error is properly handled" - end - end -end diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb deleted file mode 100644 index 184b9efa64..0000000000 --- a/spec/bundler/bundler/fetcher_spec.rb +++ /dev/null @@ -1,161 +0,0 @@ -# frozen_string_literal: true - -require "bundler/fetcher" - -RSpec.describe Bundler::Fetcher do - let(:uri) { URI("https://example.com") } - let(:remote) { double("remote", :uri => uri, :original_uri => nil) } - - subject(:fetcher) { Bundler::Fetcher.new(remote) } - - before do - allow(Bundler).to receive(:root) { Pathname.new("root") } - end - - describe "#connection" do - context "when Gem.configuration doesn't specify http_proxy" do - it "specify no http_proxy" do - expect(fetcher.http_proxy).to be_nil - end - it "consider environment vars when determine proxy" do - with_env_vars("HTTP_PROXY" => "http://proxy-example.com") do - expect(fetcher.http_proxy).to match("http://proxy-example.com") - end - end - end - context "when Gem.configuration specifies http_proxy " do - let(:proxy) { "http://proxy-example2.com" } - before do - allow(Bundler.rubygems.configuration).to receive(:[]).with(:http_proxy).and_return(proxy) - end - it "consider Gem.configuration when determine proxy" do - expect(fetcher.http_proxy).to match("http://proxy-example2.com") - end - it "consider Gem.configuration when determine proxy" do - with_env_vars("HTTP_PROXY" => "http://proxy-example.com") do - expect(fetcher.http_proxy).to match("http://proxy-example2.com") - end - end - context "when the proxy is :no_proxy" do - let(:proxy) { :no_proxy } - it "does not set a proxy" do - expect(fetcher.http_proxy).to be_nil - end - end - end - - context "when a rubygems source mirror is set" do - let(:orig_uri) { URI("http://zombo.com") } - let(:remote_with_mirror) do - double("remote", :uri => uri, :original_uri => orig_uri, :anonymized_uri => uri) - end - - let(:fetcher) { Bundler::Fetcher.new(remote_with_mirror) } - - it "sets the 'X-Gemfile-Source' header containing the original source" do - expect( - fetcher.send(:connection).override_headers["X-Gemfile-Source"] - ).to eq("http://zombo.com") - end - end - - context "when there is no rubygems source mirror set" do - let(:remote_no_mirror) do - double("remote", :uri => uri, :original_uri => nil, :anonymized_uri => uri) - end - - let(:fetcher) { Bundler::Fetcher.new(remote_no_mirror) } - - it "does not set the 'X-Gemfile-Source' header" do - expect(fetcher.send(:connection).override_headers["X-Gemfile-Source"]).to be_nil - end - end - - context "when there are proxy environment variable(s) set" do - it "consider http_proxy" do - with_env_vars("HTTP_PROXY" => "http://proxy-example3.com") do - expect(fetcher.http_proxy).to match("http://proxy-example3.com") - end - end - it "consider no_proxy" do - with_env_vars("HTTP_PROXY" => "http://proxy-example4.com", "NO_PROXY" => ".example.com,.example.net") do - expect( - fetcher.send(:connection).no_proxy - ).to eq([".example.com", ".example.net"]) - end - end - end - - context "when no ssl configuration is set" do - it "no cert" do - expect(fetcher.send(:connection).cert).to be_nil - expect(fetcher.send(:connection).key).to be_nil - end - end - - context "when bunder ssl ssl configuration is set" do - before do - cert = File.join(Spec::Path.tmpdir, "cert") - File.open(cert, "w") {|f| f.write "PEM" } - allow(Bundler.settings).to receive(:[]).and_return(nil) - allow(Bundler.settings).to receive(:[]).with(:ssl_client_cert).and_return(cert) - expect(OpenSSL::X509::Certificate).to receive(:new).with("PEM").and_return("cert") - expect(OpenSSL::PKey::RSA).to receive(:new).with("PEM").and_return("key") - end - after do - FileUtils.rm File.join(Spec::Path.tmpdir, "cert") - end - it "use bundler configuration" do - expect(fetcher.send(:connection).cert).to eq("cert") - expect(fetcher.send(:connection).key).to eq("key") - end - end - - context "when gem ssl configuration is set" do - before do - allow(Bundler.rubygems.configuration).to receive_messages( - :http_proxy => nil, - :ssl_client_cert => "cert", - :ssl_ca_cert => "ca" - ) - expect(File).to receive(:read).and_return("") - expect(OpenSSL::X509::Certificate).to receive(:new).and_return("cert") - expect(OpenSSL::PKey::RSA).to receive(:new).and_return("key") - store = double("ca store") - expect(store).to receive(:add_file) - expect(OpenSSL::X509::Store).to receive(:new).and_return(store) - end - it "use gem configuration" do - expect(fetcher.send(:connection).cert).to eq("cert") - expect(fetcher.send(:connection).key).to eq("key") - end - end - end - - describe "#user_agent" do - it "builds user_agent with current ruby version and Bundler settings" do - allow(Bundler.settings).to receive(:all).and_return(%w[foo bar]) - expect(fetcher.user_agent).to match(%r{bundler/(\d.)}) - expect(fetcher.user_agent).to match(%r{rubygems/(\d.)}) - expect(fetcher.user_agent).to match(%r{ruby/(\d.)}) - expect(fetcher.user_agent).to match(%r{options/foo,bar}) - end - - describe "include CI information" do - it "from one CI" do - with_env_vars("JENKINS_URL" => "foo") do - ci_part = fetcher.user_agent.split(" ").find {|x| x.match(%r{\Aci/}) } - expect(ci_part).to match("jenkins") - end - end - - it "from many CI" do - with_env_vars("TRAVIS" => "foo", "CI_NAME" => "my_ci") do - ci_part = fetcher.user_agent.split(" ").find {|x| x.match(%r{\Aci/}) } - expect(ci_part).to match("travis") - expect(ci_part).to match("my_ci") - end - end - end - end -end diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb deleted file mode 100644 index 2a1be491ef..0000000000 --- a/spec/bundler/bundler/friendly_errors_spec.rb +++ /dev/null @@ -1,270 +0,0 @@ -# frozen_string_literal: true - -require "bundler" -require "bundler/friendly_errors" -require "cgi" - -RSpec.describe Bundler, "friendly errors" do - context "with invalid YAML in .gemrc" do - before do - File.open(Gem.configuration.config_file_name, "w") do |f| - f.write "invalid: yaml: hah" - end - end - - after do - FileUtils.rm(Gem.configuration.config_file_name) - end - - it "reports a relevant friendly error message", :ruby => ">= 1.9", :rubygems => "< 2.5.0" do - gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - G - - bundle :install, :env => { "DEBUG" => true } - - expect(out).to include("Your RubyGems configuration") - expect(out).to include("invalid YAML syntax") - expect(out).to include("Psych::SyntaxError") - expect(out).not_to include("ERROR REPORT TEMPLATE") - expect(exitstatus).to eq(25) if exitstatus - end - - it "reports a relevant friendly error message", :ruby => ">= 1.9", :rubygems => ">= 2.5.0" do - gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - G - - bundle :install, :env => { "DEBUG" => true } - - expect(last_command.stderr).to include("Failed to load #{home(".gemrc")}") - expect(exitstatus).to eq(0) if exitstatus - end - end - - it "calls log_error in case of exception" do - exception = Exception.new - expect(Bundler::FriendlyErrors).to receive(:exit_status).with(exception).and_return(1) - expect do - Bundler.with_friendly_errors do - raise exception - end - end.to raise_error(SystemExit) - end - - it "calls exit_status on exception" do - exception = Exception.new - expect(Bundler::FriendlyErrors).to receive(:log_error).with(exception) - expect do - Bundler.with_friendly_errors do - raise exception - end - end.to raise_error(SystemExit) - end - - describe "#log_error" do - shared_examples "Bundler.ui receive error" do |error, message| - it "" do - expect(Bundler.ui).to receive(:error).with(message || error.message) - Bundler::FriendlyErrors.log_error(error) - end - end - - shared_examples "Bundler.ui receive trace" do |error| - it "" do - expect(Bundler.ui).to receive(:trace).with(error) - Bundler::FriendlyErrors.log_error(error) - end - end - - context "YamlSyntaxError" do - it_behaves_like "Bundler.ui receive error", Bundler::YamlSyntaxError.new(StandardError.new, "sample_message") - - it "Bundler.ui receive trace" do - std_error = StandardError.new - exception = Bundler::YamlSyntaxError.new(std_error, "sample_message") - expect(Bundler.ui).to receive(:trace).with(std_error) - Bundler::FriendlyErrors.log_error(exception) - end - end - - context "Dsl::DSLError, GemspecError" do - it_behaves_like "Bundler.ui receive error", Bundler::Dsl::DSLError.new("description", "dsl_path", "backtrace") - it_behaves_like "Bundler.ui receive error", Bundler::GemspecError.new - end - - context "GemRequireError" do - let(:orig_error) { StandardError.new } - let(:error) { Bundler::GemRequireError.new(orig_error, "sample_message") } - - before do - allow(orig_error).to receive(:backtrace).and_return([]) - end - - it "Bundler.ui receive error" do - expect(Bundler.ui).to receive(:error).with(error.message) - Bundler::FriendlyErrors.log_error(error) - end - - it "writes to Bundler.ui.trace" do - expect(Bundler.ui).to receive(:trace).with(orig_error, nil, true) - Bundler::FriendlyErrors.log_error(error) - end - end - - context "BundlerError" do - it "Bundler.ui receive error" do - error = Bundler::BundlerError.new - expect(Bundler.ui).to receive(:error).with(error.message, :wrap => true) - Bundler::FriendlyErrors.log_error(error) - end - it_behaves_like "Bundler.ui receive trace", Bundler::BundlerError.new - end - - context "Thor::Error" do - it_behaves_like "Bundler.ui receive error", Bundler::Thor::Error.new - end - - context "LoadError" do - let(:error) { LoadError.new("cannot load such file -- openssl") } - - it "Bundler.ui receive error" do - expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL.") - Bundler::FriendlyErrors.log_error(error) - end - - it "Bundler.ui receive warn" do - expect(Bundler.ui).to receive(:warn).with(any_args, :wrap => true) - Bundler::FriendlyErrors.log_error(error) - end - - it "Bundler.ui receive trace" do - expect(Bundler.ui).to receive(:trace).with(error) - Bundler::FriendlyErrors.log_error(error) - end - end - - context "Interrupt" do - it "Bundler.ui receive error" do - expect(Bundler.ui).to receive(:error).with("\nQuitting...") - Bundler::FriendlyErrors.log_error(Interrupt.new) - end - it_behaves_like "Bundler.ui receive trace", Interrupt.new - end - - context "Gem::InvalidSpecificationException" do - it "Bundler.ui receive error" do - error = Gem::InvalidSpecificationException.new - expect(Bundler.ui).to receive(:error).with(error.message, :wrap => true) - Bundler::FriendlyErrors.log_error(error) - end - end - - context "SystemExit" do - # Does nothing - end - - context "Java::JavaLang::OutOfMemoryError" do - module Java - module JavaLang - class OutOfMemoryError < StandardError; end - end - end - - it "Bundler.ui receive error" do - error = Java::JavaLang::OutOfMemoryError.new - expect(Bundler.ui).to receive(:error).with(/JVM has run out of memory/) - Bundler::FriendlyErrors.log_error(error) - end - end - - context "unexpected error" do - it "calls request_issue_report_for with error" do - error = StandardError.new - expect(Bundler::FriendlyErrors).to receive(:request_issue_report_for).with(error) - Bundler::FriendlyErrors.log_error(error) - end - end - end - - describe "#exit_status" do - it "calls status_code for BundlerError" do - error = Bundler::BundlerError.new - expect(error).to receive(:status_code).and_return("sample_status_code") - expect(Bundler::FriendlyErrors.exit_status(error)).to eq("sample_status_code") - end - - it "returns 15 for Thor::Error" do - error = Bundler::Thor::Error.new - expect(Bundler::FriendlyErrors.exit_status(error)).to eq(15) - end - - it "calls status for SystemExit" do - error = SystemExit.new - expect(error).to receive(:status).and_return("sample_status") - expect(Bundler::FriendlyErrors.exit_status(error)).to eq("sample_status") - end - - it "returns 1 in other cases" do - error = StandardError.new - expect(Bundler::FriendlyErrors.exit_status(error)).to eq(1) - end - end - - describe "#request_issue_report_for" do - it "calls relevant methods for Bundler.ui" do - expect(Bundler.ui).to receive(:info) - expect(Bundler.ui).to receive(:error) - expect(Bundler.ui).to receive(:warn) - Bundler::FriendlyErrors.request_issue_report_for(StandardError.new) - end - - it "includes error class, message and backlog" do - error = StandardError.new - allow(Bundler::FriendlyErrors).to receive(:issues_url).and_return("") - - expect(error).to receive(:class).at_least(:once) - expect(error).to receive(:message).at_least(:once) - expect(error).to receive(:backtrace).at_least(:once) - Bundler::FriendlyErrors.request_issue_report_for(error) - end - end - - describe "#issues_url" do - it "generates a search URL for the exception message" do - exception = Exception.new("Exception message") - - expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=Exception+message&type=Issues") - end - - it "generates a search URL for only the first line of a multi-line exception message" do - exception = Exception.new(<<END) -First line of the exception message -Second line of the exception message -END - - expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=First+line+of+the+exception+message&type=Issues") - end - - it "generates the url without colons" do - exception = Exception.new(<<END) -Exception ::: with ::: colons ::: -END - issues_url = Bundler::FriendlyErrors.issues_url(exception) - expect(issues_url).not_to include("%3A") - expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Exception with colons ")}&type=Issues") - end - - it "removes information after - for Errono::EACCES" do - exception = Exception.new(<<END) -Errno::EACCES: Permission denied @ dir_s_mkdir - /Users/foo/bar/ -END - allow(exception).to receive(:is_a?).with(Errno).and_return(true) - issues_url = Bundler::FriendlyErrors.issues_url(exception) - expect(issues_url).not_to include("/Users/foo/bar") - expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues") - end - end -end diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb deleted file mode 100644 index c36204c542..0000000000 --- a/spec/bundler/bundler/gem_helper_spec.rb +++ /dev/null @@ -1,350 +0,0 @@ -# frozen_string_literal: true - -require "rake" -require "bundler/gem_helper" - -RSpec.describe Bundler::GemHelper do - let(:app_name) { "lorem__ipsum" } - let(:app_path) { bundled_app app_name } - let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") } - - before(:each) do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false" - bundle "gem #{app_name}" - end - - context "determining gemspec" do - subject { Bundler::GemHelper.new(app_path) } - - context "fails" do - it "when there is no gemspec" do - FileUtils.rm app_gemspec_path - expect { subject }.to raise_error(/Unable to determine name/) - end - - it "when there are two gemspecs and the name isn't specified" do - FileUtils.touch app_path.join("#{app_name}-2.gemspec") - expect { subject }.to raise_error(/Unable to determine name/) - end - end - - context "interpolates the name" do - before do - # Remove exception that prevents public pushes on older RubyGems versions - if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0") - content = File.read(app_gemspec_path) - content.sub!(/raise "RubyGems 2\.0 or newer.*/, "") - File.open(app_gemspec_path, "w") {|f| f.write(content) } - end - end - - it "when there is only one gemspec" do - expect(subject.gemspec.name).to eq(app_name) - end - - it "for a hidden gemspec" do - FileUtils.mv app_gemspec_path, app_path.join(".gemspec") - expect(subject.gemspec.name).to eq(app_name) - end - end - - it "handles namespaces and converts them to CamelCase" do - bundle "gem #{app_name}-foo_bar" - underscore_path = bundled_app "#{app_name}-foo_bar" - - lib = underscore_path.join("lib/#{app_name}/foo_bar.rb").read - expect(lib).to include("module LoremIpsum") - expect(lib).to include("module FooBar") - end - end - - context "gem management" do - def mock_confirm_message(message) - expect(Bundler.ui).to receive(:confirm).with(message) - end - - def mock_build_message(name, version) - message = "#{name} #{version} built to pkg/#{name}-#{version}.gem." - mock_confirm_message message - end - - subject! { Bundler::GemHelper.new(app_path) } - let(:app_version) { "0.1.0" } - let(:app_gem_dir) { app_path.join("pkg") } - let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") } - let(:app_gemspec_content) { remove_push_guard(File.read(app_gemspec_path)) } - - before(:each) do - content = app_gemspec_content.gsub("TODO: ", "") - content.sub!(/homepage\s+= ".*"/, 'homepage = ""') - File.open(app_gemspec_path, "w") {|file| file << content } - end - - def remove_push_guard(gemspec_content) - # Remove exception that prevents public pushes on older RubyGems versions - if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0") - gemspec_content.sub!(/raise "RubyGems 2\.0 or newer.*/, "") - end - gemspec_content - end - - it "uses a shell UI for output" do - expect(Bundler.ui).to be_a(Bundler::UI::Shell) - end - - describe "#install" do - let!(:rake_application) { Rake.application } - - before(:each) do - Rake.application = Rake::Application.new - end - - after(:each) do - Rake.application = rake_application - end - - context "defines Rake tasks" do - let(:task_names) do - %w[build install release release:guard_clean - release:source_control_push release:rubygem_push] - end - - context "before installation" do - it "raises an error with appropriate message" do - task_names.each do |name| - expect { Rake.application[name] }. - to raise_error(/^Don't know how to build task '#{name}'/) - end - end - end - - context "after installation" do - before do - subject.install - end - - it "adds Rake tasks successfully" do - task_names.each do |name| - expect { Rake.application[name] }.not_to raise_error - expect(Rake.application[name]).to be_instance_of Rake::Task - end - end - - it "provides a way to access the gemspec object" do - expect(subject.gemspec.name).to eq(app_name) - end - end - end - end - - describe "#build_gem" do - context "when build failed" do - it "raises an error with appropriate message" do - # break the gemspec by adding back the TODOs - File.open(app_gemspec_path, "w") {|file| file << app_gemspec_content } - expect { subject.build_gem }.to raise_error(/TODO/) - end - end - - context "when build was successful" do - it "creates .gem file" do - mock_build_message app_name, app_version - subject.build_gem - expect(app_gem_path).to exist - end - end - end - - describe "#install_gem" do - context "when installation was successful" do - it "gem is installed" do - mock_build_message app_name, app_version - mock_confirm_message "#{app_name} (#{app_version}) installed." - subject.install_gem(nil, :local) - expect(app_gem_path).to exist - gem_command! :list - expect(out).to include("#{app_name} (#{app_version})") - end - end - - context "when installation fails" do - it "raises an error with appropriate message" do - # create empty gem file in order to simulate install failure - allow(subject).to receive(:build_gem) do - FileUtils.mkdir_p(app_gem_dir) - FileUtils.touch app_gem_path - app_gem_path - end - expect { subject.install_gem }.to raise_error(/Couldn't install gem/) - end - end - end - - describe "rake release" do - let!(:rake_application) { Rake.application } - - before(:each) do - Rake.application = Rake::Application.new - subject.install - end - - after(:each) do - Rake.application = rake_application - end - - before do - Dir.chdir(app_path) do - `git init` - `git config user.email "you@example.com"` - `git config user.name "name"` - `git config push.default simple` - end - - # silence messages - allow(Bundler.ui).to receive(:confirm) - allow(Bundler.ui).to receive(:error) - end - - context "fails" do - it "when there are unstaged files" do - expect { Rake.application["release"].invoke }. - to raise_error("There are files that need to be committed first.") - end - - it "when there are uncommitted files" do - Dir.chdir(app_path) { `git add .` } - expect { Rake.application["release"].invoke }. - to raise_error("There are files that need to be committed first.") - end - - it "when there is no git remote" do - Dir.chdir(app_path) { `git commit -a -m "initial commit"` } - expect { Rake.application["release"].invoke }.to raise_error(RuntimeError) - end - end - - context "succeeds" do - before do - Dir.chdir(gem_repo1) { `git init --bare` } - Dir.chdir(app_path) do - `git remote add origin file://#{gem_repo1}` - `git commit -a -m "initial commit"` - end - end - - it "on releasing" do - mock_build_message app_name, app_version - mock_confirm_message "Tagged v#{app_version}." - mock_confirm_message "Pushed git commits and tags." - expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) - - Dir.chdir(app_path) { sys_exec("git push -u origin master") } - - Rake.application["release"].invoke - end - - it "even if tag already exists" do - mock_build_message app_name, app_version - mock_confirm_message "Tag v#{app_version} has already been created." - expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s) - - Dir.chdir(app_path) do - `git tag -a -m \"Version #{app_version}\" v#{app_version}` - end - - Rake.application["release"].invoke - end - end - end - - describe "release:rubygem_push" do - let!(:rake_application) { Rake.application } - - before(:each) do - Rake.application = Rake::Application.new - subject.install - allow(subject).to receive(:sh) - end - - after(:each) do - Rake.application = rake_application - end - - before do - Dir.chdir(app_path) do - `git init` - `git config user.email "you@example.com"` - `git config user.name "name"` - `git config push.default simple` - end - - # silence messages - allow(Bundler.ui).to receive(:confirm) - allow(Bundler.ui).to receive(:error) - - credentials = double("credentials", "file?" => true) - allow(Bundler.user_home).to receive(:join). - with(".gem/credentials").and_return(credentials) - end - - describe "success messaging" do - context "No allowed_push_host set" do - before do - allow(subject).to receive(:allowed_push_host).and_return(nil) - end - - around do |example| - orig_host = ENV["RUBYGEMS_HOST"] - ENV["RUBYGEMS_HOST"] = rubygems_host_env - - example.run - - ENV["RUBYGEMS_HOST"] = orig_host - end - - context "RUBYGEMS_HOST env var is set" do - let(:rubygems_host_env) { "https://custom.env.gemhost.com" } - - it "should report successful push to the host from the environment" do - mock_confirm_message "Pushed #{app_name} #{app_version} to #{rubygems_host_env}" - - Rake.application["release:rubygem_push"].invoke - end - end - - context "RUBYGEMS_HOST env var is not set" do - let(:rubygems_host_env) { nil } - - it "should report successful push to rubygems.org" do - mock_confirm_message "Pushed #{app_name} #{app_version} to rubygems.org" - - Rake.application["release:rubygem_push"].invoke - end - end - - context "RUBYGEMS_HOST env var is an empty string" do - let(:rubygems_host_env) { "" } - - it "should report successful push to rubygems.org" do - mock_confirm_message "Pushed #{app_name} #{app_version} to rubygems.org" - - Rake.application["release:rubygem_push"].invoke - end - end - end - - context "allowed_push_host set in gemspec" do - before do - allow(subject).to receive(:allowed_push_host).and_return("https://my.gemhost.com") - end - - it "should report successful push to the allowed gem host" do - mock_confirm_message "Pushed #{app_name} #{app_version} to https://my.gemhost.com" - - Rake.application["release:rubygem_push"].invoke - end - end - end - end - end -end diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb deleted file mode 100644 index 01e0232fba..0000000000 --- a/spec/bundler/bundler/gem_version_promoter_spec.rb +++ /dev/null @@ -1,179 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::GemVersionPromoter do - context "conservative resolver" do - def versions(result) - result.flatten.map(&:version).map(&:to_s) - end - - def make_instance(*args) - @gvp = Bundler::GemVersionPromoter.new(*args).tap do |gvp| - gvp.class.class_eval { public :filter_dep_specs, :sort_dep_specs } - end - end - - def unlocking(options) - make_instance(Bundler::SpecSet.new([]), ["foo"]).tap do |p| - p.level = options[:level] if options[:level] - p.strict = options[:strict] if options[:strict] - end - end - - def keep_locked(options) - make_instance(Bundler::SpecSet.new([]), ["bar"]).tap do |p| - p.level = options[:level] if options[:level] - p.strict = options[:strict] if options[:strict] - end - end - - def build_spec_groups(name, versions) - versions.map do |v| - Bundler::Resolver::SpecGroup.new(build_spec(name, v)) - end - end - - # Rightmost (highest array index) in result is most preferred. - # Leftmost (lowest array index) in result is least preferred. - # `build_spec_groups` has all versions of gem in index. - # `build_spec` is the version currently in the .lock file. - # - # In default (not strict) mode, all versions in the index will - # be returned, allowing Bundler the best chance to resolve all - # dependencies, but sometimes resulting in upgrades that some - # would not consider conservative. - context "filter specs (strict) level patch" do - it "when keeping build_spec, keep current, next release" do - keep_locked(:level => :patch) - res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first - ) - expect(versions(res)).to eq %w[1.7.9 1.7.8] - end - - it "when unlocking prefer next release first" do - unlocking(:level => :patch) - res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first - ) - expect(versions(res)).to eq %w[1.7.8 1.7.9] - end - - it "when unlocking keep current when already at latest release" do - unlocking(:level => :patch) - res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), - build_spec("foo", "1.7.9").first - ) - expect(versions(res)).to eq %w[1.7.9] - end - end - - context "filter specs (strict) level minor" do - it "when unlocking favor next releases, remove minor and major increases" do - unlocking(:level => :minor) - res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first - ) - expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0] - end - - it "when keep locked, keep current, then favor next release, remove minor and major increases" do - keep_locked(:level => :minor) - res = @gvp.filter_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first - ) - expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0] - end - end - - context "sort specs (not strict) level patch" do - it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do - keep_locked(:level => :patch) - res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]), - build_spec("foo", "1.7.7").first - ) - expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7] - end - - it "when unlocking favor next release, then current over minor increase" do - unlocking(:level => :patch) - res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.8.0]), - build_spec("foo", "1.7.8").first - ) - expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9] - end - - it "when unlocking do proper integer comparison, not string" do - unlocking(:level => :patch) - res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]), - build_spec("foo", "1.7.8").first - ) - expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15] - end - - it "leave current when unlocking but already at latest release" do - unlocking(:level => :patch) - res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]), - build_spec("foo", "1.7.9").first - ) - expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9] - end - end - - context "sort specs (not strict) level minor" do - it "when unlocking favor next release, then minor increase over current" do - unlocking(:level => :minor) - res = @gvp.sort_dep_specs( - build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]), - build_spec("foo", "0.2.0").first - ) - expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0] - end - end - - context "level error handling" do - subject { Bundler::GemVersionPromoter.new } - - it "should raise if not major, minor or patch is passed" do - expect { subject.level = :minjor }.to raise_error ArgumentError - end - - it "should raise if invalid classes passed" do - [123, nil].each do |value| - expect { subject.level = value }.to raise_error ArgumentError - end - end - - it "should accept major, minor patch symbols" do - [:major, :minor, :patch].each do |value| - subject.level = value - expect(subject.level).to eq value - end - end - - it "should accept major, minor patch strings" do - %w[major minor patch].each do |value| - subject.level = value - expect(subject.level).to eq value.to_sym - end - end - end - - context "debug output" do - it "should not kerblooie on its own debug output" do - gvp = unlocking(:level => :patch) - dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby") - result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0])) - expect(result.class).to eq Array - end - end - end -end diff --git a/spec/bundler/bundler/index_spec.rb b/spec/bundler/bundler/index_spec.rb deleted file mode 100644 index 0f3f6e4944..0000000000 --- a/spec/bundler/bundler/index_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Index do - let(:specs) { [] } - subject { described_class.build {|i| i.use(specs) } } - - context "specs with a nil platform" do - let(:spec) do - Gem::Specification.new do |s| - s.name = "json" - s.version = "1.8.3" - allow(s).to receive(:platform).and_return(nil) - end - end - let(:specs) { [spec] } - - describe "#search_by_spec" do - it "finds the spec when a nil platform is specified" do - expect(subject.search(spec)).to eq([spec]) - end - - it "finds the spec when a ruby platform is specified" do - query = spec.dup.tap {|s| s.platform = "ruby" } - expect(subject.search(query)).to eq([spec]) - end - end - end - - context "with specs that include development dependencies" do - let(:specs) { [*build_spec("a", "1.0.0") {|s| s.development("b", "~> 1.0") }] } - - it "does not include b in #dependency_names" do - expect(subject.dependency_names).not_to include("b") - end - end -end diff --git a/spec/bundler/bundler/installer/gem_installer_spec.rb b/spec/bundler/bundler/installer/gem_installer_spec.rb deleted file mode 100644 index 7340a3acc0..0000000000 --- a/spec/bundler/bundler/installer/gem_installer_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require "bundler/installer/gem_installer" - -RSpec.describe Bundler::GemInstaller do - let(:installer) { instance_double("Installer") } - let(:spec_source) { instance_double("SpecSource") } - let(:spec) { instance_double("Specification", :name => "dummy", :version => "0.0.1", :loaded_from => "dummy", :source => spec_source) } - - subject { described_class.new(spec, installer) } - - context "spec_settings is nil" do - it "invokes install method with empty build_args", :rubygems => ">= 2" do - allow(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => []) - subject.install_from_spec - end - end - - context "spec_settings is build option" do - it "invokes install method with build_args", :rubygems => ">= 2" do - allow(Bundler.settings).to receive(:[]).with(:bin) - allow(Bundler.settings).to receive(:[]).with(:inline) - allow(Bundler.settings).to receive(:[]).with(:forget_cli_options) - allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy") - expect(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy"]) - subject.install_from_spec - end - end -end diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb deleted file mode 100644 index ace5c1a23a..0000000000 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require "bundler/installer/parallel_installer" - -RSpec.describe Bundler::ParallelInstaller do - let(:installer) { instance_double("Installer") } - let(:all_specs) { [] } - let(:size) { 1 } - let(:standalone) { false } - let(:force) { false } - - subject { described_class.new(installer, all_specs, size, standalone, force) } - - context "when dependencies that are not on the overall installation list are the only ones not installed" do - let(:all_specs) do - [ - build_spec("alpha", "1.0") {|s| s.runtime "a", "1" }, - ].flatten - end - - it "prints a warning" do - expect(Bundler.ui).to receive(:warn).with(<<-W.strip) -Your lockfile was created by an old Bundler that left some things out. -You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile. -The missing gems are: -* a depended upon by alpha - W - subject.check_for_corrupt_lockfile - end - - context "when size > 1" do - let(:size) { 500 } - - it "prints a warning and sets size to 1" do - expect(Bundler.ui).to receive(:warn).with(<<-W.strip) -Your lockfile was created by an old Bundler that left some things out. -Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing 500 at a time. -You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile. -The missing gems are: -* a depended upon by alpha - W - subject.check_for_corrupt_lockfile - expect(subject.size).to eq(1) - end - end - end -end diff --git a/spec/bundler/bundler/installer/spec_installation_spec.rb b/spec/bundler/bundler/installer/spec_installation_spec.rb deleted file mode 100644 index a9cf09a372..0000000000 --- a/spec/bundler/bundler/installer/spec_installation_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -require "bundler/installer/parallel_installer" - -RSpec.describe Bundler::ParallelInstaller::SpecInstallation do - let!(:dep) do - a_spec = Object.new - def a_spec.name - "I like tests" - end - a_spec - end - - describe "#ready_to_enqueue?" do - context "when in enqueued state" do - it "is falsey" do - spec = described_class.new(dep) - spec.state = :enqueued - expect(spec.ready_to_enqueue?).to be_falsey - end - end - - context "when in installed state" do - it "returns falsey" do - spec = described_class.new(dep) - spec.state = :installed - expect(spec.ready_to_enqueue?).to be_falsey - end - end - - it "returns truthy" do - spec = described_class.new(dep) - expect(spec.ready_to_enqueue?).to be_truthy - end - end - - describe "#dependencies_installed?" do - context "when all dependencies are installed" do - it "returns true" do - dependencies = [] - dependencies << instance_double("SpecInstallation", :spec => "alpha", :name => "alpha", :installed? => true, :all_dependencies => [], :type => :production) - dependencies << instance_double("SpecInstallation", :spec => "beta", :name => "beta", :installed? => true, :all_dependencies => [], :type => :production) - all_specs = dependencies + [instance_double("SpecInstallation", :spec => "gamma", :name => "gamma", :installed? => false, :all_dependencies => [], :type => :production)] - spec = described_class.new(dep) - allow(spec).to receive(:all_dependencies).and_return(dependencies) - expect(spec.dependencies_installed?(all_specs)).to be_truthy - end - end - - context "when all dependencies are not installed" do - it "returns false" do - dependencies = [] - dependencies << instance_double("SpecInstallation", :spec => "alpha", :name => "alpha", :installed? => false, :all_dependencies => [], :type => :production) - dependencies << instance_double("SpecInstallation", :spec => "beta", :name => "beta", :installed? => true, :all_dependencies => [], :type => :production) - all_specs = dependencies + [instance_double("SpecInstallation", :spec => "gamma", :name => "gamma", :installed? => false, :all_dependencies => [], :type => :production)] - spec = described_class.new(dep) - allow(spec).to receive(:all_dependencies).and_return(dependencies) - expect(spec.dependencies_installed?(all_specs)).to be_falsey - end - end - end -end diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb deleted file mode 100644 index 3a6d61336f..0000000000 --- a/spec/bundler/bundler/lockfile_parser_spec.rb +++ /dev/null @@ -1,153 +0,0 @@ -# frozen_string_literal: true - -require "bundler/lockfile_parser" - -RSpec.describe Bundler::LockfileParser do - let(:lockfile_contents) { strip_whitespace(<<-L) } - GIT - remote: https://github.com/alloy/peiji-san.git - revision: eca485d8dc95f12aaec1a434b49d295c7e91844b - specs: - peiji-san (1.2.0) - - GEM - remote: https://rubygems.org/ - specs: - rake (10.3.2) - - PLATFORMS - ruby - - DEPENDENCIES - peiji-san! - rake - - RUBY VERSION - ruby 2.1.3p242 - - BUNDLED WITH - 1.12.0.rc.2 - L - - describe ".sections_in_lockfile" do - it "returns the attributes" do - attributes = described_class.sections_in_lockfile(lockfile_contents) - expect(attributes).to contain_exactly( - "BUNDLED WITH", "DEPENDENCIES", "GEM", "GIT", "PLATFORMS", "RUBY VERSION" - ) - end - end - - describe ".unknown_sections_in_lockfile" do - let(:lockfile_contents) { strip_whitespace(<<-L) } - UNKNOWN ATTR - - UNKNOWN ATTR 2 - random contents - L - - it "returns the unknown attributes" do - attributes = described_class.unknown_sections_in_lockfile(lockfile_contents) - expect(attributes).to contain_exactly("UNKNOWN ATTR", "UNKNOWN ATTR 2") - end - end - - describe ".sections_to_ignore" do - subject { described_class.sections_to_ignore(base_version) } - - context "with a nil base version" do - let(:base_version) { nil } - - it "returns the same as > 1.0" do - expect(subject).to contain_exactly( - described_class::BUNDLED, described_class::RUBY, described_class::PLUGIN - ) - end - end - - context "with a prerelease base version" do - let(:base_version) { Gem::Version.create("1.11.0.rc.1") } - - it "returns the same as for the release version" do - expect(subject).to contain_exactly( - described_class::RUBY, described_class::PLUGIN - ) - end - end - - context "with a current version" do - let(:base_version) { Gem::Version.create(Bundler::VERSION) } - - it "returns an empty array" do - expect(subject).to eq([]) - end - end - - context "with a future version" do - let(:base_version) { Gem::Version.create("5.5.5") } - - it "returns an empty array" do - expect(subject).to eq([]) - end - end - end - - describe "#initialize" do - before { allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app("gems.rb")) } - subject { described_class.new(lockfile_contents) } - - let(:sources) do - [Bundler::Source::Git.new("uri" => "https://github.com/alloy/peiji-san.git", "revision" => "eca485d8dc95f12aaec1a434b49d295c7e91844b"), - Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"])] - end - let(:dependencies) do - { - "peiji-san" => Bundler::Dependency.new("peiji-san", ">= 0"), - "rake" => Bundler::Dependency.new("rake", ">= 0"), - } - end - let(:specs) do - [ - Bundler::LazySpecification.new("peiji-san", v("1.2.0"), rb), - Bundler::LazySpecification.new("rake", v("10.3.2"), rb), - ] - end - let(:platforms) { [rb] } - let(:bundler_version) { Gem::Version.new("1.12.0.rc.2") } - let(:ruby_version) { "ruby 2.1.3p242" } - - shared_examples_for "parsing" do - it "parses correctly" do - expect(subject.sources).to eq sources - expect(subject.dependencies).to eq dependencies - expect(subject.specs).to eq specs - expect(Hash[subject.specs.map {|s| [s, s.dependencies] }]).to eq Hash[subject.specs.map {|s| [s, s.dependencies] }] - expect(subject.platforms).to eq platforms - expect(subject.bundler_version).to eq bundler_version - expect(subject.ruby_version).to eq ruby_version - end - end - - include_examples "parsing" - - context "when an extra section is at the end" do - let(:lockfile_contents) { super() + "\n\nFOO BAR\n baz\n baa\n qux\n" } - include_examples "parsing" - end - - context "when an extra section is at the start" do - let(:lockfile_contents) { "FOO BAR\n baz\n baa\n qux\n\n" + super() } - include_examples "parsing" - end - - context "when an extra section is in the middle" do - let(:lockfile_contents) { super().split(/(?=GEM)/).insert(1, "FOO BAR\n baz\n baa\n qux\n\n").join } - include_examples "parsing" - end - - context "when a dependency has options" do - let(:lockfile_contents) { super().sub("peiji-san!", "peiji-san!\n foo: bar") } - include_examples "parsing" - end - end -end diff --git a/spec/bundler/bundler/mirror_spec.rb b/spec/bundler/bundler/mirror_spec.rb deleted file mode 100644 index 0a8b9f8926..0000000000 --- a/spec/bundler/bundler/mirror_spec.rb +++ /dev/null @@ -1,329 +0,0 @@ -# frozen_string_literal: true - -require "bundler/mirror" - -RSpec.describe Bundler::Settings::Mirror do - let(:mirror) { Bundler::Settings::Mirror.new } - - it "returns zero when fallback_timeout is not set" do - expect(mirror.fallback_timeout).to eq(0) - end - - it "takes a number as a fallback_timeout" do - mirror.fallback_timeout = 1 - expect(mirror.fallback_timeout).to eq(1) - end - - it "takes truthy as a default fallback timeout" do - mirror.fallback_timeout = true - expect(mirror.fallback_timeout).to eq(0.1) - end - - it "takes falsey as a zero fallback timeout" do - mirror.fallback_timeout = false - expect(mirror.fallback_timeout).to eq(0) - end - - it "takes a string with 'true' as a default fallback timeout" do - mirror.fallback_timeout = "true" - expect(mirror.fallback_timeout).to eq(0.1) - end - - it "takes a string with 'false' as a zero fallback timeout" do - mirror.fallback_timeout = "false" - expect(mirror.fallback_timeout).to eq(0) - end - - it "takes a string for the uri but returns an uri object" do - mirror.uri = "http://localhost:9292" - expect(mirror.uri).to eq(URI("http://localhost:9292")) - end - - it "takes an uri object for the uri" do - mirror.uri = URI("http://localhost:9293") - expect(mirror.uri).to eq(URI("http://localhost:9293")) - end - - context "without a uri" do - it "invalidates the mirror" do - mirror.validate! - expect(mirror.valid?).to be_falsey - end - end - - context "with an uri" do - before { mirror.uri = "http://localhost:9292" } - - context "without a fallback timeout" do - it "is not valid by default" do - expect(mirror.valid?).to be_falsey - end - - context "when probed" do - let(:probe) { double } - - context "with a replying mirror" do - before do - allow(probe).to receive(:replies?).and_return(true) - mirror.validate!(probe) - end - - it "is valid" do - expect(mirror.valid?).to be_truthy - end - end - - context "with a non replying mirror" do - before do - allow(probe).to receive(:replies?).and_return(false) - mirror.validate!(probe) - end - - it "is still valid" do - expect(mirror.valid?).to be_truthy - end - end - end - end - - context "with a fallback timeout" do - before { mirror.fallback_timeout = 1 } - - it "is not valid by default" do - expect(mirror.valid?).to be_falsey - end - - context "when probed" do - let(:probe) { double } - - context "with a replying mirror" do - before do - allow(probe).to receive(:replies?).and_return(true) - mirror.validate!(probe) - end - - it "is valid" do - expect(mirror.valid?).to be_truthy - end - - it "is validated only once" do - allow(probe).to receive(:replies?).and_raise("Only once!") - mirror.validate!(probe) - expect(mirror.valid?).to be_truthy - end - end - - context "with a non replying mirror" do - before do - allow(probe).to receive(:replies?).and_return(false) - mirror.validate!(probe) - end - - it "is not valid" do - expect(mirror.valid?).to be_falsey - end - - it "is validated only once" do - allow(probe).to receive(:replies?).and_raise("Only once!") - mirror.validate!(probe) - expect(mirror.valid?).to be_falsey - end - end - end - end - - describe "#==" do - it "returns true if uri and fallback timeout are the same" do - uri = "https://ruby.taobao.org" - mirror = Bundler::Settings::Mirror.new(uri, 1) - another_mirror = Bundler::Settings::Mirror.new(uri, 1) - - expect(mirror == another_mirror).to be true - end - end - end -end - -RSpec.describe Bundler::Settings::Mirrors do - let(:localhost_uri) { URI("http://localhost:9292") } - - context "with a just created mirror" do - let(:mirrors) do - probe = double - allow(probe).to receive(:replies?).and_return(true) - Bundler::Settings::Mirrors.new(probe) - end - - it "returns a mirror that contains the source uri for an unknown uri" do - mirror = mirrors.for("http://rubygems.org/") - expect(mirror).to eq(Bundler::Settings::Mirror.new("http://rubygems.org/")) - end - - it "parses a mirror key and returns a mirror for the parsed uri" do - mirrors.parse("mirror.http://rubygems.org/", localhost_uri) - expect(mirrors.for("http://rubygems.org/").uri).to eq(localhost_uri) - end - - it "parses a relative mirror key and returns a mirror for the parsed http uri" do - mirrors.parse("mirror.rubygems.org", localhost_uri) - expect(mirrors.for("http://rubygems.org/").uri).to eq(localhost_uri) - end - - it "parses a relative mirror key and returns a mirror for the parsed https uri" do - mirrors.parse("mirror.rubygems.org", localhost_uri) - expect(mirrors.for("https://rubygems.org/").uri).to eq(localhost_uri) - end - - context "with a uri parsed already" do - before { mirrors.parse("mirror.http://rubygems.org/", localhost_uri) } - - it "takes a mirror fallback_timeout and assigns the timeout" do - mirrors.parse("mirror.http://rubygems.org.fallback_timeout", "2") - expect(mirrors.for("http://rubygems.org/").fallback_timeout).to eq(2) - end - - it "parses a 'true' fallback timeout and sets the default timeout" do - mirrors.parse("mirror.http://rubygems.org.fallback_timeout", "true") - expect(mirrors.for("http://rubygems.org/").fallback_timeout).to eq(0.1) - end - - it "parses a 'false' fallback timeout and sets it to zero" do - mirrors.parse("mirror.http://rubygems.org.fallback_timeout", "false") - expect(mirrors.for("http://rubygems.org/").fallback_timeout).to eq(0) - end - end - end - - context "with a mirror prober that replies on time" do - let(:mirrors) do - probe = double - allow(probe).to receive(:replies?).and_return(true) - Bundler::Settings::Mirrors.new(probe) - end - - context "with a default fallback_timeout for rubygems.org" do - before do - mirrors.parse("mirror.http://rubygems.org/", localhost_uri) - mirrors.parse("mirror.http://rubygems.org.fallback_timeout", "true") - end - - it "returns localhost" do - expect(mirrors.for("http://rubygems.org").uri).to eq(localhost_uri) - end - end - - context "with a mirror for all" do - before do - mirrors.parse("mirror.all", localhost_uri) - end - - context "without a fallback timeout" do - it "returns localhost uri for rubygems" do - expect(mirrors.for("http://rubygems.org").uri).to eq(localhost_uri) - end - - it "returns localhost for any other url" do - expect(mirrors.for("http://whatever.com/").uri).to eq(localhost_uri) - end - end - context "with a fallback timeout" do - before { mirrors.parse("mirror.all.fallback_timeout", "1") } - - it "returns localhost uri for rubygems" do - expect(mirrors.for("http://rubygems.org").uri).to eq(localhost_uri) - end - - it "returns localhost for any other url" do - expect(mirrors.for("http://whatever.com/").uri).to eq(localhost_uri) - end - end - end - end - - context "with a mirror prober that does not reply on time" do - let(:mirrors) do - probe = double - allow(probe).to receive(:replies?).and_return(false) - Bundler::Settings::Mirrors.new(probe) - end - - context "with a localhost mirror for all" do - before { mirrors.parse("mirror.all", localhost_uri) } - - context "without a fallback timeout" do - it "returns localhost" do - expect(mirrors.for("http://whatever.com").uri).to eq(localhost_uri) - end - end - - context "with a fallback timeout" do - before { mirrors.parse("mirror.all.fallback_timeout", "true") } - - it "returns the source uri, not localhost" do - expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/")) - end - end - end - - context "with localhost as a mirror for rubygems.org" do - before { mirrors.parse("mirror.http://rubygems.org/", localhost_uri) } - - context "without a fallback timeout" do - it "returns the uri that is not mirrored" do - expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/")) - end - - it "returns localhost for rubygems.org" do - expect(mirrors.for("http://rubygems.org/").uri).to eq(localhost_uri) - end - end - - context "with a fallback timeout" do - before { mirrors.parse("mirror.http://rubygems.org/.fallback_timeout", "true") } - - it "returns the uri that is not mirrored" do - expect(mirrors.for("http://whatever.com").uri).to eq(URI("http://whatever.com/")) - end - - it "returns rubygems.org for rubygems.org" do - expect(mirrors.for("http://rubygems.org/").uri).to eq(URI("http://rubygems.org/")) - end - end - end - end -end - -RSpec.describe Bundler::Settings::TCPSocketProbe do - let(:probe) { Bundler::Settings::TCPSocketProbe.new } - - context "with a listening TCP Server" do - def with_server_and_mirror - server = TCPServer.new("127.0.0.1", 0) - mirror = Bundler::Settings::Mirror.new("http://localhost:#{server.addr[1]}", 1) - yield server, mirror - server.close unless server.closed? - end - - it "probes the server correctly" do - with_server_and_mirror do |server, mirror| - expect(server.closed?).to be_falsey - expect(probe.replies?(mirror)).to be_truthy - end - end - - it "probes falsey when the server is down" do - with_server_and_mirror do |server, mirror| - server.close - expect(probe.replies?(mirror)).to be_falsey - end - end - end - - context "with an invalid mirror" do - let(:mirror) { Bundler::Settings::Mirror.new("http://127.0.0.127:9292", true) } - - it "fails with a timeout when there is nothing to tcp handshake" do - expect(probe.replies?(mirror)).to be_falsey - end - end -end diff --git a/spec/bundler/bundler/plugin/api/source_spec.rb b/spec/bundler/bundler/plugin/api/source_spec.rb deleted file mode 100644 index 2c50ff56a4..0000000000 --- a/spec/bundler/bundler/plugin/api/source_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::API::Source do - let(:uri) { "uri://to/test" } - let(:type) { "spec_type" } - - subject(:source) do - klass = Class.new - klass.send :include, Bundler::Plugin::API::Source - klass.new("uri" => uri, "type" => type) - end - - describe "attributes" do - it "allows access to uri" do - expect(source.uri).to eq("uri://to/test") - end - - it "allows access to name" do - expect(source.name).to eq("spec_type at uri://to/test") - end - end - - context "post_install" do - let(:installer) { double(:installer) } - - before do - allow(Bundler::Source::Path::Installer).to receive(:new) { installer } - end - - it "calls Path::Installer's post_install" do - expect(installer).to receive(:post_install).once - - source.post_install(double(:spec)) - end - end - - context "install_path" do - let(:uri) { "uri://to/a/repository-name" } - let(:hash) { Digest(:SHA1).hexdigest(uri) } - let(:install_path) { Pathname.new "/bundler/install/path" } - - before do - allow(Bundler).to receive(:install_path) { install_path } - end - - it "returns basename with uri_hash" do - expected = Pathname.new "#{install_path}/repository-name-#{hash[0..11]}" - expect(source.install_path).to eq(expected) - end - end - - context "to_lock" do - it "returns the string with remote and type" do - expected = strip_whitespace <<-L - PLUGIN SOURCE - remote: #{uri} - type: #{type} - specs: - L - - expect(source.to_lock).to eq(expected) - end - - context "with additional options to lock" do - before do - allow(source).to receive(:options_to_lock) { { "first" => "option" } } - end - - it "includes them" do - expected = strip_whitespace <<-L - PLUGIN SOURCE - remote: #{uri} - type: #{type} - first: option - specs: - L - - expect(source.to_lock).to eq(expected) - end - end - end -end diff --git a/spec/bundler/bundler/plugin/api_spec.rb b/spec/bundler/bundler/plugin/api_spec.rb deleted file mode 100644 index 58fb908572..0000000000 --- a/spec/bundler/bundler/plugin/api_spec.rb +++ /dev/null @@ -1,83 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::API do - context "plugin declarations" do - before do - stub_const "UserPluginClass", Class.new(Bundler::Plugin::API) - end - - describe "#command" do - it "declares a command plugin with same class as handler" do - expect(Bundler::Plugin). - to receive(:add_command).with("meh", UserPluginClass).once - - UserPluginClass.command "meh" - end - - it "accepts another class as argument that handles the command" do - stub_const "NewClass", Class.new - expect(Bundler::Plugin).to receive(:add_command).with("meh", NewClass).once - - UserPluginClass.command "meh", NewClass - end - end - - describe "#source" do - it "declares a source plugin with same class as handler" do - expect(Bundler::Plugin). - to receive(:add_source).with("a_source", UserPluginClass).once - - UserPluginClass.source "a_source" - end - - it "accepts another class as argument that handles the command" do - stub_const "NewClass", Class.new - expect(Bundler::Plugin).to receive(:add_source).with("a_source", NewClass).once - - UserPluginClass.source "a_source", NewClass - end - end - - describe "#hook" do - it "accepts a block and passes it to Plugin module" do - foo = double("tester") - expect(foo).to receive(:called) - - expect(Bundler::Plugin).to receive(:add_hook).with("post-foo").and_yield - - Bundler::Plugin::API.hook("post-foo") { foo.called } - end - end - end - - context "bundler interfaces provided" do - before do - stub_const "UserPluginClass", Class.new(Bundler::Plugin::API) - end - - subject(:api) { UserPluginClass.new } - - # A test of delegation - it "provides the Bundler's functions" do - expect(Bundler).to receive(:an_unknown_function).once - - api.an_unknown_function - end - - it "includes Bundler::SharedHelpers' functions" do - expect(Bundler::SharedHelpers).to receive(:an_unknown_helper).once - - api.an_unknown_helper - end - - context "#tmp" do - it "provides a tmp dir" do - expect(api.tmp("mytmp")).to be_directory - end - - it "accepts multiple names for suffix" do - expect(api.tmp("myplugin", "download")).to be_directory - end - end - end -end diff --git a/spec/bundler/bundler/plugin/dsl_spec.rb b/spec/bundler/bundler/plugin/dsl_spec.rb deleted file mode 100644 index be23db3bba..0000000000 --- a/spec/bundler/bundler/plugin/dsl_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::DSL do - DSL = Bundler::Plugin::DSL - - subject(:dsl) { Bundler::Plugin::DSL.new } - - before do - allow(Bundler).to receive(:root) { Pathname.new "/" } - end - - describe "it ignores only the methods defined in Bundler::Dsl" do - it "doesn't raises error for Dsl methods" do - expect { dsl.install_if }.not_to raise_error - end - - it "raises error for other methods" do - expect { dsl.no_method }.to raise_error(DSL::PluginGemfileError) - end - end - - describe "source block" do - it "adds #source with :type to list and also inferred_plugins list" do - expect(dsl).to receive(:plugin).with("bundler-source-news").once - - dsl.source("some_random_url", :type => "news") {} - - expect(dsl.inferred_plugins).to eq(["bundler-source-news"]) - end - - it "registers a source type plugin only once for multiple declataions" do - expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once - - dsl.source("some_random_url", :type => "news") {} - dsl.source("another_random_url", :type => "news") {} - end - end -end diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb deleted file mode 100644 index 163b563b2a..0000000000 --- a/spec/bundler/bundler/plugin/index_spec.rb +++ /dev/null @@ -1,178 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::Index do - Index = Bundler::Plugin::Index - - before do - gemfile "" - path = lib_path(plugin_name) - index.register_plugin("new-plugin", path.to_s, [path.join("lib").to_s], commands, sources, hooks) - end - - let(:plugin_name) { "new-plugin" } - let(:commands) { [] } - let(:sources) { [] } - let(:hooks) { [] } - - subject(:index) { Index.new } - - describe "#register plugin" do - it "is available for retrieval" do - expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name)) - end - - it "load_paths is available for retrival" do - expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s]) - end - - it "is persistent" do - new_index = Index.new - expect(new_index.plugin_path(plugin_name)).to eq(lib_path(plugin_name)) - end - - it "load_paths are persistent" do - new_index = Index.new - expect(new_index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s]) - end - end - - describe "commands" do - let(:commands) { ["newco"] } - - it "returns the plugins name on query" do - expect(index.command_plugin("newco")).to eq(plugin_name) - end - - it "raises error on conflict" do - expect do - index.register_plugin("aplugin", lib_path("aplugin").to_s, lib_path("aplugin").join("lib").to_s, ["newco"], [], []) - end.to raise_error(Index::CommandConflict) - end - - it "is persistent" do - new_index = Index.new - expect(new_index.command_plugin("newco")).to eq(plugin_name) - end - end - - describe "source" do - let(:sources) { ["new_source"] } - - it "returns the plugins name on query" do - expect(index.source_plugin("new_source")).to eq(plugin_name) - end - - it "raises error on conflict" do - expect do - index.register_plugin("aplugin", lib_path("aplugin").to_s, lib_path("aplugin").join("lib").to_s, [], ["new_source"], []) - end.to raise_error(Index::SourceConflict) - end - - it "is persistent" do - new_index = Index.new - expect(new_index.source_plugin("new_source")).to eq(plugin_name) - end - end - - describe "hook" do - let(:hooks) { ["after-bar"] } - - it "returns the plugins name on query" do - expect(index.hook_plugins("after-bar")).to include(plugin_name) - end - - it "is persistent" do - new_index = Index.new - expect(new_index.hook_plugins("after-bar")).to eq([plugin_name]) - end - - context "that are not registered", :focused do - let(:file) { double("index-file") } - - before do - index.hook_plugins("not-there") - allow(File).to receive(:open).and_yield(file) - end - - it "should not save it with next registered hook" do - expect(file).to receive(:puts) do |content| - expect(content).not_to include("not-there") - end - - index.register_plugin("aplugin", lib_path("aplugin").to_s, lib_path("aplugin").join("lib").to_s, [], [], []) - end - end - end - - describe "global index" do - before do - Dir.chdir(tmp) do - Bundler::Plugin.reset! - path = lib_path("gplugin") - index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], []) - end - end - - it "skips sources" do - new_index = Index.new - expect(new_index.source_plugin("glb_source")).to be_falsy - end - end - - describe "after conflict" do - let(:commands) { ["foo"] } - let(:sources) { ["bar"] } - let(:hooks) { ["hoook"] } - - shared_examples "it cleans up" do - it "the path" do - expect(index.installed?("cplugin")).to be_falsy - end - - it "the command" do - expect(index.command_plugin("xfoo")).to be_falsy - end - - it "the source" do - expect(index.source_plugin("xbar")).to be_falsy - end - - it "the hook" do - expect(index.hook_plugins("xhoook")).to be_empty - end - end - - context "on command conflict it cleans up" do - before do - expect do - path = lib_path("cplugin") - index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["xbar"], ["xhoook"]) - end.to raise_error(Index::CommandConflict) - end - - include_examples "it cleans up" - end - - context "on source conflict it cleans up" do - before do - expect do - path = lib_path("cplugin") - index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["xfoo"], ["bar"], ["xhoook"]) - end.to raise_error(Index::SourceConflict) - end - - include_examples "it cleans up" - end - - context "on command and source conflict it cleans up" do - before do - expect do - path = lib_path("cplugin") - index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["bar"], ["xhoook"]) - end.to raise_error(Index::CommandConflict) - end - - include_examples "it cleans up" - end - end -end diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb deleted file mode 100644 index f8bf8450c9..0000000000 --- a/spec/bundler/bundler/plugin/installer_spec.rb +++ /dev/null @@ -1,104 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::Installer do - subject(:installer) { Bundler::Plugin::Installer.new } - - before do - # allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(Pathname.new("/Gemfile")) - end - - describe "cli install" do - it "uses Gem.sources when non of the source is provided" do - sources = double(:sources) - Bundler.settings # initialize it before we have to touch rubygems.ext_lock - allow(Bundler).to receive_message_chain("rubygems.sources") { sources } - - allow(installer).to receive(:install_rubygems). - with("new-plugin", [">= 0"], sources).once - - installer.install("new-plugin", {}) - end - - describe "with mocked installers" do - let(:spec) { double(:spec) } - it "returns the installed spec after installing git plugins" do - allow(installer).to receive(:install_git). - and_return("new-plugin" => spec) - - expect(installer.install(["new-plugin"], :git => "https://some.ran/dom")). - to eq("new-plugin" => spec) - end - - it "returns the installed spec after installing rubygems plugins" do - allow(installer).to receive(:install_rubygems). - and_return("new-plugin" => spec) - - expect(installer.install(["new-plugin"], :source => "https://some.ran/dom")). - to eq("new-plugin" => spec) - end - end - - describe "with actual installers" do - before do - build_repo2 do - build_plugin "re-plugin" - build_plugin "ma-plugin" - end - end - - context "git plugins" do - before do - build_git "ga-plugin", :path => lib_path("ga-plugin") do |s| - s.write "plugins.rb" - end - end - - let(:result) do - installer.install(["ga-plugin"], :git => "file://#{lib_path("ga-plugin")}") - end - - it "returns the installed spec after installing" do - spec = result["ga-plugin"] - expect(spec.full_name).to eq "ga-plugin-1.0" - end - - it "has expected full gem path" do - rev = revision_for(lib_path("ga-plugin")) - expect(result["ga-plugin"].full_gem_path). - to eq(Bundler::Plugin.root.join("bundler", "gems", "ga-plugin-#{rev[0..11]}").to_s) - end - end - - context "rubygems plugins" do - let(:result) do - installer.install(["re-plugin"], :source => "file://#{gem_repo2}") - end - - it "returns the installed spec after installing " do - expect(result["re-plugin"]).to be_kind_of(Bundler::RemoteSpecification) - end - - it "has expected full_gem)path" do - expect(result["re-plugin"].full_gem_path). - to eq(global_plugin_gem("re-plugin-1.0").to_s) - end - end - - context "multiple plugins" do - let(:result) do - installer.install(["re-plugin", "ma-plugin"], :source => "file://#{gem_repo2}") - end - - it "returns the installed spec after installing " do - expect(result["re-plugin"]).to be_kind_of(Bundler::RemoteSpecification) - expect(result["ma-plugin"]).to be_kind_of(Bundler::RemoteSpecification) - end - - it "has expected full_gem)path" do - expect(result["re-plugin"].full_gem_path).to eq(global_plugin_gem("re-plugin-1.0").to_s) - expect(result["ma-plugin"].full_gem_path).to eq(global_plugin_gem("ma-plugin-1.0").to_s) - end - end - end - end -end diff --git a/spec/bundler/bundler/plugin/source_list_spec.rb b/spec/bundler/bundler/plugin/source_list_spec.rb deleted file mode 100644 index 64a1233dd1..0000000000 --- a/spec/bundler/bundler/plugin/source_list_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin::SourceList do - SourceList = Bundler::Plugin::SourceList - - before do - allow(Bundler).to receive(:root) { Pathname.new "/" } - end - - subject(:source_list) { SourceList.new } - - describe "adding sources uses classes for plugin" do - it "uses Plugin::Installer::Rubygems for rubygems sources" do - source = source_list. - add_rubygems_source("remotes" => ["https://existing-rubygems.org"]) - expect(source).to be_instance_of(Bundler::Plugin::Installer::Rubygems) - end - - it "uses Plugin::Installer::Git for git sources" do - source = source_list. - add_git_source("uri" => "git://existing-git.org/path.git") - expect(source).to be_instance_of(Bundler::Plugin::Installer::Git) - end - end -end diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb deleted file mode 100644 index 9796b580a3..0000000000 --- a/spec/bundler/bundler/plugin_spec.rb +++ /dev/null @@ -1,291 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Plugin do - Plugin = Bundler::Plugin - - let(:installer) { double(:installer) } - let(:index) { double(:index) } - let(:spec) { double(:spec) } - let(:spec2) { double(:spec2) } - - before do - build_lib "new-plugin", :path => lib_path("new-plugin") do |s| - s.write "plugins.rb" - end - - build_lib "another-plugin", :path => lib_path("another-plugin") do |s| - s.write "plugins.rb" - end - - allow(spec).to receive(:full_gem_path). - and_return(lib_path("new-plugin").to_s) - allow(spec).to receive(:load_paths). - and_return([lib_path("new-plugin").join("lib").to_s]) - - allow(spec2).to receive(:full_gem_path). - and_return(lib_path("another-plugin").to_s) - allow(spec2).to receive(:load_paths). - and_return([lib_path("another-plugin").join("lib").to_s]) - - allow(Plugin::Installer).to receive(:new) { installer } - allow(Plugin).to receive(:index) { index } - allow(index).to receive(:register_plugin) - end - - describe "install command" do - let(:opts) { { "version" => "~> 1.0", "source" => "foo" } } - - before do - allow(installer).to receive(:install).with(["new-plugin"], opts) do - { "new-plugin" => spec } - end - end - - it "passes the name and options to installer" do - allow(installer).to receive(:install).with(["new-plugin"], opts) do - { "new-plugin" => spec } - end.once - - subject.install ["new-plugin"], opts - end - - it "validates the installed plugin" do - allow(subject). - to receive(:validate_plugin!).with(lib_path("new-plugin")).once - - subject.install ["new-plugin"], opts - end - - it "registers the plugin with index" do - allow(index).to receive(:register_plugin). - with("new-plugin", lib_path("new-plugin").to_s, [lib_path("new-plugin").join("lib").to_s], []).once - subject.install ["new-plugin"], opts - end - - context "multiple plugins" do - it do - allow(installer).to receive(:install). - with(["new-plugin", "another-plugin"], opts) do - { - "new-plugin" => spec, - "another-plugin" => spec2, - } - end.once - - allow(subject).to receive(:validate_plugin!).twice - allow(index).to receive(:register_plugin).twice - subject.install ["new-plugin", "another-plugin"], opts - end - end - end - - describe "evaluate gemfile for plugins" do - let(:definition) { double("definition") } - let(:builder) { double("builder") } - let(:gemfile) { bundled_app("Gemfile") } - - before do - allow(Plugin::DSL).to receive(:new) { builder } - allow(builder).to receive(:eval_gemfile).with(gemfile) - allow(builder).to receive(:to_definition) { definition } - allow(builder).to receive(:inferred_plugins) { [] } - end - - it "doesn't calls installer without any plugins" do - allow(definition).to receive(:dependencies) { [] } - allow(installer).to receive(:install_definition).never - - subject.gemfile_install(gemfile) - end - - context "with dependencies" do - let(:plugin_specs) do - { - "new-plugin" => spec, - "another-plugin" => spec2, - } - end - - before do - allow(index).to receive(:installed?) { nil } - allow(definition).to receive(:dependencies) { [Bundler::Dependency.new("new-plugin", ">=0"), Bundler::Dependency.new("another-plugin", ">=0")] } - allow(installer).to receive(:install_definition) { plugin_specs } - end - - it "should validate and register the plugins" do - expect(subject).to receive(:validate_plugin!).twice - expect(subject).to receive(:register_plugin).twice - - subject.gemfile_install(gemfile) - end - - it "should pass the optional plugins to #register_plugin" do - allow(builder).to receive(:inferred_plugins) { ["another-plugin"] } - - expect(subject).to receive(:register_plugin). - with("new-plugin", spec, false).once - - expect(subject).to receive(:register_plugin). - with("another-plugin", spec2, true).once - - subject.gemfile_install(gemfile) - end - end - end - - describe "#command?" do - it "returns true value for commands in index" do - allow(index). - to receive(:command_plugin).with("newcommand") { "my-plugin" } - result = subject.command? "newcommand" - expect(result).to be_truthy - end - - it "returns false value for commands not in index" do - allow(index).to receive(:command_plugin).with("newcommand") { nil } - result = subject.command? "newcommand" - expect(result).to be_falsy - end - end - - describe "#exec_command" do - it "raises UndefinedCommandError when command is not found" do - allow(index).to receive(:command_plugin).with("newcommand") { nil } - expect { subject.exec_command("newcommand", []) }. - to raise_error(Plugin::UndefinedCommandError) - end - end - - describe "#source?" do - it "returns true value for sources in index" do - allow(index). - to receive(:command_plugin).with("foo-source") { "my-plugin" } - result = subject.command? "foo-source" - expect(result).to be_truthy - end - - it "returns false value for source not in index" do - allow(index).to receive(:command_plugin).with("foo-source") { nil } - result = subject.command? "foo-source" - expect(result).to be_falsy - end - end - - describe "#source" do - it "raises UnknownSourceError when source is not found" do - allow(index).to receive(:source_plugin).with("bar") { nil } - expect { subject.source("bar") }. - to raise_error(Plugin::UnknownSourceError) - end - - it "loads the plugin, if not loaded" do - allow(index).to receive(:source_plugin).with("foo-bar") { "plugin_name" } - - expect(subject).to receive(:load_plugin).with("plugin_name") - subject.source("foo-bar") - end - - it "returns the class registered with #add_source" do - allow(index).to receive(:source_plugin).with("foo") { "plugin_name" } - stub_const "NewClass", Class.new - - subject.add_source("foo", NewClass) - expect(subject.source("foo")).to be(NewClass) - end - end - - describe "#source_from_lock" do - it "returns instance of registered class initialized with locked opts" do - opts = { "type" => "l_source", "remote" => "xyz", "other" => "random" } - allow(index).to receive(:source_plugin).with("l_source") { "plugin_name" } - - stub_const "SClass", Class.new - s_instance = double(:s_instance) - subject.add_source("l_source", SClass) - - expect(SClass).to receive(:new). - with(hash_including("type" => "l_source", "uri" => "xyz", "other" => "random")) { s_instance } - expect(subject.source_from_lock(opts)).to be(s_instance) - end - end - - describe "#root" do - context "in app dir" do - before do - gemfile "" - end - - it "returns plugin dir in app .bundle path" do - expect(subject.root).to eq(bundled_app.join(".bundle/plugin")) - end - end - - context "outside app dir" do - it "returns plugin dir in global bundle path" do - Dir.chdir tmp - expect(subject.root).to eq(home.join(".bundle/plugin")) - end - end - end - - describe "#hook" do - before do - path = lib_path("foo-plugin") - build_lib "foo-plugin", :path => path do |s| - s.write "plugins.rb", code - end - - allow(index).to receive(:hook_plugins).with(event). - and_return(["foo-plugin"]) - allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path) - allow(index).to receive(:load_paths).with("foo-plugin").and_return([]) - end - - let(:code) { <<-RUBY } - Bundler::Plugin::API.hook("event-1") { puts "hook for event 1" } - RUBY - - let(:event) { "event-1" } - - it "executes the hook" do - out = capture(:stdout) do - Plugin.hook("event-1") - end.strip - - expect(out).to eq("hook for event 1") - end - - context "single plugin declaring more than one hook" do - let(:code) { <<-RUBY } - Bundler::Plugin::API.hook("event-1") {} - Bundler::Plugin::API.hook("event-2") {} - puts "loaded" - RUBY - - let(:event) { /event-1|event-2/ } - - it "evals plugins.rb once" do - out = capture(:stdout) do - Plugin.hook("event-1") - Plugin.hook("event-2") - end.strip - - expect(out).to eq("loaded") - end - end - - context "a block is passed" do - let(:code) { <<-RUBY } - Bundler::Plugin::API.hook("#{event}") { |&blk| blk.call } - RUBY - - it "is passed to the hook" do - out = capture(:stdout) do - Plugin.hook("event-1") { puts "win" } - end.strip - - expect(out).to eq("win") - end - end - end -end diff --git a/spec/bundler/bundler/psyched_yaml_spec.rb b/spec/bundler/bundler/psyched_yaml_spec.rb deleted file mode 100644 index d5d68c5cc3..0000000000 --- a/spec/bundler/bundler/psyched_yaml_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -require "bundler/psyched_yaml" - -RSpec.describe "Bundler::YamlLibrarySyntaxError" do - it "is raised on YAML parse errors" do - expect { YAML.parse "{foo" }.to raise_error(Bundler::YamlLibrarySyntaxError) - end -end diff --git a/spec/bundler/bundler/remote_specification_spec.rb b/spec/bundler/bundler/remote_specification_spec.rb deleted file mode 100644 index 8115e026d8..0000000000 --- a/spec/bundler/bundler/remote_specification_spec.rb +++ /dev/null @@ -1,187 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::RemoteSpecification do - let(:name) { "foo" } - let(:version) { Gem::Version.new("1.0.0") } - let(:platform) { Gem::Platform::RUBY } - let(:spec_fetcher) { double(:spec_fetcher) } - - subject { described_class.new(name, version, platform, spec_fetcher) } - - it "is Comparable" do - expect(described_class.ancestors).to include(Comparable) - end - - it "can match platforms" do - expect(described_class.ancestors).to include(Bundler::MatchPlatform) - end - - describe "#fetch_platform" do - let(:remote_spec) { double(:remote_spec, :platform => "jruby") } - - before { allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec) } - - it "should return the spec platform" do - expect(subject.fetch_platform).to eq("jruby") - end - end - - describe "#full_name" do - context "when platform is ruby" do - it "should return the spec name and version" do - expect(subject.full_name).to eq("foo-1.0.0") - end - end - - context "when platform is nil" do - let(:platform) { nil } - - it "should return the spec name and version" do - expect(subject.full_name).to eq("foo-1.0.0") - end - end - - context "when platform is a non-ruby platform" do - let(:platform) { "jruby" } - - it "should return the spec name, version, and platform" do - expect(subject.full_name).to eq("foo-1.0.0-jruby") - end - end - end - - describe "#<=>" do - let(:other_name) { name } - let(:other_version) { version } - let(:other_platform) { platform } - let(:other_spec_fetcher) { spec_fetcher } - - shared_examples_for "a comparison" do - context "which exactly matches" do - it "returns 0" do - expect(subject <=> other).to eq(0) - end - end - - context "which is different by name" do - let(:other_name) { "a" } - it "returns 1" do - expect(subject <=> other).to eq(1) - end - end - - context "which has a lower version" do - let(:other_version) { Gem::Version.new("0.9.0") } - it "returns 1" do - expect(subject <=> other).to eq(1) - end - end - - context "which has a higher version" do - let(:other_version) { Gem::Version.new("1.1.0") } - it "returns -1" do - expect(subject <=> other).to eq(-1) - end - end - - context "which has a different platform" do - let(:other_platform) { Gem::Platform.new("x86-mswin32") } - it "returns -1" do - expect(subject <=> other).to eq(-1) - end - end - end - - context "comparing another Bundler::RemoteSpecification" do - let(:other) do - Bundler::RemoteSpecification.new(other_name, other_version, - other_platform, nil) - end - - it_should_behave_like "a comparison" - end - - context "comparing a Gem::Specification" do - let(:other) do - Gem::Specification.new(other_name, other_version).tap do |s| - s.platform = other_platform - end - end - - it_should_behave_like "a comparison" - end - - context "comparing a non sortable object" do - let(:other) { Object.new } - let(:remote_spec) { double(:remote_spec, :platform => "jruby") } - - before do - allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec) - allow(remote_spec).to receive(:<=>).and_return(nil) - end - - it "should use default object comparison" do - expect(subject <=> other).to eq(nil) - end - end - end - - describe "#__swap__" do - let(:spec) { double(:spec, :dependencies => []) } - let(:new_spec) { double(:new_spec, :dependencies => [], :runtime_dependencies => []) } - - before { subject.instance_variable_set(:@_remote_specification, spec) } - - it "should replace remote specification with the passed spec" do - expect(subject.instance_variable_get(:@_remote_specification)).to be(spec) - subject.__swap__(new_spec) - expect(subject.instance_variable_get(:@_remote_specification)).to be(new_spec) - end - end - - describe "#sort_obj" do - context "when platform is ruby" do - it "should return a sorting delegate array with name, version, and -1" do - expect(subject.sort_obj).to match_array(["foo", version, -1]) - end - end - - context "when platform is not ruby" do - let(:platform) { "jruby" } - - it "should return a sorting delegate array with name, version, and 1" do - expect(subject.sort_obj).to match_array(["foo", version, 1]) - end - end - end - - describe "method missing" do - context "and is present in Gem::Specification" do - let(:remote_spec) { double(:remote_spec, :authors => "abcd") } - - before do - allow(subject).to receive(:_remote_specification).and_return(remote_spec) - expect(subject.methods.map(&:to_sym)).not_to include(:authors) - end - - it "should send through to Gem::Specification" do - expect(subject.authors).to eq("abcd") - end - end - end - - describe "respond to missing?" do - context "and is present in Gem::Specification" do - let(:remote_spec) { double(:remote_spec, :authors => "abcd") } - - before do - allow(subject).to receive(:_remote_specification).and_return(remote_spec) - expect(subject.methods.map(&:to_sym)).not_to include(:authors) - end - - it "should send through to Gem::Specification" do - expect(subject.respond_to?(:authors)).to be_truthy - end - end - end -end diff --git a/spec/bundler/bundler/retry_spec.rb b/spec/bundler/bundler/retry_spec.rb deleted file mode 100644 index b893580d72..0000000000 --- a/spec/bundler/bundler/retry_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Retry do - it "return successful result if no errors" do - attempts = 0 - result = Bundler::Retry.new(nil, nil, 3).attempt do - attempts += 1 - :success - end - expect(result).to eq(:success) - expect(attempts).to eq(1) - end - - it "returns the first valid result" do - jobs = [proc { raise "foo" }, proc { :bar }, proc { raise "foo" }] - attempts = 0 - result = Bundler::Retry.new(nil, nil, 3).attempt do - attempts += 1 - jobs.shift.call - end - expect(result).to eq(:bar) - expect(attempts).to eq(2) - end - - it "raises the last error" do - errors = [StandardError, StandardError, StandardError, Bundler::GemfileNotFound] - attempts = 0 - expect do - Bundler::Retry.new(nil, nil, 3).attempt do - attempts += 1 - raise errors.shift - end - end.to raise_error(Bundler::GemfileNotFound) - expect(attempts).to eq(4) - end - - it "raises exceptions" do - error = Bundler::GemfileNotFound - attempts = 0 - expect do - Bundler::Retry.new(nil, error).attempt do - attempts += 1 - raise error - end - end.to raise_error(error) - expect(attempts).to eq(1) - end - - context "logging" do - let(:error) { Bundler::GemfileNotFound } - let(:failure_message) { "Retrying test due to error (2/2): #{error} #{error}" } - - context "with debugging on" do - it "print error message with newline" do - allow(Bundler.ui).to receive(:debug?).and_return(true) - expect(Bundler.ui).to_not receive(:info) - expect(Bundler.ui).to receive(:warn).with(failure_message, true) - - expect do - Bundler::Retry.new("test", [], 1).attempt do - raise error - end - end.to raise_error(error) - end - end - - context "with debugging off" do - it "print error message with newlines" do - allow(Bundler.ui).to receive(:debug?).and_return(false) - expect(Bundler.ui).to receive(:info).with("").twice - expect(Bundler.ui).to receive(:warn).with(failure_message, false) - - expect do - Bundler::Retry.new("test", [], 1).attempt do - raise error - end - end.to raise_error(error) - end - end - end -end diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb deleted file mode 100644 index bc1ca98457..0000000000 --- a/spec/bundler/bundler/ruby_dsl_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ -# frozen_string_literal: true - -require "bundler/ruby_dsl" - -RSpec.describe Bundler::RubyDsl do - class MockDSL - include Bundler::RubyDsl - - attr_reader :ruby_version - end - - let(:dsl) { MockDSL.new } - let(:ruby_version) { "2.0.0" } - let(:version) { "2.0.0" } - let(:engine) { "jruby" } - let(:engine_version) { "9000" } - let(:patchlevel) { "100" } - let(:options) do - { :patchlevel => patchlevel, - :engine => engine, - :engine_version => engine_version } - end - - let(:invoke) do - proc do - args = Array(ruby_version) + [options] - dsl.ruby(*args) - end - end - - subject do - invoke.call - dsl.ruby_version - end - - describe "#ruby_version" do - shared_examples_for "it stores the ruby version" do - it "stores the version" do - expect(subject.versions).to eq(Array(ruby_version)) - expect(subject.gem_version.version).to eq(version) - end - - it "stores the engine details" do - expect(subject.engine).to eq(engine) - expect(subject.engine_versions).to eq(Array(engine_version)) - end - - it "stores the patchlevel" do - expect(subject.patchlevel).to eq(patchlevel) - end - end - - context "with a plain version" do - it_behaves_like "it stores the ruby version" - end - - context "with a single requirement" do - let(:ruby_version) { ">= 2.0.0" } - it_behaves_like "it stores the ruby version" - end - - context "with two requirements in the same string" do - let(:ruby_version) { ">= 2.0.0, < 3.0" } - it "raises an error" do - expect { subject }.to raise_error(ArgumentError) - end - end - - context "with two requirements" do - let(:ruby_version) { ["~> 2.0.0", "> 2.0.1"] } - it_behaves_like "it stores the ruby version" - end - - context "with multiple engine versions" do - let(:engine_version) { ["> 200", "< 300"] } - it_behaves_like "it stores the ruby version" - end - - context "with no options hash" do - let(:invoke) { proc { dsl.ruby(ruby_version) } } - - let(:patchlevel) { nil } - let(:engine) { "ruby" } - let(:engine_version) { version } - - it_behaves_like "it stores the ruby version" - - context "and with multiple requirements" do - let(:ruby_version) { ["~> 2.0.0", "> 2.0.1"] } - let(:engine_version) { ruby_version } - it_behaves_like "it stores the ruby version" - end - end - end -end diff --git a/spec/bundler/bundler/ruby_version_spec.rb b/spec/bundler/bundler/ruby_version_spec.rb deleted file mode 100644 index 3f30821b5c..0000000000 --- a/spec/bundler/bundler/ruby_version_spec.rb +++ /dev/null @@ -1,524 +0,0 @@ -# frozen_string_literal: true - -require "bundler/ruby_version" - -RSpec.describe "Bundler::RubyVersion and its subclasses" do - let(:version) { "2.0.0" } - let(:patchlevel) { "645" } - let(:engine) { "jruby" } - let(:engine_version) { "2.0.1" } - - describe Bundler::RubyVersion do - subject { Bundler::RubyVersion.new(version, patchlevel, engine, engine_version) } - - let(:ruby_version) { subject } - let(:other_version) { version } - let(:other_patchlevel) { patchlevel } - let(:other_engine) { engine } - let(:other_engine_version) { engine_version } - let(:other_ruby_version) { Bundler::RubyVersion.new(other_version, other_patchlevel, other_engine, other_engine_version) } - - describe "#initialize" do - context "no engine is passed" do - let(:engine) { nil } - - it "should set ruby as the engine" do - expect(subject.engine).to eq("ruby") - end - end - - context "no engine_version is passed" do - let(:engine_version) { nil } - - it "should set engine version as the passed version" do - expect(subject.engine_versions).to eq(["2.0.0"]) - end - end - - context "with engine in symbol" do - let(:engine) { :jruby } - - it "should coerce engine to string" do - expect(subject.engine).to eq("jruby") - end - end - - context "is called with multiple requirements" do - let(:version) { ["<= 2.0.0", "> 1.9.3"] } - let(:engine_version) { nil } - - it "sets the versions" do - expect(subject.versions).to eq(version) - end - - it "sets the engine versions" do - expect(subject.engine_versions).to eq(version) - end - end - - context "is called with multiple engine requirements" do - let(:engine_version) { [">= 2.0", "< 2.3"] } - - it "sets the engine versions" do - expect(subject.engine_versions).to eq(engine_version) - end - end - end - - describe ".from_string" do - shared_examples_for "returning" do - it "returns the original RubyVersion" do - expect(described_class.from_string(subject.to_s)).to eq(subject) - end - end - - include_examples "returning" - - context "no patchlevel" do - let(:patchlevel) { nil } - - include_examples "returning" - end - - context "engine is ruby" do - let(:engine) { "ruby" } - let(:engine_version) { version } - - include_examples "returning" - end - - context "with multiple requirements" do - let(:engine_version) { ["> 9", "< 11"] } - let(:version) { ["> 8", "< 10"] } - let(:patchlevel) { nil } - - it "returns nil" do - expect(described_class.from_string(subject.to_s)).to be_nil - end - end - end - - describe "#to_s" do - it "should return info string with the ruby version, patchlevel, engine, and engine version" do - expect(subject.to_s).to eq("ruby 2.0.0p645 (jruby 2.0.1)") - end - - context "no patchlevel" do - let(:patchlevel) { nil } - - it "should return info string with the version, engine, and engine version" do - expect(subject.to_s).to eq("ruby 2.0.0 (jruby 2.0.1)") - end - end - - context "engine is ruby" do - let(:engine) { "ruby" } - - it "should return info string with the ruby version and patchlevel" do - expect(subject.to_s).to eq("ruby 2.0.0p645") - end - end - - context "with multiple requirements" do - let(:engine_version) { ["> 9", "< 11"] } - let(:version) { ["> 8", "< 10"] } - let(:patchlevel) { nil } - - it "should return info string with all requirements" do - expect(subject.to_s).to eq("ruby > 8, < 10 (jruby > 9, < 11)") - end - end - end - - describe "#==" do - shared_examples_for "two ruby versions are not equal" do - it "should return false" do - expect(subject).to_not eq(other_ruby_version) - end - end - - context "the versions, pathlevels, engines, and engine_versions match" do - it "should return true" do - expect(subject).to eq(other_ruby_version) - end - end - - context "the versions do not match" do - let(:other_version) { "1.21.6" } - - it_behaves_like "two ruby versions are not equal" - end - - context "the patchlevels do not match" do - let(:other_patchlevel) { "21" } - - it_behaves_like "two ruby versions are not equal" - end - - context "the engines do not match" do - let(:other_engine) { "ruby" } - - it_behaves_like "two ruby versions are not equal" - end - - context "the engine versions do not match" do - let(:other_engine_version) { "1.11.2" } - - it_behaves_like "two ruby versions are not equal" - end - end - - describe "#host" do - before do - allow(RbConfig::CONFIG).to receive(:[]).with("host_cpu").and_return("x86_64") - allow(RbConfig::CONFIG).to receive(:[]).with("host_vendor").and_return("apple") - allow(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("darwin14.5.0") - end - - it "should return an info string with the host cpu, vendor, and os" do - expect(subject.host).to eq("x86_64-apple-darwin14.5.0") - end - - it "memoizes the info string with the host cpu, vendor, and os" do - expect(RbConfig::CONFIG).to receive(:[]).with("host_cpu").once.and_call_original - expect(RbConfig::CONFIG).to receive(:[]).with("host_vendor").once.and_call_original - expect(RbConfig::CONFIG).to receive(:[]).with("host_os").once.and_call_original - 2.times { ruby_version.host } - end - end - - describe "#gem_version" do - let(:gem_version) { "2.0.0" } - let(:gem_version_obj) { Gem::Version.new(gem_version) } - - shared_examples_for "it parses the version from the requirement string" do |version| - let(:version) { version } - it "should return the underlying version" do - expect(ruby_version.gem_version).to eq(gem_version_obj) - expect(ruby_version.gem_version.version).to eq(gem_version) - end - end - - it_behaves_like "it parses the version from the requirement string", "2.0.0" - it_behaves_like "it parses the version from the requirement string", ">= 2.0.0" - it_behaves_like "it parses the version from the requirement string", "~> 2.0.0" - it_behaves_like "it parses the version from the requirement string", "< 2.0.0" - it_behaves_like "it parses the version from the requirement string", "= 2.0.0" - it_behaves_like "it parses the version from the requirement string", ["> 2.0.0", "< 2.4.5"] - end - - describe "#diff" do - let(:engine) { "ruby" } - - shared_examples_for "there is a difference in the engines" do - it "should return a tuple with :engine and the two different engines" do - expect(ruby_version.diff(other_ruby_version)).to eq([:engine, engine, other_engine]) - end - end - - shared_examples_for "there is a difference in the versions" do - it "should return a tuple with :version and the two different versions" do - expect(ruby_version.diff(other_ruby_version)).to eq([:version, Array(version).join(", "), Array(other_version).join(", ")]) - end - end - - shared_examples_for "there is a difference in the engine versions" do - it "should return a tuple with :engine_version and the two different engine versions" do - expect(ruby_version.diff(other_ruby_version)).to eq([:engine_version, Array(engine_version).join(", "), Array(other_engine_version).join(", ")]) - end - end - - shared_examples_for "there is a difference in the patchlevels" do - it "should return a tuple with :patchlevel and the two different patchlevels" do - expect(ruby_version.diff(other_ruby_version)).to eq([:patchlevel, patchlevel, other_patchlevel]) - end - end - - shared_examples_for "there are no differences" do - it "should return nil" do - expect(ruby_version.diff(other_ruby_version)).to be_nil - end - end - - context "all things match exactly" do - it_behaves_like "there are no differences" - end - - context "detects engine discrepancies first" do - let(:other_version) { "2.0.1" } - let(:other_patchlevel) { "643" } - let(:other_engine) { "rbx" } - let(:other_engine_version) { "2.0.0" } - - it_behaves_like "there is a difference in the engines" - end - - context "detects version discrepancies second" do - let(:other_version) { "2.0.1" } - let(:other_patchlevel) { "643" } - let(:other_engine_version) { "2.0.0" } - - it_behaves_like "there is a difference in the versions" - end - - context "detects version discrepancies with multiple requirements second" do - let(:other_version) { "2.0.1" } - let(:other_patchlevel) { "643" } - let(:other_engine_version) { "2.0.0" } - - let(:version) { ["> 2.0.0", "< 1.0.0"] } - - it_behaves_like "there is a difference in the versions" - end - - context "detects engine version discrepancies third" do - let(:other_patchlevel) { "643" } - let(:other_engine_version) { "2.0.0" } - - it_behaves_like "there is a difference in the engine versions" - end - - context "detects engine version discrepancies with multiple requirements third" do - let(:other_patchlevel) { "643" } - let(:other_engine_version) { "2.0.0" } - - let(:engine_version) { ["> 2.0.0", "< 1.0.0"] } - - it_behaves_like "there is a difference in the engine versions" - end - - context "detects patchlevel discrepancies last" do - let(:other_patchlevel) { "643" } - - it_behaves_like "there is a difference in the patchlevels" - end - - context "successfully matches gem requirements" do - let(:version) { ">= 2.0.0" } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { "2.0.0" } - let(:other_patchlevel) { "642" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.0.5" } - - it_behaves_like "there are no differences" - end - - context "successfully matches multiple gem requirements" do - let(:version) { [">= 2.0.0", "< 2.4.5"] } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { ["~> 2.0.1", "< 2.4.5"] } - let(:other_version) { "2.0.0" } - let(:other_patchlevel) { "642" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.0.5" } - - it_behaves_like "there are no differences" - end - - context "successfully detects bad gem requirements with versions with multiple requirements" do - let(:version) { ["~> 2.0.0", "< 2.0.5"] } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { "2.0.5" } - let(:other_patchlevel) { "642" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.0.5" } - - it_behaves_like "there is a difference in the versions" - end - - context "successfully detects bad gem requirements with versions" do - let(:version) { "~> 2.0.0" } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { "2.1.0" } - let(:other_patchlevel) { "642" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.0.5" } - - it_behaves_like "there is a difference in the versions" - end - - context "successfully detects bad gem requirements with patchlevels" do - let(:version) { ">= 2.0.0" } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { "2.0.0" } - let(:other_patchlevel) { "645" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.0.5" } - - it_behaves_like "there is a difference in the patchlevels" - end - - context "successfully detects bad gem requirements with engine versions" do - let(:version) { ">= 2.0.0" } - let(:patchlevel) { "< 643" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { "2.0.0" } - let(:other_patchlevel) { "642" } - let(:other_engine) { "ruby" } - let(:other_engine_version) { "2.1.0" } - - it_behaves_like "there is a difference in the engine versions" - end - - context "with a patchlevel of -1" do - let(:version) { ">= 2.0.0" } - let(:patchlevel) { "-1" } - let(:engine) { "ruby" } - let(:engine_version) { "~> 2.0.1" } - let(:other_version) { version } - let(:other_engine) { engine } - let(:other_engine_version) { engine_version } - - context "and comparing with another patchlevel of -1" do - let(:other_patchlevel) { patchlevel } - - it_behaves_like "there are no differences" - end - - context "and comparing with a patchlevel that is not -1" do - let(:other_patchlevel) { "642" } - - it_behaves_like "there is a difference in the patchlevels" - end - end - end - - describe "#system" do - subject { Bundler::RubyVersion.system } - - let(:bundler_system_ruby_version) { subject } - - before do - Bundler::RubyVersion.instance_variable_set("@ruby_version", nil) - end - - it "should return an instance of Bundler::RubyVersion" do - expect(subject).to be_kind_of(Bundler::RubyVersion) - end - - it "memoizes the instance of Bundler::RubyVersion" do - expect(Bundler::RubyVersion).to receive(:new).once.and_call_original - 2.times { subject } - end - - describe "#version" do - it "should return a copy of the value of RUBY_VERSION" do - expect(subject.versions).to eq([RUBY_VERSION]) - expect(subject.versions.first).to_not be(RUBY_VERSION) - end - end - - describe "#engine" do - context "RUBY_ENGINE is defined" do - before { stub_const("RUBY_ENGINE", "jruby") } - before { stub_const("JRUBY_VERSION", "2.1.1") } - - it "should return a copy of the value of RUBY_ENGINE" do - expect(subject.engine).to eq("jruby") - expect(subject.engine).to_not be(RUBY_ENGINE) - end - end - - context "RUBY_ENGINE is not defined" do - before { stub_const("RUBY_ENGINE", nil) } - - it "should return the string 'ruby'" do - expect(subject.engine).to eq("ruby") - end - end - end - - describe "#engine_version" do - context "engine is ruby" do - before do - stub_const("RUBY_VERSION", "2.2.4") - allow(Bundler).to receive(:ruby_engine).and_return("ruby") - end - - it "should return a copy of the value of RUBY_VERSION" do - expect(bundler_system_ruby_version.engine_versions).to eq(["2.2.4"]) - expect(bundler_system_ruby_version.engine_versions.first).to_not be(RUBY_VERSION) - end - end - - context "engine is rbx" do - before do - stub_const("RUBY_ENGINE", "rbx") - stub_const("Rubinius::VERSION", "2.0.0") - end - - it "should return a copy of the value of Rubinius::VERSION" do - expect(bundler_system_ruby_version.engine_versions).to eq(["2.0.0"]) - expect(bundler_system_ruby_version.engine_versions.first).to_not be(Rubinius::VERSION) - end - end - - context "engine is jruby" do - before do - stub_const("RUBY_ENGINE", "jruby") - stub_const("JRUBY_VERSION", "2.1.1") - end - - it "should return a copy of the value of JRUBY_VERSION" do - expect(subject.engine_versions).to eq(["2.1.1"]) - expect(bundler_system_ruby_version.engine_versions.first).to_not be(JRUBY_VERSION) - end - end - - context "engine is some other ruby engine" do - before do - stub_const("RUBY_ENGINE", "not_supported_ruby_engine") - allow(Bundler).to receive(:ruby_engine).and_return("not_supported_ruby_engine") - end - - it "should raise a BundlerError with a 'not recognized' message" do - expect { bundler_system_ruby_version.engine_versions }.to raise_error(Bundler::BundlerError, "RUBY_ENGINE value not_supported_ruby_engine is not recognized") - end - end - end - - describe "#patchlevel" do - it "should return a string with the value of RUBY_PATCHLEVEL" do - expect(subject.patchlevel).to eq(RUBY_PATCHLEVEL.to_s) - end - end - end - - describe "#to_gem_version_with_patchlevel" do - shared_examples_for "the patchlevel is omitted" do - it "does not include a patch level" do - expect(subject.to_gem_version_with_patchlevel.to_s).to eq(version) - end - end - - context "with nil patch number" do - let(:patchlevel) { nil } - - it_behaves_like "the patchlevel is omitted" - end - - context "with negative patch number" do - let(:patchlevel) { -1 } - - it_behaves_like "the patchlevel is omitted" - end - - context "with a valid patch number" do - it "uses the specified patchlevel as patchlevel" do - expect(subject.to_gem_version_with_patchlevel.to_s).to eq("#{version}.#{patchlevel}") - end - end - end - end -end diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb deleted file mode 100644 index b1b15d9e5d..0000000000 --- a/spec/bundler/bundler/rubygems_integration_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::RubygemsIntegration do - it "uses the same chdir lock as rubygems", :rubygems => "2.1" do - expect(Bundler.rubygems.ext_lock).to eq(Gem::Ext::Builder::CHDIR_MONITOR) - end - - context "#validate" do - let(:spec) do - Gem::Specification.new do |s| - s.name = "to-validate" - s.version = "1.0.0" - s.loaded_from = __FILE__ - end - end - subject { Bundler.rubygems.validate(spec) } - - it "skips overly-strict gemspec validation", :rubygems => "< 1.7" do - expect(spec).to_not receive(:validate) - subject - end - - it "validates with packaging mode disabled", :rubygems => "1.7" do - expect(spec).to receive(:validate).with(false) - subject - end - - it "should set a summary to avoid an overly-strict error", :rubygems => "~> 1.7.0" do - spec.summary = nil - expect { subject }.not_to raise_error - expect(spec.summary).to eq("") - end - - context "with an invalid spec" do - before do - expect(spec).to receive(:validate).with(false). - and_raise(Gem::InvalidSpecificationException.new("TODO is not an author")) - end - - it "should raise a Gem::InvalidSpecificationException and produce a helpful warning message", - :rubygems => "1.7" do - expect { subject }.to raise_error(Gem::InvalidSpecificationException, - "The gemspec at #{__FILE__} is not valid. "\ - "Please fix this gemspec.\nThe validation error was 'TODO is not an author'\n") - end - end - end - - describe "#configuration" do - it "handles Gem::SystemExitException errors" do - allow(Gem).to receive(:configuration) { raise Gem::SystemExitException.new(1) } - expect { Bundler.rubygems.configuration }.to raise_error(Gem::SystemExitException) - end - end - - describe "#download_gem", :rubygems => ">= 2.0" do - let(:bundler_retry) { double(Bundler::Retry) } - let(:retry) { double("Bundler::Retry") } - let(:uri) { URI.parse("https://foo.bar") } - let(:path) { Gem.path.first } - let(:spec) do - spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"), - Gem::Platform::RUBY, nil) - spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s) - spec - end - let(:fetcher) { double("gem_remote_fetcher") } - - it "successfully downloads gem with retries" do - expect(Bundler.rubygems).to receive(:gem_remote_fetcher).and_return(fetcher) - expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "https://foo.bar") - expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/"). - and_return(bundler_retry) - expect(bundler_retry).to receive(:attempts).and_yield - expect(fetcher).to receive(:download).with(spec, uri, path) - - Bundler.rubygems.download_gem(spec, uri, path) - end - end - - describe "#fetch_all_remote_specs", :rubygems => ">= 2.0" do - let(:uri) { URI("https://example.com") } - let(:fetcher) { double("gem_remote_fetcher") } - let(:specs_response) { Marshal.dump(["specs"]) } - let(:prerelease_specs_response) { Marshal.dump(["prerelease_specs"]) } - - context "when a rubygems source mirror is set" do - let(:orig_uri) { URI("http://zombo.com") } - let(:remote_with_mirror) { double("remote", :uri => uri, :original_uri => orig_uri) } - - it "sets the 'X-Gemfile-Source' header containing the original source" do - expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher) - expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "http://zombo.com").twice - expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response) - expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response) - result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror) - expect(result).to eq(%w[specs prerelease_specs]) - end - end - - context "when there is no rubygems source mirror set" do - let(:remote_no_mirror) { double("remote", :uri => uri, :original_uri => nil) } - - it "does not set the 'X-Gemfile-Source' header" do - expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher) - expect(fetcher).to_not receive(:headers=) - expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response) - expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response) - result = Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror) - expect(result).to eq(%w[specs prerelease_specs]) - end - end - end -end diff --git a/spec/bundler/bundler/settings/validator_spec.rb b/spec/bundler/bundler/settings/validator_spec.rb deleted file mode 100644 index e4ffd89435..0000000000 --- a/spec/bundler/bundler/settings/validator_spec.rb +++ /dev/null @@ -1,111 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Settings::Validator do - describe ".validate!" do - def validate!(key, value, settings) - transformed_key = Bundler.settings.key_for(key) - if value.nil? - settings.delete(transformed_key) - else - settings[transformed_key] = value - end - described_class.validate!(key, value, settings) - settings - end - - it "path and path.system are mutually exclusive" do - expect(validate!("path", "bundle", {})).to eq("BUNDLE_PATH" => "bundle") - expect(validate!("path", "bundle", "BUNDLE_PATH__SYSTEM" => false)).to eq("BUNDLE_PATH" => "bundle") - expect(validate!("path", "bundle", "BUNDLE_PATH__SYSTEM" => true)).to eq("BUNDLE_PATH" => "bundle") - expect(validate!("path", nil, "BUNDLE_PATH__SYSTEM" => true)).to eq("BUNDLE_PATH__SYSTEM" => true) - expect(validate!("path", nil, "BUNDLE_PATH__SYSTEM" => false)).to eq("BUNDLE_PATH__SYSTEM" => false) - expect(validate!("path", nil, {})).to eq({}) - - expect(validate!("path.system", true, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH__SYSTEM" => true) - expect(validate!("path.system", false, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH" => "bundle", "BUNDLE_PATH__SYSTEM" => false) - expect(validate!("path.system", nil, "BUNDLE_PATH" => "bundle")).to eq("BUNDLE_PATH" => "bundle") - expect(validate!("path.system", true, {})).to eq("BUNDLE_PATH__SYSTEM" => true) - expect(validate!("path.system", false, {})).to eq("BUNDLE_PATH__SYSTEM" => false) - expect(validate!("path.system", nil, {})).to eq({}) - end - - it "a group cannot be in both `with` & `without` simultaneously" do - expect do - validate!("with", "", {}) - validate!("with", nil, {}) - validate!("with", "", "BUNDLE_WITHOUT" => "a") - validate!("with", nil, "BUNDLE_WITHOUT" => "a") - validate!("with", "b:c", "BUNDLE_WITHOUT" => "a") - - validate!("without", "", {}) - validate!("without", nil, {}) - validate!("without", "", "BUNDLE_WITH" => "a") - validate!("without", nil, "BUNDLE_WITH" => "a") - validate!("without", "b:c", "BUNDLE_WITH" => "a") - end.not_to raise_error - - expect { validate!("with", "b:c", "BUNDLE_WITHOUT" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip - Setting `with` to "b:c" failed: - - a group cannot be in both `with` & `without` simultaneously - - `without` is current set to [:c, :d] - - the `c` groups conflict - EOS - - expect { validate!("without", "b:c", "BUNDLE_WITH" => "c:d") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip - Setting `without` to "b:c" failed: - - a group cannot be in both `with` & `without` simultaneously - - `with` is current set to [:c, :d] - - the `c` groups conflict - EOS - end - end - - describe described_class::Rule do - let(:keys) { %w[key] } - let(:description) { "rule description" } - let(:validate) { proc { raise "validate called!" } } - subject(:rule) { described_class.new(keys, description, &validate) } - - describe "#validate!" do - it "calls the block" do - expect { rule.validate!("key", nil, {}) }.to raise_error(RuntimeError, /validate called!/) - end - end - - describe "#fail!" do - it "raises with a helpful message" do - expect { subject.fail!("key", "value", "reason1", "reason2") }.to raise_error Bundler::InvalidOption, strip_whitespace(<<-EOS).strip - Setting `key` to "value" failed: - - rule description - - reason1 - - reason2 - EOS - end - end - - describe "#set" do - it "works when the value has not changed" do - allow(Bundler.ui).to receive(:info).never - - subject.set({}, "key", nil) - subject.set({ "BUNDLE_KEY" => "value" }, "key", "value") - end - - it "prints out when the value is changing" do - settings = {} - - expect(Bundler.ui).to receive(:info).with("Setting `key` to \"value\", since rule description, reason1") - subject.set(settings, "key", "value", "reason1") - expect(settings).to eq("BUNDLE_KEY" => "value") - - expect(Bundler.ui).to receive(:info).with("Setting `key` to \"value2\", since rule description, reason2") - subject.set(settings, "key", "value2", "reason2") - expect(settings).to eq("BUNDLE_KEY" => "value2") - - expect(Bundler.ui).to receive(:info).with("Setting `key` to nil, since rule description, reason3") - subject.set(settings, "key", nil, "reason3") - expect(settings).to eq({}) - end - end - end -end diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb deleted file mode 100644 index 1a31493e20..0000000000 --- a/spec/bundler/bundler/settings_spec.rb +++ /dev/null @@ -1,326 +0,0 @@ -# frozen_string_literal: true - -require "bundler/settings" - -RSpec.describe Bundler::Settings do - subject(:settings) { described_class.new(bundled_app) } - - describe "#set_local" do - context "when the local config file is not found" do - subject(:settings) { described_class.new(nil) } - - it "raises a GemfileNotFound error with explanation" do - expect { subject.set_local("foo", "bar") }. - to raise_error(Bundler::GemfileNotFound, "Could not locate Gemfile") - end - end - end - - describe "load_config" do - let(:hash) do - { - "build.thrift" => "--with-cppflags=-D_FORTIFY_SOURCE=0", - "build.libv8" => "--with-system-v8", - "build.therubyracer" => "--with-v8-dir", - "build.pg" => "--with-pg-config=/usr/local/Cellar/postgresql92/9.2.8_1/bin/pg_config", - "gem.coc" => "false", - "gem.mit" => "false", - "gem.test" => "minitest", - "thingy" => <<-EOS.tr("\n", " "), ---asdf --fdsa --ty=oh man i hope this doesnt break bundler because -that would suck --ehhh=oh geez it looks like i might have broken bundler somehow ---very-important-option=DontDeleteRoo ---very-important-option=DontDeleteRoo ---very-important-option=DontDeleteRoo ---very-important-option=DontDeleteRoo - EOS - "xyz" => "zyx", - } - end - - before do - hash.each do |key, value| - settings.set_local key, value - end - end - - it "can load the config" do - loaded = settings.send(:load_config, bundled_app("config")) - expected = Hash[hash.map do |k, v| - [settings.send(:key_for, k), v.to_s] - end] - expect(loaded).to eq(expected) - end - - context "when BUNDLE_IGNORE_CONFIG is set" do - before { ENV["BUNDLE_IGNORE_CONFIG"] = "TRUE" } - - it "ignores the config" do - loaded = settings.send(:load_config, bundled_app("config")) - expect(loaded).to eq({}) - end - end - end - - describe "#global_config_file" do - context "when $HOME is not accessible" do - context "when $TMPDIR is not writable" do - it "does not raise" do - expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil) - expect(FileUtils).to receive(:mkpath).twice.with(File.join(Dir.tmpdir, "bundler", "home")).and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler") - - expect(subject.send(:global_config_file)).to be_nil - end - end - end - end - - describe "#[]" do - context "when the local config file is not found" do - subject(:settings) { described_class.new } - - it "does not raise" do - expect do - subject["foo"] - end.not_to raise_error - end - end - - context "when not set" do - context "when default value present" do - it "retrieves value" do - expect(settings[:retry]).to be 3 - end - end - - it "returns nil" do - expect(settings[:buttermilk]).to be nil - end - end - - context "when is boolean" do - it "returns a boolean" do - settings.set_local :frozen, "true" - expect(settings[:frozen]).to be true - end - context "when specific gem is configured" do - it "returns a boolean" do - settings.set_local "ignore_messages.foobar", "true" - expect(settings["ignore_messages.foobar"]).to be true - end - end - end - - context "when is number" do - it "returns a number" do - settings.set_local :ssl_verify_mode, "1" - expect(settings[:ssl_verify_mode]).to be 1 - end - end - - context "when it's not possible to write to the file" do - it "raises an PermissionError with explanation" do - expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:local_config_file).dirname). - and_raise(Errno::EACCES) - expect { settings.set_local :frozen, "1" }. - to raise_error(Bundler::PermissionError, /config/) - end - end - end - - describe "#temporary" do - it "reset after used" do - Bundler.settings.set_local :no_install, true - - Bundler.settings.temporary(:no_install => false) do - expect(Bundler.settings[:no_install]).to eq false - end - - expect(Bundler.settings[:no_install]).to eq true - end - - it "returns the return value of the block" do - ret = Bundler.settings.temporary({}) { :ret } - expect(ret).to eq :ret - end - - context "when called without a block" do - it "leaves the setting changed" do - Bundler.settings.temporary(:foo => :random) - expect(Bundler.settings[:foo]).to eq "random" - end - - it "returns nil" do - expect(Bundler.settings.temporary(:foo => :bar)).to be_nil - end - end - end - - describe "#set_global" do - context "when it's not possible to write to the file" do - it "raises an PermissionError with explanation" do - expect(bundler_fileutils).to receive(:mkdir_p).with(settings.send(:global_config_file).dirname). - and_raise(Errno::EACCES) - expect { settings.set_global(:frozen, "1") }. - to raise_error(Bundler::PermissionError, %r{\.bundle/config}) - end - end - end - - describe "#pretty_values_for" do - it "prints the converted value rather than the raw string" do - bool_key = described_class::BOOL_KEYS.first - settings.set_local(bool_key, "false") - expect(subject.pretty_values_for(bool_key)).to eq [ - "Set for your local app (#{bundled_app("config")}): false", - ] - end - end - - describe "#mirror_for" do - let(:uri) { URI("https://rubygems.org/") } - - context "with no configured mirror" do - it "returns the original URI" do - expect(settings.mirror_for(uri)).to eq(uri) - end - - it "converts a string parameter to a URI" do - expect(settings.mirror_for("https://rubygems.org/")).to eq(uri) - end - end - - context "with a configured mirror" do - let(:mirror_uri) { URI("https://rubygems-mirror.org/") } - - before { settings.set_local "mirror.https://rubygems.org/", mirror_uri.to_s } - - it "returns the mirror URI" do - expect(settings.mirror_for(uri)).to eq(mirror_uri) - end - - it "converts a string parameter to a URI" do - expect(settings.mirror_for("https://rubygems.org/")).to eq(mirror_uri) - end - - it "normalizes the URI" do - expect(settings.mirror_for("https://rubygems.org")).to eq(mirror_uri) - end - - it "is case insensitive" do - expect(settings.mirror_for("HTTPS://RUBYGEMS.ORG/")).to eq(mirror_uri) - end - - context "with a file URI" do - let(:mirror_uri) { URI("file:/foo/BAR/baz/qUx/") } - - it "returns the mirror URI" do - expect(settings.mirror_for(uri)).to eq(mirror_uri) - end - - it "converts a string parameter to a URI" do - expect(settings.mirror_for("file:/foo/BAR/baz/qUx/")).to eq(mirror_uri) - end - - it "normalizes the URI" do - expect(settings.mirror_for("file:/foo/BAR/baz/qUx")).to eq(mirror_uri) - end - end - end - end - - describe "#credentials_for" do - let(:uri) { URI("https://gemserver.example.org/") } - let(:credentials) { "username:password" } - - context "with no configured credentials" do - it "returns nil" do - expect(settings.credentials_for(uri)).to be_nil - end - end - - context "with credentials configured by URL" do - before { settings.set_local "https://gemserver.example.org/", credentials } - - it "returns the configured credentials" do - expect(settings.credentials_for(uri)).to eq(credentials) - end - end - - context "with credentials configured by hostname" do - before { settings.set_local "gemserver.example.org", credentials } - - it "returns the configured credentials" do - expect(settings.credentials_for(uri)).to eq(credentials) - end - end - end - - describe "URI normalization" do - it "normalizes HTTP URIs in credentials configuration" do - settings.set_local "http://gemserver.example.org", "username:password" - expect(settings.all).to include("http://gemserver.example.org/") - end - - it "normalizes HTTPS URIs in credentials configuration" do - settings.set_local "https://gemserver.example.org", "username:password" - expect(settings.all).to include("https://gemserver.example.org/") - end - - it "normalizes HTTP URIs in mirror configuration" do - settings.set_local "mirror.http://rubygems.org", "http://rubygems-mirror.org" - expect(settings.all).to include("mirror.http://rubygems.org/") - end - - it "normalizes HTTPS URIs in mirror configuration" do - settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org" - expect(settings.all).to include("mirror.https://rubygems.org/") - end - - it "does not normalize other config keys that happen to contain 'http'" do - settings.set_local "local.httparty", home("httparty") - expect(settings.all).to include("local.httparty") - end - - it "does not normalize other config keys that happen to contain 'https'" do - settings.set_local "local.httpsmarty", home("httpsmarty") - expect(settings.all).to include("local.httpsmarty") - end - - it "reads older keys without trailing slashes" do - settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org" - expect(settings.mirror_for("https://rubygems.org/")).to eq( - URI("http://rubygems-mirror.org/") - ) - end - - it "normalizes URIs with a fallback_timeout option" do - settings.set_local "mirror.https://rubygems.org/.fallback_timeout", "true" - expect(settings.all).to include("mirror.https://rubygems.org/.fallback_timeout") - end - - it "normalizes URIs with a fallback_timeout option without a trailing slash" do - settings.set_local "mirror.https://rubygems.org.fallback_timeout", "true" - expect(settings.all).to include("mirror.https://rubygems.org/.fallback_timeout") - end - end - - describe "BUNDLE_ keys format" do - let(:settings) { described_class.new(bundled_app(".bundle")) } - - it "converts older keys without double dashes" do - config("BUNDLE_MY__PERSONAL.RACK" => "~/Work/git/rack") - expect(settings["my.personal.rack"]).to eq("~/Work/git/rack") - end - - it "converts older keys without trailing slashes and double dashes" do - config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://rubygems-mirror.org") - expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") - end - - it "reads newer keys format properly" do - config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org") - expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org") - end - end -end diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb deleted file mode 100644 index b8f099d5ba..0000000000 --- a/spec/bundler/bundler/shared_helpers_spec.rb +++ /dev/null @@ -1,493 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::SharedHelpers do - let(:ext_lock_double) { double(:ext_lock) } - - before do - allow(Bundler.rubygems).to receive(:ext_lock).and_return(ext_lock_double) - allow(ext_lock_double).to receive(:synchronize) {|&block| block.call } - end - - subject { Bundler::SharedHelpers } - - describe "#default_gemfile" do - before { ENV["BUNDLE_GEMFILE"] = "/path/Gemfile" } - - context "Gemfile is present" do - let(:expected_gemfile_path) { Pathname.new("/path/Gemfile") } - - it "returns the Gemfile path" do - expect(subject.default_gemfile).to eq(expected_gemfile_path) - end - end - - context "Gemfile is not present" do - before { ENV["BUNDLE_GEMFILE"] = nil } - - it "raises a GemfileNotFound error" do - expect { subject.default_gemfile }.to raise_error( - Bundler::GemfileNotFound, "Could not locate Gemfile" - ) - end - end - - context "Gemfile is not an absolute path" do - before { ENV["BUNDLE_GEMFILE"] = "Gemfile" } - - let(:expected_gemfile_path) { Pathname.new("Gemfile").expand_path } - - it "returns the Gemfile path" do - expect(subject.default_gemfile).to eq(expected_gemfile_path) - end - end - end - - describe "#default_lockfile" do - context "gemfile is gems.rb" do - let(:gemfile_path) { Pathname.new("/path/gems.rb") } - let(:expected_lockfile_path) { Pathname.new("/path/gems.locked") } - - before { allow(subject).to receive(:default_gemfile).and_return(gemfile_path) } - - it "returns the gems.locked path" do - expect(subject.default_lockfile).to eq(expected_lockfile_path) - end - end - - context "is a regular Gemfile" do - let(:gemfile_path) { Pathname.new("/path/Gemfile") } - let(:expected_lockfile_path) { Pathname.new("/path/Gemfile.lock") } - - before { allow(subject).to receive(:default_gemfile).and_return(gemfile_path) } - - it "returns the lock file path" do - expect(subject.default_lockfile).to eq(expected_lockfile_path) - end - end - end - - describe "#default_bundle_dir" do - context ".bundle does not exist" do - it "returns nil" do - expect(subject.default_bundle_dir).to be_nil - end - end - - context ".bundle is global .bundle" do - let(:global_rubygems_dir) { Pathname.new("#{bundled_app}") } - - before do - Dir.mkdir ".bundle" - allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir) - end - - it "returns nil" do - expect(subject.default_bundle_dir).to be_nil - end - end - - context ".bundle is not global .bundle" do - let(:global_rubygems_dir) { Pathname.new("/path/rubygems") } - let(:expected_bundle_dir_path) { Pathname.new("#{bundled_app}/.bundle") } - - before do - Dir.mkdir ".bundle" - allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir) - end - - it "returns the .bundle path" do - expect(subject.default_bundle_dir).to eq(expected_bundle_dir_path) - end - end - end - - describe "#in_bundle?" do - it "calls the find_gemfile method" do - expect(subject).to receive(:find_gemfile) - subject.in_bundle? - end - - shared_examples_for "correctly determines whether to return a Gemfile path" do - context "currently in directory with a Gemfile" do - before { File.new("Gemfile", "w") } - - it "returns path of the bundle Gemfile" do - expect(subject.in_bundle?).to eq("#{bundled_app}/Gemfile") - end - end - - context "currently in directory without a Gemfile" do - it "returns nil" do - expect(subject.in_bundle?).to be_nil - end - end - end - - context "ENV['BUNDLE_GEMFILE'] set" do - before { ENV["BUNDLE_GEMFILE"] = "/path/Gemfile" } - - it "returns ENV['BUNDLE_GEMFILE']" do - expect(subject.in_bundle?).to eq("/path/Gemfile") - end - end - - context "ENV['BUNDLE_GEMFILE'] not set" do - before { ENV["BUNDLE_GEMFILE"] = nil } - - it_behaves_like "correctly determines whether to return a Gemfile path" - end - - context "ENV['BUNDLE_GEMFILE'] is blank" do - before { ENV["BUNDLE_GEMFILE"] = "" } - - it_behaves_like "correctly determines whether to return a Gemfile path" - end - end - - describe "#chdir" do - let(:op_block) { proc { Dir.mkdir "nested_dir" } } - - before { Dir.mkdir "chdir_test_dir" } - - it "executes the passed block while in the specified directory" do - subject.chdir("chdir_test_dir", &op_block) - expect(Pathname.new("chdir_test_dir/nested_dir")).to exist - end - end - - describe "#pwd" do - it "returns the current absolute path" do - expect(subject.pwd).to eq(bundled_app) - end - end - - describe "#with_clean_git_env" do - let(:with_clean_git_env_block) { proc { Dir.mkdir "with_clean_git_env_test_dir" } } - - before do - ENV["GIT_DIR"] = "ORIGINAL_ENV_GIT_DIR" - ENV["GIT_WORK_TREE"] = "ORIGINAL_ENV_GIT_WORK_TREE" - end - - it "executes the passed block" do - subject.with_clean_git_env(&with_clean_git_env_block) - expect(Pathname.new("with_clean_git_env_test_dir")).to exist - end - - context "when a block is passed" do - let(:with_clean_git_env_block) do - proc do - Dir.mkdir "git_dir_test_dir" unless ENV["GIT_DIR"].nil? - Dir.mkdir "git_work_tree_test_dir" unless ENV["GIT_WORK_TREE"].nil? - end end - - it "uses a fresh git env for execution" do - subject.with_clean_git_env(&with_clean_git_env_block) - expect(Pathname.new("git_dir_test_dir")).to_not exist - expect(Pathname.new("git_work_tree_test_dir")).to_not exist - end - end - - context "passed block does not throw errors" do - let(:with_clean_git_env_block) do - proc do - ENV["GIT_DIR"] = "NEW_ENV_GIT_DIR" - ENV["GIT_WORK_TREE"] = "NEW_ENV_GIT_WORK_TREE" - end end - - it "restores the git env after" do - subject.with_clean_git_env(&with_clean_git_env_block) - expect(ENV["GIT_DIR"]).to eq("ORIGINAL_ENV_GIT_DIR") - expect(ENV["GIT_WORK_TREE"]).to eq("ORIGINAL_ENV_GIT_WORK_TREE") - end - end - - context "passed block throws errors" do - let(:with_clean_git_env_block) do - proc do - ENV["GIT_DIR"] = "NEW_ENV_GIT_DIR" - ENV["GIT_WORK_TREE"] = "NEW_ENV_GIT_WORK_TREE" - raise RuntimeError.new - end end - - it "restores the git env after" do - expect { subject.with_clean_git_env(&with_clean_git_env_block) }.to raise_error(RuntimeError) - expect(ENV["GIT_DIR"]).to eq("ORIGINAL_ENV_GIT_DIR") - expect(ENV["GIT_WORK_TREE"]).to eq("ORIGINAL_ENV_GIT_WORK_TREE") - end - end - end - - describe "#set_bundle_environment" do - before do - ENV["BUNDLE_GEMFILE"] = "Gemfile" - end - - shared_examples_for "ENV['PATH'] gets set correctly" do - before { Dir.mkdir ".bundle" } - - it "ensures bundle bin path is in ENV['PATH']" do - subject.set_bundle_environment - paths = ENV["PATH"].split(File::PATH_SEPARATOR) - expect(paths).to include("#{Bundler.bundle_path}/bin") - end - end - - shared_examples_for "ENV['RUBYOPT'] gets set correctly" do - it "ensures -rbundler/setup is at the beginning of ENV['RUBYOPT']" do - subject.set_bundle_environment - expect(ENV["RUBYOPT"].split(" ")).to start_with("-rbundler/setup") - end - end - - shared_examples_for "ENV['RUBYLIB'] gets set correctly" do - let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } - - before do - allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(ruby_lib_path) - end - - it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do - subject.set_bundle_environment - paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR) - expect(paths).to include(ruby_lib_path) - end - end - - it "calls the appropriate set methods" do - expect(subject).to receive(:set_path) - expect(subject).to receive(:set_rubyopt) - expect(subject).to receive(:set_rubylib) - subject.set_bundle_environment - end - - it "exits if bundle path contains the unix-like path separator" do - if Gem.respond_to?(:path_separator) - allow(Gem).to receive(:path_separator).and_return(":") - else - stub_const("File::PATH_SEPARATOR", ":".freeze) - end - allow(Bundler).to receive(:bundle_path) { Pathname.new("so:me/dir/bin") } - expect { subject.send(:validate_bundle_path) }.to raise_error( - Bundler::PathError, - "Your bundle path contains text matching \":\", which is the " \ - "path separator for your system. Bundler cannot " \ - "function correctly when the Bundle path contains the " \ - "system's PATH separator. Please change your " \ - "bundle path to not match \":\".\nYour current bundle " \ - "path is '#{Bundler.bundle_path}'." - ) - end - - context "with a jruby path_separator regex", :ruby => "1.9" do - # In versions of jruby that supported ruby 1.8, the path separator was the standard File::PATH_SEPARATOR - let(:regex) { Regexp.new("(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):") } - it "does not exit if bundle path is the standard uri path" do - allow(Bundler.rubygems).to receive(:path_separator).and_return(regex) - allow(Bundler).to receive(:bundle_path) { Pathname.new("uri:classloader:/WEB-INF/gems") } - expect { subject.send(:validate_bundle_path) }.not_to raise_error - end - - it "exits if bundle path contains another directory" do - allow(Bundler.rubygems).to receive(:path_separator).and_return(regex) - allow(Bundler).to receive(:bundle_path) { - Pathname.new("uri:classloader:/WEB-INF/gems:other/dir") - } - - expect { subject.send(:validate_bundle_path) }.to raise_error( - Bundler::PathError, - "Your bundle path contains text matching " \ - "/(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):/, which is the " \ - "path separator for your system. Bundler cannot " \ - "function correctly when the Bundle path contains the " \ - "system's PATH separator. Please change your " \ - "bundle path to not match " \ - "/(?<!jar:file|jar|file|classpath|uri:classloader|uri|http|https):/." \ - "\nYour current bundle path is '#{Bundler.bundle_path}'." - ) - end - end - - context "ENV['PATH'] does not exist" do - before { ENV.delete("PATH") } - - it_behaves_like "ENV['PATH'] gets set correctly" - end - - context "ENV['PATH'] is empty" do - before { ENV["PATH"] = "" } - - it_behaves_like "ENV['PATH'] gets set correctly" - end - - context "ENV['PATH'] exists" do - before { ENV["PATH"] = "/some_path/bin" } - - it_behaves_like "ENV['PATH'] gets set correctly" - end - - context "ENV['PATH'] already contains the bundle bin path" do - let(:bundle_path) { "#{Bundler.bundle_path}/bin" } - - before do - ENV["PATH"] = bundle_path - end - - it_behaves_like "ENV['PATH'] gets set correctly" - - it "ENV['PATH'] should only contain one instance of bundle bin path" do - subject.set_bundle_environment - paths = (ENV["PATH"]).split(File::PATH_SEPARATOR) - expect(paths.count(bundle_path)).to eq(1) - end - end - - context "ENV['RUBYOPT'] does not exist" do - before { ENV.delete("RUBYOPT") } - - it_behaves_like "ENV['RUBYOPT'] gets set correctly" - end - - context "ENV['RUBYOPT'] exists without -rbundler/setup" do - before { ENV["RUBYOPT"] = "-I/some_app_path/lib" } - - it_behaves_like "ENV['RUBYOPT'] gets set correctly" - end - - context "ENV['RUBYOPT'] exists and contains -rbundler/setup" do - before { ENV["RUBYOPT"] = "-rbundler/setup" } - - it_behaves_like "ENV['RUBYOPT'] gets set correctly" - end - - context "ENV['RUBYLIB'] does not exist" do - before { ENV.delete("RUBYLIB") } - - it_behaves_like "ENV['RUBYLIB'] gets set correctly" - end - - context "ENV['RUBYLIB'] is empty" do - before { ENV["PATH"] = "" } - - it_behaves_like "ENV['RUBYLIB'] gets set correctly" - end - - context "ENV['RUBYLIB'] exists" do - before { ENV["PATH"] = "/some_path/bin" } - - it_behaves_like "ENV['RUBYLIB'] gets set correctly" - end - - context "ENV['RUBYLIB'] already contains the bundler's ruby version lib path" do - let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } - - before do - ENV["RUBYLIB"] = ruby_lib_path - end - - it_behaves_like "ENV['RUBYLIB'] gets set correctly" - - it "ENV['RUBYLIB'] should only contain one instance of bundler's ruby version lib path" do - subject.set_bundle_environment - paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR) - expect(paths.count(ruby_lib_path)).to eq(1) - end - end - end - - describe "#filesystem_access" do - context "system has proper permission access" do - let(:file_op_block) { proc {|path| FileUtils.mkdir_p(path) } } - - it "performs the operation in the passed block" do - subject.filesystem_access("./test_dir", &file_op_block) - expect(Pathname.new("test_dir")).to exist - end - end - - context "system throws Errno::EACESS" do - let(:file_op_block) { proc {|_path| raise Errno::EACCES } } - - it "raises a PermissionError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::PermissionError - ) - end - end - - context "system throws Errno::EAGAIN" do - let(:file_op_block) { proc {|_path| raise Errno::EAGAIN } } - - it "raises a TemporaryResourceError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::TemporaryResourceError - ) - end - end - - context "system throws Errno::EPROTO" do - let(:file_op_block) { proc {|_path| raise Errno::EPROTO } } - - it "raises a VirtualProtocolError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::VirtualProtocolError - ) - end - end - - context "system throws Errno::ENOTSUP", :ruby => "1.9" do - let(:file_op_block) { proc {|_path| raise Errno::ENOTSUP } } - - it "raises a OperationNotSupportedError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::OperationNotSupportedError - ) - end - end - - context "system throws Errno::ENOSPC" do - let(:file_op_block) { proc {|_path| raise Errno::ENOSPC } } - - it "raises a NoSpaceOnDeviceError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::NoSpaceOnDeviceError - ) - end - end - - context "system throws an unhandled SystemCallError" do - let(:error) { SystemCallError.new("Shields down", 1337) } - let(:file_op_block) { proc {|_path| raise error } } - - it "raises a GenericSystemCallError" do - expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error( - Bundler::GenericSystemCallError, /error accessing.+underlying.+Shields down/m - ) - end - end - end - - describe "#const_get_safely" do - module TargetNamespace - VALID_CONSTANT = 1 - end - - context "when the namespace does have the requested constant" do - it "returns the value of the requested constant" do - expect(subject.const_get_safely(:VALID_CONSTANT, TargetNamespace)).to eq(1) - end - end - - context "when the requested constant is passed as a string" do - it "returns the value of the requested constant" do - expect(subject.const_get_safely("VALID_CONSTANT", TargetNamespace)).to eq(1) - end - end - - context "when the namespace does not have the requested constant" do - it "returns nil" do - expect(subject.const_get_safely("INVALID_CONSTANT", TargetNamespace)).to be_nil - end - end - end -end diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb deleted file mode 100644 index d282a449a5..0000000000 --- a/spec/bundler/bundler/source/git/git_proxy_spec.rb +++ /dev/null @@ -1,116 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Source::Git::GitProxy do - let(:uri) { "https://github.com/bundler/bundler.git" } - subject { described_class.new(Pathname("path"), uri, "HEAD") } - - context "with configured credentials" do - it "adds username and password to URI" do - Bundler.settings.temporary(uri => "u:p") - expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) - subject.checkout - end - - it "adds username and password to URI for host" do - Bundler.settings.temporary("github.com" => "u:p") - expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git")) - subject.checkout - end - - it "does not add username and password to mismatched URI" do - Bundler.settings.temporary("https://u:p@github.com/bundler/bundler-mismatch.git" => "u:p") - expect(subject).to receive(:git_retry).with(match(uri)) - subject.checkout - end - - it "keeps original userinfo" do - Bundler.settings.temporary("github.com" => "u:p") - original = "https://orig:info@github.com/bundler/bundler.git" - subject = described_class.new(Pathname("path"), original, "HEAD") - expect(subject).to receive(:git_retry).with(match(original)) - subject.checkout - end - end - - describe "#version" do - context "with a normal version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3") - end - - it "returns the git version number" do - expect(subject.version).to eq("1.2.3") - end - - it "does not raise an error when passed into Gem::Version.create" do - expect { Gem::Version.create subject.version }.not_to raise_error - end - end - - context "with a OSX version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3 (Apple Git-BS)") - end - - it "strips out OSX specific additions in the version string" do - expect(subject.version).to eq("1.2.3") - end - - it "does not raise an error when passed into Gem::Version.create" do - expect { Gem::Version.create subject.version }.not_to raise_error - end - end - - context "with a msysgit version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3.msysgit.0") - end - - it "strips out msysgit specific additions in the version string" do - expect(subject.version).to eq("1.2.3") - end - - it "does not raise an error when passed into Gem::Version.create" do - expect { Gem::Version.create subject.version }.not_to raise_error - end - end - end - - describe "#full_version" do - context "with a normal version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3") - end - - it "returns the git version number" do - expect(subject.full_version).to eq("1.2.3") - end - end - - context "with a OSX version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3 (Apple Git-BS)") - end - - it "does not strip out OSX specific additions in the version string" do - expect(subject.full_version).to eq("1.2.3 (Apple Git-BS)") - end - end - - context "with a msysgit version number" do - before do - expect(subject).to receive(:git).with("--version"). - and_return("git version 1.2.3.msysgit.0") - end - - it "does not strip out msysgit specific additions in the version string" do - expect(subject.full_version).to eq("1.2.3.msysgit.0") - end - end - end -end diff --git a/spec/bundler/bundler/source/path_spec.rb b/spec/bundler/bundler/source/path_spec.rb deleted file mode 100644 index 1d13e03ec1..0000000000 --- a/spec/bundler/bundler/source/path_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Source::Path do - before do - allow(Bundler).to receive(:root) { Pathname.new("root") } - end - - describe "#eql?" do - subject { described_class.new("path" => "gems/a") } - - context "with two equivalent relative paths from different roots" do - let(:a_gem_opts) { { "path" => "../gems/a", "root_path" => Bundler.root.join("nested") } } - let(:a_gem) { described_class.new a_gem_opts } - - it "returns true" do - expect(subject).to eq a_gem - end - end - - context "with the same (but not equivalent) relative path from different roots" do - subject { described_class.new("path" => "gems/a") } - - let(:a_gem_opts) { { "path" => "gems/a", "root_path" => Bundler.root.join("nested") } } - let(:a_gem) { described_class.new a_gem_opts } - - it "returns false" do - expect(subject).to_not eq a_gem - end - end - end -end diff --git a/spec/bundler/bundler/source/rubygems/remote_spec.rb b/spec/bundler/bundler/source/rubygems/remote_spec.rb deleted file mode 100644 index 9a7ab42128..0000000000 --- a/spec/bundler/bundler/source/rubygems/remote_spec.rb +++ /dev/null @@ -1,162 +0,0 @@ -# frozen_string_literal: true - -require "bundler/source/rubygems/remote" - -RSpec.describe Bundler::Source::Rubygems::Remote do - def remote(uri) - Bundler::Source::Rubygems::Remote.new(uri) - end - - before do - allow(Digest(:MD5)).to receive(:hexdigest).with(duck_type(:to_s)) {|string| "MD5HEX(#{string})" } - end - - let(:uri_no_auth) { URI("https://gems.example.com") } - let(:uri_with_auth) { URI("https://#{credentials}@gems.example.com") } - let(:credentials) { "username:password" } - - context "when the original URI has no credentials" do - describe "#uri" do - it "returns the original URI" do - expect(remote(uri_no_auth).uri).to eq(uri_no_auth) - end - - it "applies configured credentials" do - Bundler.settings.temporary(uri_no_auth.to_s => credentials) - expect(remote(uri_no_auth).uri).to eq(uri_with_auth) - end - end - - describe "#anonymized_uri" do - it "returns the original URI" do - expect(remote(uri_no_auth).anonymized_uri).to eq(uri_no_auth) - end - - it "does not apply given credentials" do - Bundler.settings.temporary(uri_no_auth.to_s => credentials) - expect(remote(uri_no_auth).anonymized_uri).to eq(uri_no_auth) - end - end - - describe "#cache_slug" do - it "returns the correct slug" do - expect(remote(uri_no_auth).cache_slug).to eq("gems.example.com.443.MD5HEX(gems.example.com.443./)") - end - - it "only applies the given user" do - Bundler.settings.temporary(uri_no_auth.to_s => credentials) - expect(remote(uri_no_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)") - end - end - end - - context "when the original URI has a username and password" do - describe "#uri" do - it "returns the original URI" do - expect(remote(uri_with_auth).uri).to eq(uri_with_auth) - end - - it "does not apply configured credentials" do - Bundler.settings.temporary(uri_no_auth.to_s => "other:stuff") - expect(remote(uri_with_auth).uri).to eq(uri_with_auth) - end - end - - describe "#anonymized_uri" do - it "returns the URI without username and password" do - expect(remote(uri_with_auth).anonymized_uri).to eq(uri_no_auth) - end - - it "does not apply given credentials" do - Bundler.settings.temporary(uri_no_auth.to_s => "other:stuff") - expect(remote(uri_with_auth).anonymized_uri).to eq(uri_no_auth) - end - end - - describe "#cache_slug" do - it "returns the correct slug" do - expect(remote(uri_with_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)") - end - - it "does not apply given credentials" do - Bundler.settings.temporary(uri_with_auth.to_s => credentials) - expect(remote(uri_with_auth).cache_slug).to eq("gems.example.com.username.443.MD5HEX(gems.example.com.username.443./)") - end - end - end - - context "when the original URI has only a username" do - let(:uri) { URI("https://SeCrEt-ToKeN@gem.fury.io/me/") } - - describe "#anonymized_uri" do - it "returns the URI without username and password" do - expect(remote(uri).anonymized_uri).to eq(URI("https://gem.fury.io/me/")) - end - end - - describe "#cache_slug" do - it "returns the correct slug" do - expect(remote(uri).cache_slug).to eq("gem.fury.io.SeCrEt-ToKeN.443.MD5HEX(gem.fury.io.SeCrEt-ToKeN.443./me/)") - end - end - end - - context "when a mirror with inline credentials is configured for the URI" do - let(:uri) { URI("https://rubygems.org/") } - let(:mirror_uri_with_auth) { URI("https://username:password@rubygems-mirror.org/") } - let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") } - - before { Bundler.settings.set_local("mirror.https://rubygems.org/", mirror_uri_with_auth.to_s) } - - specify "#uri returns the mirror URI with credentials" do - expect(remote(uri).uri).to eq(mirror_uri_with_auth) - end - - specify "#anonymized_uri returns the mirror URI without credentials" do - expect(remote(uri).anonymized_uri).to eq(mirror_uri_no_auth) - end - - specify "#original_uri returns the original source" do - expect(remote(uri).original_uri).to eq(uri) - end - - specify "#cache_slug returns the correct slug" do - expect(remote(uri).cache_slug).to eq("rubygems.org.443.MD5HEX(rubygems.org.443./)") - end - end - - context "when a mirror with configured credentials is configured for the URI" do - let(:uri) { URI("https://rubygems.org/") } - let(:mirror_uri_with_auth) { URI("https://#{credentials}@rubygems-mirror.org/") } - let(:mirror_uri_no_auth) { URI("https://rubygems-mirror.org/") } - - before do - Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_no_auth.to_s) - Bundler.settings.temporary(mirror_uri_no_auth.to_s => credentials) - end - - specify "#uri returns the mirror URI with credentials" do - expect(remote(uri).uri).to eq(mirror_uri_with_auth) - end - - specify "#anonymized_uri returns the mirror URI without credentials" do - expect(remote(uri).anonymized_uri).to eq(mirror_uri_no_auth) - end - - specify "#original_uri returns the original source" do - expect(remote(uri).original_uri).to eq(uri) - end - - specify "#cache_slug returns the original source" do - expect(remote(uri).cache_slug).to eq("rubygems.org.443.MD5HEX(rubygems.org.443./)") - end - end - - context "when there is no mirror set" do - describe "#original_uri" do - it "is not set" do - expect(remote(uri_no_auth).original_uri).to be_nil - end - end - end -end diff --git a/spec/bundler/bundler/source/rubygems_spec.rb b/spec/bundler/bundler/source/rubygems_spec.rb deleted file mode 100644 index 7c457a7265..0000000000 --- a/spec/bundler/bundler/source/rubygems_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Source::Rubygems do - before do - allow(Bundler).to receive(:root) { Pathname.new("root") } - end - - describe "caches" do - it "includes Bundler.app_cache" do - expect(subject.caches).to include(Bundler.app_cache) - end - - it "includes GEM_PATH entries" do - Gem.path.each do |path| - expect(subject.caches).to include(File.expand_path("#{path}/cache")) - end - end - - it "is an array of strings or pathnames" do - subject.caches.each do |cache| - expect([String, Pathname]).to include(cache.class) - end - end - end - - describe "#add_remote" do - context "when the source is an HTTP(s) URI with no host" do - it "raises error" do - expect { subject.add_remote("https:rubygems.org") }.to raise_error(ArgumentError) - end - end - end -end diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb deleted file mode 100644 index ce3353012c..0000000000 --- a/spec/bundler/bundler/source_list_spec.rb +++ /dev/null @@ -1,463 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::SourceList do - before do - allow(Bundler).to receive(:root) { Pathname.new "./tmp/bundled_app" } - - stub_const "ASourcePlugin", Class.new(Bundler::Plugin::API) - ASourcePlugin.source "new_source" - allow(Bundler::Plugin).to receive(:source?).with("new_source").and_return(true) - end - - subject(:source_list) { Bundler::SourceList.new } - - let(:rubygems_aggregate) { Bundler::Source::Rubygems.new } - let(:metadata_source) { Bundler::Source::Metadata.new } - - describe "adding sources" do - before do - source_list.add_path_source("path" => "/existing/path/to/gem") - source_list.add_git_source("uri" => "git://existing-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://existing-rubygems.org"]) - source_list.add_plugin_source("new_source", "uri" => "https://some.url/a") - end - - describe "#add_path_source" do - before do - @duplicate = source_list.add_path_source("path" => "/path/to/gem") - @new_source = source_list.add_path_source("path" => "/path/to/gem") - end - - it "returns the new path source" do - expect(@new_source).to be_instance_of(Bundler::Source::Path) - end - - it "passes the provided options to the new source" do - expect(@new_source.options).to eq("path" => "/path/to/gem") - end - - it "adds the source to the beginning of path_sources" do - expect(source_list.path_sources.first).to equal(@new_source) - end - - it "removes existing duplicates" do - expect(source_list.path_sources).not_to include equal(@duplicate) - end - end - - describe "#add_git_source" do - before do - @duplicate = source_list.add_git_source("uri" => "git://host/path.git") - @new_source = source_list.add_git_source("uri" => "git://host/path.git") - end - - it "returns the new git source" do - expect(@new_source).to be_instance_of(Bundler::Source::Git) - end - - it "passes the provided options to the new source" do - @new_source = source_list.add_git_source("uri" => "git://host/path.git") - expect(@new_source.options).to eq("uri" => "git://host/path.git") - end - - it "adds the source to the beginning of git_sources" do - @new_source = source_list.add_git_source("uri" => "git://host/path.git") - expect(source_list.git_sources.first).to equal(@new_source) - end - - it "removes existing duplicates" do - @duplicate = source_list.add_git_source("uri" => "git://host/path.git") - @new_source = source_list.add_git_source("uri" => "git://host/path.git") - expect(source_list.git_sources).not_to include equal(@duplicate) - end - - context "with the git: protocol" do - let(:msg) do - "The git source `git://existing-git.org/path.git` " \ - "uses the `git` protocol, which transmits data without encryption. " \ - "Disable this warning with `bundle config git.allow_insecure true`, " \ - "or switch to the `https` protocol to keep your data secure." - end - - it "warns about git protocols" do - expect(Bundler.ui).to receive(:warn).with(msg) - source_list.add_git_source("uri" => "git://existing-git.org/path.git") - end - - it "ignores git protocols on request" do - Bundler.settings.temporary(:"git.allow_insecure" => true) - expect(Bundler.ui).to_not receive(:warn).with(msg) - source_list.add_git_source("uri" => "git://existing-git.org/path.git") - end - end - end - - describe "#add_rubygems_source" do - before do - @duplicate = source_list.add_rubygems_source("remotes" => ["https://rubygems.org/"]) - @new_source = source_list.add_rubygems_source("remotes" => ["https://rubygems.org/"]) - end - - it "returns the new rubygems source" do - expect(@new_source).to be_instance_of(Bundler::Source::Rubygems) - end - - it "passes the provided options to the new source" do - expect(@new_source.options).to eq("remotes" => ["https://rubygems.org/"]) - end - - it "adds the source to the beginning of rubygems_sources" do - expect(source_list.rubygems_sources.first).to equal(@new_source) - end - - it "removes duplicates" do - expect(source_list.rubygems_sources).not_to include equal(@duplicate) - end - end - - describe "#add_rubygems_remote", :bundler => "< 2" do - let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") } - - it "returns the aggregate rubygems source" do - expect(returned_source).to be_instance_of(Bundler::Source::Rubygems) - end - - it "adds the provided remote to the beginning of the aggregate source" do - source_list.add_rubygems_remote("https://othersource.org") - expect(returned_source.remotes).to eq [ - URI("https://othersource.org/"), - URI("https://rubygems.org/"), - ] - end - end - - describe "#add_plugin_source" do - before do - @duplicate = source_list.add_plugin_source("new_source", "uri" => "http://host/path.") - @new_source = source_list.add_plugin_source("new_source", "uri" => "http://host/path.") - end - - it "returns the new plugin source" do - expect(@new_source).to be_a(Bundler::Plugin::API::Source) - end - - it "passes the provided options to the new source" do - expect(@new_source.options).to eq("uri" => "http://host/path.") - end - - it "adds the source to the beginning of git_sources" do - expect(source_list.plugin_sources.first).to equal(@new_source) - end - - it "removes existing duplicates" do - expect(source_list.plugin_sources).not_to include equal(@duplicate) - end - end - end - - describe "#all_sources" do - it "includes the aggregate rubygems source when rubygems sources have been added" do - source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) - source_list.add_path_source("path" => "/path/to/gem") - source_list.add_plugin_source("new_source", "uri" => "https://some.url/a") - - expect(source_list.all_sources).to include rubygems_aggregate - end - - it "includes the aggregate rubygems source when no rubygems sources have been added" do - source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_path_source("path" => "/path/to/gem") - source_list.add_plugin_source("new_source", "uri" => "https://some.url/a") - - expect(source_list.all_sources).to include rubygems_aggregate - end - - it "returns sources of the same type in the reverse order that they were added" do - source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://fifth-rubygems.org"]) - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_plugin_source("new_source", "uri" => "https://some.url/b") - source_list.add_rubygems_source("remotes" => ["https://fourth-rubygems.org"]) - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://third-rubygems.org"]) - source_list.add_plugin_source("new_source", "uri" => "https://some.o.url/") - source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://second-rubygems.org"]) - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_plugin_source("new_source", "uri" => "https://some.url/c") - source_list.add_rubygems_source("remotes" => ["https://first-rubygems.org"]) - source_list.add_git_source("uri" => "git://first-git.org/path.git") - - expect(source_list.all_sources).to eq [ - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - ASourcePlugin.new("uri" => "https://some.url/c"), - ASourcePlugin.new("uri" => "https://some.o.url/"), - ASourcePlugin.new("uri" => "https://some.url/b"), - Bundler::Source::Rubygems.new("remotes" => ["https://first-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://second-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]), - rubygems_aggregate, - metadata_source, - ] - end - end - - describe "#path_sources" do - it "returns an empty array when no path sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") - source_list.add_git_source("uri" => "git://host/path.git") - expect(source_list.path_sources).to be_empty - end - - it "returns path sources in the reverse order that they were added" do - source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") - source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") - source_list.add_git_source("uri" => "git://first-git.org/path.git") - - expect(source_list.path_sources).to eq [ - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - ] - end - end - - describe "#git_sources" do - it "returns an empty array when no git sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") - source_list.add_path_source("path" => "/path/to/gem") - - expect(source_list.git_sources).to be_empty - end - - it "returns git sources in the reverse order that they were added" do - source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_remote("https://fifth-rubygems.org") - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") - source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") - source_list.add_git_source("uri" => "git://first-git.org/path.git") - - expect(source_list.git_sources).to eq [ - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - ] - end - end - - describe "#plugin_sources" do - it "returns an empty array when no plugin sources have been added" do - source_list.add_rubygems_remote("https://rubygems.org") - source_list.add_path_source("path" => "/path/to/gem") - - expect(source_list.plugin_sources).to be_empty - end - - it "returns plugin sources in the reverse order that they were added" do - source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git") - source_list.add_git_source("https://new-git.org") - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_remote("https://fourth-rubygems.org") - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_remote("https://third-rubygems.org") - source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git") - source_list.add_rubygems_remote("https://second-rubygems.org") - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_remote("https://first-rubygems.org") - source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git") - - expect(source_list.plugin_sources).to eq [ - ASourcePlugin.new("uri" => "git://first-git.org/path.git"), - ASourcePlugin.new("uri" => "git://second-git.org/path.git"), - ASourcePlugin.new("uri" => "https://third-git.org/path.git"), - ] - end - end - - describe "#rubygems_sources" do - it "includes the aggregate rubygems source when rubygems sources have been added" do - source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) - source_list.add_path_source("path" => "/path/to/gem") - - expect(source_list.rubygems_sources).to include rubygems_aggregate - end - - it "returns only the aggregate rubygems source when no rubygems sources have been added" do - source_list.add_git_source("uri" => "git://host/path.git") - source_list.add_path_source("path" => "/path/to/gem") - - expect(source_list.rubygems_sources).to eq [rubygems_aggregate] - end - - it "returns rubygems sources in the reverse order that they were added" do - source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://fifth-rubygems.org"]) - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://fourth-rubygems.org"]) - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://third-rubygems.org"]) - source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://second-rubygems.org"]) - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://first-rubygems.org"]) - source_list.add_git_source("uri" => "git://first-git.org/path.git") - - expect(source_list.rubygems_sources).to eq [ - Bundler::Source::Rubygems.new("remotes" => ["https://first-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://second-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]), - rubygems_aggregate, - ] - end - end - - describe "#get" do - context "when it includes an equal source" do - let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) } - before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") } - - it "returns the equal source" do - expect(source_list.get(rubygems_source)).to be @equal_source - end - end - - context "when it does not include an equal source" do - let(:path_source) { Bundler::Source::Path.new("path" => "/path/to/gem") } - - it "returns nil" do - expect(source_list.get(path_source)).to be_nil - end - end - end - - describe "#lock_sources" do - before do - source_list.add_git_source("uri" => "git://third-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://duplicate-rubygems.org"]) - source_list.add_plugin_source("new_source", "uri" => "https://third-bar.org/foo") - source_list.add_path_source("path" => "/third/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://third-rubygems.org"]) - source_list.add_path_source("path" => "/second/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://second-rubygems.org"]) - source_list.add_git_source("uri" => "git://second-git.org/path.git") - source_list.add_rubygems_source("remotes" => ["https://first-rubygems.org"]) - source_list.add_plugin_source("new_source", "uri" => "https://second-plugin.org/random") - source_list.add_path_source("path" => "/first/path/to/gem") - source_list.add_rubygems_source("remotes" => ["https://duplicate-rubygems.org"]) - source_list.add_git_source("uri" => "git://first-git.org/path.git") - end - - it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 2" do - expect(source_list.lock_sources).to eq [ - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - ASourcePlugin.new("uri" => "https://second-plugin.org/random"), - ASourcePlugin.new("uri" => "https://third-bar.org/foo"), - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - Bundler::Source::Rubygems.new("remotes" => [ - "https://duplicate-rubygems.org", - "https://first-rubygems.org", - "https://second-rubygems.org", - "https://third-rubygems.org", - ]), - ] - end - - it "returns all sources, without combining rubygems sources", :bundler => "2" do - expect(source_list.lock_sources).to eq [ - Bundler::Source::Rubygems.new, - Bundler::Source::Rubygems.new("remotes" => ["https://duplicate-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://first-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://second-rubygems.org"]), - Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]), - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - ASourcePlugin.new("uri" => "https://second-plugin.org/random"), - ASourcePlugin.new("uri" => "https://third-bar.org/foo"), - ] - end - end - - describe "replace_sources!" do - let(:existing_locked_source) { Bundler::Source::Path.new("path" => "/existing/path") } - let(:removed_locked_source) { Bundler::Source::Path.new("path" => "/removed/path") } - - let(:locked_sources) { [existing_locked_source, removed_locked_source] } - - before do - @existing_source = source_list.add_path_source("path" => "/existing/path") - @new_source = source_list.add_path_source("path" => "/new/path") - source_list.replace_sources!(locked_sources) - end - - it "maintains the order and number of sources" do - expect(source_list.path_sources).to eq [@new_source, @existing_source] - end - - it "retains the same instance of the new source" do - expect(source_list.path_sources[0]).to be @new_source - end - - it "replaces the instance of the existing source" do - expect(source_list.path_sources[1]).to be existing_locked_source - end - end - - describe "#cached!" do - let(:rubygems_source) { source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) } - let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } - let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } - - it "calls #cached! on all the sources" do - expect(rubygems_source).to receive(:cached!) - expect(git_source).to receive(:cached!) - expect(path_source).to receive(:cached!) - source_list.cached! - end - end - - describe "#remote!" do - let(:rubygems_source) { source_list.add_rubygems_source("remotes" => ["https://rubygems.org"]) } - let(:git_source) { source_list.add_git_source("uri" => "git://host/path.git") } - let(:path_source) { source_list.add_path_source("path" => "/path/to/gem") } - - it "calls #remote! on all the sources" do - expect(rubygems_source).to receive(:remote!) - expect(git_source).to receive(:remote!) - expect(path_source).to receive(:remote!) - source_list.remote! - end - end -end diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb deleted file mode 100644 index 9ef8e7e50f..0000000000 --- a/spec/bundler/bundler/source_spec.rb +++ /dev/null @@ -1,154 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::Source do - class ExampleSource < Bundler::Source - end - - subject { ExampleSource.new } - - describe "#unmet_deps" do - let(:specs) { double(:specs) } - let(:unmet_dependency_names) { double(:unmet_dependency_names) } - - before do - allow(subject).to receive(:specs).and_return(specs) - allow(specs).to receive(:unmet_dependency_names).and_return(unmet_dependency_names) - end - - it "should return the names of unmet dependencies" do - expect(subject.unmet_deps).to eq(unmet_dependency_names) - end - end - - describe "#version_message" do - let(:spec) { double(:spec, :name => "nokogiri", :version => ">= 1.6", :platform => rb) } - - shared_examples_for "the lockfile specs are not relevant" do - it "should return a string with the spec name and version" do - expect(subject.version_message(spec)).to eq("nokogiri >= 1.6") - end - end - - context "when there are locked gems" do - let(:locked_gems) { double(:locked_gems) } - - before { allow(Bundler).to receive(:locked_gems).and_return(locked_gems) } - - context "that contain the relevant gem spec" do - before do - specs = double(:specs) - allow(locked_gems).to receive(:specs).and_return(specs) - allow(specs).to receive(:find).and_return(locked_gem) - end - - context "without a version" do - let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => nil) } - - it_behaves_like "the lockfile specs are not relevant" - end - - context "with the same version" do - let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => ">= 1.6") } - - it_behaves_like "the lockfile specs are not relevant" - end - - context "with a different version" do - let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "< 1.5") } - - context "with color" do - before { Bundler.ui = Bundler::UI::Shell.new } - - it "should return a string with the spec name and version and locked spec version" do - expect(subject.version_message(spec)).to eq("nokogiri >= 1.6\e[32m (was < 1.5)\e[0m") - end - end - - context "without color" do - it "should return a string with the spec name and version and locked spec version" do - expect(subject.version_message(spec)).to eq("nokogiri >= 1.6 (was < 1.5)") - end - end - end - - context "with a more recent version" do - let(:spec) { double(:spec, :name => "nokogiri", :version => "1.6.1", :platform => rb) } - let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "1.7.0") } - - context "with color" do - before { Bundler.ui = Bundler::UI::Shell.new } - - it "should return a string with the locked spec version in yellow" do - expect(subject.version_message(spec)).to eq("nokogiri 1.6.1\e[33m (was 1.7.0)\e[0m") - end - end - end - - context "with an older version" do - let(:spec) { double(:spec, :name => "nokogiri", :version => "1.7.1", :platform => rb) } - let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => "1.7.0") } - - context "with color" do - before { Bundler.ui = Bundler::UI::Shell.new } - - it "should return a string with the locked spec version in green" do - expect(subject.version_message(spec)).to eq("nokogiri 1.7.1\e[32m (was 1.7.0)\e[0m") - end - end - end - end - - context "that do not contain the relevant gem spec" do - before do - specs = double(:specs) - allow(locked_gems).to receive(:specs).and_return(specs) - allow(specs).to receive(:find).and_return(nil) - end - - it_behaves_like "the lockfile specs are not relevant" - end - end - - context "when there are no locked gems" do - before { allow(Bundler).to receive(:locked_gems).and_return(nil) } - - it_behaves_like "the lockfile specs are not relevant" - end - end - - describe "#can_lock?" do - context "when the passed spec's source is equivalent" do - let(:spec) { double(:spec, :source => subject) } - - it "should return true" do - expect(subject.can_lock?(spec)).to be_truthy - end - end - - context "when the passed spec's source is not equivalent" do - let(:spec) { double(:spec, :source => double(:other_source)) } - - it "should return false" do - expect(subject.can_lock?(spec)).to be_falsey - end - end - end - - describe "#include?" do - context "when the passed source is equivalent" do - let(:source) { subject } - - it "should return true" do - expect(subject).to include(source) - end - end - - context "when the passed source is not equivalent" do - let(:source) { double(:source) } - - it "should return false" do - expect(subject).to_not include(source) - end - end - end -end diff --git a/spec/bundler/bundler/spec_set_spec.rb b/spec/bundler/bundler/spec_set_spec.rb deleted file mode 100644 index 6fedd38b50..0000000000 --- a/spec/bundler/bundler/spec_set_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::SpecSet do - let(:specs) do - [ - build_spec("a", "1.0"), - build_spec("b", "1.0"), - build_spec("c", "1.1") do |s| - s.dep "a", "< 2.0" - s.dep "e", "> 0" - end, - build_spec("d", "2.0") do |s| - s.dep "a", "1.0" - s.dep "c", "~> 1.0" - end, - build_spec("e", "1.0.0.pre.1"), - ].flatten - end - - subject { described_class.new(specs) } - - context "enumerable methods" do - it "has a length" do - expect(subject.length).to eq(5) - end - - it "has a size" do - expect(subject.size).to eq(5) - end - end - - describe "#find_by_name_and_platform" do - let(:platform) { Gem::Platform.new("universal-darwin-64") } - let(:platform_spec) { build_spec("b", "2.0", platform).first } - let(:specs) do - [ - build_spec("a", "1.0"), - platform_spec, - ].flatten - end - - it "finds spec with given name and platform" do - spec = described_class.new(specs).find_by_name_and_platform("b", platform) - expect(spec).to eq platform_spec - end - end - - describe "#merge" do - let(:other_specs) do - [ - build_spec("f", "1.0"), - build_spec("g", "2.0"), - ].flatten - end - - let(:other_spec_set) { described_class.new(other_specs) } - - it "merges the items in each gemspec" do - new_spec_set = subject.merge(other_spec_set) - specs = new_spec_set.to_a.map(&:full_name) - expect(specs).to include("a-1.0") - expect(specs).to include("f-1.0") - end - end - - describe "#to_a" do - it "returns the specs in order" do - expect(subject.to_a.map(&:full_name)).to eq %w[ - a-1.0 - b-1.0 - e-1.0.0.pre.1 - c-1.1 - d-2.0 - ] - end - end -end diff --git a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb b/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb deleted file mode 100644 index d1ec08bdc4..0000000000 --- a/spec/bundler/bundler/ssl_certs/certificate_manager_spec.rb +++ /dev/null @@ -1,141 +0,0 @@ -# frozen_string_literal: true - -require "bundler/ssl_certs/certificate_manager" - -RSpec.describe Bundler::SSLCerts::CertificateManager do - let(:rubygems_path) { root } - let(:stub_cert) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem") } - let(:rubygems_certs_dir) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org") } - - subject { described_class.new(rubygems_path) } - - # Pretend bundler root is rubygems root - before do - # Backing up rubygems ceriticates - FileUtils.mv(rubygems_certs_dir, rubygems_certs_dir + ".back") if !!(ENV["BUNDLE_RUBY"] && ENV["BUNDLE_GEM"]) - - FileUtils.mkdir_p(rubygems_certs_dir) - FileUtils.touch(stub_cert) - end - - after do - rubygems_dir = File.join(root.to_s, "lib", "rubygems") - FileUtils.rm_rf(rubygems_certs_dir) - - # Restore rubygems certificates - FileUtils.mv(rubygems_certs_dir + ".back", rubygems_certs_dir) if !!(ENV["BUNDLE_RUBY"] && ENV["BUNDLE_GEM"]) - end - - describe "#update_from" do - let(:cert_manager) { double(:cert_manager) } - - before { allow(described_class).to receive(:new).with(rubygems_path).and_return(cert_manager) } - - it "should update the certs through a new certificate manager" do - allow(cert_manager).to receive(:update!) - expect(described_class.update_from!(rubygems_path)).to be_nil - end - end - - describe "#initialize" do - it "should set bundler_cert_path as path of the subdir with bundler ssl certs" do - expect(subject.bundler_cert_path).to eq(File.join(root, "lib/bundler/ssl_certs")) - end - - it "should set bundler_certs as the paths of the bundler ssl certs" do - expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem")) - expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem")) - end - - context "when rubygems_path is not nil" do - it "should set rubygems_certs" do - expect(subject.rubygems_certs).to include(File.join(root, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem")) - end - end - end - - describe "#up_to_date?" do - context "when bundler certs and rubygems certs are the same" do - before do - bundler_certs = Dir[File.join(root.to_s, "lib", "bundler", "ssl_certs", "**", "*.pem")] - FileUtils.rm(stub_cert) - FileUtils.cp(bundler_certs, rubygems_certs_dir) - end - - it "should return true" do - expect(subject).to be_up_to_date - end - end - - context "when bundler certs and rubygems certs are not the same" do - it "should return false" do - expect(subject).to_not be_up_to_date - end - end - end - - describe "#update!" do - context "when certificate manager is not up to date" do - before do - allow(subject).to receive(:up_to_date?).and_return(false) - allow(bundler_fileutils).to receive(:rm) - allow(bundler_fileutils).to receive(:cp) - end - - it "should remove the current bundler certs" do - expect(bundler_fileutils).to receive(:rm).with(subject.bundler_certs) - subject.update! - end - - it "should copy the rubygems certs into bundler certs" do - expect(bundler_fileutils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path) - subject.update! - end - - it "should return nil" do - expect(subject.update!).to be_nil - end - end - - context "when certificate manager is up to date" do - before { allow(subject).to receive(:up_to_date?).and_return(true) } - - it "should return nil" do - expect(subject.update!).to be_nil - end - end - end - - describe "#connect_to" do - let(:host) { "http://www.host.com" } - let(:http) { Net::HTTP.new(host, 443) } - let(:cert_store) { OpenSSL::X509::Store.new } - let(:http_header_response) { double(:http_header_response) } - - before do - allow(Net::HTTP).to receive(:new).with(host, 443).and_return(http) - allow(OpenSSL::X509::Store).to receive(:new).and_return(cert_store) - allow(http).to receive(:head).with("/").and_return(http_header_response) - end - - it "should use ssl for the http request" do - expect(http).to receive(:use_ssl=).with(true) - subject.connect_to(host) - end - - it "use verify peer mode" do - expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER) - subject.connect_to(host) - end - - it "set its cert store as a OpenSSL::X509::Store populated with bundler certs" do - expect(cert_store).to receive(:add_file).at_least(:once) - expect(http).to receive(:cert_store=).with(cert_store) - subject.connect_to(host) - end - - it "return the headers of the request response" do - expect(subject.connect_to(host)).to eq(http_header_response) - end - end -end diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb deleted file mode 100644 index 5521d83769..0000000000 --- a/spec/bundler/bundler/stub_specification_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::StubSpecification do - let(:gemspec) do - Gem::Specification.new do |s| - s.name = "gemname" - s.version = "1.0.0" - s.loaded_from = __FILE__ - end - end - - let(:with_bundler_stub_spec) do - described_class.from_stub(gemspec) - end - - if Bundler.rubygems.provides?(">= 2.1") - describe "#from_stub" do - it "returns the same stub if already a Bundler::StubSpecification" do - stub = described_class.from_stub(with_bundler_stub_spec) - expect(stub).to be(with_bundler_stub_spec) - end - end - end -end diff --git a/spec/bundler/bundler/ui/shell_spec.rb b/spec/bundler/bundler/ui/shell_spec.rb deleted file mode 100644 index 9a47a3572f..0000000000 --- a/spec/bundler/bundler/ui/shell_spec.rb +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::UI::Shell do - subject { described_class.new } - - before { subject.level = "debug" } - - describe "#info" do - before { subject.level = "info" } - it "prints to stdout" do - expect { subject.info("info") }.to output("info\n").to_stdout - end - end - - describe "#confirm" do - before { subject.level = "confirm" } - it "prints to stdout" do - expect { subject.confirm("confirm") }.to output("confirm\n").to_stdout - end - end - - describe "#warn" do - before { subject.level = "warn" } - it "prints to stdout", :bundler => "< 2" do - expect { subject.warn("warning") }.to output("warning\n").to_stdout - end - - it "prints to stderr", :bundler => "2" do - expect { subject.warn("warning") }.to output("warning\n").to_stderr - end - - context "when stderr flag is enabled" do - before { Bundler.settings.temporary(:error_on_stderr => true) } - it "prints to stderr" do - expect { subject.warn("warning!") }.to output("warning!\n").to_stderr - end - end - end - - describe "#debug" do - it "prints to stdout" do - expect { subject.debug("debug") }.to output("debug\n").to_stdout - end - end - - describe "#error" do - before { subject.level = "error" } - - it "prints to stdout", :bundler => "< 2" do - expect { subject.error("error!!!") }.to output("error!!!\n").to_stdout - end - - it "prints to stderr", :bundler => "2" do - expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr - end - - context "when stderr flag is enabled" do - before { Bundler.settings.temporary(:error_on_stderr => true) } - it "prints to stderr" do - expect { subject.error("error!!!") }.to output("error!!!\n").to_stderr - end - end - end -end diff --git a/spec/bundler/bundler/ui_spec.rb b/spec/bundler/bundler/ui_spec.rb deleted file mode 100644 index 6ef8729277..0000000000 --- a/spec/bundler/bundler/ui_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::UI do - describe Bundler::UI::Silent do - it "has the same instance methods as Shell", :ruby => ">= 1.9" do - shell = Bundler::UI::Shell - methods = proc do |cls| - cls.instance_methods.map do |i| - m = shell.instance_method(i) - [i, m.parameters] - end.sort_by(&:first) - end - expect(methods.call(described_class)).to eq(methods.call(shell)) - end - - it "has the same instance class as Shell", :ruby => ">= 1.9" do - shell = Bundler::UI::Shell - methods = proc do |cls| - cls.methods.map do |i| - m = shell.method(i) - [i, m.parameters] - end.sort_by(&:first) - end - expect(methods.call(described_class)).to eq(methods.call(shell)) - end - end - - describe Bundler::UI::Shell do - let(:options) { {} } - subject { described_class.new(options) } - describe "debug?" do - it "returns a boolean" do - subject.level = :debug - expect(subject.debug?).to eq(true) - - subject.level = :error - expect(subject.debug?).to eq(false) - end - end - end -end diff --git a/spec/bundler/bundler/uri_credentials_filter_spec.rb b/spec/bundler/bundler/uri_credentials_filter_spec.rb deleted file mode 100644 index fe52d16306..0000000000 --- a/spec/bundler/bundler/uri_credentials_filter_spec.rb +++ /dev/null @@ -1,127 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bundler::URICredentialsFilter do - subject { described_class } - - describe "#credential_filtered_uri" do - shared_examples_for "original type of uri is maintained" do - it "maintains same type for return value as uri input type" do - expect(subject.credential_filtered_uri(uri)).to be_kind_of(uri.class) - end - end - - shared_examples_for "sensitive credentials in uri are filtered out" do - context "authentication using oauth credentials" do - context "specified via 'x-oauth-basic'" do - let(:credentials) { "oauth_token:x-oauth-basic@" } - - it "returns the uri without the oauth token" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://x-oauth-basic@github.com/company/private-repo").to_s) - end - - it_behaves_like "original type of uri is maintained" - end - - context "specified via 'x'" do - let(:credentials) { "oauth_token:x@" } - - it "returns the uri without the oauth token" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://x@github.com/company/private-repo").to_s) - end - - it_behaves_like "original type of uri is maintained" - end - end - - context "authentication using login credentials" do - let(:credentials) { "username1:hunter3@" } - - it "returns the uri without the password" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(URI("https://username1@github.com/company/private-repo").to_s) - end - - it_behaves_like "original type of uri is maintained" - end - - context "authentication without credentials" do - let(:credentials) { "" } - - it "returns the same uri" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(uri.to_s) - end - - it_behaves_like "original type of uri is maintained" - end - end - - context "uri is a uri object" do - let(:uri) { URI("https://#{credentials}github.com/company/private-repo") } - - it_behaves_like "sensitive credentials in uri are filtered out" - end - - context "uri is a uri string" do - let(:uri) { "https://#{credentials}github.com/company/private-repo" } - - it_behaves_like "sensitive credentials in uri are filtered out" - end - - context "uri is a non-uri format string (ex. path)" do - let(:uri) { "/path/to/repo" } - - it "returns the same uri" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(uri.to_s) - end - - it_behaves_like "original type of uri is maintained" - end - - context "uri is nil" do - let(:uri) { nil } - - it "returns nil" do - expect(subject.credential_filtered_uri(uri)).to be_nil - end - - it_behaves_like "original type of uri is maintained" - end - end - - describe "#credential_filtered_string" do - let(:str_to_filter) { "This is a git message containing a uri #{uri}!" } - let(:credentials) { "" } - let(:uri) { URI("https://#{credentials}github.com/company/private-repo") } - - context "with a uri that contains credentials" do - let(:credentials) { "oauth_token:x-oauth-basic@" } - - it "returns the string without the sensitive credentials" do - expect(subject.credential_filtered_string(str_to_filter, uri)).to eq( - "This is a git message containing a uri https://x-oauth-basic@github.com/company/private-repo!" - ) - end - end - - context "that does not contains credentials" do - it "returns the same string" do - expect(subject.credential_filtered_string(str_to_filter, uri)).to eq(str_to_filter) - end - end - - context "string to filter is nil" do - let(:str_to_filter) { nil } - - it "returns nil" do - expect(subject.credential_filtered_string(str_to_filter, uri)).to be_nil - end - end - - context "uri to filter out is nil" do - let(:uri) { nil } - - it "returns the same string" do - expect(subject.credential_filtered_string(str_to_filter, uri)).to eq(str_to_filter) - end - end - end -end diff --git a/spec/bundler/bundler/vendored_persistent_spec.rb b/spec/bundler/bundler/vendored_persistent_spec.rb deleted file mode 100644 index 338431c4a6..0000000000 --- a/spec/bundler/bundler/vendored_persistent_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" -require "bundler/vendored_persistent" - -RSpec.describe Bundler::PersistentHTTP do - describe "#warn_old_tls_version_rubygems_connection" do - let(:uri) { "https://index.rubygems.org" } - let(:connection) { instance_double(subject.http_class) } - let(:tls_version) { "TLSv1.2" } - let(:socket) { double("Socket") } - let(:socket_io) { double("SocketIO") } - - before do - allow(connection).to receive(:use_ssl?).and_return(!tls_version.nil?) - allow(socket).to receive(:io).and_return(socket_io) - connection.instance_variable_set(:@socket, socket) - - if tls_version - allow(socket_io).to receive(:ssl_version).and_return(tls_version) - end - end - - shared_examples_for "does not warn" do - it "does not warn" do - allow(Bundler.ui).to receive(:warn).never - subject.warn_old_tls_version_rubygems_connection(URI(uri), connection) - end - end - - shared_examples_for "does warn" do |*expected| - it "warns" do - expect(Bundler.ui).to receive(:warn).with(*expected) - subject.warn_old_tls_version_rubygems_connection(URI(uri), connection) - end - end - - context "an HTTPS uri with TLSv1.2" do - include_examples "does not warn" - end - - context "without SSL" do - let(:tls_version) { nil } - - include_examples "does not warn" - end - - context "without a socket" do - let(:socket) { nil } - - include_examples "does not warn" - end - - context "with a different TLD" do - let(:uri) { "https://foo.bar" } - include_examples "does not warn" - - context "and an outdated TLS version" do - let(:tls_version) { "TLSv1" } - include_examples "does not warn" - end - end - - context "with a nonsense TLS version" do - let(:tls_version) { "BlahBlah2.0Blah" } - include_examples "does not warn" - end - - context "with an outdated TLS version" do - let(:tls_version) { "TLSv1" } - include_examples "does warn", - "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \ - "Starting in January 2018, RubyGems.org will refuse connection requests from these very old versions of OpenSSL. " \ - "If you will need to continue installing gems after January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.", - :wrap => true - end - end -end diff --git a/spec/bundler/bundler/version_ranges_spec.rb b/spec/bundler/bundler/version_ranges_spec.rb deleted file mode 100644 index ccbb9285d5..0000000000 --- a/spec/bundler/bundler/version_ranges_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -require "bundler/version_ranges" - -RSpec.describe Bundler::VersionRanges do - describe ".empty?" do - shared_examples_for "empty?" do |exp, *req| - it "returns #{exp} for #{req}" do - r = Gem::Requirement.new(*req) - ranges = described_class.for(r) - expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty" - end - end - - include_examples "empty?", false - include_examples "empty?", false, "!= 1" - include_examples "empty?", false, "!= 1", "= 2" - include_examples "empty?", false, "!= 1", "> 1" - include_examples "empty?", false, "!= 1", ">= 1" - include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1" - include_examples "empty?", false, "= 1", ">= 1", "<= 1" - include_examples "empty?", false, "= 1", "~> 1" - include_examples "empty?", false, ">= 0.z", "= 0" - include_examples "empty?", false, ">= 0" - include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" - include_examples "empty?", false, "~> 1" - include_examples "empty?", false, "~> 2.0", "~> 2.1" - include_examples "empty?", true, "!= 1", "< 2", "> 2" - include_examples "empty?", true, "!= 1", "<= 1", ">= 1" - include_examples "empty?", true, "< 2", "> 2" - include_examples "empty?", true, "= 1", "!= 1" - include_examples "empty?", true, "= 1", "= 2" - include_examples "empty?", true, "= 1", "~> 2" - include_examples "empty?", true, ">= 0", "<= 0.a" - include_examples "empty?", true, "~> 2.0", "~> 3" - end -end diff --git a/spec/bundler/bundler/worker_spec.rb b/spec/bundler/bundler/worker_spec.rb deleted file mode 100644 index 2e5642709d..0000000000 --- a/spec/bundler/bundler/worker_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require "bundler/worker" - -RSpec.describe Bundler::Worker do - let(:size) { 5 } - let(:name) { "Spec Worker" } - let(:function) { proc {|object, worker_number| [object, worker_number] } } - subject { described_class.new(size, name, function) } - - after { subject.stop } - - describe "#initialize" do - context "when Thread.start raises ThreadError" do - it "raises when no threads can be created" do - allow(Thread).to receive(:start).and_raise(ThreadError, "error creating thread") - - expect { subject.enq "a" }.to raise_error(Bundler::ThreadCreationError, "Failed to create threads for the Spec Worker worker: error creating thread") - end - end - end -end diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb deleted file mode 100644 index 1241c74bbf..0000000000 --- a/spec/bundler/bundler/yaml_serializer_spec.rb +++ /dev/null @@ -1,194 +0,0 @@ -# frozen_string_literal: true - -require "bundler/yaml_serializer" - -RSpec.describe Bundler::YAMLSerializer do - subject(:serializer) { Bundler::YAMLSerializer } - - describe "#dump" do - it "works for simple hash" do - hash = { "Q" => "Where does Thursday come before Wednesday? In the dictionary. :P" } - - expected = strip_whitespace <<-YAML - --- - Q: "Where does Thursday come before Wednesday? In the dictionary. :P" - YAML - - expect(serializer.dump(hash)).to eq(expected) - end - - it "handles nested hash" do - hash = { - "nice-one" => { - "read_ahead" => "All generalizations are false, including this one", - }, - } - - expected = strip_whitespace <<-YAML - --- - nice-one: - read_ahead: "All generalizations are false, including this one" - YAML - - expect(serializer.dump(hash)).to eq(expected) - end - - it "array inside an hash" do - hash = { - "nested_hash" => { - "contains_array" => [ - "Jack and Jill went up the hill", - "To fetch a pail of water.", - "Jack fell down and broke his crown,", - "And Jill came tumbling after.", - ], - }, - } - - expected = strip_whitespace <<-YAML - --- - nested_hash: - contains_array: - - "Jack and Jill went up the hill" - - "To fetch a pail of water." - - "Jack fell down and broke his crown," - - "And Jill came tumbling after." - YAML - - expect(serializer.dump(hash)).to eq(expected) - end - end - - describe "#load" do - it "works for simple hash" do - yaml = strip_whitespace <<-YAML - --- - Jon: "Air is free dude!" - Jack: "Yes.. until you buy a bag of chips!" - YAML - - hash = { - "Jon" => "Air is free dude!", - "Jack" => "Yes.. until you buy a bag of chips!", - } - - expect(serializer.load(yaml)).to eq(hash) - end - - it "works for nested hash" do - yaml = strip_whitespace <<-YAML - --- - baa: - baa: "black sheep" - have: "you any wool?" - yes: "merry have I" - three: "bags full" - YAML - - hash = { - "baa" => { - "baa" => "black sheep", - "have" => "you any wool?", - "yes" => "merry have I", - }, - "three" => "bags full", - } - - expect(serializer.load(yaml)).to eq(hash) - end - - it "handles colon in key/value" do - yaml = strip_whitespace <<-YAML - BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: http://rubygems-mirror.org - YAML - - expect(serializer.load(yaml)).to eq("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org") - end - - it "handles arrays inside hashes" do - yaml = strip_whitespace <<-YAML - --- - nested_hash: - contains_array: - - "Why shouldn't you write with a broken pencil?" - - "Because it's pointless!" - YAML - - hash = { - "nested_hash" => { - "contains_array" => [ - "Why shouldn't you write with a broken pencil?", - "Because it's pointless!", - ], - }, - } - - expect(serializer.load(yaml)).to eq(hash) - end - - it "handles windows-style CRLF line endings" do - yaml = strip_whitespace(<<-YAML).gsub("\n", "\r\n") - --- - nested_hash: - contains_array: - - "Why shouldn't you write with a broken pencil?" - - "Because it's pointless!" - - oh so silly - YAML - - hash = { - "nested_hash" => { - "contains_array" => [ - "Why shouldn't you write with a broken pencil?", - "Because it's pointless!", - "oh so silly", - ], - }, - } - - expect(serializer.load(yaml)).to eq(hash) - end - end - - describe "against yaml lib" do - let(:hash) do - { - "a_joke" => { - "my-stand" => "I can totally keep secrets", - "but" => "The people I tell them to can't :P", - "wouldn't it be funny if this string were empty?" => "", - }, - "more" => { - "first" => [ - "Can a kangaroo jump higher than a house?", - "Of course, a house doesn't jump at all.", - ], - "second" => [ - "What did the sea say to the sand?", - "Nothing, it simply waved.", - ], - "array with empty string" => [""], - }, - "sales" => { - "item" => "A Parachute", - "description" => "Only used once, never opened.", - }, - "one-more" => "I'd tell you a chemistry joke but I know I wouldn't get a reaction.", - } - end - - context "#load" do - it "retrieves the original hash" do - require "yaml" - expect(serializer.load(YAML.dump(hash))).to eq(hash) - end - end - - context "#dump" do - it "retrieves the original hash" do - require "yaml" - expect(YAML.load(serializer.dump(hash))).to eq(hash) - end - end - end -end |