Files
brew/Library/Homebrew/test/dev-cmd/bump-formula-pr_spec.rb
T
Mike McQuaid 204ea7e964 Make tests use public APIs and enable their cops
- Make every statically-poked method public and call it directly,
  keeping `public_send` only for dynamically-named public methods.
- Read and write state through public `attr_*` accessors instead of
  instance variable reflection.
- Enable `Homebrew/NoSendInTests` and
  `Homebrew/NoInstanceVariableAccessInTests` now the test suite is
  clean, so neither pattern creeps back in.
- Keep rare justified disables, e.g. `Module#remove_const` is
  private core Ruby and raw memoisation state has no accessor.
2026-07-27 08:11:46 +01:00

258 lines
9.1 KiB
Ruby

# typed: true
# frozen_string_literal: true
require "cmd/shared_examples/args_parse"
require "dev-cmd/bump-formula-pr"
require "utils/pypi"
RSpec.describe Homebrew::DevCmd::BumpFormulaPr do
subject(:bump_formula_pr) { described_class.new(["test"]) }
let(:f) do
formula("test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.2.3.tgz"
end
end
it_behaves_like "parseable arguments"
describe "#run" do
it "adds updated mirrors as string literals" do
formula_path = CoreTap.instance.new_formula_path("couchdb")
formula_path.dirname.mkpath
formula_path.write <<~RUBY
class Couchdb < Formula
url "https://www.apache.org/dyn/closer.lua?path=couchdb/source/3.5.1/apache-couchdb-3.5.1.tar.gz"
mirror "https://archive.apache.org/dist/couchdb/source/3.5.1/apache-couchdb-3.5.1.tar.gz"
sha256 "#{"a" * 64}"
end
RUBY
CoreTap.instance.clear_cache
Formulary.clear_cache
Formula.clear_cache
formula = Formulary.from_contents("couchdb", formula_path, formula_path.read)
resource_path = mktmpdir/"apache-couchdb-3.5.2.tar.gz"
resource_path.write("couchdb")
updated_mirror = "https://archive.apache.org/dist/couchdb/source/3.5.2/apache-couchdb-3.5.2.tar.gz"
command = described_class.new(["--write-only", "--no-audit", "--version=3.5.2", "couchdb"])
allow(Homebrew).to receive(:install_bundler_gems!)
allow(CoreTap.instance).to receive_messages(allow_bump?: true, git?: true,
remote_repository: "Homebrew/homebrew-core")
allow(command).to receive(:check_new_version)
allow(command).to receive(:fetch_resource_and_forced_version).and_return([resource_path, false])
allow(command).to receive_messages(run_audit: false, update_matching_version_resources!: {})
allow(PyPI).to receive(:update_python_resources!)
allow(Utils::Tar).to receive(:validate_file).with(resource_path)
allow(command.args.named).to receive(:to_formulae).and_return([formula])
allow(Formula).to receive(:[]).with("couchdb").and_return(formula)
expect_any_instance_of(Utils::AST::FormulaAST)
.to receive(:add_stable_stanzas_after) do |formula_ast, name, stanzas|
expect(name).to eq(:url)
expect(stanzas).to include([:mirror, "mirror #{updated_mirror.inspect}"])
formula_ast.add_stanzas_after(name, stanzas, parent: formula_ast.stanza(:stable, type: :block_call))
end
command.run
expect(formula_path.read).to include " mirror #{updated_mirror.inspect}\n " \
"sha256 #{resource_path.sha256.inspect}\n"
end
end
describe "::check_throttle" do
let(:tap) { Tap.fetch("test", "tap") }
let(:f_throttle) do
formula("throttle-test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.2.3.tgz"
livecheck do
throttle 5
end
end
end
let(:f_throttle_days) do
formula("throttle-days-test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.2.3.tgz"
livecheck do
throttle days: 1
end
end
end
let(:f_throttle_rate_and_days) do
formula("throttle-rate-and-days-test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.2.3.tgz"
livecheck do
throttle 5, days: 1
end
end
end
let(:throttle_error) { "Error: throttle-test should only be updated every 5 releases on multiples of 5\n" }
let(:throttle_days_error) { "Error: throttle-days-test should only be updated every 1 day\n" }
let(:throttle_rate_days_error) do
"Error: throttle-rate-and-days-test should only be updated every 5 releases on multiples of 5 or 1 day\n"
end
context "when formula is not in a tap" do
it "outputs nothing" do
allow(f).to receive(:tap).and_return(nil)
expect { bump_formula_pr.check_throttle(f, "1.2.4") }.not_to output.to_stderr
end
end
context "when a livecheck throttle value isn't present" do
it "does not throttle" do
allow(f).to receive(:tap).and_return(tap)
expect { bump_formula_pr.check_throttle(f, "1.2.4") }.not_to output.to_stderr
end
end
context "when patch version is a multiple of throttle rate" do
it "does not throttle" do
allow(f_throttle).to receive(:tap).and_return(tap)
expect { bump_formula_pr.check_throttle(f_throttle, "1.2.5") }.not_to output.to_stderr
end
end
context "when patch version is not a multiple of throttle rate" do
it "throttles version" do
allow(f_throttle).to receive(:tap).and_return(tap)
expect do
bump_formula_pr.check_throttle(f_throttle, "1.2.4")
rescue SystemExit
nil
end.to output(throttle_error).to_stderr
end
end
context "when patch version is not a multiple and throttle days are set" do
before do
allow(f_throttle_rate_and_days).to receive(:tap).and_return(tap)
end
it "throttles version when throttle interval has not elapsed" do
allow(Homebrew::Livecheck).to receive(:throttle_interval_elapsed?).and_return(false)
expect do
bump_formula_pr.check_throttle(f_throttle_rate_and_days, "1.2.4")
rescue SystemExit
nil
end.to output(throttle_rate_days_error).to_stderr
end
it "does not throttle when throttle interval has elapsed" do
allow(Homebrew::Livecheck).to receive(:throttle_interval_elapsed?).and_return(true)
expect { bump_formula_pr.check_throttle(f_throttle_rate_and_days, "1.2.4") }.not_to output.to_stderr
end
end
context "when only throttle days is set" do
before do
allow(f_throttle_days).to receive(:tap).and_return(tap)
end
it "throttles version when throttle interval has not elapsed" do
allow(Homebrew::Livecheck).to receive(:throttle_interval_elapsed?).and_return(false)
expect do
bump_formula_pr.check_throttle(f_throttle_days, "1.2.4")
rescue SystemExit
next
end.to output(throttle_days_error).to_stderr
end
it "does not throttle when throttle interval has elapsed" do
allow(Homebrew::Livecheck).to receive(:throttle_interval_elapsed?).and_return(true)
expect do
bump_formula_pr.check_throttle(f_throttle_days, "1.2.4")
end.not_to output.to_stderr
end
end
end
describe "::update_matching_version_resources!" do
let(:f) do
formula("test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.2.3.tgz"
resource "parent" do
url "https://brew.sh/parent-1.2.3.tar.gz"
livecheck do
formula :parent
end
end
resource "no-parent" do
url "https://brew.sh/no-parent-1.2.3.tar.gz"
end
end
end
let(:resource) { f.resource("parent") }
let(:version) { "1.2.4" }
it "only updates `:parent` resource" do
expect(bump_formula_pr).to receive(:update_resource_block!).with(f, resource, version).and_return(:success)
expect(bump_formula_pr.update_matching_version_resources!(f, version:)).to eq({ "parent" => :success })
end
it "does not update `:parent` resource if set in `--resource-versions`" do
resource_versions = { "parent" => { current_version: "1.2.3", latest_version: version } }
expect(bump_formula_pr).not_to receive(:update_resource_block!)
expect(bump_formula_pr.update_matching_version_resources!(f, version:, resource_versions:)).to eq({})
end
end
describe "::update_resources!" do
let(:f) do
formula("test") do
T.bind(self, T.class_of(Formula))
url "https://brew.sh/test-1.0.0.tgz"
resource "foo" do
url "https://brew.sh/foo-1.2.3.tar.gz"
end
end
end
let(:r) { f.resource("foo") }
it "updates to requested version" do
version = "2.1.0"
resource_versions = { "foo" => { current_version: "1.2.3", latest_version: version } }
expect(bump_formula_pr).to receive(:update_resource_block!).with(f, r, version).and_return(:success)
expect(bump_formula_pr.update_resources!(f, resource_versions:)).to eq({ "foo" => :success })
end
it "downgrades to requested version" do
version = "0.1.2"
resource_versions = { "foo" => { current_version: "1.2.3", latest_version: version } }
expect(bump_formula_pr).to receive(:update_resource_block!).with(f, r, version).and_return(:success)
expect(bump_formula_pr.update_resources!(f, resource_versions:)).to eq({ "foo" => :downgraded })
end
it "returns update failures" do
version = "0.1.2"
resource_versions = { "foo" => { current_version: "1.2.3", latest_version: version } }
expect(bump_formula_pr).to receive(:update_resource_block!).with(f, r, version).and_return(:url_unchanged)
expect(bump_formula_pr.update_resources!(f, resource_versions:)).to eq({ "foo" => :url_unchanged })
end
end
end