300 lines
11 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "services/cli"
require "services/system"
require "services/formula_wrapper"
RSpec.describe Services::Cli do
subject(:services_cli) { described_class }
let(:service_string) { "service" }
describe "#bin" do
it "outputs command name" do
expect(services_cli.bin).to eq("brew services")
end
end
describe "#running" do
it "macOS - returns the currently running services" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Utils).to receive(:popen_read).and_return <<~EOS
77513 50 homebrew.mxcl.php
495 0 homebrew.mxcl.node_exporter
1234 34 homebrew.mxcl.postgresql@14
EOS
expect(services_cli.running).to eq([
"homebrew.mxcl.php",
"homebrew.mxcl.node_exporter",
"homebrew.mxcl.postgresql@14",
])
end
it "systemD - returns the currently running services" do
allow(Services::System).to receive(:launchctl?).and_return(false)
allow(Services::System::Systemctl).to receive(:popen_read).and_return <<~EOS
homebrew.php.service loaded active running Homebrew PHP service
systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files
udisks2.service loaded active running Disk Manager
user@1000.service loaded active running User Manager for UID 1000
EOS
expect(services_cli.running).to eq(["homebrew.php.service"])
end
end
describe "#check" do
it "checks the input does not exist" do
expect do
services_cli.check([])
end.to raise_error(UsageError, "Invalid usage: Formula(e) missing, please provide a formula name or use --all")
end
it "checks the input exists" do
expect do
services_cli.check("hello")
end.not_to raise_error(UsageError,
"Invalid usage: Formula(e) missing, please provide a formula name or use --all")
end
end
describe "#kill_orphaned_services" do
it "skips unmanaged services" do
allow(services_cli).to receive(:running).and_return(["example_service"])
expect do
services_cli.kill_orphaned_services
end.to output("Warning: Service example_service not managed by `brew services` => skipping\n").to_stderr
end
it "tries but is unable to kill a non existing service" do
service = instance_double(
service_string,
name: "example_service",
pid?: true,
dest: Pathname("this_path_does_not_exist"),
keep_alive?: false,
)
allow(service).to receive(:service_name)
allow(Services::FormulaWrapper).to receive(:from).and_return(service)
allow(services_cli).to receive(:running).and_return(["example_service"])
expect do
services_cli.kill_orphaned_services
end.to output("Killing `example_service`... (might take a while)\n").to_stdout
end
end
describe "#run" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
services_cli.run([])
end
it "checks if target service is already running and suggests restart instead" do
expected_output = "Service `example_service` already running, " \
"use `brew services restart example_service` to restart.\n"
service = instance_double(service_string, name: "example_service", pid?: true)
expect do
services_cli.run([service])
end.to output(expected_output).to_stdout
end
end
describe "#start" do
it "checks missing file causes error" do
expect(Services::System).not_to receive(:root?)
expect do
services_cli.start(["service_name"], "/hfdkjshksdjhfkjsdhf/fdsjghsdkjhb")
end.to raise_error(UsageError, "Invalid usage: Provided service file does not exist")
end
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
services_cli.start([])
end
it "checks if target service has already been started and suggests restart instead" do
expected_output = "Service `example_service` already started, " \
"use `brew services restart example_service` to restart.\n"
service = instance_double(service_string, name: "example_service", pid?: true)
expect do
services_cli.start([service])
end.to output(expected_output).to_stdout
end
end
describe "#stop" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
services_cli.stop([])
end
end
describe "#kill" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
services_cli.kill([])
end
it "prints a message if service is not running" do
expected_output = "Service `example_service` is not started.\n"
service = instance_double(service_string, name: "example_service", pid?: false)
expect do
services_cli.kill([service])
end.to output(expected_output).to_stdout
end
it "prints a message if service is set to keep alive" do
expected_output = "Service `example_service` is set to automatically restart and can't be killed.\n"
service = instance_double(service_string, name: "example_service", pid?: true, keep_alive?: true)
expect do
services_cli.kill([service])
end.to output(expected_output).to_stdout
end
end
describe "#install_service_file" do
it "checks service is installed" do
service = instance_double(Services::FormulaWrapper, name: "name", installed?: false)
expect do
services_cli.install_service_file(service, nil)
end.to raise_error(UsageError, "Invalid usage: Formula `name` is not installed")
end
it "checks service file exists" do
service = instance_double(
Services::FormulaWrapper,
name: "name",
installed?: true,
service_file: instance_double(Pathname, exist?: false),
)
expect do
services_cli.install_service_file(service, nil)
end.to raise_error(
UsageError,
"Invalid usage: Formula `name` has not implemented #plist, #service or installed a locatable service file",
)
end
end
describe "#systemd_load", :needs_linux do
it "checks non-enabling run" do
expect(Services::System::Systemctl).to receive(:executable).once.and_return("/bin/systemctl")
expect(Services::System::Systemctl).to receive(:scope).once.and_return("--user")
services_cli.systemd_load(
instance_double(Services::FormulaWrapper, service_name: "name"),
enable: false,
)
end
it "checks enabling run" do
expect(Services::System::Systemctl).to receive(:executable).twice.and_return("/bin/systemctl")
expect(Services::System::Systemctl).to receive(:scope).twice.and_return("--user")
services_cli.systemd_load(
instance_double(Services::FormulaWrapper, service_name: "name"),
enable: true,
)
end
end
describe "#launchctl_load", :needs_macos do
it "checks non-enabling run" do
expect(Services::System).to receive(:domain_target).once.and_return("target")
expect(Services::System).to receive(:launchctl).once.and_return("/bin/launchctl")
expect(described_class).to receive(:safe_system).once.and_return(true)
services_cli.launchctl_load(instance_double(Services::FormulaWrapper), file: "a", enable: false)
end
it "checks enabling run" do
expect(Services::System).to receive(:domain_target).twice.and_return("target")
expect(Services::System).to receive(:launchctl).twice.and_return("/bin/launchctl")
expect(described_class).to receive(:safe_system).twice.and_return(true)
services_cli.launchctl_load(instance_double(Services::FormulaWrapper, service_name: "name"), file: "a",
enable: true)
end
end
describe "#service_load" do
it "checks non-root for login" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(false)
expect(Services::System).to receive(:root?).once.and_return(true)
expect do
services_cli.service_load(
instance_double(Services::FormulaWrapper, name: "name", service_name: "service.name",
service_startup?: false), enable: false
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "checks root for startup" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(false)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect do
services_cli.service_load(
instance_double(Services::FormulaWrapper, name: "name", service_name: "service.name",
service_startup?: true),
enable: false,
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "triggers launchctl" do
expect(Services::System).to receive(:launchctl?).once.and_return(true)
expect(Services::System).not_to receive(:systemctl?)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(described_class).to receive(:launchctl_load).once.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
service_file: instance_double(Pathname, exist?: false),
),
enable: false,
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "triggers systemctl" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(true)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Services::System::Systemctl).to receive(:run).once.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
dest: instance_double(Pathname, exist?: true),
),
enable: false,
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "represents correct action" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(true)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Services::System::Systemctl).to receive(:run).twice.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
dest: instance_double(Pathname, exist?: true),
),
enable: true,
)
end.to output("==> Successfully started `name` (label: service.name)\n").to_stdout
end
end
end