Merge pull request #16299 from jawshooah/refactor-uninstall-test
Refactor uninstall_test.rb (bonus: bugfixes!)
This commit is contained in:
commit
92015efb53
|
@ -225,19 +225,7 @@ class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base
|
||||||
# :early_script should not delete files, better defer that to :script.
|
# :early_script should not delete files, better defer that to :script.
|
||||||
# If Cask writers never need :early_script it may be removed in the future.
|
# If Cask writers never need :early_script it may be removed in the future.
|
||||||
def uninstall_early_script(directives)
|
def uninstall_early_script(directives)
|
||||||
executable, script_arguments = self.class.read_script_arguments(
|
uninstall_script(directives, directive_name: :early_script)
|
||||||
directives,
|
|
||||||
'uninstall',
|
|
||||||
{:must_succeed => true, :sudo => true},
|
|
||||||
{:print_stdout => true},
|
|
||||||
:early_script
|
|
||||||
)
|
|
||||||
ohai "Running uninstall script #{executable}"
|
|
||||||
raise Hbc::CaskInvalidError.new(@cask, "#{stanza} :early_script without :executable") if executable.nil?
|
|
||||||
executable_path = @cask.staged_path.join(executable)
|
|
||||||
@command.run('/bin/chmod', :args => ['+x', executable_path]) if File.exists?(executable_path)
|
|
||||||
@command.run(executable_path, script_arguments)
|
|
||||||
sleep 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
|
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
|
||||||
|
@ -306,7 +294,7 @@ class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base
|
||||||
|
|
||||||
def get_unix_pids(bundle_id)
|
def get_unix_pids(bundle_id)
|
||||||
pid_string = @command.run!('/usr/bin/osascript',
|
pid_string = @command.run!('/usr/bin/osascript',
|
||||||
:args => ['-e', %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{id}"}],
|
:args => ['-e', %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}"}],
|
||||||
:sudo => true).stdout.chomp
|
:sudo => true).stdout.chomp
|
||||||
return [] unless pid_string.match(%r{\A\d+(?:\s*,\s*\d+)*\Z}) # sanity check
|
return [] unless pid_string.match(%r{\A\d+(?:\s*,\s*\d+)*\Z}) # sanity check
|
||||||
pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i)
|
pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i)
|
||||||
|
@ -335,14 +323,17 @@ class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
# :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted
|
# :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted
|
||||||
def uninstall_script(directives)
|
def uninstall_script(directives, directive_name: :script)
|
||||||
executable, script_arguments = self.class.read_script_arguments(directives,
|
executable, script_arguments = self.class.read_script_arguments(directives,
|
||||||
'uninstall',
|
'uninstall',
|
||||||
{:must_succeed => true, :sudo => true},
|
{:must_succeed => true, :sudo => true},
|
||||||
{:print_stdout => true},
|
{:print_stdout => true},
|
||||||
:script)
|
directive_name)
|
||||||
raise Hbc::CaskInvalidError.new(@cask, "#{stanza} :script without :executable.") if executable.nil?
|
ohai "Running uninstall script #{executable}"
|
||||||
@command.run(@cask.staged_path.join(executable), script_arguments)
|
raise Hbc::CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
|
||||||
|
executable_path = @cask.staged_path.join(executable)
|
||||||
|
@command.run('/bin/chmod', :args => ['+x', '--', executable_path]) if File.exists?(executable_path)
|
||||||
|
@command.run(executable_path, script_arguments)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -355,7 +346,7 @@ class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_delete(directives, expand_tilde=true)
|
def uninstall_delete(directives, expand_tilde=true)
|
||||||
Array(directives[:delete]).flatten.each_slice(PATH_ARG_SLICE_SIZE) do |path_slice|
|
Array(directives[:delete]).concat(Array(directives[:trash])).flatten.each_slice(PATH_ARG_SLICE_SIZE) do |path_slice|
|
||||||
ohai "Removing files: #{path_slice.utf8_inspect}"
|
ohai "Removing files: #{path_slice.utf8_inspect}"
|
||||||
path_slice = self.class.expand_path_strings(path_slice) if expand_tilde
|
path_slice = self.class.expand_path_strings(path_slice) if expand_tilde
|
||||||
path_slice = self.class.remove_relative_path_strings(:delete, path_slice)
|
path_slice = self.class.remove_relative_path_strings(:delete, path_slice)
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
describe Hbc::Artifact::Uninstall do
|
describe Hbc::Artifact::Uninstall do
|
||||||
|
let(:cask) { Hbc.load('with-installable') }
|
||||||
|
let(:uninstall_artifact) { Hbc::Artifact::Uninstall.new(cask, Hbc::FakeSystemCommand) }
|
||||||
|
|
||||||
before {
|
before {
|
||||||
@cask = Hbc.load('with-installable')
|
|
||||||
shutup do
|
shutup do
|
||||||
TestHelper.install_without_artifacts(@cask)
|
TestHelper.install_without_artifacts(cask)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
describe 'install_phase' do
|
describe 'install_phase' do
|
||||||
it 'does nothing, because the install_phase method is a no-op' do
|
it 'does nothing, because the install_phase method is a no-op' do
|
||||||
uninstall_artifact = Hbc::Artifact::Uninstall.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
shutup do
|
shutup do
|
||||||
uninstall_artifact.install_phase
|
uninstall_artifact.install_phase
|
||||||
end
|
end
|
||||||
|
@ -19,7 +20,6 @@ describe Hbc::Artifact::Uninstall do
|
||||||
|
|
||||||
describe 'zap_phase' do
|
describe 'zap_phase' do
|
||||||
it 'does nothing, because the zap_phase method is a no-op' do
|
it 'does nothing, because the zap_phase method is a no-op' do
|
||||||
uninstall_artifact = Hbc::Artifact::Uninstall.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
shutup do
|
shutup do
|
||||||
uninstall_artifact.zap_phase
|
uninstall_artifact.zap_phase
|
||||||
end
|
end
|
||||||
|
@ -27,86 +27,20 @@ describe Hbc::Artifact::Uninstall do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'uninstall_phase' do
|
describe 'uninstall_phase' do
|
||||||
# todo: uninstall tests for :signal (implementation does not use SystemCommand)
|
subject {
|
||||||
it 'runs the specified uninstaller for the Cask' do
|
|
||||||
uninstall_artifact = Hbc::Artifact::Uninstall.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1')
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit'])
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/osascript', '-e', 'tell application "System Events" to delete every login item whose name is "Fancy"'])
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', @cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'])
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-rf', '--', Pathname.new('/permissible/absolute/path'), Pathname.new('~/permissible/path/with/tilde').expand_path])
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--', Pathname.new(TestHelper.local_binary_path('empty_directory')).join('.DS_Store')])
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rmdir', '--', Pathname.new(TestHelper.local_binary_path('empty_directory'))])
|
|
||||||
|
|
||||||
shutup do
|
shutup do
|
||||||
uninstall_artifact.uninstall_phase
|
uninstall_artifact.uninstall_phase
|
||||||
end
|
end
|
||||||
end
|
}
|
||||||
|
|
||||||
it 'can uninstall using pkgutil, launchctl, and file lists' do
|
describe 'when using launchctl' do
|
||||||
cask = Hbc.load('with-pkgutil-uninstall')
|
let(:cask) { Hbc.load('with-uninstall-launchctl') }
|
||||||
uninstall_artifact = Hbc::Artifact::Uninstall.new(cask, Hbc::FakeSystemCommand)
|
let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] }
|
||||||
|
let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service]}
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
let(:unknown_response) { "launchctl list returned unknown response\n" }
|
||||||
['/usr/sbin/pkgutil', '--pkgs=my.fancy.package.*'],
|
let(:service_info) {
|
||||||
[
|
<<-PLIST.undent
|
||||||
'my.fancy.package.main',
|
{
|
||||||
'my.fancy.package.agent',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy/bin/fancy.exe',
|
|
||||||
'fancy/var/fancy.data',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy',
|
|
||||||
'fancy/bin',
|
|
||||||
'fancy/var',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy',
|
|
||||||
'fancy/bin',
|
|
||||||
'fancy/var',
|
|
||||||
'fancy/bin/fancy.exe',
|
|
||||||
'fancy/var/fancy.data',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.main'],
|
|
||||||
<<-PLIST
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>install-location</key>
|
|
||||||
<string>tmp</string>
|
|
||||||
<key>volume</key>
|
|
||||||
<string>/</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
PLIST
|
|
||||||
)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/bin/launchctl', 'list', 'my.fancy.package.service'],
|
|
||||||
"launchctl list returned unknown response\n"
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'list', 'my.fancy.package.service'],
|
|
||||||
<<-"PLIST"
|
|
||||||
{
|
|
||||||
"LimitLoadToSessionType" = "Aqua";
|
"LimitLoadToSessionType" = "Aqua";
|
||||||
"Label" = "my.fancy.package.service";
|
"Label" = "my.fancy.package.service";
|
||||||
"TimeOut" = 30;
|
"TimeOut" = 30;
|
||||||
|
@ -115,80 +49,260 @@ describe Hbc::Artifact::Uninstall do
|
||||||
"ProgramArguments" = (
|
"ProgramArguments" = (
|
||||||
"argument";
|
"argument";
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
PLIST
|
PLIST
|
||||||
)
|
}
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'remove', 'my.fancy.package.service'])
|
describe 'when launchctl job is owned by user' do
|
||||||
|
it 'can uninstall' do
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/kextstat', '-l', '-b', 'my.fancy.package.kernelextension'], 'loaded')
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/sbin/kextunload', '-b', 'my.fancy.package.kernelextension'])
|
launchctl_list_cmd,
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.main'])
|
service_info)
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.agent'],
|
sudo(launchctl_list_cmd),
|
||||||
[
|
unknown_response)
|
||||||
'fancy/agent/fancy-agent.exe',
|
|
||||||
'fancy/agent/fancy-agent.pid',
|
Hbc::FakeSystemCommand.expects_command(launchctl_remove_cmd)
|
||||||
'fancy/agent/fancy-agent.log',
|
|
||||||
].join("\n")
|
subject
|
||||||
)
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when launchctl job is owned by system' do
|
||||||
|
it 'can uninstall' do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.agent'],
|
launchctl_list_cmd,
|
||||||
[
|
unknown_response)
|
||||||
'fancy',
|
|
||||||
'fancy/agent',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--files', 'my.fancy.package.agent'],
|
sudo(launchctl_list_cmd),
|
||||||
[
|
service_info)
|
||||||
'fancy',
|
|
||||||
'fancy/agent',
|
Hbc::FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd))
|
||||||
'fancy/agent/fancy-agent.exe',
|
|
||||||
'fancy/agent/fancy-agent.pid',
|
subject
|
||||||
'fancy/agent/fancy-agent.log',
|
end
|
||||||
].join("\n")
|
end
|
||||||
)
|
end
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.agent'],
|
describe 'when using pkgutil' do
|
||||||
<<-PLIST
|
let(:cask) { Hbc.load('with-uninstall-pkgutil') }
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
let(:main_pkg_id) { 'my.fancy.package.main' }
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
let(:agent_pkg_id) { 'my.fancy.package.agent' }
|
||||||
<plist version="1.0">
|
let(:main_files) {
|
||||||
<dict>
|
%w[
|
||||||
|
fancy/bin/fancy.exe
|
||||||
|
fancy/var/fancy.data
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:main_dirs) {
|
||||||
|
%w[
|
||||||
|
fancy
|
||||||
|
fancy/bin
|
||||||
|
fancy/var
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:agent_files) {
|
||||||
|
%w[
|
||||||
|
fancy/agent/fancy-agent.exe
|
||||||
|
fancy/agent/fancy-agent.pid
|
||||||
|
fancy/agent/fancy-agent.log
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:agent_dirs) {
|
||||||
|
%w[
|
||||||
|
fancy
|
||||||
|
fancy/agent
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:pkg_info_plist) {
|
||||||
|
<<-PLIST.undent
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
<key>install-location</key>
|
<key>install-location</key>
|
||||||
<string>tmp</string>
|
<string>tmp</string>
|
||||||
<key>volume</key>
|
<key>volume</key>
|
||||||
<string>/</string>
|
<string>/</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
PLIST
|
PLIST
|
||||||
)
|
}
|
||||||
|
|
||||||
%w[
|
it 'can uninstall' do
|
||||||
/tmp/fancy
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
/tmp/fancy/agent
|
%w[/usr/sbin/pkgutil --pkgs=my.fancy.package.*],
|
||||||
/tmp/fancy/bin
|
"#{main_pkg_id}\n#{agent_pkg_id}")
|
||||||
/tmp/fancy/var
|
|
||||||
].each do |dir|
|
[
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/chmod', '--', '777', '#{dir}'])
|
[main_pkg_id, main_files, main_dirs],
|
||||||
|
[agent_pkg_id, agent_files, agent_dirs]
|
||||||
|
].each do |pkg_id, pkg_files, pkg_dirs|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --only-files --files #{pkg_id}],
|
||||||
|
pkg_files.join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --only-dirs --files #{pkg_id}],
|
||||||
|
pkg_dirs.join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --files #{pkg_id}],
|
||||||
|
(pkg_files + pkg_dirs).join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --pkg-info-plist #{pkg_id}],
|
||||||
|
pkg_info_plist)
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(sudo(%W[/usr/sbin/pkgutil --forget #{pkg_id}]))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}")}))
|
||||||
end
|
end
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.agent'])
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
|
describe 'when using kext' do
|
||||||
Pathname.new('/tmp/fancy/bin/fancy.exe'),
|
let(:cask) { Hbc.load('with-uninstall-kext') }
|
||||||
Pathname.new('/tmp/fancy/var/fancy.data')])
|
let(:kext_id) { 'my.fancy.package.kernelextension' }
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.exe'),
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.pid'),
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.log')])
|
|
||||||
|
|
||||||
# No assertions after call since all assertions are implicit from the interactions setup above.
|
it 'can uninstall' do
|
||||||
# TODO: verify rmdir commands (requires setting up actual file tree or faking out .exists?
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
shutup do
|
sudo(%W[/usr/sbin/kextstat -l -b #{kext_id}]), 'loaded')
|
||||||
uninstall_artifact.uninstall_phase
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%W[/sbin/kextunload -b #{kext_id}]))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using quit' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-quit') }
|
||||||
|
let(:bundle_id) { 'my.fancy.package.app' }
|
||||||
|
let(:count_processes_script) {
|
||||||
|
'tell application "System Events" to count processes ' +
|
||||||
|
%Q{whose bundle identifier is "#{bundle_id}"}
|
||||||
|
}
|
||||||
|
let(:quit_application_script) {
|
||||||
|
%Q{tell application id "#{bundle_id}" to quit}
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{count_processes_script}]), '1')
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{quit_application_script}]))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using signal' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-signal') }
|
||||||
|
let(:bundle_id) { 'my.fancy.package.app' }
|
||||||
|
let(:signals) { %w[TERM KILL] }
|
||||||
|
let(:unix_pids) { [12345, 67890] }
|
||||||
|
let(:get_unix_pids_script) {
|
||||||
|
'tell application "System Events" to get the unix id of every process ' +
|
||||||
|
%Q{whose bundle identifier is "#{bundle_id}"}
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{get_unix_pids_script}]), unix_pids.join(', '))
|
||||||
|
|
||||||
|
signals.each do |signal|
|
||||||
|
Process.expects(:kill).with(signal, *unix_pids)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using delete' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-delete') }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -rf --],
|
||||||
|
Pathname.new('/permissible/absolute/path'),
|
||||||
|
Pathname.new('~/permissible/path/with/tilde').expand_path))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using trash' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-trash') }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -rf --],
|
||||||
|
Pathname.new('/permissible/absolute/path'),
|
||||||
|
Pathname.new('~/permissible/path/with/tilde').expand_path))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using rmdir' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-rmdir') }
|
||||||
|
let(:dir_pathname) { Pathname(TestHelper.local_binary_path('empty_directory')) }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -f --], dir_pathname.join('.DS_Store')))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rmdir --], dir_pathname))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using script' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-script') }
|
||||||
|
let(:script_pathname) { cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool') }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod +x --] + [script_pathname])
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using early_script' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-early-script') }
|
||||||
|
let(:script_pathname) { cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool') }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod +x --] + [script_pathname])
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using login_item' do
|
||||||
|
let(:cask) { Hbc.load('with-uninstall-login-item') }
|
||||||
|
|
||||||
|
it 'can uninstall' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
['/usr/bin/osascript', '-e', 'tell application "System Events" to delete every login ' \
|
||||||
|
'item whose name is "Fancy"'])
|
||||||
|
|
||||||
|
subject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,18 @@ require 'test_helper'
|
||||||
|
|
||||||
# todo
|
# todo
|
||||||
# - test that zap removes an alternate version of the same Cask
|
# - test that zap removes an alternate version of the same Cask
|
||||||
|
|
||||||
describe Hbc::Artifact::Zap do
|
describe Hbc::Artifact::Zap do
|
||||||
|
let(:cask) { Hbc.load('with-installable') }
|
||||||
|
let(:zap_artifact) { Hbc::Artifact::Zap.new(cask, Hbc::FakeSystemCommand) }
|
||||||
|
|
||||||
before {
|
before {
|
||||||
@cask = Hbc.load('with-zap')
|
|
||||||
shutup do
|
shutup do
|
||||||
TestHelper.install_without_artifacts(@cask)
|
TestHelper.install_without_artifacts(cask)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
describe 'install_phase' do
|
describe 'install_phase' do
|
||||||
it 'does nothing, because the install_phase method is a no-op' do
|
it 'does nothing, because the install_phase method is a no-op' do
|
||||||
zap_artifact = Hbc::Artifact::Zap.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
shutup do
|
shutup do
|
||||||
zap_artifact.install_phase
|
zap_artifact.install_phase
|
||||||
end
|
end
|
||||||
|
@ -22,7 +22,6 @@ describe Hbc::Artifact::Zap do
|
||||||
|
|
||||||
describe 'uninstall_phase' do
|
describe 'uninstall_phase' do
|
||||||
it 'does nothing, because the uninstall_phase method is a no-op' do
|
it 'does nothing, because the uninstall_phase method is a no-op' do
|
||||||
zap_artifact = Hbc::Artifact::Zap.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
shutup do
|
shutup do
|
||||||
zap_artifact.uninstall_phase
|
zap_artifact.uninstall_phase
|
||||||
end
|
end
|
||||||
|
@ -30,85 +29,20 @@ describe Hbc::Artifact::Zap do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'zap_phase' do
|
describe 'zap_phase' do
|
||||||
# todo: zap tests for :signal (implementation does not use SystemCommand)
|
subject {
|
||||||
it 'runs the specified zap procedures for the Cask' do
|
|
||||||
zap_artifact = Hbc::Artifact::Zap.new(@cask, Hbc::FakeSystemCommand)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1')
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit'])
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/osascript', '-e', 'tell application "System Events" to delete every login item whose name is "Fancy"'])
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', @cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'])
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-rf', '--',
|
|
||||||
Pathname.new('~/Library/Preferences/my.fancy.app.plist').expand_path])
|
|
||||||
|
|
||||||
shutup do
|
shutup do
|
||||||
zap_artifact.zap_phase
|
zap_artifact.zap_phase
|
||||||
end
|
end
|
||||||
end
|
}
|
||||||
|
|
||||||
it 'can zap using pkgutil, launchctl, and file lists' do
|
describe 'when using launchctl' do
|
||||||
cask = Hbc.load('with-pkgutil-zap')
|
let(:cask) { Hbc.load('with-zap-launchctl') }
|
||||||
zap_artifact = Hbc::Artifact::Zap.new(cask, Hbc::FakeSystemCommand)
|
let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] }
|
||||||
|
let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service]}
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
let(:unknown_response) { "launchctl list returned unknown response\n" }
|
||||||
['/usr/sbin/pkgutil', '--pkgs=my.fancy.package.*'],
|
let(:service_info) {
|
||||||
[
|
<<-PLIST.undent
|
||||||
'my.fancy.package.main',
|
{
|
||||||
'my.fancy.package.agent',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy/bin/fancy.exe',
|
|
||||||
'fancy/var/fancy.data',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy',
|
|
||||||
'fancy/bin',
|
|
||||||
'fancy/var',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--files', 'my.fancy.package.main'],
|
|
||||||
[
|
|
||||||
'fancy',
|
|
||||||
'fancy/bin',
|
|
||||||
'fancy/var',
|
|
||||||
'fancy/bin/fancy.exe',
|
|
||||||
'fancy/var/fancy.data',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.main'],
|
|
||||||
<<-PLIST
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>install-location</key>
|
|
||||||
<string>tmp</string>
|
|
||||||
<key>volume</key>
|
|
||||||
<string>/</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
PLIST
|
|
||||||
)
|
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/bin/launchctl', 'list', 'my.fancy.package.service'],
|
|
||||||
"launchctl list returned unknown response\n"
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'list', 'my.fancy.package.service'],
|
|
||||||
<<-"PLIST"
|
|
||||||
{
|
|
||||||
"LimitLoadToSessionType" = "Aqua";
|
"LimitLoadToSessionType" = "Aqua";
|
||||||
"Label" = "my.fancy.package.service";
|
"Label" = "my.fancy.package.service";
|
||||||
"TimeOut" = 30;
|
"TimeOut" = 30;
|
||||||
|
@ -117,80 +51,260 @@ describe Hbc::Artifact::Zap do
|
||||||
"ProgramArguments" = (
|
"ProgramArguments" = (
|
||||||
"argument";
|
"argument";
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
PLIST
|
PLIST
|
||||||
)
|
}
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'remove', 'my.fancy.package.service'])
|
describe 'when launchctl job is owned by user' do
|
||||||
|
it 'can zap' do
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/kextstat', '-l', '-b', 'my.fancy.package.kernelextension'], 'loaded')
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/sbin/kextunload', '-b', 'my.fancy.package.kernelextension'])
|
launchctl_list_cmd,
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.main'])
|
service_info)
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.agent'],
|
sudo(launchctl_list_cmd),
|
||||||
[
|
unknown_response)
|
||||||
'fancy/agent/fancy-agent.exe',
|
|
||||||
'fancy/agent/fancy-agent.pid',
|
Hbc::FakeSystemCommand.expects_command(launchctl_remove_cmd)
|
||||||
'fancy/agent/fancy-agent.log',
|
|
||||||
].join("\n")
|
subject
|
||||||
)
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when launchctl job is owned by system' do
|
||||||
|
it 'can zap' do
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.agent'],
|
launchctl_list_cmd,
|
||||||
[
|
unknown_response)
|
||||||
'fancy',
|
|
||||||
'fancy/agent',
|
|
||||||
].join("\n")
|
|
||||||
)
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
['/usr/sbin/pkgutil', '--files', 'my.fancy.package.agent'],
|
sudo(launchctl_list_cmd),
|
||||||
[
|
service_info)
|
||||||
'fancy',
|
|
||||||
'fancy/agent',
|
Hbc::FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd))
|
||||||
'fancy/agent/fancy-agent.exe',
|
|
||||||
'fancy/agent/fancy-agent.pid',
|
subject
|
||||||
'fancy/agent/fancy-agent.log',
|
end
|
||||||
].join("\n")
|
end
|
||||||
)
|
end
|
||||||
Hbc::FakeSystemCommand.stubs_command(
|
|
||||||
['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.agent'],
|
describe 'when using pkgutil' do
|
||||||
<<-PLIST
|
let(:cask) { Hbc.load('with-zap-pkgutil') }
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
let(:main_pkg_id) { 'my.fancy.package.main' }
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
let(:agent_pkg_id) { 'my.fancy.package.agent' }
|
||||||
<plist version="1.0">
|
let(:main_files) {
|
||||||
<dict>
|
%w[
|
||||||
|
fancy/bin/fancy.exe
|
||||||
|
fancy/var/fancy.data
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:main_dirs) {
|
||||||
|
%w[
|
||||||
|
fancy
|
||||||
|
fancy/bin
|
||||||
|
fancy/var
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:agent_files) {
|
||||||
|
%w[
|
||||||
|
fancy/agent/fancy-agent.exe
|
||||||
|
fancy/agent/fancy-agent.pid
|
||||||
|
fancy/agent/fancy-agent.log
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:agent_dirs) {
|
||||||
|
%w[
|
||||||
|
fancy
|
||||||
|
fancy/agent
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let(:pkg_info_plist) {
|
||||||
|
<<-PLIST.undent
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
<key>install-location</key>
|
<key>install-location</key>
|
||||||
<string>tmp</string>
|
<string>tmp</string>
|
||||||
<key>volume</key>
|
<key>volume</key>
|
||||||
<string>/</string>
|
<string>/</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
PLIST
|
PLIST
|
||||||
)
|
}
|
||||||
|
|
||||||
%w[
|
it 'can zap' do
|
||||||
/tmp/fancy
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
/tmp/fancy/agent
|
%w[/usr/sbin/pkgutil --pkgs=my.fancy.package.*],
|
||||||
/tmp/fancy/bin
|
"#{main_pkg_id}\n#{agent_pkg_id}")
|
||||||
/tmp/fancy/var
|
|
||||||
].each do |dir|
|
[
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/chmod', '--', '777', '#{dir}'])
|
[main_pkg_id, main_files, main_dirs],
|
||||||
|
[agent_pkg_id, agent_files, agent_dirs]
|
||||||
|
].each do |pkg_id, pkg_files, pkg_dirs|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --only-files --files #{pkg_id}],
|
||||||
|
pkg_files.join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --only-dirs --files #{pkg_id}],
|
||||||
|
pkg_dirs.join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --files #{pkg_id}],
|
||||||
|
(pkg_files + pkg_dirs).join("\n"))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
%W[/usr/sbin/pkgutil --pkg-info-plist #{pkg_id}],
|
||||||
|
pkg_info_plist)
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(sudo(%W[/usr/sbin/pkgutil --forget #{pkg_id}]))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}")}))
|
||||||
end
|
end
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.agent'])
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
|
describe 'when using kext' do
|
||||||
Pathname.new('/tmp/fancy/bin/fancy.exe'),
|
let(:cask) { Hbc.load('with-zap-kext') }
|
||||||
Pathname.new('/tmp/fancy/var/fancy.data')])
|
let(:kext_id) { 'my.fancy.package.kernelextension' }
|
||||||
Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.exe'),
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.pid'),
|
|
||||||
Pathname.new('/tmp/fancy/agent/fancy-agent.log')])
|
|
||||||
|
|
||||||
# No assertions after call since all assertions are implicit from the interactions setup above.
|
it 'can zap' do
|
||||||
# TODO: verify rmdir commands (requires setting up actual file tree or faking out .exists?
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
shutup do
|
sudo(%W[/usr/sbin/kextstat -l -b #{kext_id}]), 'loaded')
|
||||||
zap_artifact.zap_phase
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%W[/sbin/kextunload -b #{kext_id}]))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using quit' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-quit') }
|
||||||
|
let(:bundle_id) { 'my.fancy.package.app' }
|
||||||
|
let(:count_processes_script) {
|
||||||
|
'tell application "System Events" to count processes ' +
|
||||||
|
%Q{whose bundle identifier is "#{bundle_id}"}
|
||||||
|
}
|
||||||
|
let(:quit_application_script) {
|
||||||
|
%Q{tell application id "#{bundle_id}" to quit}
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{count_processes_script}]), '1')
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{quit_application_script}]))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using signal' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-signal') }
|
||||||
|
let(:bundle_id) { 'my.fancy.package.app' }
|
||||||
|
let(:signals) { %w[TERM KILL] }
|
||||||
|
let(:unix_pids) { [12345, 67890] }
|
||||||
|
let(:get_unix_pids_script) {
|
||||||
|
'tell application "System Events" to get the unix id of every process ' +
|
||||||
|
%Q{whose bundle identifier is "#{bundle_id}"}
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.stubs_command(
|
||||||
|
sudo(%W[/usr/bin/osascript -e #{get_unix_pids_script}]), unix_pids.join(', '))
|
||||||
|
|
||||||
|
signals.each do |signal|
|
||||||
|
Process.expects(:kill).with(signal, *unix_pids)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using delete' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-delete') }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -rf --],
|
||||||
|
Pathname.new('/permissible/absolute/path'),
|
||||||
|
Pathname.new('~/permissible/path/with/tilde').expand_path))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using trash' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-trash') }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -rf --],
|
||||||
|
Pathname.new('/permissible/absolute/path'),
|
||||||
|
Pathname.new('~/permissible/path/with/tilde').expand_path))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using rmdir' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-rmdir') }
|
||||||
|
let(:dir_pathname) { Pathname(TestHelper.local_binary_path('empty_directory')) }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rm -f --], dir_pathname.join('.DS_Store')))
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(%w[/bin/rmdir --], dir_pathname))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using script' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-script') }
|
||||||
|
let(:script_pathname) { cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool') }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod +x --] + [script_pathname])
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using early_script' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-early-script') }
|
||||||
|
let(:script_pathname) { cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool') }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod +x --] + [script_pathname])
|
||||||
|
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
sudo(cask.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please'))
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when using login_item' do
|
||||||
|
let(:cask) { Hbc.load('with-zap-login-item') }
|
||||||
|
|
||||||
|
it 'can zap' do
|
||||||
|
Hbc::FakeSystemCommand.expects_command(
|
||||||
|
['/usr/bin/osascript', '-e', 'tell application "System Events" to delete every login ' \
|
||||||
|
'item whose name is "Fancy"'])
|
||||||
|
|
||||||
|
subject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
test_cask 'with-uninstall-delete' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :delete => [
|
||||||
|
'/permissible/absolute/path',
|
||||||
|
'~/permissible/path/with/tilde',
|
||||||
|
'impermissible/relative/path',
|
||||||
|
'/another/impermissible/../relative/path',
|
||||||
|
]
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-uninstall-early-script' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :early_script => { :executable => 'MyFancyPkg/FancyUninstaller.tool', :args => %w[--please] }
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
test_cask 'with-pkgutil-uninstall' do
|
test_cask 'with-uninstall-kext' do
|
||||||
version '1.2.3'
|
version '1.2.3'
|
||||||
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
@ -6,7 +6,5 @@ test_cask 'with-pkgutil-uninstall' do
|
||||||
homepage 'http://example.com/fancy-pkg'
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
pkg 'Fancy.pkg'
|
pkg 'Fancy.pkg'
|
||||||
uninstall :pkgutil => 'my.fancy.package.*',
|
uninstall :kext => 'my.fancy.package.kernelextension'
|
||||||
:kext => 'my.fancy.package.kernelextension',
|
|
||||||
:launchctl => 'my.fancy.package.service'
|
|
||||||
end
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-uninstall-launchctl' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyApp.zip')
|
||||||
|
homepage 'http://example.com/fancy'
|
||||||
|
|
||||||
|
app 'Fancy.app'
|
||||||
|
|
||||||
|
uninstall :launchctl => 'my.fancy.package.service'
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-uninstall-login-item' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :login_item => 'Fancy'
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test_cask 'with-uninstall-pkgutil' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
uninstall :pkgutil => 'my.fancy.package.*'
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-uninstall-quit' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :quit => 'my.fancy.package.app'
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test_cask 'with-uninstall-rmdir' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
uninstall :rmdir => TestHelper.local_binary_path('empty_directory')
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-uninstall-script' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :script => { :executable => 'MyFancyPkg/FancyUninstaller.tool', :args => %w[--please] }
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
test_cask 'with-uninstall-signal' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :signal => [
|
||||||
|
['TERM', 'my.fancy.package.app'],
|
||||||
|
['KILL', 'my.fancy.package.app']
|
||||||
|
]
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
test_cask 'with-uninstall-trash' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
|
||||||
|
uninstall :trash => [
|
||||||
|
'/permissible/absolute/path',
|
||||||
|
'~/permissible/path/with/tilde',
|
||||||
|
'impermissible/relative/path',
|
||||||
|
'/another/impermissible/../relative/path',
|
||||||
|
]
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
test_cask 'with-zap-delete' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
|
||||||
|
zap :delete => [
|
||||||
|
'/permissible/absolute/path',
|
||||||
|
'~/permissible/path/with/tilde',
|
||||||
|
'impermissible/relative/path',
|
||||||
|
'/another/impermissible/../relative/path',
|
||||||
|
]
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-zap-early-script' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
zap :early_script => { :executable => 'MyFancyPkg/FancyUninstaller.tool', :args => %w[--please] }
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test_cask 'with-zap-kext' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
zap :kext => 'my.fancy.package.kernelextension'
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-zap-launchctl' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyApp.zip')
|
||||||
|
homepage 'http://example.com/fancy'
|
||||||
|
|
||||||
|
app 'Fancy.app'
|
||||||
|
|
||||||
|
zap :launchctl => 'my.fancy.package.service'
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-zap-login-item' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
zap :login_item => 'Fancy'
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test_cask 'with-zap-pkgutil' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
zap :pkgutil => 'my.fancy.package.*'
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-zap-quit' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
zap :quit => 'my.fancy.package.app'
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
test_cask 'with-zap-rmdir' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
zap :rmdir => TestHelper.local_binary_path('empty_directory')
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
test_cask 'with-zap-script' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
zap :script => { :executable => 'MyFancyPkg/FancyUninstaller.tool', :args => %w[--please] }
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
test_cask 'with-zap-signal' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'MyFancyPkg/Fancy.pkg'
|
||||||
|
|
||||||
|
zap :signal => [
|
||||||
|
['TERM', 'my.fancy.package.app'],
|
||||||
|
['KILL', 'my.fancy.package.app']
|
||||||
|
]
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
test_cask 'with-zap-trash' do
|
||||||
|
version '1.2.3'
|
||||||
|
sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
|
||||||
|
|
||||||
|
url TestHelper.local_binary_url('MyFancyPkg.zip')
|
||||||
|
homepage 'http://example.com/fancy-pkg'
|
||||||
|
|
||||||
|
pkg 'Fancy.pkg'
|
||||||
|
|
||||||
|
zap :trash => [
|
||||||
|
'/permissible/absolute/path',
|
||||||
|
'~/permissible/path/with/tilde',
|
||||||
|
'impermissible/relative/path',
|
||||||
|
'/another/impermissible/../relative/path',
|
||||||
|
]
|
||||||
|
end
|
|
@ -41,6 +41,10 @@ def shutup
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sudo(*args)
|
||||||
|
%w[/usr/bin/sudo -E --] + Array(args).flatten
|
||||||
|
end
|
||||||
|
|
||||||
# making homebrew's cache dir allows us to actually download Casks in tests
|
# making homebrew's cache dir allows us to actually download Casks in tests
|
||||||
HOMEBREW_CACHE.mkpath
|
HOMEBREW_CACHE.mkpath
|
||||||
HOMEBREW_CACHE.join('Casks').mkpath
|
HOMEBREW_CACHE.join('Casks').mkpath
|
||||||
|
|
Loading…
Reference in New Issue