spec/appbundler/app_spec.rb in appbundler-0.5.0 vs spec/appbundler/app_spec.rb in appbundler-0.6.0
- old
+ new
@@ -1,335 +1,421 @@
-require 'spec_helper'
-require 'tmpdir'
-require 'fileutils'
-require 'mixlib/shellout'
-require 'appbundler/app'
-
-describe Appbundler do
-
- def all_specs
- @all_specs ||= []
- end
-
- def double_spec(name, version, dep_names)
- deps = dep_names.map {|n| double("Bundler::Dependency #{n}", :name => n.to_s) }
- spec = double("Bundler::LazySpecification '#{name}'", :name => name.to_s, :version => version, :dependencies => deps)
- all_specs << spec
- spec
- end
-
- def shellout!(cmd)
- s = Mixlib::ShellOut.new(cmd, :env => {"RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil, "APPBUNDLER_ALLOW_RVM" => "true"})
- s.run_command
- s.error!
- s
- end
-
- def target_bindir
- File.expand_path("../../test-tmp/bin", __FILE__)
- end
-
- context "given an app with multiple levels of dependencies" do
-
- let!(:second_level_dep_a_a) do
- double_spec(:second_level_dep_a_a, "2.1.0", [])
- end
-
- let!(:second_level_dep_shared) do
- double_spec(:second_level_dep_shared, "2.3.0", [])
- end
-
- let!(:second_level_dep_b_a) do
- double_spec(:second_level_dep_b_a, "2.2.0", [])
- end
-
- let!(:first_level_dep_a) do
- double_spec(:first_level_dep_a, "1.1.0", [:second_level_dep_a_a, :second_level_dep_shared])
- end
-
- let!(:first_level_dep_b) do
- double_spec(:first_level_dep_b, "1.2.0", [:second_level_dep_b_a, :second_level_dep_shared])
- end
-
- let!(:app_spec) do
- double_spec(:app, "1.0.0", [:first_level_dep_a, :first_level_dep_b])
- end
-
- let(:bin_path) { File.join(target_bindir, "foo") }
-
- let(:app_root) { "/opt/app/embedded/apps/app" }
-
- let(:app) do
- Appbundler::App.new(app_root, target_bindir)
- end
-
- before do
- allow(app).to receive(:gemfile_lock_specs).and_return(all_specs)
- end
-
- it "finds the running ruby interpreter" do
- expect(app.ruby).to eq(Gem.ruby)
- end
-
- it "finds all runtime dependencies of the app" do
- # we want to find the minimum set of gems that we need to activate to run
- # the application. To do this, we look at the app's runtime deps and
- # recursively search through the list of gemspecs that we got from the
- # Gemfile.lock, collecting all the runtime deps. This should get us the
- # smallest possible "activate.rb" file that can launch the application
- # with locked gem versions.
- expect(app.runtime_dep_specs).to include(first_level_dep_a)
- expect(app.runtime_dep_specs).to include(first_level_dep_b)
- expect(app.runtime_dep_specs).to include(second_level_dep_a_a)
- expect(app.runtime_dep_specs).to include(second_level_dep_b_a)
- expect(app.runtime_dep_specs).to include(second_level_dep_shared)
- expect(app.runtime_dep_specs.select {|s| s == second_level_dep_shared}.size).to eq(1)
- end
-
- it "generates gem activation code for the app" do
- # this is code with a bunch of gem "foo", "= X.Y.Z" statements. The top
- # level application is _not_ included in this, it's added to the load
- # path instead.
- expect(app.runtime_activate).to include(%q{gem "first_level_dep_a", "= 1.1.0"})
- expect(app.runtime_activate).to include(%q{gem "second_level_dep_a_a", "= 2.1.0"})
- expect(app.runtime_activate).to include(%q{gem "second_level_dep_shared", "= 2.3.0"})
- expect(app.runtime_activate).to include(%q{gem "first_level_dep_b", "= 1.2.0"})
- expect(app.runtime_activate).to include(%q{gem "second_level_dep_b_a", "= 2.2.0"})
- expect(app.runtime_activate).to_not include(%q{gem "app"})
- end
-
- it "locks the main app's gem via rubygems, and loads the proper binary" do
- expected_loading_code = <<-CODE
-gem "app", "= 1.0.0"
-
-spec = Gem::Specification.find_by_name("app", "= 1.0.0")
-bin_file = spec.bin_file("foo")
-
-Kernel.load(bin_file)
-CODE
- expect(app.load_statement_for(bin_path)).to eq(expected_loading_code)
- end
-
- it "generates code to override GEM_HOME and GEM_PATH (e.g., rvm)" do
- expected = %Q{ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"}
- expect(app.env_sanitizer).to eq(expected)
- expect(app.runtime_activate).to include(expected)
- end
-
- context "on windows" do
-
- let(:target_bindir) { "C:/opscode/chef/bin" }
-
- before do
- allow(app).to receive(:ruby).and_return("C:/opscode/chef/embedded/bin/ruby.exe")
- end
-
- it "computes the relative path to ruby" do
- expect(app.ruby_relative_path).to eq("../embedded/bin/ruby.exe")
- end
-
- it "generates batchfile stub code" do
- expected_batch_code=<<-E
-@ECHO OFF
-"%~dp0\\..\\embedded\\bin\\ruby.exe" "%~dpn0" %*
-E
- expect(app.batchfile_stub).to eq(expected_batch_code)
- end
-
- end
-
- end
-
- context "when created with the example application" do
- FIXTURES_PATH = File.expand_path("../../fixtures/", __FILE__).freeze
-
- APP_ROOT = File.join(FIXTURES_PATH, "appbundler-example-app").freeze
-
- let(:app_root) { APP_ROOT }
-
- let(:app) do
- Appbundler::App.new(APP_ROOT, target_bindir)
- end
-
- before(:all) do
- Dir.chdir(APP_ROOT) do
- shellout!("bundle install")
- shellout!("gem build appbundler-example-app.gemspec")
- shellout!("gem install appbundler-example-app-1.0.0.gem")
- end
- end
-
- before do
- FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
- FileUtils.mkdir_p(target_bindir)
- end
-
- after(:all) do
- shellout!("gem uninstall appbundler-example-app -a -q -x")
- FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
- end
-
- it "initializes ok" do
- app
- end
-
- it "names the app using the directory basename" do
- expect(app.name).to eq("appbundler-example-app")
- end
-
- it "lists the app's dependencies" do
- # only runtime deps
- expect(app.app_dependency_names).to eq(["chef"])
- end
-
- it "generates runtime activation code for the app" do
- expected_gem_activates=<<-E
-ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
-gem "chef", "= 12.4.1"
-gem "chef-config", "= 12.4.1"
-gem "mixlib-config", "= 2.2.1"
-gem "mixlib-shellout", "= 2.2.0"
-gem "chef-zero", "= 4.3.0"
-gem "ffi-yajl", "= 2.2.2"
-gem "libyajl2", "= 1.2.0"
-gem "hashie", "= 2.1.2"
-gem "mixlib-log", "= 1.6.0"
-gem "rack", "= 1.6.4"
-gem "uuidtools", "= 2.1.5"
-gem "diff-lcs", "= 1.2.5"
-gem "erubis", "= 2.7.0"
-gem "highline", "= 1.7.3"
-gem "mixlib-authentication", "= 1.3.0"
-gem "mixlib-cli", "= 1.5.0"
-gem "net-ssh", "= 2.9.2"
-gem "net-ssh-multi", "= 1.2.1"
-gem "net-ssh-gateway", "= 1.2.0"
-gem "ohai", "= 8.5.1"
-gem "ffi", "= 1.9.10"
-gem "ipaddress", "= 0.8.0"
-gem "mime-types", "= 2.6.1"
-gem "rake", "= 10.1.1"
-gem "systemu", "= 2.6.5"
-gem "wmi-lite", "= 1.0.0"
-gem "plist", "= 3.1.0"
-gem "pry", "= 0.9.12.6"
-gem "coderay", "= 1.1.0"
-gem "method_source", "= 0.8.2"
-gem "slop", "= 3.4.7"
-gem "rspec-core", "= 3.3.2"
-gem "rspec-support", "= 3.3.0"
-gem "rspec-expectations", "= 3.3.1"
-gem "rspec-mocks", "= 3.3.2"
-gem "rspec_junit_formatter", "= 0.2.3"
-gem "builder", "= 3.2.2"
-gem "serverspec", "= 2.23.1"
-gem "multi_json", "= 1.11.2"
-gem "rspec", "= 3.3.0"
-gem "rspec-its", "= 1.2.0"
-gem "specinfra", "= 2.43.3"
-gem "net-scp", "= 1.2.1"
-gem "net-telnet", "= 0.1.1"
-gem "sfl", "= 2.2"
-gem "syslog-logger", "= 1.6.8"
-E
- expect(app.runtime_activate).to include(expected_gem_activates)
- end
-
- it "lists the app's executables" do
- expected_executables = %w[app-binary-1 app-binary-2].map do |basename|
- File.join(app_root, "/bin", basename)
- end
- expect(app.executables).to match_array(expected_executables)
- end
-
- it "generates an executable 'stub' for an executable in the app" do
- app_binary_1_path = app.executables.grep(/app\-binary\-1/).first
- executable_content = app.binstub(app_binary_1_path)
-
- shebang = executable_content.lines.first
- expect(shebang).to match(/^\#\!/)
- expect(shebang).to include(Gem.ruby)
-
- expect(executable_content).to include(app.runtime_activate)
-
- load_binary = executable_content.lines.to_a.last
-
- expected_load_path = %Q[Kernel.load(bin_file)\n]
-
- expect(load_binary).to eq(expected_load_path)
- end
-
- it "generates executable stubs for all executables in the app" do
- app.write_executable_stubs
- binary_1 = File.join(target_bindir, "app-binary-1")
- binary_2 = File.join(target_bindir, "app-binary-2")
- expect(File.exist?(binary_1)).to be(true)
- expect(File.exist?(binary_2)).to be(true)
- expect(File.executable?(binary_1)).to be(true)
- expect(File.executable?(binary_1)).to be(true)
- expect(shellout!(binary_1).stdout).to eq("binary 1 ran\n")
- expect(shellout!(binary_2).stdout).to eq("binary 2 ran\n")
- end
-
- context "and the executable is symlinked to a different directory" do
-
- let(:symlinks_root_dir) do
- Dir.mktmpdir
- end
-
- let(:symlinks_bin_dir) do
- d = File.join(symlinks_root_dir, "bin")
- FileUtils.mkdir(d)
- d
- end
-
- let(:binary_symlinked_path) { File.join(symlinks_bin_dir, "app-binary-1") }
-
- let(:binary_orignal_path) { File.join(target_bindir, "app-binary-1") }
-
- before do
- app.write_executable_stubs
- FileUtils.ln_s(binary_orignal_path, binary_symlinked_path)
- end
-
- after do
- FileUtils.rm_rf(symlinks_root_dir)
- end
-
- it "correctly runs the executable via the symlinked executable" do
- expect(shellout!(binary_symlinked_path).stdout).to eq("binary 1 ran\n")
- end
-
- end
-
- context "on windows" do
-
- let(:expected_ruby_relpath) do
- app.ruby_relative_path.gsub('/', '\\')
- end
-
- let(:expected_batch_code) do
- <<-E
-@ECHO OFF
-"%~dp0\\#{expected_ruby_relpath}" "%~dpn0" %*
-E
- end
-
- before do
- stub_const("RUBY_PLATFORM", "mingw")
- end
-
- it "creates a batchfile wrapper for each executable" do
- app.write_executable_stubs
- binary_1 = File.join(target_bindir, "app-binary-1.bat")
- binary_2 = File.join(target_bindir, "app-binary-2.bat")
- expect(File.exist?(binary_1)).to be(true)
- expect(File.exist?(binary_2)).to be(true)
- expect(IO.read(binary_1)).to eq(expected_batch_code)
- expect(IO.read(binary_2)).to eq(expected_batch_code)
- end
-
- end
-
- end
-
-end
+require 'spec_helper'
+require 'tmpdir'
+require 'fileutils'
+require 'mixlib/shellout'
+require 'appbundler/app'
+
+describe Appbundler do
+
+ def all_specs
+ @all_specs ||= []
+ end
+
+ def double_spec(name, version, dep_names)
+ deps = dep_names.map {|n| double("Bundler::Dependency #{n}", :name => n.to_s) }
+ spec = double("Bundler::LazySpecification '#{name}'", :name => name.to_s, :version => version, :dependencies => deps)
+ all_specs << spec
+ spec
+ end
+
+ def shellout!(cmd)
+ s = Mixlib::ShellOut.new(cmd, :env => {"RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil, "APPBUNDLER_ALLOW_RVM" => "true"})
+ s.run_command
+ s.error!
+ s
+ end
+
+ def target_bindir
+ File.expand_path("../../test-tmp/bin", __FILE__)
+ end
+
+ context "given an app with multiple levels of dependencies" do
+
+ let!(:second_level_dep_a_a) do
+ double_spec(:second_level_dep_a_a, "2.1.0", [])
+ end
+
+ let!(:second_level_dep_shared) do
+ double_spec(:second_level_dep_shared, "2.3.0", [])
+ end
+
+ let!(:second_level_dep_b_a) do
+ double_spec(:second_level_dep_b_a, "2.2.0", [])
+ end
+
+ let!(:first_level_dep_a) do
+ double_spec(:first_level_dep_a, "1.1.0", [:second_level_dep_a_a, :second_level_dep_shared])
+ end
+
+ let!(:first_level_dep_b) do
+ double_spec(:first_level_dep_b, "1.2.0", [:second_level_dep_b_a, :second_level_dep_shared])
+ end
+
+ let!(:app_spec) do
+ double_spec(:app, "1.0.0", [:first_level_dep_a, :first_level_dep_b])
+ end
+
+ let(:bin_path) { File.join(target_bindir, "foo") }
+
+ let(:app_root) { "/opt/app/embedded/apps/app" }
+
+ let(:app) do
+ Appbundler::App.new(app_root, target_bindir)
+ end
+
+ before do
+ allow(app).to receive(:gemfile_lock_specs).and_return(all_specs)
+ end
+
+ it "finds the running ruby interpreter" do
+ expect(app.ruby).to eq(Gem.ruby)
+ end
+
+ it "finds all runtime dependencies of the app" do
+ # we want to find the minimum set of gems that we need to activate to run
+ # the application. To do this, we look at the app's runtime deps and
+ # recursively search through the list of gemspecs that we got from the
+ # Gemfile.lock, collecting all the runtime deps. This should get us the
+ # smallest possible "activate.rb" file that can launch the application
+ # with locked gem versions.
+ expect(app.runtime_dep_specs).to include(first_level_dep_a)
+ expect(app.runtime_dep_specs).to include(first_level_dep_b)
+ expect(app.runtime_dep_specs).to include(second_level_dep_a_a)
+ expect(app.runtime_dep_specs).to include(second_level_dep_b_a)
+ expect(app.runtime_dep_specs).to include(second_level_dep_shared)
+ expect(app.runtime_dep_specs.select {|s| s == second_level_dep_shared}.size).to eq(1)
+ end
+
+ it "generates gem activation code for the app" do
+ # this is code with a bunch of gem "foo", "= X.Y.Z" statements. The top
+ # level application is _not_ included in this, it's added to the load
+ # path instead.
+ expect(app.runtime_activate).to include(%q{gem "first_level_dep_a", "= 1.1.0"})
+ expect(app.runtime_activate).to include(%q{gem "second_level_dep_a_a", "= 2.1.0"})
+ expect(app.runtime_activate).to include(%q{gem "second_level_dep_shared", "= 2.3.0"})
+ expect(app.runtime_activate).to include(%q{gem "first_level_dep_b", "= 1.2.0"})
+ expect(app.runtime_activate).to include(%q{gem "second_level_dep_b_a", "= 2.2.0"})
+ expect(app.runtime_activate).to_not include(%q{gem "app"})
+ end
+
+ it "locks the main app's gem via rubygems, and loads the proper binary" do
+ expected_loading_code = <<-CODE
+gem "app", "= 1.0.0"
+
+spec = Gem::Specification.find_by_name("app", "= 1.0.0")
+bin_file = spec.bin_file("foo")
+
+Kernel.load(bin_file)
+CODE
+ expect(app.load_statement_for(bin_path)).to eq(expected_loading_code)
+ end
+
+ it "generates code to override GEM_HOME and GEM_PATH (e.g., rvm)" do
+ expected = %Q{ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"}
+ expect(app.env_sanitizer).to eq(expected)
+ expect(app.runtime_activate).to include(expected)
+ end
+
+ context "on windows" do
+
+ let(:target_bindir) { "C:/opscode/chef/bin" }
+
+ before do
+ allow(app).to receive(:ruby).and_return("C:/opscode/chef/embedded/bin/ruby.exe")
+ end
+
+ it "computes the relative path to ruby" do
+ expect(app.ruby_relative_path).to eq("../embedded/bin/ruby.exe")
+ end
+
+ it "generates batchfile stub code" do
+ expected_batch_code=<<-E
+@ECHO OFF
+"%~dp0\\..\\embedded\\bin\\ruby.exe" "%~dpn0" %*
+E
+ expect(app.batchfile_stub).to eq(expected_batch_code)
+ end
+
+ end
+
+ end
+
+ context "when created with the example application" do
+ FIXTURES_PATH = File.expand_path("../../fixtures/", __FILE__).freeze
+
+ APP_ROOT = File.join(FIXTURES_PATH, "appbundler-example-app").freeze
+
+ let(:app_root) { APP_ROOT }
+
+ let(:app) do
+ Appbundler::App.new(APP_ROOT, target_bindir)
+ end
+
+ before(:all) do
+ Dir.chdir(APP_ROOT) do
+ if windows?
+ FileUtils.cp("Gemfile.lock.windows", "Gemfile.lock")
+ else
+ FileUtils.cp("Gemfile.lock.unix", "Gemfile.lock")
+ end
+ shellout!("bundle install")
+ shellout!("gem build appbundler-example-app.gemspec")
+ shellout!("gem install appbundler-example-app-1.0.0.gem")
+ Gem.clear_paths
+ end
+ end
+
+ before do
+ FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
+ FileUtils.mkdir_p(target_bindir)
+ end
+
+ after(:all) do
+ shellout!("gem uninstall appbundler-example-app -a -q -x")
+ FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
+ FileUtils.rm(File.join(APP_ROOT, "Gemfile.lock"))
+ end
+
+ it "initializes ok" do
+ app
+ end
+
+ it "names the app using the directory basename" do
+ expect(app.name).to eq("appbundler-example-app")
+ end
+
+ it "lists the app's dependencies" do
+ # only runtime deps
+ expect(app.app_dependency_names).to eq(["chef"])
+ end
+
+ it "generates runtime activation code for the app" do
+ expected_gem_activates= if windows?
+ <<-E
+ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
+gem "chef", "= 12.4.1"
+gem "chef-config", "= 12.4.1"
+gem "mixlib-config", "= 2.2.1"
+gem "mixlib-shellout", "= 2.2.0"
+gem "win32-process", "= 0.7.5"
+gem "ffi", "= 1.9.10"
+gem "chef-zero", "= 4.3.0"
+gem "ffi-yajl", "= 2.2.2"
+gem "libyajl2", "= 1.2.0"
+gem "hashie", "= 2.1.2"
+gem "mixlib-log", "= 1.6.0"
+gem "rack", "= 1.6.4"
+gem "uuidtools", "= 2.1.5"
+gem "diff-lcs", "= 1.2.5"
+gem "erubis", "= 2.7.0"
+gem "highline", "= 1.7.3"
+gem "mixlib-authentication", "= 1.3.0"
+gem "mixlib-cli", "= 1.5.0"
+gem "net-ssh", "= 2.9.2"
+gem "net-ssh-multi", "= 1.2.1"
+gem "net-ssh-gateway", "= 1.2.0"
+gem "ohai", "= 8.5.1"
+gem "ipaddress", "= 0.8.0"
+gem "mime-types", "= 2.6.1"
+gem "rake", "= 10.1.1"
+gem "systemu", "= 2.6.5"
+gem "wmi-lite", "= 1.0.0"
+gem "plist", "= 3.1.0"
+gem "pry", "= 0.9.12.6"
+gem "coderay", "= 1.1.0"
+gem "method_source", "= 0.8.2"
+gem "slop", "= 3.4.7"
+gem "win32console", "= 1.3.2"
+gem "rspec-core", "= 3.3.2"
+gem "rspec-support", "= 3.3.0"
+gem "rspec-expectations", "= 3.3.1"
+gem "rspec-mocks", "= 3.3.2"
+gem "rspec_junit_formatter", "= 0.2.3"
+gem "builder", "= 3.2.2"
+gem "serverspec", "= 2.23.1"
+gem "multi_json", "= 1.11.2"
+gem "rspec", "= 3.3.0"
+gem "rspec-its", "= 1.2.0"
+gem "specinfra", "= 2.43.3"
+gem "net-scp", "= 1.2.1"
+gem "net-telnet", "= 0.1.1"
+gem "sfl", "= 2.2"
+gem "syslog-logger", "= 1.6.8"
+gem "win32-api", "= 1.5.3"
+gem "win32-dir", "= 0.5.0"
+gem "win32-event", "= 0.6.1"
+gem "win32-ipc", "= 0.6.6"
+gem "win32-eventlog", "= 0.6.3"
+gem "win32-mmap", "= 0.4.1"
+gem "win32-mutex", "= 0.4.2"
+gem "win32-service", "= 0.8.6"
+gem "windows-api", "= 0.4.4"
+gem "windows-pr", "= 1.2.4"
+E
+ else
+ <<-E
+ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
+gem "chef", "= 12.4.1"
+gem "chef-config", "= 12.4.1"
+gem "mixlib-config", "= 2.2.1"
+gem "mixlib-shellout", "= 2.2.0"
+gem "chef-zero", "= 4.3.0"
+gem "ffi-yajl", "= 2.2.2"
+gem "libyajl2", "= 1.2.0"
+gem "hashie", "= 2.1.2"
+gem "mixlib-log", "= 1.6.0"
+gem "rack", "= 1.6.4"
+gem "uuidtools", "= 2.1.5"
+gem "diff-lcs", "= 1.2.5"
+gem "erubis", "= 2.7.0"
+gem "highline", "= 1.7.3"
+gem "mixlib-authentication", "= 1.3.0"
+gem "mixlib-cli", "= 1.5.0"
+gem "net-ssh", "= 2.9.2"
+gem "net-ssh-multi", "= 1.2.1"
+gem "net-ssh-gateway", "= 1.2.0"
+gem "ohai", "= 8.5.1"
+gem "ffi", "= 1.9.10"
+gem "ipaddress", "= 0.8.0"
+gem "mime-types", "= 2.6.1"
+gem "rake", "= 10.1.1"
+gem "systemu", "= 2.6.5"
+gem "wmi-lite", "= 1.0.0"
+gem "plist", "= 3.1.0"
+gem "pry", "= 0.9.12.6"
+gem "coderay", "= 1.1.0"
+gem "method_source", "= 0.8.2"
+gem "slop", "= 3.4.7"
+gem "rspec-core", "= 3.3.2"
+gem "rspec-support", "= 3.3.0"
+gem "rspec-expectations", "= 3.3.1"
+gem "rspec-mocks", "= 3.3.2"
+gem "rspec_junit_formatter", "= 0.2.3"
+gem "builder", "= 3.2.2"
+gem "serverspec", "= 2.23.1"
+gem "multi_json", "= 1.11.2"
+gem "rspec", "= 3.3.0"
+gem "rspec-its", "= 1.2.0"
+gem "specinfra", "= 2.43.3"
+gem "net-scp", "= 1.2.1"
+gem "net-telnet", "= 0.1.1"
+gem "sfl", "= 2.2"
+gem "syslog-logger", "= 1.6.8"
+E
+ end
+ expect(app.runtime_activate).to include(expected_gem_activates)
+ end
+
+ it "lists the app's executables" do
+ spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
+ expected_executables = %w[app-binary-1 app-binary-2].map do |basename|
+ File.join(spec.gem_dir, "/bin", basename)
+ end
+ expect(app.executables).to match_array(expected_executables)
+ end
+
+ it "generates an executable 'stub' for an executable in the app" do
+ app_binary_1_path = app.executables.grep(/app\-binary\-1/).first
+ executable_content = app.binstub(app_binary_1_path)
+
+ shebang = executable_content.lines.first
+ expect(shebang).to match(/^\#\!/)
+ expect(shebang).to include(Gem.ruby)
+
+ expect(executable_content).to include(app.runtime_activate)
+
+ load_binary = executable_content.lines.to_a.last
+
+ expected_load_path = %Q[Kernel.load(bin_file)\n]
+
+ expect(load_binary).to eq(expected_load_path)
+ end
+
+ it "generates executable stubs for all executables in the app" do
+ app.write_executable_stubs
+ binary_1 = File.join(target_bindir, "app-binary-1")
+ binary_2 = File.join(target_bindir, "app-binary-2")
+ expect(File.exist?(binary_1)).to be(true)
+ expect(File.exist?(binary_2)).to be(true)
+ expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
+ expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
+ expect(shellout!(binary_1).stdout.strip).to eq("binary 1 ran")
+ expect(shellout!(binary_2).stdout.strip).to eq("binary 2 ran")
+ end
+
+ it "copies over Gemfile.lock to the gem directory" do
+ spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
+ gem_path = spec.gem_dir
+ app.copy_bundler_env
+ expect(File.exists?(File.join(gem_path, 'Gemfile.lock'))).to be(true)
+ end
+
+ it "copies over .bundler to the gem directory" do
+ spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
+ gem_path = spec.gem_dir
+ app.copy_bundler_env
+ expect(File.directory?(File.join(gem_path, '.bundle'))).to be(true)
+ expect(File.exists?(File.join(gem_path, '.bundle/config'))).to be(true)
+ end
+ context "and the executable is symlinked to a different directory", :not_supported_on_windows do
+
+ let(:symlinks_root_dir) do
+ Dir.mktmpdir
+ end
+
+ let(:symlinks_bin_dir) do
+ d = File.join(symlinks_root_dir, "bin")
+ FileUtils.mkdir(d)
+ d
+ end
+
+ let(:binary_symlinked_path) { File.join(symlinks_bin_dir, "app-binary-1") }
+
+ let(:binary_orignal_path) { File.join(target_bindir, "app-binary-1") }
+
+ before do
+ app.write_executable_stubs
+ FileUtils.ln_s(binary_orignal_path, binary_symlinked_path)
+ end
+
+ after do
+ FileUtils.rm_rf(symlinks_root_dir)
+ end
+
+ it "correctly runs the executable via the symlinked executable" do
+ expect(shellout!(binary_symlinked_path).stdout).to eq("binary 1 ran\n")
+ end
+
+ end
+
+ context "on windows" do
+
+ let(:expected_ruby_relpath) do
+ app.ruby_relative_path.gsub('/', '\\')
+ end
+
+ let(:expected_batch_code) do
+ <<-E
+@ECHO OFF
+"%~dp0\\#{expected_ruby_relpath}" "%~dpn0" %*
+E
+ end
+
+ before do
+ stub_const("RUBY_PLATFORM", "mingw")
+ end
+
+ it "creates a batchfile wrapper for each executable" do
+ app.write_executable_stubs
+ binary_1 = File.join(target_bindir, "app-binary-1.bat")
+ binary_2 = File.join(target_bindir, "app-binary-2.bat")
+ expect(File.exist?(binary_1)).to be(true)
+ expect(File.exist?(binary_2)).to be(true)
+ expect(IO.read(binary_1)).to eq(expected_batch_code)
+ expect(IO.read(binary_2)).to eq(expected_batch_code)
+ end
+
+ end
+
+ end
+
+end