require 'spec_helper' module Omnibus describe Builder do let(:software) do double(Software, name: 'chefdk', install_dir: project_dir, project_dir: project_dir, ) end let(:project_dir) { on_windows ? 'C:/opscode/chefdk' : '/opt/chefdk' } let(:on_windows) { false } let(:msys_bash) { "C:\\opscode\\chefdk\\embedded\\msys\\1.0\\bin\\bash.exe" } def run_build_command subject.send(:build_commands)[0].run(subject) end subject { described_class.new(software) } before do allow(subject).to receive(:windows?).and_return(on_windows) allow(subject).to receive(:windows_safe_path) do |*args| path = File.join(*args) path.gsub!(File::SEPARATOR, '\\') if on_windows end end describe '#command' do it 'is a DSL method' do expect(subject).to have_exposed_method(:command) end end describe '#workers' do it 'is a DSL method' do expect(subject).to have_exposed_method(:workers) end end describe '#ruby' do it 'is a DSL method' do expect(subject).to have_exposed_method(:ruby) end end describe '#gem' do it 'is a DSL method' do expect(subject).to have_exposed_method(:gem) end end describe '#bundle' do it 'is a DSL method' do expect(subject).to have_exposed_method(:bundle) end end describe '#appbundle' do it 'is a DSL method' do expect(subject).to have_exposed_method(:appbundle) end end describe '#block' do it 'is a DSL method' do expect(subject).to have_exposed_method(:block) end end describe '#erb' do it 'is a DSL method' do expect(subject).to have_exposed_method(:erb) end end describe '#mkdir' do it 'is a DSL method' do expect(subject).to have_exposed_method(:mkdir) end end describe '#touch' do it 'is a DSL method' do expect(subject).to have_exposed_method(:touch) end end describe '#delete' do it 'is a DSL method' do expect(subject).to have_exposed_method(:delete) end end describe '#copy' do it 'is a DSL method' do expect(subject).to have_exposed_method(:copy) end end describe '#move' do it 'is a DSL method' do expect(subject).to have_exposed_method(:move) end end describe '#link' do it 'is a DSL method' do expect(subject).to have_exposed_method(:link) end end describe '#sync' do it 'is a DSL method' do expect(subject).to have_exposed_method(:sync) end end describe '#update_config_guess' do it 'is a DSL method' do expect(subject).to have_exposed_method(:update_config_guess) end end describe '#windows_safe_path' do it 'is a DSL method' do expect(subject).to have_exposed_method(:windows_safe_path) end end describe '#project_dir' do it 'is a DSL method' do expect(subject).to have_exposed_method(:project_dir) end end describe '#install_dir' do it 'is a DSL method' do expect(subject).to have_exposed_method(:install_dir) end end describe '#make' do before do allow(subject).to receive(:command) end it 'is a DSL method' do expect(subject).to have_exposed_method(:make) end context 'when :bin is present' do it 'uses the custom bin' do expect(subject).to receive(:command) .with('/path/to/make', in_msys_bash: true) subject.make(bin: '/path/to/make') end end context 'when gmake is present' do before do allow(Omnibus).to receive(:which) .with('gmake') .and_return('/bin/gmake') end it 'uses gmake and sets MAKE=gmake' do expect(subject).to receive(:command) .with('gmake', env: { 'MAKE' => 'gmake' }, in_msys_bash: true) subject.make end end context 'when gmake is not present' do before do allow(Omnibus).to receive(:which) .and_return(nil) end it 'uses make' do expect(subject).to receive(:command) .with('make', in_msys_bash: true) subject.make end end it 'accepts 0 options' do expect(subject).to receive(:command) .with('make', in_msys_bash: true) expect { subject.make }.to_not raise_error end it 'accepts an additional command string' do expect(subject).to receive(:command) .with('make install', in_msys_bash: true) expect { subject.make('install') }.to_not raise_error end it 'persists given options' do expect(subject).to receive(:command) .with('make', timeout: 3600, in_msys_bash: true) subject.make(timeout: 3600) end end describe '#configure' do before do allow(subject).to receive(:command) end it 'is a DSL method' do expect(subject).to have_exposed_method(:configure) end context 'on 64-bit windows' do let(:on_windows) { true } let(:windows_i386) { false } before do allow(subject).to receive(:windows_arch_i386?) .and_return(windows_i386) end it 'invokes appends platform host to the options' do expect(subject).to receive(:command) .with("./configure --host=x86_64-w64-mingw32 --prefix=#{project_dir}/embedded", in_msys_bash: true) subject.configure() end end context 'when :bin is present' do it 'uses the custom bin' do expect(subject).to receive(:command) .with("/path/to/configure --prefix=#{project_dir}/embedded", in_msys_bash: true) subject.configure(bin: '/path/to/configure') end end context 'when :prefix is present' do it 'emits non-empty prefix' do expect(subject).to receive(:command) .with("./configure --prefix=/some/prefix", in_msys_bash: true) subject.configure(prefix: '/some/prefix') end it 'omits prefix if empty' do expect(subject).to receive(:command) .with("./configure", in_msys_bash: true) subject.configure(prefix: '') end end it 'accepts 0 options' do expect(subject).to receive(:command) .with("./configure --prefix=#{project_dir}/embedded", in_msys_bash: true) expect { subject.configure }.to_not raise_error end it 'accepts an additional command string' do expect(subject).to receive(:command) .with("./configure --prefix=#{project_dir}/embedded --myopt", in_msys_bash: true) expect { subject.configure('--myopt') }.to_not raise_error end it 'persists given options' do expect(subject).to receive(:command) .with("./configure --prefix=#{project_dir}/embedded", timeout: 3600, in_msys_bash: true) subject.configure(timeout: 3600) end end describe '#patch' do before do allow(subject).to receive(:find_file) .with('config/patches', 'good_patch') .and_return( [ ["#{project_dir}/patch_location1/good_patch", "#{project_dir}/patch_location2/good_patch"], "#{project_dir}/patch_location2/good_patch" ]) end it 'is a DSL method' do expect(subject).to have_exposed_method(:patch) end it 'invokes patch with patch level 1 unless specified' do expect { subject.patch(source: 'good_patch') }.to_not raise_error expect(subject).to receive(:shellout!) .with("patch -p1 -i #{project_dir}/patch_location2/good_patch", in_msys_bash: true) run_build_command end it 'invokes patch with patch level provided' do expect { subject.patch(source: 'good_patch', plevel: 0) }.to_not raise_error expect(subject).to receive(:shellout!) .with("patch -p0 -i #{project_dir}/patch_location2/good_patch", in_msys_bash: true) run_build_command end it 'invokes patch differently if target is provided' do expect { subject.patch(source: 'good_patch', target: 'target/path') }.to_not raise_error expect(subject).to receive(:shellout!) .with("cat #{project_dir}/patch_location2/good_patch | patch -p1 target/path", in_msys_bash: true) run_build_command end it 'persists other options' do expect { subject.patch(source: 'good_patch', timeout:3600) }.to_not raise_error expect(subject).to receive(:shellout!) .with("patch -p1 -i #{project_dir}/patch_location2/good_patch", timeout: 3600, in_msys_bash: true) run_build_command end end describe "#shasum" do let(:build_step) do Proc.new { block do command("true") end } end let(:tmp_dir) { Dir.mktmpdir } after { FileUtils.rmdir(tmp_dir) } let(:software) do double(Software, name: 'chefdk', install_dir: tmp_dir, project_dir: tmp_dir, overridden?: false) end let(:before_build_shasum) do b = described_class.new(software) b.evaluate(&build_step) b.shasum end it "returns the same value when called before or after the build" do subject.evaluate(&build_step) subject.build expect(subject.shasum).to eq(before_build_shasum) end end end end