aboutsummaryrefslogtreecommitdiffstats
path: root/spec/bundler/realworld
diff options
context:
space:
mode:
authorhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-08 08:45:41 +0000
committerhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-08 08:45:41 +0000
commit8598f8c2dc78c6d1ae87cb6ae19c34ba2cb29241 (patch)
tree0bbd28f684e745cb212761b7c74fe08668f85cc8 /spec/bundler/realworld
parentf2e04b77aa8a363d7e36ce5a9cdb60714a537a3c (diff)
downloadruby-8598f8c2dc78c6d1ae87cb6ae19c34ba2cb29241.tar.gz
Merge bundler to standard libraries.
rubygems 2.7.x depends bundler-1.15.x. This is preparation for rubygems and bundler migration. * lib/bundler.rb, lib/bundler/*: files of bundler-1.15.4 * spec/bundler/*: rspec examples of bundler-1.15.4. I applied patches. * https://github.com/bundler/bundler/pull/6007 * Exclude not working examples on ruby repository. * Fake ruby interpriter instead of installed ruby. * Makefile.in: Added test task named `test-bundler`. This task is only working macOS/linux yet. I'm going to support Windows environment later. * tool/sync_default_gems.rb: Added sync task for bundler. [Feature #12733][ruby-core:77172] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59779 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/bundler/realworld')
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb49
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb382
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb53
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb143
-rw-r--r--spec/bundler/realworld/parallel_spec.rb81
5 files changed, 708 insertions, 0 deletions
diff --git a/spec/bundler/realworld/dependency_api_spec.rb b/spec/bundler/realworld/dependency_api_spec.rb
new file mode 100644
index 0000000000..468fa3644c
--- /dev/null
+++ b/spec/bundler/realworld/dependency_api_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe "gemcutter's dependency API", :realworld => true do
+ context "when Gemcutter API takes too long to respond" do
+ before do
+ require_rack
+
+ port = find_unused_port
+ @server_uri = "http://127.0.0.1:#{port}"
+
+ require File.expand_path("../../support/artifice/endpoint_timeout", __FILE__)
+ require "thread"
+ @t = Thread.new do
+ server = Rack::Server.start(:app => EndpointTimeout,
+ :Host => "0.0.0.0",
+ :Port => port,
+ :server => "webrick",
+ :AccessLog => [],
+ :Logger => Spec::SilentLogger.new)
+ server.start
+ end
+ @t.run
+
+ wait_for_server("127.0.0.1", port)
+ end
+
+ after do
+ Artifice.deactivate
+ @t.kill
+ @t.join
+ end
+
+ it "times out and falls back on the modern index" do
+ gemfile <<-G
+ source "#{@server_uri}"
+ gem "rack"
+
+ old_v, $VERBOSE = $VERBOSE, nil
+ Bundler::Fetcher.api_timeout = 1
+ $VERBOSE = old_v
+ G
+
+ bundle :install
+ expect(out).to include("Fetching source index from #{@server_uri}/")
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+ end
+end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
new file mode 100644
index 0000000000..302fd57cf0
--- /dev/null
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -0,0 +1,382 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
+ def rubygems_version(name, requirement)
+ require "bundler/source/rubygems/remote"
+ require "bundler/fetcher"
+ source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org"))
+ fetcher = Bundler::Fetcher.new(source)
+ index = fetcher.specs([name], nil)
+ rubygem = index.search(Gem::Dependency.new(name, requirement)).last
+ if rubygem.nil?
+ raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
+ "Found specs:\n#{index.send(:specs).inspect}"
+ end
+ "#{name} (#{rubygem.version})"
+ end
+
+ # there is no rbx-relative-require gem that will install on 1.9
+ it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do
+ gemfile <<-G
+ source "https://rubygems.org"
+ gem "linecache", "0.46"
+ G
+ bundle :lock
+ expect(err).to lack_errors
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+
+ # https://github.com/bundler/bundler/issues/1202
+ it "bundle cache works with rubygems 1.3.7 and pre gems",
+ :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do
+ install_gemfile <<-G
+ source "https://rubygems.org"
+ gem "rack", "1.3.0.beta2"
+ gem "will_paginate", "3.0.pre2"
+ G
+ bundle :cache
+ expect(out).not_to include("Removing outdated .gem files from vendor/cache")
+ end
+
+ # https://github.com/bundler/bundler/issues/1486
+ # this is a hash collision that only manifests on 1.8.7
+ it "finds the correct child versions", :ruby => "~> 1.8.7" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'i18n', '~> 0.6.0'
+ gem 'activesupport', '~> 3.0.5'
+ gem 'activerecord', '~> 3.0.5'
+ gem 'builder', '~> 2.1.2'
+ G
+ bundle :lock
+ expect(lockfile).to include("activemodel (3.0.5)")
+ end
+
+ it "resolves dependencies correctly", :ruby => "1.9.3" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'rails', '~> 3.0'
+ gem 'capybara', '~> 2.2.0'
+ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
+ G
+ bundle! :lock
+ expect(lockfile).to include(rubygems_version("rails", "~> 3.0"))
+ expect(lockfile).to include("capybara (2.2.1)")
+ end
+
+ it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem "sass-rails"
+ gem "rails", "~> 3"
+ gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written
+ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
+ G
+ bundle :lock
+ expect(lockfile).to include("gxapi_rails (0.0.6)")
+ end
+
+ it "installs the latest version of i18n" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem "i18n", "~> 0.6.0"
+ gem "activesupport", "~> 3.0"
+ gem "activerecord", "~> 3.0"
+ gem "builder", "~> 2.1.2"
+ G
+ bundle :lock
+ expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0"))
+ expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0"))
+ end
+
+ it "is able to update a top-level dependency when there is a conflict on a shared transitive child", :ruby => "2.1" do
+ # from https://github.com/bundler/bundler/issues/5031
+
+ gemfile <<-G
+ source "https://rubygems.org"
+ gem 'rails', '~> 4.2.7.1'
+ gem 'paperclip', '~> 5.1.0'
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (4.2.7.1)
+ actionpack (= 4.2.7.1)
+ actionview (= 4.2.7.1)
+ activejob (= 4.2.7.1)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ actionpack (4.2.7.1)
+ actionview (= 4.2.7.1)
+ activesupport (= 4.2.7.1)
+ rack (~> 1.6)
+ rack-test (~> 0.6.2)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (4.2.7.1)
+ activesupport (= 4.2.7.1)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ activejob (4.2.7.1)
+ activesupport (= 4.2.7.1)
+ globalid (>= 0.3.0)
+ activemodel (4.2.7.1)
+ activesupport (= 4.2.7.1)
+ builder (~> 3.1)
+ activerecord (4.2.7.1)
+ activemodel (= 4.2.7.1)
+ activesupport (= 4.2.7.1)
+ arel (~> 6.0)
+ activesupport (4.2.7.1)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ arel (6.0.3)
+ builder (3.2.2)
+ climate_control (0.0.3)
+ activesupport (>= 3.0)
+ cocaine (0.5.8)
+ climate_control (>= 0.0.3, < 1.0)
+ concurrent-ruby (1.0.2)
+ erubis (2.7.0)
+ globalid (0.3.7)
+ activesupport (>= 4.1.0)
+ i18n (0.7.0)
+ json (1.8.3)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ mail (2.6.4)
+ mime-types (>= 1.16, < 4)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mimemagic (0.3.2)
+ mini_portile2 (2.1.0)
+ minitest (5.9.1)
+ nokogiri (1.6.8)
+ mini_portile2 (~> 2.1.0)
+ pkg-config (~> 1.1.7)
+ paperclip (5.1.0)
+ activemodel (>= 4.2.0)
+ activesupport (>= 4.2.0)
+ cocaine (~> 0.5.5)
+ mime-types
+ mimemagic (~> 0.3.0)
+ pkg-config (1.1.7)
+ rack (1.6.4)
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (4.2.7.1)
+ actionmailer (= 4.2.7.1)
+ actionpack (= 4.2.7.1)
+ actionview (= 4.2.7.1)
+ activejob (= 4.2.7.1)
+ activemodel (= 4.2.7.1)
+ activerecord (= 4.2.7.1)
+ activesupport (= 4.2.7.1)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.2.7.1)
+ sprockets-rails
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (1.0.7)
+ activesupport (>= 4.2.0.beta, < 5.0)
+ nokogiri (~> 1.6.0)
+ rails-deprecated_sanitizer (>= 1.0.1)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ railties (4.2.7.1)
+ actionpack (= 4.2.7.1)
+ activesupport (= 4.2.7.1)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (11.3.0)
+ sprockets (3.7.0)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.0)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ thor (0.19.1)
+ thread_safe (0.3.5)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ paperclip (~> 5.1.0)
+ rails (~> 4.2.7.1)
+
+ BUNDLED WITH
+ 1.13.1
+ L
+
+ bundle! "lock --update paperclip"
+
+ expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
+ end
+
+ # https://github.com/bundler/bundler/issues/1500
+ it "does not fail install because of gem plugins" do
+ realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2")
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'rack', '1.0.1'
+ G
+
+ bundle "install --path vendor/bundle"
+ expect(err).not_to include("Could not find rake")
+ expect(err).to lack_errors
+ end
+
+ it "checks out git repos when the lockfile is corrupted" do
+ gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
+ gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
+ gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
+ G
+
+ lockfile <<-L
+ GIT
+ remote: git://github.com/carlhuda/rails-bundler-test.git
+ revision: 369e28a87419565f1940815219ea9200474589d4
+ branch: master
+ specs:
+ actionpack (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.1)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.2)
+ activemodel (3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ activerecord (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.2)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+
+ GIT
+ remote: git://github.com/carlhuda/rails-bundler-test.git
+ revision: 369e28a87419565f1940815219ea9200474589d4
+ branch: master
+ specs:
+ actionpack (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.1)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.2)
+ activemodel (3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ activerecord (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.2)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+
+ GIT
+ remote: git://github.com/carlhuda/rails-bundler-test.git
+ revision: 369e28a87419565f1940815219ea9200474589d4
+ branch: master
+ specs:
+ actionpack (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.1)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.2)
+ activemodel (3.2.2)
+ activesupport (= 3.2.2)
+ builder (~> 3.0.0)
+ activerecord (3.2.2)
+ activemodel (= 3.2.2)
+ activesupport (= 3.2.2)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activesupport (3.2.2)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ arel (3.0.2)
+ builder (3.0.0)
+ erubis (2.7.0)
+ hike (1.2.1)
+ i18n (0.6.0)
+ journey (1.0.3)
+ multi_json (1.1.0)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ sprockets (2.1.2)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ tilt (1.3.3)
+ tzinfo (0.3.32)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ actionpack!
+ activerecord!
+ activesupport!
+ L
+
+ bundle :lock
+ expect(err).to eq("")
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+
+ it "outputs a helpful error message when gems have invalid gemspecs" do
+ install_gemfile <<-G, :standalone => true
+ source 'https://rubygems.org'
+ gem "resque-scheduler", "2.2.0"
+ G
+ expect(out).to include("You have one or more invalid gemspecs that need to be fixed.")
+ expect(out).to include("resque-scheduler 2.2.0 has an invalid gemspec")
+ end
+end
diff --git a/spec/bundler/realworld/gemfile_source_header_spec.rb b/spec/bundler/realworld/gemfile_source_header_spec.rb
new file mode 100644
index 0000000000..ba888d43bd
--- /dev/null
+++ b/spec/bundler/realworld/gemfile_source_header_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+require "spec_helper"
+require "thread"
+
+RSpec.describe "fetching dependencies with a mirrored source", :realworld => true, :rubygems => ">= 2.0" do
+ let(:mirror) { "https://server.example.org" }
+ let(:original) { "http://127.0.0.1:#{@port}" }
+
+ before do
+ setup_server
+ bundle "config --local mirror.#{mirror} #{original}"
+ end
+
+ after do
+ Artifice.deactivate
+ @t.kill
+ @t.join
+ end
+
+ it "sets the 'X-Gemfile-Source' header and bundles successfully" do
+ gemfile <<-G
+ source "#{mirror}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+
+ private
+
+ def setup_server
+ require_rack
+ @port = find_unused_port
+ @server_uri = "http://127.0.0.1:#{@port}"
+
+ require File.expand_path("../../support/artifice/endpoint_mirror_source", __FILE__)
+
+ @t = Thread.new do
+ Rack::Server.start(:app => EndpointMirrorSource,
+ :Host => "0.0.0.0",
+ :Port => @port,
+ :server => "webrick",
+ :AccessLog => [],
+ :Logger => Spec::SilentLogger.new)
+ end.run
+
+ wait_for_server("127.0.0.1", @port)
+ end
+end
diff --git a/spec/bundler/realworld/mirror_probe_spec.rb b/spec/bundler/realworld/mirror_probe_spec.rb
new file mode 100644
index 0000000000..93dca0c173
--- /dev/null
+++ b/spec/bundler/realworld/mirror_probe_spec.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+require "spec_helper"
+require "thread"
+
+RSpec.describe "fetching dependencies with a not available mirror", :realworld => true do
+ let(:mirror) { @mirror_uri }
+ let(:original) { @server_uri }
+ let(:server_port) { @server_port }
+ let(:host) { "127.0.0.1" }
+
+ before do
+ require_rack
+ setup_server
+ setup_mirror
+ end
+
+ after do
+ Artifice.deactivate
+ @server_thread.kill
+ @server_thread.join
+ end
+
+ context "with a specific fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/__FALLBACK_TIMEOUT/" => "true",
+ "BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ gemfile <<-G
+ source "#{original}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a global fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__ALL__FALLBACK_TIMEOUT/" => "1",
+ "BUNDLE_MIRROR__ALL" => mirror)
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ gemfile <<-G
+ source "#{original}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a specific mirror without a fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
+ end
+
+ it "fails to install the gem with a timeout error" do
+ gemfile <<-G
+ source "#{original}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to include("Fetching source index from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Could not fetch specs from #{mirror}")
+ end
+
+ it "prints each error and warning on a new line" do
+ gemfile <<-G
+ source "#{original}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to eq "Fetching source index from #{mirror}/
+
+Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
+Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
+Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
+Could not fetch specs from #{mirror}/"
+ end
+ end
+
+ context "with a global mirror without a fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__ALL" => mirror)
+ end
+
+ it "fails to install the gem with a timeout error" do
+ gemfile <<-G
+ source "#{original}"
+ gem 'weakling'
+ G
+
+ bundle :install
+
+ expect(out).to include("Fetching source index from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
+ expect(out).to include("Could not fetch specs from #{mirror}")
+ end
+ end
+
+ def setup_server
+ @server_port = find_unused_port
+ @server_uri = "http://#{host}:#{@server_port}"
+
+ require File.expand_path("../../support/artifice/endpoint", __FILE__)
+
+ @server_thread = Thread.new do
+ Rack::Server.start(:app => Endpoint,
+ :Host => host,
+ :Port => @server_port,
+ :server => "webrick",
+ :AccessLog => [],
+ :Logger => Spec::SilentLogger.new)
+ end.run
+
+ wait_for_server(host, @server_port)
+ end
+
+ def setup_mirror
+ mirror_port = find_unused_port
+ @mirror_uri = "http://#{host}:#{mirror_port}"
+ end
+end
diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb
new file mode 100644
index 0000000000..6950bead19
--- /dev/null
+++ b/spec/bundler/realworld/parallel_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe "parallel", :realworld => true, :sometimes => true do
+ it "installs" do
+ gemfile <<-G
+ source "https://rubygems.org"
+ gem 'activesupport', '~> 3.2.13'
+ gem 'faker', '~> 1.1.2'
+ gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
+ G
+
+ bundle :install, :jobs => 4, :env => { "DEBUG" => "1" }
+
+ if Bundler.rubygems.provides?(">= 2.1.0")
+ expect(out).to match(/[1-3]: /)
+ else
+ expect(out).to include("is not threadsafe")
+ end
+
+ bundle "show activesupport"
+ expect(out).to match(/activesupport/)
+
+ bundle "show faker"
+ expect(out).to match(/faker/)
+
+ bundle "config jobs"
+ expect(out).to match(/: "4"/)
+ end
+
+ it "updates" do
+ install_gemfile <<-G
+ source "https://rubygems.org"
+ gem 'activesupport', '3.2.12'
+ gem 'faker', '~> 1.1.2'
+ G
+
+ gemfile <<-G
+ source "https://rubygems.org"
+ gem 'activesupport', '~> 3.2.12'
+ gem 'faker', '~> 1.1.2'
+ gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
+ G
+
+ bundle :update, :jobs => 4, :env => { "DEBUG" => "1" }
+
+ if Bundler.rubygems.provides?(">= 2.1.0")
+ expect(out).to match(/[1-3]: /)
+ else
+ expect(out).to include("is not threadsafe")
+ end
+
+ bundle "show activesupport"
+ expect(out).to match(/activesupport-3\.2\.\d+/)
+
+ bundle "show faker"
+ expect(out).to match(/faker/)
+
+ bundle "config jobs"
+ expect(out).to match(/: "4"/)
+ end
+
+ it "works with --standalone" do
+ gemfile <<-G, :standalone => true
+ source "https://rubygems.org"
+ gem "diff-lcs"
+ G
+
+ bundle :install, :standalone => true, :jobs => 4
+
+ ruby <<-RUBY, :no_lib => true
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ require "diff/lcs"
+ puts Diff::LCS
+ RUBY
+
+ expect(out).to eq("Diff::LCS")
+ end
+end