# frozen_string_literal: true require "bundler" require "tmpdir" RSpec.describe Bundler do describe "#load_marshal" do it "is a private method and raises an error" do data = Marshal.dump(Bundler) expect { Bundler.load_marshal(data) }.to raise_error(NoMethodError, /private method `load_marshal' called/) end it "loads any data" do data = Marshal.dump(Bundler) expect(Bundler.send(:load_marshal, data)).to eq(Bundler) end end describe "#safe_load_marshal" do it "fails on unexpected class" do data = Marshal.dump(Bundler) expect { Bundler.safe_load_marshal(data) }.to raise_error(Bundler::MarshalError) end it "loads simple structure" do simple_structure = { "name" => [:abc] } data = Marshal.dump(simple_structure) expect(Bundler.safe_load_marshal(data)).to eq(simple_structure) end it "loads Gem::Version" do gem_version = Gem::Version.new("3.7.2") data = Marshal.dump(gem_version) expect(Bundler.safe_load_marshal(data)).to eq(gem_version) end it "loads Gem::Specification" do gem_spec = Gem::Specification.new("name", "3.7.2") data = Marshal.dump(gem_spec) expect(Bundler.safe_load_marshal(data)).to eq(gem_spec) end end 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 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 # -*- 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) do if Gem.win_platform? %w[C:/a C:/b C:/c C:/../d C:/e] else %w[/a /b c ../d /e] end end 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) do if Gem.win_platform? "C:/e/executable" else "/e/executable" end end 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 expect(Bundler).to receive(:use_system_gems?).and_return(false) Bundler.send(:configure_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 = <