brew/Library/Homebrew/test/extend/on_system_spec.rb
Sam Ford 473f448b22
OnSystem: handle non-macOS current_os values
The `OnSystem.os_condition_met?` method only handles Linux and macOS
values for the current OS, so this fails when testing with a generic
OS. This shortcoming is only being surfaced now because there weren't
any tests for `OnSystem` before.

This addresses the issue by accounting for macOS values (`:macos` or
a symbol from `MacOSVersion::SYMBOLS`) and returning `false` for any
other values (`:linux`, `:generic`, etc.).
2025-06-08 10:13:40 -04:00

225 lines
7.2 KiB
Ruby

# frozen_string_literal: true
require "extend/on_system"
RSpec.describe OnSystem do
shared_examples "a class with on_arch methods" do
it "adds on_arch methods to class for `ARCH_OPTIONS`" do
OnSystem::ARCH_OPTIONS.each do |arch|
expect(subject.method_defined?(:"on_#{arch}")).to be true
end
end
end
shared_examples "a class with on_base_os methods" do
it "adds on_os methods to class for `BASE_OS_OPTIONS`" do
OnSystem::BASE_OS_OPTIONS.each do |os|
expect(subject.method_defined?(:"on_#{os}")).to be true
end
end
end
shared_examples "a class with on_macos methods" do
it "adds on_os methods to class for `MacOSVersion::SYMBOLS` keys" do
MacOSVersion::SYMBOLS.each_key do |os|
expect(subject.method_defined?(:"on_#{os}")).to be true
end
end
end
describe "UsesOnSystem" do
uses_on_system_empty = described_class::UsesOnSystem.new
uses_on_system_present = described_class::UsesOnSystem.new(arm: true)
describe "#empty?" do
it "returns true if all properties are default values" do
expect(uses_on_system_empty.empty?).to be true
end
it "returns false if any properties have a non-default value" do
expect(uses_on_system_present.empty?).to be false
end
end
describe "#present?" do
it "returns true if object is not empty" do
expect(uses_on_system_present.present?).to be true
end
it "returns false if object is empty" do
expect(uses_on_system_empty.present?).to be false
end
end
end
describe "::comparator_from_or_condition" do
it 'returns ">=" for `:or_newer` symbol' do
expect(described_class.comparator_from_or_condition(:or_newer)).to eq(">=")
end
it 'returns "<=" for `:or_older` symbol' do
expect(described_class.comparator_from_or_condition(:or_older)).to eq("<=")
end
it 'returns "==" for an unsupported symbol' do
expect(described_class.comparator_from_or_condition(:nonexistent)).to eq("==")
end
it 'returns "==" for `nil`' do
expect(described_class.comparator_from_or_condition(nil)).to eq("==")
end
end
describe "::arch_condition_met?" do
it "returns true if current arch equals provided arch" do
Homebrew::SimulateSystem.with(arch: :arm) do
expect(described_class.arch_condition_met?(:arm)).to be true
end
end
it "returns false if current arch does not equal provided arch" do
Homebrew::SimulateSystem.with(arch: :arm) do
expect(described_class.arch_condition_met?(:intel)).to be false
end
end
it "raises error if provided arch is not valid" do
expect { described_class.arch_condition_met?(:nonexistent_arch) }
.to raise_error(ArgumentError)
end
end
describe "::os_condition_met?" do
let(:newest_macos) { MacOSVersion::SYMBOLS.keys.first }
it "returns result of `SimulateSystem.simulating_or_running_on_<os_name>` for supported OS" do
Homebrew::SimulateSystem.with(os: newest_macos) do
# This needs to use a value from `BASE_OS_OPTIONS`
expect(described_class.os_condition_met?(:macos)).to be true
end
end
it "returns false if `os_name` is a macOS version but OS is Linux" do
Homebrew::SimulateSystem.with(os: :linux) do
expect(described_class.os_condition_met?(newest_macos)).to be false
end
end
it "returns false if `os_name` is a macOS version but current OS is `:generic`" do
allow(Homebrew::SimulateSystem).to receive(:current_os).and_return(:generic)
expect(described_class.os_condition_met?(newest_macos)).to be false
end
it "returns false if current OS is `:macos` and `os_name` is a macOS version" do
# A generic macOS version is treated as less than any other version.
Homebrew::SimulateSystem.with(os: :macos) do
expect(described_class.os_condition_met?(newest_macos)).to be false
end
end
it "returns true if current OS equals the `os_name` macOS version" do
Homebrew::SimulateSystem.with(os: newest_macos) do
expect(described_class.os_condition_met?(newest_macos)).to be true
end
end
it "returns true if current OS meets the `or_condition` for `os_name` macOS version" do
current_os = :ventura
Homebrew::SimulateSystem.with(os: current_os) do
expect(described_class.os_condition_met?(current_os, :or_newer)).to be true
expect(described_class.os_condition_met?(:big_sur, :or_newer)).to be true
expect(described_class.os_condition_met?(current_os, :or_older)).to be true
expect(described_class.os_condition_met?(newest_macos, :or_older)).to be true
end
end
it "returns false if current OS does not meet the `or_condition` for `os_name` macOS version" do
Homebrew::SimulateSystem.with(os: :ventura) do
expect(described_class.os_condition_met?(newest_macos, :or_newer)).to be false
expect(described_class.os_condition_met?(:big_sur, :or_older)).to be false
end
end
it "raises an error if `os_name` is not valid" do
expect { described_class.os_condition_met?(:nonexistent_os) }
.to raise_error(ArgumentError, /Invalid OS condition:/)
end
it "raises an error if `os_name` is a macOS version but `or_condition` is not valid" do
expect do
described_class.os_condition_met?(newest_macos, :nonexistent_condition)
end.to raise_error(ArgumentError, /Invalid OS `or_\*` condition:/)
end
end
describe "::condition_from_method_name" do
it "returns a symbol with any `on_` prefix removed" do
expect(described_class.condition_from_method_name(:on_arm)).to eq(:arm)
end
it "returns provided symbol if there is no `on_` prefix" do
expect(described_class.condition_from_method_name(:arm)).to eq(:arm)
end
end
describe "::setup_arch_methods" do
subject do
klass = Class.new
described_class.setup_arch_methods(klass)
klass
end
it_behaves_like "a class with on_arch methods"
end
describe "::setup_base_os_methods" do
subject do
klass = Class.new
described_class.setup_base_os_methods(klass)
klass
end
it_behaves_like "a class with on_base_os methods"
end
describe "::setup_macos_methods" do
subject do
klass = Class.new
described_class.setup_macos_methods(klass)
klass
end
it_behaves_like "a class with on_macos methods"
end
describe "::included" do
it "raises an error" do
expect { Class.new { include OnSystem } }
.to raise_error(/Do not include `OnSystem` directly/)
end
end
describe "::MacOSAndLinux" do
subject { Class.new { include OnSystem::MacOSAndLinux } }
it "can be included" do
expect { Class.new { include OnSystem::MacOSAndLinux } }.not_to raise_error
end
it_behaves_like "a class with on_arch methods"
it_behaves_like "a class with on_base_os methods"
it_behaves_like "a class with on_macos methods"
end
describe "::MacOSOnly" do
subject { Class.new { include OnSystem::MacOSAndLinux } }
it "can be included" do
expect { Class.new { include OnSystem::MacOSOnly } }.not_to raise_error
end
it_behaves_like "a class with on_arch methods"
it_behaves_like "a class with on_macos methods"
end
end