diff --git a/Library/Homebrew/test/extend/on_system_spec.rb b/Library/Homebrew/test/extend/on_system_spec.rb new file mode 100644 index 0000000000..605c37f0d8 --- /dev/null +++ b/Library/Homebrew/test/extend/on_system_spec.rb @@ -0,0 +1,176 @@ +# 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 "::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_` 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 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