2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2024-02-18 15:11:11 -08:00
|
|
|
RSpec.describe Cask::Pkg, :cask do
|
2017-03-08 03:03:49 +01:00
|
|
|
describe "#uninstall" do
|
2018-07-19 23:56:51 +02:00
|
|
|
let(:fake_system_command) { NeverSudoSystemCommand }
|
2023-01-22 17:04:54 -08:00
|
|
|
let(:empty_response) do
|
|
|
|
instance_double(
|
|
|
|
SystemCommand::Result,
|
|
|
|
stdout: "",
|
|
|
|
plist: { "volume" => "/", "install-location" => "", "paths" => {} },
|
|
|
|
)
|
|
|
|
end
|
2017-02-08 09:58:38 +01:00
|
|
|
let(:pkg) { described_class.new("my.fake.pkg", fake_system_command) }
|
|
|
|
|
2020-06-29 09:50:51 +01:00
|
|
|
it "removes files and dirs referenced by the pkg" do
|
|
|
|
some_files = Array.new(3) { Pathname.new(Tempfile.new("plain_file").path) }
|
|
|
|
|
|
|
|
some_specials = Array.new(3) { Pathname.new(Tempfile.new("special_file").path) }
|
|
|
|
|
|
|
|
some_dirs = Array.new(3) { mktmpdir }
|
|
|
|
|
|
|
|
root_dir = Pathname.new(mktmpdir)
|
2023-12-14 02:52:30 +00:00
|
|
|
allow(pkg).to receive_messages(pkgutil_bom_files: some_files, pkgutil_bom_specials: some_specials,
|
|
|
|
pkgutil_bom_dirs: some_dirs, root: root_dir)
|
2020-06-29 09:50:51 +01:00
|
|
|
|
|
|
|
allow(pkg).to receive(:forget)
|
|
|
|
|
|
|
|
pkg.uninstall
|
|
|
|
|
|
|
|
some_files.each do |file|
|
|
|
|
expect(file).not_to exist
|
|
|
|
end
|
|
|
|
|
2022-10-18 01:32:55 +01:00
|
|
|
some_specials.each do |file|
|
|
|
|
expect(file).not_to exist
|
|
|
|
end
|
|
|
|
|
2020-06-29 09:50:51 +01:00
|
|
|
some_dirs.each do |dir|
|
|
|
|
expect(dir).not_to exist
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(root_dir).not_to exist
|
2022-10-18 01:32:55 +01:00
|
|
|
ensure
|
|
|
|
some_files&.each { |path| FileUtils.rm_rf(path) }
|
|
|
|
some_specials&.each { |path| FileUtils.rm_rf(path) }
|
|
|
|
some_dirs&.each { |path| FileUtils.rm_rf(path) }
|
|
|
|
FileUtils.rm_rf(root_dir) if root_dir
|
2020-06-29 09:50:51 +01:00
|
|
|
end
|
|
|
|
|
2021-02-19 23:15:33 +00:00
|
|
|
describe "pkgutil" do
|
2017-02-08 09:58:38 +01:00
|
|
|
it "forgets the pkg" do
|
|
|
|
allow(fake_system_command).to receive(:run!).with(
|
|
|
|
"/usr/sbin/pkgutil",
|
2017-04-21 15:50:39 +02:00
|
|
|
args: ["--pkg-info-plist", "my.fake.pkg"],
|
|
|
|
).and_return(empty_response)
|
|
|
|
|
|
|
|
expect(fake_system_command).to receive(:run!).with(
|
|
|
|
"/usr/sbin/pkgutil",
|
|
|
|
args: ["--files", "my.fake.pkg"],
|
2017-02-08 09:58:38 +01:00
|
|
|
).and_return(empty_response)
|
|
|
|
|
|
|
|
expect(fake_system_command).to receive(:run!).with(
|
|
|
|
"/usr/sbin/pkgutil",
|
2023-04-26 19:51:26 -07:00
|
|
|
args: ["--forget", "my.fake.pkg"],
|
|
|
|
sudo: true,
|
|
|
|
sudo_as_root: true,
|
2017-02-08 09:58:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
pkg.uninstall
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "removes broken symlinks" do
|
2017-08-06 12:30:40 +02:00
|
|
|
fake_root = mktmpdir
|
|
|
|
fake_dir = mktmpdir
|
2018-09-02 16:15:09 +01:00
|
|
|
fake_file = fake_dir.join("ima_file").tap do |path|
|
|
|
|
FileUtils.touch(path)
|
|
|
|
end
|
2017-02-08 09:58:38 +01:00
|
|
|
|
|
|
|
intact_symlink = fake_dir.join("intact_symlink").tap { |path| path.make_symlink(fake_file) }
|
|
|
|
broken_symlink = fake_dir.join("broken_symlink").tap { |path| path.make_symlink("im_nota_file") }
|
|
|
|
|
2023-12-14 02:52:30 +00:00
|
|
|
allow(pkg).to receive_messages(pkgutil_bom_specials: [], pkgutil_bom_files: [], pkgutil_bom_dirs: [fake_dir],
|
|
|
|
root: fake_root)
|
2017-02-08 09:58:38 +01:00
|
|
|
allow(pkg).to receive(:forget)
|
|
|
|
|
|
|
|
pkg.uninstall
|
|
|
|
|
|
|
|
expect(intact_symlink).to exist
|
|
|
|
expect(broken_symlink).not_to exist
|
|
|
|
expect(fake_dir).to exist
|
2017-03-09 22:01:46 +01:00
|
|
|
expect(fake_root).not_to exist
|
2022-10-18 01:32:55 +01:00
|
|
|
ensure
|
|
|
|
FileUtils.rm_rf(fake_dir) if fake_dir
|
|
|
|
FileUtils.rm_rf(fake_root) if fake_root
|
2017-02-08 09:58:38 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
it "snags permissions on ornery dirs, but returns them afterwards" do
|
2017-08-06 12:30:40 +02:00
|
|
|
fake_root = mktmpdir
|
|
|
|
fake_dir = mktmpdir
|
|
|
|
fake_file = fake_dir.join("ima_unrelated_file").tap { |path| FileUtils.touch(path) }
|
2017-02-08 09:58:38 +01:00
|
|
|
fake_dir.chmod(0000)
|
|
|
|
|
2023-12-14 02:52:30 +00:00
|
|
|
allow(pkg).to receive_messages(pkgutil_bom_specials: [], pkgutil_bom_files: [], pkgutil_bom_dirs: [fake_dir],
|
|
|
|
root: fake_root)
|
2017-02-08 09:58:38 +01:00
|
|
|
allow(pkg).to receive(:forget)
|
|
|
|
|
2021-03-16 02:07:06 +01:00
|
|
|
# This is expected to fail in tests since we don't use `sudo`.
|
|
|
|
allow(fake_system_command).to receive(:run!).and_call_original
|
|
|
|
expect(fake_system_command).to receive(:run!).with(
|
|
|
|
"/usr/bin/xargs",
|
2023-04-26 19:51:26 -07:00
|
|
|
args: ["-0", "--", a_string_including("rmdir")],
|
|
|
|
input: [fake_dir].join("\0"),
|
|
|
|
sudo: true,
|
|
|
|
sudo_as_root: true,
|
2021-03-16 02:07:06 +01:00
|
|
|
).and_return(instance_double(SystemCommand::Result, stdout: ""))
|
|
|
|
|
2017-07-29 19:55:05 +02:00
|
|
|
pkg.uninstall
|
2017-02-08 09:58:38 +01:00
|
|
|
|
|
|
|
expect(fake_dir).to be_a_directory
|
2025-05-05 14:35:08 -07:00
|
|
|
expect(fake_dir.stat.mode % 01000).to eq(0)
|
2017-08-06 12:30:40 +02:00
|
|
|
|
|
|
|
fake_dir.chmod(0777)
|
|
|
|
expect(fake_file).to be_a_file
|
2022-10-18 01:32:55 +01:00
|
|
|
ensure
|
|
|
|
if fake_dir
|
|
|
|
fake_dir.chmod(0777)
|
|
|
|
FileUtils.rm_rf(fake_dir)
|
|
|
|
end
|
|
|
|
FileUtils.rm_rf(fake_root) if fake_root
|
2017-02-08 09:58:38 +01:00
|
|
|
end
|
|
|
|
end
|
2017-03-09 22:01:46 +01:00
|
|
|
|
|
|
|
describe "#info" do
|
2018-07-19 23:56:51 +02:00
|
|
|
let(:fake_system_command) { class_double(SystemCommand) }
|
2017-03-09 22:01:46 +01:00
|
|
|
|
|
|
|
let(:volume) { "/" }
|
|
|
|
let(:install_location) { "tmp" }
|
|
|
|
|
|
|
|
let(:pkg_id) { "my.fancy.package.main" }
|
|
|
|
|
|
|
|
let(:pkg_files) do
|
|
|
|
%w[
|
|
|
|
fancy/bin/fancy.exe
|
|
|
|
fancy/var/fancy.data
|
|
|
|
]
|
|
|
|
end
|
|
|
|
let(:pkg_directories) do
|
|
|
|
%w[
|
|
|
|
fancy
|
|
|
|
fancy/bin
|
|
|
|
fancy/var
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:pkg_info_plist) do
|
2018-07-11 15:17:40 +02:00
|
|
|
<<~XML
|
2017-03-09 22:01:46 +01:00
|
|
|
<?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>#{install_location}</string>
|
|
|
|
<key>volume</key>
|
|
|
|
<string>#{volume}</string>
|
|
|
|
<key>paths</key>
|
|
|
|
<dict>
|
2018-06-14 22:48:37 +02:00
|
|
|
#{(pkg_files + pkg_directories).map { |f| "<key>#{f}</key><dict></dict>" }.join}
|
2017-03-09 22:01:46 +01:00
|
|
|
</dict>
|
|
|
|
</dict>
|
|
|
|
</plist>
|
2018-07-11 15:17:40 +02:00
|
|
|
XML
|
2017-03-09 22:01:46 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
it "correctly parses a Property List" do
|
2019-07-23 17:09:57 +01:00
|
|
|
pkg = described_class.new(pkg_id, fake_system_command)
|
2017-03-09 22:01:46 +01:00
|
|
|
|
|
|
|
expect(fake_system_command).to receive(:run!).with(
|
|
|
|
"/usr/sbin/pkgutil",
|
2018-06-06 23:34:19 -04:00
|
|
|
args: ["--pkg-info-plist", pkg_id],
|
2017-03-09 22:01:46 +01:00
|
|
|
).and_return(
|
2020-11-23 02:05:50 +01:00
|
|
|
SystemCommand::Result.new(
|
|
|
|
["/usr/sbin/pkgutil", "--pkg-info-plist", pkg_id],
|
|
|
|
[[:stdout, pkg_info_plist]],
|
|
|
|
instance_double(Process::Status, exitstatus: 0),
|
|
|
|
secrets: [],
|
|
|
|
),
|
2017-03-09 22:01:46 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
info = pkg.info
|
|
|
|
|
|
|
|
expect(info["install-location"]).to eq(install_location)
|
|
|
|
expect(info["volume"]).to eq(volume)
|
|
|
|
expect(info["paths"].keys).to eq(pkg_files + pkg_directories)
|
|
|
|
end
|
|
|
|
end
|
2017-02-08 09:58:38 +01:00
|
|
|
end
|