style: remove RSpec/MultipleDescribes violations

Co-authored-by: Nanda H Krishna <nanda.harishankar@gmail.com>
This commit is contained in:
Rylan Polster 2021-01-31 14:50:29 -05:00
parent af40e072b0
commit d5d7b6c3db
No known key found for this signature in database
GPG Key ID: 46A744940CFF4D64
63 changed files with 3961 additions and 3795 deletions

View File

@ -3,7 +3,8 @@
require "extend/ENV"
shared_examples EnvActivation do
describe "ENV" do
shared_examples EnvActivation do
subject(:env) { env_activation.extend(described_class) }
let(:env_activation) { {}.extend(EnvActivation) }
@ -170,13 +171,13 @@ shared_examples EnvActivation do
expect(subject.compiler_any_clang?(:llvm_clang)).to be true
end
end
end
end
describe Stdenv do
describe Stdenv do
include_examples EnvActivation
end
end
describe Superenv do
describe Superenv do
include_examples EnvActivation
it "initializes deps" do
@ -204,4 +205,5 @@ describe Superenv do
expect(env["HOMEBREW_CCCFG"]).to include("g")
end
end
end
end

View File

@ -8,28 +8,6 @@ require "fileutils"
using Homebrew::Cleanup::CleanupRefinement
describe Homebrew::Cleanup::CleanupRefinement do
describe "::prune?" do
alias_matcher :be_pruned, :be_prune
subject(:path) { HOMEBREW_CACHE/"foo" }
before do
path.mkpath
end
it "returns true when ctime and mtime < days_default" do
allow_any_instance_of(Pathname).to receive(:ctime).and_return(2.days.ago)
allow_any_instance_of(Pathname).to receive(:mtime).and_return(2.days.ago)
expect(path.prune?(1)).to be true
end
it "returns false when ctime and mtime >= days_default" do
expect(path.prune?(2)).to be false
end
end
end
describe Homebrew::Cleanup do
subject(:cleanup) { described_class.new }
@ -49,6 +27,26 @@ describe Homebrew::Cleanup do
FileUtils.rm_rf HOMEBREW_LIBRARY/"Homebrew"
end
describe "::CleanupRefinement::prune?" do
alias_matcher :be_pruned, :be_prune
subject(:path) { HOMEBREW_CACHE/"foo" }
before do
path.mkpath
end
it "returns true when ctime and mtime < days_default" do
allow_any_instance_of(Pathname).to receive(:ctime).and_return(2.days.ago)
allow_any_instance_of(Pathname).to receive(:mtime).and_return(2.days.ago)
expect(path.prune?(1)).to be true
end
it "returns false when ctime and mtime >= days_default" do
expect(path.prune?(2)).to be false
end
end
describe "::cleanup" do
it "removes .DS_Store and lock files" do
cleanup.clean!

View File

@ -100,9 +100,8 @@ describe Dependency do
expect(foo1).not_to eq(foo3)
expect(foo1).not_to eql(foo3)
end
end
describe TapDependency do
describe TapDependency do
subject(:dependency) { described_class.new("foo/bar/dog") }
specify "#tap" do
@ -112,4 +111,5 @@ describe TapDependency do
specify "#option_names" do
expect(dependency.option_names).to eq(%w[dog])
end
end
end

View File

@ -0,0 +1,37 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe AbstractDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:specs) { {} }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { nil }
let(:args) { %w[foo bar baz] }
specify "#source_modified_time" do
Mktemp.new("mtime") do
FileUtils.touch "foo", mtime: Time.now - 10
FileUtils.touch "bar", mtime: Time.now - 100
FileUtils.ln_s "not-exist", "baz"
expect(strategy.source_modified_time).to eq(File.mtime("foo"))
end
end
context "when specs[:bottle]" do
let(:specs) { { bottle: true } }
it "extends Pourable" do
expect(strategy).to be_a_kind_of(AbstractDownloadStrategy::Pourable)
end
end
context "without specs[:bottle]" do
it "is does not extend Pourable" do
expect(strategy).not_to be_a_kind_of(AbstractDownloadStrategy::Pourable)
end
end
end

View File

@ -0,0 +1,58 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe CurlPostDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { {} }
describe "#fetch" do
before do
strategy.temporary_path.dirname.mkpath
FileUtils.touch strategy.temporary_path
end
context "with :using and :data specified" do
let(:specs) {
{
using: :post,
data: {
form: "data",
is: "good",
},
}
}
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-d", "form=data").and(array_including_cons("-d", "is=good"))),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with :using but no :data" do
let(:specs) { { using: :post } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-X", "POST")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
end
end

View File

@ -0,0 +1,191 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe CurlDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { { user: "download:123456" } }
it "parses the opts and sets the corresponding args" do
expect(strategy.send(:_curl_args)).to eq(["--user", "download:123456"])
end
describe "#cached_location" do
subject(:location) { described_class.new(url, name, version, **specs).cached_location }
context "when URL ends with file" do
it {
expect(location).to eq(
HOMEBREW_CACHE/"downloads/3d1c0ae7da22be9d83fb1eb774df96b7c4da71d3cf07e1cb28555cf9a5e5af70--foo.tar.gz",
)
}
end
context "when URL file is in middle" do
let(:url) { "https://example.com/foo.tar.gz/from/this/mirror" }
it {
expect(location).to eq(
HOMEBREW_CACHE/"downloads/1ab61269ba52c83994510b1e28dd04167a2f2e8393a35a9c50c1f7d33fd8f619--foo.tar.gz",
)
}
end
end
describe "#fetch" do
before do
strategy.temporary_path.dirname.mkpath
FileUtils.touch strategy.temporary_path
end
it "calls curl with default arguments" do
expect(strategy).to receive(:curl).with(
"--location",
"--remote-time",
"--continue-at", "0",
"--output", an_instance_of(Pathname),
url,
an_instance_of(Hash)
)
strategy.fetch
end
context "with an explicit user agent" do
let(:specs) { { user_agent: "Mozilla/25.0.1" } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("--user-agent", "Mozilla/25.0.1")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with a generalized fake user agent" do
alias_matcher :a_string_matching, :match
let(:specs) { { user_agent: :fake } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons(
"--user-agent",
a_string_matching(/Mozilla.*Mac OS X 10.*AppleWebKit/),
)),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with cookies set" do
let(:specs) {
{
cookies: {
coo: "k/e",
mon: "ster",
},
}
}
it "adds the appropriate curl args and does not URL-encode the cookies" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-b", "coo=k/e;mon=ster")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with referer set" do
let(:specs) { { referer: "https://somehost/also" } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-e", "https://somehost/also")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with headers set" do
alias_matcher :a_string_matching, :match
let(:specs) { { headers: ["foo", "bar"] } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("--header", "foo").and(array_including_cons("--header", "bar"))),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
end
describe "#cached_location" do
context "with a file name trailing the URL path" do
let(:url) { "https://example.com/cask.dmg" }
its("cached_location.extname") { is_expected.to eq(".dmg") }
end
context "with a file name trailing the first query parameter" do
let(:url) { "https://example.com/download?file=cask.zip&a=1" }
its("cached_location.extname") { is_expected.to eq(".zip") }
end
context "with a file name trailing the second query parameter" do
let(:url) { "https://example.com/dl?a=1&file=cask.zip&b=2" }
its("cached_location.extname") { is_expected.to eq(".zip") }
end
context "with an unusually long query string" do
let(:url) do
[
"https://node49152.ssl.fancycdn.example.com",
"/fancycdn/node/49152/file/upload/download",
"?cask_class=zf920df",
"&cask_group=2348779087242312",
"&cask_archive_file_name=cask.zip",
"&signature=CGmDulxL8pmutKTlCleNTUY%2FyO9Xyl5u9yVZUE0",
"uWrjadjuz67Jp7zx3H7NEOhSyOhu8nzicEHRBjr3uSoOJzwkLC8L",
"BLKnz%2B2X%2Biq5m6IdwSVFcLp2Q1Hr2kR7ETn3rF1DIq5o0lHC",
"yzMmyNe5giEKJNW8WF0KXriULhzLTWLSA3ZTLCIofAdRiiGje1kN",
"YY3C0SBqymQB8CG3ONn5kj7CIGbxrDOq5xI2ZSJdIyPysSX7SLvE",
"DBw2KdR24q9t1wfjS9LUzelf5TWk6ojj8p9%2FHjl%2Fi%2FVCXN",
"N4o1mW%2FMayy2tTY1qcC%2FTmqI1ulZS8SNuaSgr9Iys9oDF1%2",
"BPK%2B4Sg==",
].join
end
its("cached_location.extname") { is_expected.to eq(".zip") }
its("cached_location.to_path.length") { is_expected.to be_between(0, 255) }
end
end
end

View File

@ -0,0 +1,35 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe DownloadStrategyDetector do
describe "::detect" do
subject(:strategy_detector) { described_class.detect(url, strategy) }
let(:url) { Object.new }
let(:strategy) { nil }
context "when given Git URL" do
let(:url) { "git://example.com/foo.git" }
it { is_expected.to eq(GitDownloadStrategy) }
end
context "when given a GitHub Git URL" do
let(:url) { "https://github.com/homebrew/brew.git" }
it { is_expected.to eq(GitHubGitDownloadStrategy) }
end
it "defaults to curl" do
expect(strategy_detector).to eq(CurlDownloadStrategy)
end
it "raises an error when passed an unrecognized strategy" do
expect {
described_class.detect("foo", Class.new)
}.to raise_error(TypeError)
end
end
end

View File

@ -0,0 +1,69 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe GitDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version) }
let(:name) { "baz" }
let(:url) { "https://github.com/homebrew/foo" }
let(:version) { nil }
let(:cached_location) { subject.cached_location }
before do
@commit_id = 1
FileUtils.mkpath cached_location
end
def git_commit_all
system "git", "add", "--all"
system "git", "commit", "-m", "commit number #{@commit_id}"
@commit_id += 1
end
def setup_git_repo
system "git", "init"
system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
FileUtils.touch "README"
git_commit_all
end
describe "#source_modified_time" do
it "returns the right modification time" do
cached_location.cd do
setup_git_repo
end
expect(strategy.source_modified_time.to_i).to eq(1_485_115_153)
end
end
specify "#last_commit" do
cached_location.cd do
setup_git_repo
FileUtils.touch "LICENSE"
git_commit_all
end
expect(strategy.last_commit).to eq("f68266e")
end
describe "#fetch_last_commit" do
let(:url) { "file://#{remote_repo}" }
let(:version) { Version.create("HEAD") }
let(:remote_repo) { HOMEBREW_PREFIX/"remote_repo" }
before { remote_repo.mkpath }
after { FileUtils.rm_rf remote_repo }
it "fetches the hash of the last commit" do
remote_repo.cd do
setup_git_repo
FileUtils.touch "LICENSE"
git_commit_all
end
expect(strategy.fetch_last_commit).to eq("f68266e")
end
end
end

View File

@ -0,0 +1,17 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe GitHubGitDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version) }
let(:name) { "brew" }
let(:url) { "https://github.com/homebrew/brew.git" }
let(:version) { nil }
it "parses the URL and sets the corresponding instance variables" do
expect(strategy.instance_variable_get(:@user)).to eq("homebrew")
expect(strategy.instance_variable_get(:@repo)).to eq("brew")
end
end

View File

@ -0,0 +1,36 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe SubversionDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { {} }
describe "#fetch" do
context "with :trust_cert set" do
let(:specs) { { trust_cert: true } }
it "adds the appropriate svn args" do
expect(strategy).to receive(:system_command!)
.with("svn", hash_including(args: array_including("--trust-server-cert", "--non-interactive")))
strategy.fetch
end
end
context "with :revision set" do
let(:specs) { { revision: "10" } }
it "adds svn arguments for :revision" do
expect(strategy).to receive(:system_command!)
.with("svn", hash_including(args: array_including_cons("-r", "10")))
strategy.fetch
end
end
end
end

View File

@ -0,0 +1,17 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe VCSDownloadStrategy do
let(:url) { "https://example.com/bar" }
let(:version) { nil }
describe "#cached_location" do
it "returns the path of the cached resource" do
allow_any_instance_of(described_class).to receive(:cache_tag).and_return("foo")
downloader = described_class.new(url, "baz", version)
expect(downloader.cached_location).to eq(HOMEBREW_CACHE/"baz--foo")
end
end
end

View File

@ -1,432 +0,0 @@
# typed: false
# frozen_string_literal: true
require "download_strategy"
describe AbstractDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:specs) { {} }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { nil }
let(:args) { %w[foo bar baz] }
specify "#source_modified_time" do
Mktemp.new("mtime") do
FileUtils.touch "foo", mtime: Time.now - 10
FileUtils.touch "bar", mtime: Time.now - 100
FileUtils.ln_s "not-exist", "baz"
expect(strategy.source_modified_time).to eq(File.mtime("foo"))
end
end
context "when specs[:bottle]" do
let(:specs) { { bottle: true } }
it "extends Pourable" do
expect(strategy).to be_a_kind_of(AbstractDownloadStrategy::Pourable)
end
end
context "without specs[:bottle]" do
it "is does not extend Pourable" do
expect(strategy).not_to be_a_kind_of(AbstractDownloadStrategy::Pourable)
end
end
end
describe VCSDownloadStrategy do
let(:url) { "https://example.com/bar" }
let(:version) { nil }
describe "#cached_location" do
it "returns the path of the cached resource" do
allow_any_instance_of(described_class).to receive(:cache_tag).and_return("foo")
downloader = described_class.new(url, "baz", version)
expect(downloader.cached_location).to eq(HOMEBREW_CACHE/"baz--foo")
end
end
end
describe GitHubGitDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version) }
let(:name) { "brew" }
let(:url) { "https://github.com/homebrew/brew.git" }
let(:version) { nil }
it "parses the URL and sets the corresponding instance variables" do
expect(strategy.instance_variable_get(:@user)).to eq("homebrew")
expect(strategy.instance_variable_get(:@repo)).to eq("brew")
end
end
describe GitDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version) }
let(:name) { "baz" }
let(:url) { "https://github.com/homebrew/foo" }
let(:version) { nil }
let(:cached_location) { subject.cached_location }
before do
@commit_id = 1
FileUtils.mkpath cached_location
end
def git_commit_all
system "git", "add", "--all"
system "git", "commit", "-m", "commit number #{@commit_id}"
@commit_id += 1
end
def setup_git_repo
system "git", "init"
system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
FileUtils.touch "README"
git_commit_all
end
describe "#source_modified_time" do
it "returns the right modification time" do
cached_location.cd do
setup_git_repo
end
expect(strategy.source_modified_time.to_i).to eq(1_485_115_153)
end
end
specify "#last_commit" do
cached_location.cd do
setup_git_repo
FileUtils.touch "LICENSE"
git_commit_all
end
expect(strategy.last_commit).to eq("f68266e")
end
describe "#fetch_last_commit" do
let(:url) { "file://#{remote_repo}" }
let(:version) { Version.create("HEAD") }
let(:remote_repo) { HOMEBREW_PREFIX/"remote_repo" }
before { remote_repo.mkpath }
after { FileUtils.rm_rf remote_repo }
it "fetches the hash of the last commit" do
remote_repo.cd do
setup_git_repo
FileUtils.touch "LICENSE"
git_commit_all
end
expect(strategy.fetch_last_commit).to eq("f68266e")
end
end
end
describe CurlDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { { user: "download:123456" } }
it "parses the opts and sets the corresponding args" do
expect(strategy.send(:_curl_args)).to eq(["--user", "download:123456"])
end
describe "#cached_location" do
subject(:location) { described_class.new(url, name, version, **specs).cached_location }
context "when URL ends with file" do
it {
expect(location).to eq(
HOMEBREW_CACHE/"downloads/3d1c0ae7da22be9d83fb1eb774df96b7c4da71d3cf07e1cb28555cf9a5e5af70--foo.tar.gz",
)
}
end
context "when URL file is in middle" do
let(:url) { "https://example.com/foo.tar.gz/from/this/mirror" }
it {
expect(location).to eq(
HOMEBREW_CACHE/"downloads/1ab61269ba52c83994510b1e28dd04167a2f2e8393a35a9c50c1f7d33fd8f619--foo.tar.gz",
)
}
end
end
describe "#fetch" do
before do
strategy.temporary_path.dirname.mkpath
FileUtils.touch strategy.temporary_path
end
it "calls curl with default arguments" do
expect(strategy).to receive(:curl).with(
"--location",
"--remote-time",
"--continue-at", "0",
"--output", an_instance_of(Pathname),
url,
an_instance_of(Hash)
)
strategy.fetch
end
context "with an explicit user agent" do
let(:specs) { { user_agent: "Mozilla/25.0.1" } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("--user-agent", "Mozilla/25.0.1")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with a generalized fake user agent" do
alias_matcher :a_string_matching, :match
let(:specs) { { user_agent: :fake } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons(
"--user-agent",
a_string_matching(/Mozilla.*Mac OS X 10.*AppleWebKit/),
)),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with cookies set" do
let(:specs) {
{
cookies: {
coo: "k/e",
mon: "ster",
},
}
}
it "adds the appropriate curl args and does not URL-encode the cookies" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-b", "coo=k/e;mon=ster")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with referer set" do
let(:specs) { { referer: "https://somehost/also" } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-e", "https://somehost/also")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with headers set" do
alias_matcher :a_string_matching, :match
let(:specs) { { headers: ["foo", "bar"] } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("--header", "foo").and(array_including_cons("--header", "bar"))),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
end
describe "#cached_location" do
context "with a file name trailing the URL path" do
let(:url) { "https://example.com/cask.dmg" }
its("cached_location.extname") { is_expected.to eq(".dmg") }
end
context "with a file name trailing the first query parameter" do
let(:url) { "https://example.com/download?file=cask.zip&a=1" }
its("cached_location.extname") { is_expected.to eq(".zip") }
end
context "with a file name trailing the second query parameter" do
let(:url) { "https://example.com/dl?a=1&file=cask.zip&b=2" }
its("cached_location.extname") { is_expected.to eq(".zip") }
end
context "with an unusually long query string" do
let(:url) do
[
"https://node49152.ssl.fancycdn.example.com",
"/fancycdn/node/49152/file/upload/download",
"?cask_class=zf920df",
"&cask_group=2348779087242312",
"&cask_archive_file_name=cask.zip",
"&signature=CGmDulxL8pmutKTlCleNTUY%2FyO9Xyl5u9yVZUE0",
"uWrjadjuz67Jp7zx3H7NEOhSyOhu8nzicEHRBjr3uSoOJzwkLC8L",
"BLKnz%2B2X%2Biq5m6IdwSVFcLp2Q1Hr2kR7ETn3rF1DIq5o0lHC",
"yzMmyNe5giEKJNW8WF0KXriULhzLTWLSA3ZTLCIofAdRiiGje1kN",
"YY3C0SBqymQB8CG3ONn5kj7CIGbxrDOq5xI2ZSJdIyPysSX7SLvE",
"DBw2KdR24q9t1wfjS9LUzelf5TWk6ojj8p9%2FHjl%2Fi%2FVCXN",
"N4o1mW%2FMayy2tTY1qcC%2FTmqI1ulZS8SNuaSgr9Iys9oDF1%2",
"BPK%2B4Sg==",
].join
end
its("cached_location.extname") { is_expected.to eq(".zip") }
its("cached_location.to_path.length") { is_expected.to be_between(0, 255) }
end
end
end
describe CurlPostDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { {} }
describe "#fetch" do
before do
strategy.temporary_path.dirname.mkpath
FileUtils.touch strategy.temporary_path
end
context "with :using and :data specified" do
let(:specs) {
{
using: :post,
data: {
form: "data",
is: "good",
},
}
}
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-d", "form=data").and(array_including_cons("-d", "is=good"))),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
context "with :using but no :data" do
let(:specs) { { using: :post } }
it "adds the appropriate curl args" do
expect(strategy).to receive(:system_command).with(
/curl/,
hash_including(args: array_including_cons("-X", "POST")),
)
.at_least(:once)
.and_return(instance_double(SystemCommand::Result, success?: true, stdout: "", assert_success!: nil))
strategy.fetch
end
end
end
end
describe SubversionDownloadStrategy do
subject(:strategy) { described_class.new(url, name, version, **specs) }
let(:name) { "foo" }
let(:url) { "https://example.com/foo.tar.gz" }
let(:version) { "1.2.3" }
let(:specs) { {} }
describe "#fetch" do
context "with :trust_cert set" do
let(:specs) { { trust_cert: true } }
it "adds the appropriate svn args" do
expect(strategy).to receive(:system_command!)
.with("svn", hash_including(args: array_including("--trust-server-cert", "--non-interactive")))
strategy.fetch
end
end
context "with :revision set" do
let(:specs) { { revision: "10" } }
it "adds svn arguments for :revision" do
expect(strategy).to receive(:system_command!)
.with("svn", hash_including(args: array_including_cons("-r", "10")))
strategy.fetch
end
end
end
end
describe DownloadStrategyDetector do
describe "::detect" do
subject(:strategy_detector) { described_class.detect(url, strategy) }
let(:url) { Object.new }
let(:strategy) { nil }
context "when given Git URL" do
let(:url) { "git://example.com/foo.git" }
it { is_expected.to eq(GitDownloadStrategy) }
end
context "when given a GitHub Git URL" do
let(:url) { "https://github.com/homebrew/brew.git" }
it { is_expected.to eq(GitHubGitDownloadStrategy) }
end
it "defaults to curl" do
expect(strategy_detector).to eq(CurlDownloadStrategy)
end
it "raises an error when passed an unrecognized strategy" do
expect {
described_class.detect("foo", Class.new)
}.to raise_error(TypeError)
end
end
end

View File

@ -3,7 +3,8 @@
require "exceptions"
describe MultipleVersionsInstalledError do
describe "Exception" do
describe MultipleVersionsInstalledError do
subject {
described_class.new <<~EOS
foo has multiple installed versions
@ -17,23 +18,23 @@ describe MultipleVersionsInstalledError do
Run `brew uninstall --force foo` to remove all versions.
EOS
}
end
end
describe NoSuchKegError do
describe NoSuchKegError do
subject { described_class.new("foo") }
its(:to_s) { is_expected.to eq("No such keg: #{HOMEBREW_CELLAR}/foo") }
end
end
describe FormulaValidationError do
describe FormulaValidationError do
subject(:error) { described_class.new("foo", "sha257", "magic") }
its(:to_s) {
expect(error.to_s).to eq(%q(invalid attribute for formula 'foo': sha257 ("magic")))
}
end
end
describe FormulaUnavailableError do
describe FormulaUnavailableError do
subject(:error) { described_class.new("foo") }
describe "#dependent_s" do
@ -65,17 +66,17 @@ describe FormulaUnavailableError do
expect(error.to_s).to eq('No available formula with the name "foo" (dependency of foobar).')
}
end
end
end
describe TapFormulaUnavailableError do
describe TapFormulaUnavailableError do
subject { described_class.new(tap, "foo") }
let(:tap) { double(Tap, user: "u", repo: "r", to_s: "u/r", installed?: false) }
its(:to_s) { is_expected.to match(%r{Please tap it and then try again: brew tap u/r}) }
end
end
describe FormulaClassUnavailableError do
describe FormulaClassUnavailableError do
subject(:error) { described_class.new("foo", "foo.rb", "Foo", list) }
let(:mod) do
@ -107,68 +108,68 @@ describe FormulaClassUnavailableError do
its(:to_s) { is_expected.to match(/Expected to find class Foo, but only found: Baz\./) }
end
end
end
describe FormulaUnreadableError do
describe FormulaUnreadableError do
subject { described_class.new("foo", formula_error) }
let(:formula_error) { LoadError.new("bar") }
its(:to_s) { is_expected.to eq("foo: bar") }
end
end
describe TapUnavailableError do
describe TapUnavailableError do
subject { described_class.new("foo") }
its(:to_s) { is_expected.to eq("No available tap foo.\n") }
end
end
describe TapAlreadyTappedError do
describe TapAlreadyTappedError do
subject { described_class.new("foo") }
its(:to_s) { is_expected.to eq("Tap foo already tapped.\n") }
end
end
describe BuildError do
describe BuildError do
subject { described_class.new(formula, "badprg", %w[arg1 arg2], {}) }
let(:formula) { double(Formula, name: "foo") }
its(:to_s) { is_expected.to eq("Failed executing: badprg arg1 arg2") }
end
end
describe OperationInProgressError do
describe OperationInProgressError do
subject { described_class.new("foo") }
its(:to_s) { is_expected.to match(/Operation already in progress for foo/) }
end
end
describe FormulaInstallationAlreadyAttemptedError do
describe FormulaInstallationAlreadyAttemptedError do
subject { described_class.new(formula) }
let(:formula) { double(Formula, full_name: "foo/bar") }
its(:to_s) { is_expected.to eq("Formula installation already attempted: foo/bar") }
end
end
describe FormulaConflictError do
describe FormulaConflictError do
subject { described_class.new(formula, [conflict]) }
let(:formula) { double(Formula, full_name: "foo/qux") }
let(:conflict) { double(name: "bar", reason: "I decided to") }
its(:to_s) { is_expected.to match(/Please `brew unlink bar` before continuing\./) }
end
end
describe CompilerSelectionError do
describe CompilerSelectionError do
subject { described_class.new(formula) }
let(:formula) { double(Formula, full_name: "foo") }
its(:to_s) { is_expected.to match(/foo cannot be built with any available compilers\./) }
end
end
describe CurlDownloadStrategyError do
describe CurlDownloadStrategyError do
context "file does not exist" do
subject { described_class.new("file:///tmp/foo") }
@ -180,52 +181,53 @@ describe CurlDownloadStrategyError do
its(:to_s) { is_expected.to eq("Download failed: https://brew.sh") }
end
end
end
describe ErrorDuringExecution do
describe ErrorDuringExecution do
subject { described_class.new(["badprg", "arg1", "arg2"], status: status) }
let(:status) { instance_double(Process::Status, exitstatus: 17) }
its(:to_s) { is_expected.to eq("Failure while executing; `badprg arg1 arg2` exited with 17.") }
end
end
describe ChecksumMismatchError do
describe ChecksumMismatchError do
subject { described_class.new("/file.tar.gz", hash1, hash2) }
let(:hash1) { double(hash_type: "sha256", to_s: "deadbeef") }
let(:hash2) { double(hash_type: "sha256", to_s: "deadcafe") }
its(:to_s) { is_expected.to match(/SHA256 mismatch/) }
end
end
describe ResourceMissingError do
describe ResourceMissingError do
subject { described_class.new(formula, resource) }
let(:formula) { double(Formula, full_name: "bar") }
let(:resource) { double(inspect: "<resource foo>") }
its(:to_s) { is_expected.to eq("bar does not define resource <resource foo>") }
end
end
describe DuplicateResourceError do
describe DuplicateResourceError do
subject { described_class.new(resource) }
let(:resource) { double(inspect: "<resource foo>") }
its(:to_s) { is_expected.to eq("Resource <resource foo> is defined more than once") }
end
end
describe BottleFormulaUnavailableError do
describe BottleFormulaUnavailableError do
subject { described_class.new("/foo.bottle.tar.gz", "foo/1.0/.brew/foo.rb") }
let(:formula) { double(Formula, full_name: "foo") }
its(:to_s) { is_expected.to match(/This bottle does not contain the formula file/) }
end
end
describe BuildFlagsError do
describe BuildFlagsError do
subject { described_class.new(["-s"]) }
its(:to_s) { is_expected.to match(/flag:\s+-s\nrequires building tools/) }
end
end

View File

@ -3,20 +3,6 @@
require "formula_support"
describe KegOnlyReason do
describe "#to_s" do
it "returns the reason provided" do
r = described_class.new :provided_by_macos, "test"
expect(r.to_s).to eq("test")
end
it "returns a default message when no reason is provided" do
r = described_class.new :provided_by_macos, ""
expect(r.to_s).to match(/^macOS already provides/)
end
end
end
describe BottleDisableReason do
specify ":unneeded" do
bottle_disable_reason = described_class.new :unneeded, nil

View File

@ -0,0 +1,18 @@
# typed: false
# frozen_string_literal: true
require "formula_support"
describe KegOnlyReason do
describe "#to_s" do
it "returns the reason provided" do
r = described_class.new :provided_by_macos, "test"
expect(r.to_s).to eq("test")
end
it "returns a default message when no reason is provided" do
r = described_class.new :provided_by_macos, ""
expect(r.to_s).to match(/^macOS already provides/)
end
end
end

View File

@ -0,0 +1,47 @@
# typed: false
# frozen_string_literal: true
require "language/python"
require "utils/shebang"
describe Language::Python::Shebang do
let(:file) { Tempfile.new("python-shebang") }
let(:python_f) do
formula "python" do
url "https://brew.sh/python-1.0.tgz"
end
end
let(:f) do
formula "foo" do
url "https://brew.sh/foo-1.0.tgz"
depends_on "python"
end
end
before do
file.write <<~EOS
#!/usr/bin/env python3
a
b
c
EOS
file.flush
end
after { file.unlink }
describe "#detected_python_shebang" do
it "can be used to replace Python shebangs" do
expect(Formulary).to receive(:factory).with(python_f.name).and_return(python_f)
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f), file
expect(File.read(file)).to eq <<~EOS
#!#{HOMEBREW_PREFIX}/opt/python/bin/python3
a
b
c
EOS
end
end
end

View File

@ -0,0 +1,98 @@
# typed: false
# frozen_string_literal: true
require "language/python"
require "resource"
describe Language::Python::Virtualenv::Virtualenv, :needs_python do
subject(:virtualenv) { described_class.new(formula, dir, "python") }
let(:dir) { mktmpdir }
let(:resource) { double("resource", stage: true) }
let(:formula_bin) { dir/"formula_bin" }
let(:formula) { double("formula", resource: resource, bin: formula_bin) }
describe "#create" do
it "creates a venv" do
expect(formula).to receive(:system).with("python", "-m", "venv", dir)
virtualenv.create
end
end
describe "#pip_install" do
it "accepts a string" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo")
.and_return(true)
virtualenv.pip_install "foo"
end
it "accepts a multi-line strings" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo", "bar")
.and_return(true)
virtualenv.pip_install <<~EOS
foo
bar
EOS
end
it "accepts an array" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo")
.and_return(true)
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "bar")
.and_return(true)
virtualenv.pip_install ["foo", "bar"]
end
it "accepts a Resource" do
res = Resource.new("test")
expect(res).to receive(:stage).and_yield
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", Pathname.pwd)
.and_return(true)
virtualenv.pip_install res
end
end
describe "#pip_install_and_link" do
let(:src_bin) { dir/"bin" }
let(:dest_bin) { formula.bin }
it "can link scripts" do
src_bin.mkpath
expect(src_bin/"kilroy").not_to exist
expect(dest_bin/"kilroy").not_to exist
FileUtils.touch src_bin/"irrelevant"
bin_before = Dir.glob(src_bin/"*")
FileUtils.touch src_bin/"kilroy"
bin_after = Dir.glob(src_bin/"*")
expect(virtualenv).to receive(:pip_install).with("foo")
expect(Dir).to receive(:[]).with(src_bin/"*").twice.and_return(bin_before, bin_after)
virtualenv.pip_install_and_link "foo"
expect(src_bin/"kilroy").to exist
expect(dest_bin/"kilroy").to exist
expect(dest_bin/"kilroy").to be_a_symlink
expect((src_bin/"kilroy").realpath).to eq((dest_bin/"kilroy").realpath)
expect(dest_bin/"irrelevant").not_to exist
end
end
end

View File

@ -2,8 +2,6 @@
# frozen_string_literal: true
require "language/python"
require "resource"
require "utils/shebang"
describe Language::Python, :needs_python do
describe "#major_minor_version" do
@ -33,138 +31,3 @@ describe Language::Python, :needs_python do
end
end
end
describe Language::Python::Shebang do
let(:file) { Tempfile.new("python-shebang") }
let(:python_f) do
formula "python" do
url "https://brew.sh/python-1.0.tgz"
end
end
let(:f) do
formula "foo" do
url "https://brew.sh/foo-1.0.tgz"
depends_on "python"
end
end
before do
file.write <<~EOS
#!/usr/bin/env python3
a
b
c
EOS
file.flush
end
after { file.unlink }
describe "#detected_python_shebang" do
it "can be used to replace Python shebangs" do
expect(Formulary).to receive(:factory).with(python_f.name).and_return(python_f)
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f), file
expect(File.read(file)).to eq <<~EOS
#!#{HOMEBREW_PREFIX}/opt/python/bin/python3
a
b
c
EOS
end
end
end
describe Language::Python::Virtualenv::Virtualenv do
subject(:virtualenv) { described_class.new(formula, dir, "python") }
let(:dir) { mktmpdir }
let(:resource) { double("resource", stage: true) }
let(:formula_bin) { dir/"formula_bin" }
let(:formula) { double("formula", resource: resource, bin: formula_bin) }
describe "#create" do
it "creates a venv" do
expect(formula).to receive(:system).with("python", "-m", "venv", dir)
virtualenv.create
end
end
describe "#pip_install" do
it "accepts a string" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo")
.and_return(true)
virtualenv.pip_install "foo"
end
it "accepts a multi-line strings" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo", "bar")
.and_return(true)
virtualenv.pip_install <<~EOS
foo
bar
EOS
end
it "accepts an array" do
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "foo")
.and_return(true)
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", "bar")
.and_return(true)
virtualenv.pip_install ["foo", "bar"]
end
it "accepts a Resource" do
res = Resource.new("test")
expect(res).to receive(:stage).and_yield
expect(formula).to receive(:system)
.with(dir/"bin/pip", "install", "-v", "--no-deps",
"--no-binary", ":all:", "--no-user", "--ignore-installed", Pathname.pwd)
.and_return(true)
virtualenv.pip_install res
end
end
describe "#pip_install_and_link" do
let(:src_bin) { dir/"bin" }
let(:dest_bin) { formula.bin }
it "can link scripts" do
src_bin.mkpath
expect(src_bin/"kilroy").not_to exist
expect(dest_bin/"kilroy").not_to exist
FileUtils.touch src_bin/"irrelevant"
bin_before = Dir.glob(src_bin/"*")
FileUtils.touch src_bin/"kilroy"
bin_after = Dir.glob(src_bin/"*")
expect(virtualenv).to receive(:pip_install).with("foo")
expect(Dir).to receive(:[]).with(src_bin/"*").twice.and_return(bin_before, bin_after)
virtualenv.pip_install_and_link "foo"
expect(src_bin/"kilroy").to exist
expect(dest_bin/"kilroy").to exist
expect(dest_bin/"kilroy").to be_a_symlink
expect((src_bin/"kilroy").realpath).to eq((dest_bin/"kilroy").realpath)
expect(dest_bin/"irrelevant").not_to exist
end
end
end

View File

@ -0,0 +1,33 @@
# typed: false
# frozen_string_literal: true
require "options"
describe DeprecatedOption do
subject(:option) { described_class.new("foo", "bar") }
specify "#old" do
expect(option.old).to eq("foo")
end
specify "#old_flag" do
expect(option.old_flag).to eq("--foo")
end
specify "#current" do
expect(option.current).to eq("bar")
end
specify "#current_flag" do
expect(option.current_flag).to eq("--bar")
end
specify "equality" do
foobar = described_class.new("foo", "bar")
boofar = described_class.new("boo", "far")
expect(foobar).to eq(option)
expect(option).to eq(foobar)
expect(boofar).not_to eq(option)
expect(option).not_to eq(boofar)
end
end

View File

@ -0,0 +1,30 @@
# typed: false
# frozen_string_literal: true
require "options"
describe Option do
subject(:option) { described_class.new("foo") }
specify "#to_s" do
expect(option.to_s).to eq("--foo")
end
specify "equality" do
foo = described_class.new("foo")
bar = described_class.new("bar")
expect(option).to eq(foo)
expect(option).not_to eq(bar)
expect(option).to eql(foo)
expect(option).not_to eql(bar)
end
specify "#description" do
expect(option.description).to be_empty
expect(described_class.new("foo", "foo").description).to eq("foo")
end
specify "#inspect" do
expect(option.inspect).to eq("#<Option: \"--foo\">")
end
end

View File

@ -3,61 +3,6 @@
require "options"
describe Option do
subject(:option) { described_class.new("foo") }
specify "#to_s" do
expect(option.to_s).to eq("--foo")
end
specify "equality" do
foo = described_class.new("foo")
bar = described_class.new("bar")
expect(option).to eq(foo)
expect(option).not_to eq(bar)
expect(option).to eql(foo)
expect(option).not_to eql(bar)
end
specify "#description" do
expect(option.description).to be_empty
expect(described_class.new("foo", "foo").description).to eq("foo")
end
specify "#inspect" do
expect(option.inspect).to eq("#<Option: \"--foo\">")
end
end
describe DeprecatedOption do
subject(:option) { described_class.new("foo", "bar") }
specify "#old" do
expect(option.old).to eq("foo")
end
specify "#old_flag" do
expect(option.old_flag).to eq("--foo")
end
specify "#current" do
expect(option.current).to eq("bar")
end
specify "#current_flag" do
expect(option.current_flag).to eq("--bar")
end
specify "equality" do
foobar = described_class.new("foo", "bar")
boofar = described_class.new("boo", "far")
expect(foobar).to eq(option)
expect(option).to eq(foobar)
expect(boofar).not_to eq(option)
expect(option).not_to eq(boofar)
end
end
describe Options do
subject(:options) { described_class.new }

View File

@ -1,7 +1,8 @@
# typed: false
# frozen_string_literal: true
describe "Mach-O Pathname tests" do
describe "Mach-O" do
describe "Pathname tests" do
specify "fat dylib" do
pn = dylib_path("fat")
expect(pn).to be_universal
@ -106,9 +107,9 @@ describe "Mach-O Pathname tests" do
expect(pn).not_to be_mach_o_bundle
expect(pn.arch).to eq(:dunno)
end
end
end
describe ArchitectureListExtension do
describe ArchitectureListExtension do
let(:archs) { [:i386, :x86_64, :ppc7400, :ppc64].extend(described_class) }
specify "universal checks" do
@ -126,9 +127,9 @@ describe ArchitectureListExtension do
expect(pn.archs).to be_universal
expect(pn.archs.as_arch_flags).to eq("-arch x86_64 -arch i386")
end
end
end
describe "text executables" do
describe "text executables" do
let(:pn) { HOMEBREW_PREFIX/"an_executable" }
after { pn.unlink }
@ -174,4 +175,5 @@ describe "text executables" do
expect(pn.archs).to eq([])
expect(pn.arch).to eq(:dunno)
end
end
end

View File

@ -75,17 +75,16 @@ describe Patch do
expect(patch.patch_files.count).to eq(7)
end
end
end
describe EmbeddedPatch do
describe EmbeddedPatch do
describe "#new" do
subject { described_class.new(:p1) }
its(:inspect) { is_expected.to eq("#<EmbeddedPatch: :p1>") }
end
end
end
describe ExternalPatch do
describe ExternalPatch do
subject(:patch) { described_class.new(:p1) { url "file:///my.patch" } }
describe "#url" do
@ -103,4 +102,5 @@ describe ExternalPatch do
its(:cached_download) { is_expected.to eq("/tmp/foo.tar.gz") }
end
end
end

View File

@ -0,0 +1,70 @@
# typed: false
# frozen_string_literal: true
require "rubocops/checksum"
describe RuboCop::Cop::FormulaAudit::ChecksumCase do
subject(:cop) { described_class.new }
context "when auditing spec checksums" do
it "reports an offense if a checksum contains uppercase letters" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0A645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
^ sha256 should be lowercase
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1Ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
^ sha256 should be lowercase
end
end
end
RUBY
end
it "reports and corrects an offense if a checksum outside a `stable` block contains uppercase letters" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
resource "foo-outside" do
url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz"
sha256 "A4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9"
^ sha256 should be lowercase
end
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
end
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
resource "foo-outside" do
url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz"
sha256 "a4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9"
end
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
end
end
end
RUBY
end
end
end

View File

@ -91,69 +91,3 @@ describe RuboCop::Cop::FormulaAudit::Checksum do
end
end
end
describe RuboCop::Cop::FormulaAudit::ChecksumCase do
subject(:cop) { described_class.new }
context "when auditing spec checksums" do
it "reports an offense if a checksum contains uppercase letters" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0A645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
^ sha256 should be lowercase
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1Ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
^ sha256 should be lowercase
end
end
end
RUBY
end
it "reports and corrects an offense if a checksum outside a `stable` block contains uppercase letters" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
resource "foo-outside" do
url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz"
sha256 "A4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9"
^ sha256 should be lowercase
end
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
end
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
resource "foo-outside" do
url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz"
sha256 "a4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9"
end
stable do
url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a"
resource "foo-package" do
url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz"
sha256 "5cf6e1ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9"
end
end
end
RUBY
end
end
end

View File

@ -0,0 +1,44 @@
# typed: false
# frozen_string_literal: true
require "rubocops/class"
describe RuboCop::Cop::FormulaAudit::ClassName do
subject(:cop) { described_class.new }
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
it "reports and corrects an offense when using ScriptFileFormula" do
expect_offense(<<~RUBY)
class Foo < ScriptFileFormula
^^^^^^^^^^^^^^^^^ ScriptFileFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
it "reports and corrects an offense when using GithubGistFormula" do
expect_offense(<<~RUBY)
class Foo < GithubGistFormula
^^^^^^^^^^^^^^^^^ GithubGistFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
it "reports and corrects an offense when using AmazonWebServicesFormula" do
expect_offense(<<~RUBY)
class Foo < AmazonWebServicesFormula
^^^^^^^^^^^^^^^^^^^^^^^^ AmazonWebServicesFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
end

View File

@ -0,0 +1,17 @@
# typed: false
# frozen_string_literal: true
require "rubocops/class"
describe RuboCop::Cop::FormulaAuditStrict::TestPresent do
subject(:cop) { described_class.new }
it "reports an offense when there is no test block" do
expect_offense(<<~RUBY)
class Foo < Formula
^^^^^^^^^^^^^^^^^^^ A `test do` test block should be added
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
end
end

View File

@ -3,46 +3,6 @@
require "rubocops/class"
describe RuboCop::Cop::FormulaAudit::ClassName do
subject(:cop) { described_class.new }
corrected_source = <<~RUBY
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
it "reports and corrects an offense when using ScriptFileFormula" do
expect_offense(<<~RUBY)
class Foo < ScriptFileFormula
^^^^^^^^^^^^^^^^^ ScriptFileFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
it "reports and corrects an offense when using GithubGistFormula" do
expect_offense(<<~RUBY)
class Foo < GithubGistFormula
^^^^^^^^^^^^^^^^^ GithubGistFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
it "reports and corrects an offense when using AmazonWebServicesFormula" do
expect_offense(<<~RUBY)
class Foo < AmazonWebServicesFormula
^^^^^^^^^^^^^^^^^^^^^^^^ AmazonWebServicesFormula is deprecated, use Formula instead
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
expect_correction(corrected_source)
end
end
describe RuboCop::Cop::FormulaAudit::Test do
subject(:cop) { described_class.new }
@ -117,16 +77,3 @@ describe RuboCop::Cop::FormulaAudit::Test do
RUBY
end
end
describe RuboCop::Cop::FormulaAuditStrict::TestPresent do
subject(:cop) { described_class.new }
it "reports an offense when there is no test block" do
expect_offense(<<~RUBY)
class Foo < Formula
^^^^^^^^^^^^^^^^^^^ A `test do` test block should be added
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
end
end

View File

@ -0,0 +1,152 @@
# typed: false
# frozen_string_literal: true
require "rubocops/deprecate_disable"
describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
subject(:cop) { described_class.new }
context "when auditing `deprecate!`" do
it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
end
it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if no `date` is specified" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate!
end
RUBY
end
it "reports no offenses if no `date` is specified (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end
end
context "when auditing `disable!`" do
it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
end
it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if no `date` is specified" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable!
end
RUBY
end
it "reports no offenses if no `date` is specified (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end
end
end

View File

@ -3,154 +3,6 @@
require "rubocops/deprecate_disable"
describe RuboCop::Cop::FormulaAudit::DeprecateDisableDate do
subject(:cop) { described_class.new }
context "when auditing `deprecate!`" do
it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
end
it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if no `date` is specified" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate!
end
RUBY
end
it "reports no offenses if no `date` is specified (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
deprecate! because: "is broken"
end
RUBY
end
end
context "when auditing `disable!`" do
it "reports and corrects an offense if `date` is not ISO 8601 compliant" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
end
it "reports and corrects an offense if `date` is not ISO 8601 compliant (with `reason`)" do
expect_offense(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "June 25, 2020"
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! date: "2020-06-25"
end
RUBY
end
it "reports no offenses if `date` is ISO 8601 compliant (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken", date: "2020-06-25"
end
RUBY
end
it "reports no offenses if no `date` is specified" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable!
end
RUBY
end
it "reports no offenses if no `date` is specified (with `reason`)" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url 'https://brew.sh/foo-1.0.tgz'
disable! because: "is broken"
end
RUBY
end
end
end
describe RuboCop::Cop::FormulaAudit::DeprecateDisableReason do
subject(:cop) { described_class.new }

View File

@ -0,0 +1,20 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::ClassInheritance do
subject(:cop) { described_class.new }
context "when auditing formula class inheritance" do
it "reports an offense when not using spaces for class inheritance" do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo<Formula
^^^^^^^ Use a space in class inheritance: class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
end
end
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckRegexCaseInsensitive do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` is not case-insensitive" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching.
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` is case-insensitive" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,46 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckRegexExtension do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` does not use `\\.t` for archive file extensions" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.tgz}i)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `\\.t` instead of `\\.tgz`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` uses `\\.t` for archive file extensions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,36 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckRegexIfPageMatch do
subject(:cop) { described_class.new }
it "reports an offense when there is no `regex` for `strategy :page_match`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `regex` is required if `strategy :page_match` is present.
url :stable
strategy :page_match
end
end
RUBY
end
it "reports no offenses when a `regex` is specified for `strategy :page_match`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
strategy :page_match
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,46 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckRegexParentheses do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` call in the livecheck block does not use parentheses" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex %r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `regex` call should always use parentheses.
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` call in the livecheck block uses parentheses" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,44 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckSkip do
subject(:cop) { described_class.new }
it "reports an offense when a skipped formula's livecheck block contains other information" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ Skipped formulae must not contain other livecheck information.
skip "Not maintained"
url :stable
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end
it "reports no offenses when a skipped formula's livecheck block contains no other information" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end
end

View File

@ -0,0 +1,34 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckUrlProvided do
subject(:cop) { described_class.new }
it "reports an offense when a `url` is not specified in the livecheck block" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `url` must be provided to livecheck.
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when a `url` is specified in the livecheck block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,43 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckUrlSymbol do
subject(:cop) { described_class.new }
it "reports an offense when the `url` specified in the livecheck block is identical to a formula URL" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo-1.0.tgz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `url :stable`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
end
end
RUBY
end
it "reports no offenses when the `url` specified in the livecheck block is not identical to a formula URL" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo/releases/"
end
end
RUBY
end
end

View File

@ -1,271 +0,0 @@
# typed: false
# frozen_string_literal: true
require "rubocops/livecheck"
describe RuboCop::Cop::FormulaAudit::LivecheckSkip do
subject(:cop) { described_class.new }
it "reports an offense when a skipped formula's livecheck block contains other information" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ Skipped formulae must not contain other livecheck information.
skip "Not maintained"
url :stable
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end
it "reports no offenses when a skipped formula's livecheck block contains no other information" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
skip "Not maintained"
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckUrlProvided do
subject(:cop) { described_class.new }
it "reports an offense when a `url` is not specified in the livecheck block" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `url` must be provided to livecheck.
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when a `url` is specified in the livecheck block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckUrlSymbol do
subject(:cop) { described_class.new }
it "reports an offense when the `url` specified in the livecheck block is identical to a formula URL" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo-1.0.tgz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `url :stable`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
end
end
RUBY
end
it "reports no offenses when the `url` specified in the livecheck block is not identical to a formula URL" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url "https://brew.sh/foo/releases/"
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckRegexParentheses do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` call in the livecheck block does not use parentheses" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex %r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `regex` call should always use parentheses.
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` call in the livecheck block uses parentheses" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckRegexExtension do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` does not use `\\.t` for archive file extensions" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.tgz}i)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `\\.t` instead of `\\.tgz`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` uses `\\.t` for archive file extensions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckRegexIfPageMatch do
subject(:cop) { described_class.new }
it "reports an offense when there is no `regex` for `strategy :page_match`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
^^^^^^^^^^^^ A `regex` is required if `strategy :page_match` is present.
url :stable
strategy :page_match
end
end
RUBY
end
it "rreports no offenses when a `regex` is specified for `strategy :page_match`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
strategy :page_match
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end
describe RuboCop::Cop::FormulaAudit::LivecheckRegexCaseInsensitive do
subject(:cop) { described_class.new }
it "reports an offense when the `regex` is not case-insensitive" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching.
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
it "reports no offenses when the `regex` is case-insensitive" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
livecheck do
url :stable
regex(%r{href=.*?/formula[._-]v?(\\d+(?:\\.\\d+)+)\\.t}i)
end
end
RUBY
end
end

View File

@ -0,0 +1,54 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::AssertStatements do
subject(:cop) { described_class.new }
context "when auditing formula assertions" do
it "reports an offense when assert ... include is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
assert File.read("inbox").include?("Sample message 1")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `assert_match` instead of `assert ...include?`
end
RUBY
end
it "reports an offense when assert ... exist? is used without a negation" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
assert File.exist? "default.ini"
^^^^^^^^^^^^^^^^^^^^^^^^^ Use `assert_predicate <path_to_file>, :exist?` instead of `assert File.exist? "default.ini"`
end
RUBY
end
it "reports an offense when assert ... exist? is used with a negation" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
assert !File.exist?("default.ini")
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `refute_predicate <path_to_file>, :exist?` instead of `assert !File.exist?("default.ini")`
end
RUBY
end
it "reports an offense when assert ... executable? is used without a negation" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
assert File.executable? f
^^^^^^^^^^^^^^^^^^ Use `assert_predicate <path_to_file>, :executable?` instead of `assert File.executable? f`
end
RUBY
end
end
end

View File

@ -0,0 +1,58 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::Comments do
subject(:cop) { described_class.new }
context "when auditing comment text" do
it "reports an offense when commented cmake calls exist" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
# system "cmake", ".", *std_cmake_args
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please remove default template comments
end
RUBY
end
it "reports an offense when default template comments exist" do
expect_offense(<<~RUBY)
class Foo < Formula
# PLEASE REMOVE
^^^^^^^^^^^^^^^ Please remove default template comments
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
end
it "reports an offense when `depends_on` is commented" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
# depends_on "foo"
^^^^^^^^^^^^^^^^^^ Commented-out dependency "foo"
end
RUBY
end
it "reports an offense if citation tags are present" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
# cite Howell_2009:
^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should not use `cite` comments
# doi "10.111/222.x"
^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should not use `doi` comments
# tag "software"
^^^^^^^^^^^^^^^^ Formulae in homebrew/core should not use `tag` comments
end
RUBY
end
end
end

View File

@ -0,0 +1,59 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::LicenseArrays do
subject(:cop) { described_class.new }
context "when auditing license arrays" do
it "reports no offenses for license strings" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license "MIT"
end
RUBY
end
it "reports no offenses for license symbols" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license :public_domain
end
RUBY
end
it "reports no offenses for license hashes" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: ["MIT", "0BSD"]
end
RUBY
end
it "reports and corrects use of a license array" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license ["MIT", "0BSD"]
^^^^^^^^^^^^^^^^^^^^^^^ Use `license any_of: ["MIT", "0BSD"]` instead of `license ["MIT", "0BSD"]`
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: ["MIT", "0BSD"]
end
RUBY
end
end
end

View File

@ -0,0 +1,88 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::Licenses do
subject(:cop) { described_class.new }
context "when auditing licenses" do
it "reports no offenses for license strings" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license "MIT"
end
RUBY
end
it "reports no offenses for license symbols" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license :public_domain
end
RUBY
end
it "reports no offenses for license hashes" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: ["MIT", "0BSD"]
end
RUBY
end
it "reports no offenses for license exceptions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license "MIT" => { with: "LLVM-exception" }
end
RUBY
end
it "reports no offenses for multiline nested license hashes" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: [
"MIT",
all_of: ["0BSD", "Zlib"],
]
end
RUBY
end
it "reports no offenses for multiline nested license hashes with exceptions" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: [
"MIT",
all_of: ["0BSD", "Zlib"],
"GPL-2.0-only" => { with: "LLVM-exception" },
]
end
RUBY
end
it "reports an offense for nested license hashes on a single line" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
license any_of: ["MIT", all_of: ["0BSD", "Zlib"]]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Split nested license declarations onto multiple lines
end
RUBY
end
end
end

View File

@ -0,0 +1,46 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAuditStrict::MakeCheck do
subject(:cop) { described_class.new }
let(:path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-core" }
before do
path.mkpath
(path/"style_exceptions").mkpath
end
def setup_style_exceptions
(path/"style_exceptions/make_check_allowlist.json").write <<~JSON
[ "bar" ]
JSON
end
it "reports an offense when formulae in homebrew/core run build-time checks" do
setup_style_exceptions
expect_offense(<<~RUBY, "#{path}/Formula/foo.rb")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "make", "-j1", "test"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core (except e.g. cryptography, libraries) should not run build-time checks
end
RUBY
end
it "reports no offenses when exempted formulae in homebrew/core run build-time checks" do
setup_style_exceptions
expect_no_offenses(<<~RUBY, "#{path}/Formula/bar.rb")
class Bar < Formula
desc "bar"
url 'https://brew.sh/bar-1.0.tgz'
system "make", "-j1", "test"
end
RUBY
end
end

View File

@ -0,0 +1,483 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::Miscellaneous do
subject(:cop) { described_class.new }
context "when auditing formula miscellany" do
it "reports an offense for unneeded `FileUtils` usage" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
FileUtils.mv "hello"
^^^^^^^^^^^^^^^^^^^^ Don\'t need \'FileUtils.\' before mv
end
RUBY
end
it "reports an offense for long `inreplace` block variable names" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
inreplace "foo" do |longvar|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \"inreplace <filenames> do |s|\" is preferred over \"|longvar|\".
somerandomCall(longvar)
end
end
RUBY
end
it "reports an offense for invalid `rebuild` numbers" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
bottle do
rebuild 0
^^^^^^^^^ 'rebuild 0' should be removed
sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
end
end
RUBY
end
it "reports an offense when `OS.linux?` is used in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
bottle do
if OS.linux?
^^^^^^^^^ Don\'t use OS.linux?; homebrew/core only supports macOS
nil
end
sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
end
end
RUBY
end
it "reports an offense when a useless `fails_with :llvm` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
bottle do
sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
end
fails_with :llvm do
^^^^^^^^^^^^^^^^ 'fails_with :llvm' is now a no-op so should be removed
build 2335
cause "foo"
end
end
RUBY
end
it "reports an offense when `def test` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def test
^^^^^^^^ Use new-style test definitions (test do)
assert_equals "1", "1"
end
end
RUBY
end
it "reports an offense when `skip_clean` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
skip_clean :all
^^^^^^^^^^^^^^^ `skip_clean :all` is deprecated; brew no longer strips symbols. Pass explicit paths to prevent Homebrew from removing empty folders.
end
RUBY
end
it "reports an offense when `build.universal?` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
if build.universal?
^^^^^^^^^^^^^^^^ macOS has been 64-bit only since 10.6 so build.universal? is deprecated.
"foo"
end
end
RUBY
end
it "reports no offenses when `build.universal?` is used in an exempt formula" do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/wine.rb")
class Wine < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
if build.universal?
"foo"
end
end
RUBY
end
it "reports an offense when `ENV.universal_binary` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
if build?
ENV.universal_binary
^^^^^^^^^^^^^^^^^^^^ macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated.
end
end
RUBY
end
it "reports no offenses when `ENV.universal_binary` is used in an exempt formula" do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/wine.rb")
class Wine < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
if build?
ENV.universal_binary
end
end
RUBY
end
it "reports an offense when `install_name_tool` is called" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "install_name_tool", "-id"
^^^^^^^^^^^^^^^^^^^ Use ruby-macho instead of calling "install_name_tool"
end
RUBY
end
it "reports an offense when `npm install` is called without Language::Node arguments" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "npm", "install"
^^^^^^^^^^^^^^^^^^^^^^^ Use Language::Node for npm install args
end
RUBY
end
it "reports no offenses when `npm install` is called without Language::Node arguments in an exempt formula" do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/kibana@4.4.rb")
class KibanaAT44 < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "npm", "install"
end
RUBY
end
it "reports an offense when `depends_on` is called with an instance" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on FOO::BAR.new
^^^^^^^^^^^^ `depends_on` can take requirement classes instead of instances
end
RUBY
end
it "reports an offense when `Dir` is called without a globbing argument" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
rm_rf Dir["src/{llvm,test,librustdoc,etc/snapshot.pyc}"]
rm_rf Dir["src/snapshot.pyc"]
^^^^^^^^^^^^^^^^^^ Dir(["src/snapshot.pyc"]) is unnecessary; just use "src/snapshot.pyc"
end
RUBY
end
it "reports an offense when executing a system command for which there is a Ruby FileUtils equivalent" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "mkdir", "foo"
^^^^^^^ Use the `mkdir` Ruby method instead of `system "mkdir", "foo"`
end
RUBY
end
it "reports an offense when top-level functions are defined outside of a class body" do
expect_offense(<<~RUBY)
def test
^^^^^^^^ Define method test in the class body, not at the top-level
nil
end
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
end
RUBY
end
it 'reports an offense when `man+"man8"` is used' do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
man1.install man+"man8" => "faad.1"
^^^^^^ "man+"man8"" should be "man8"
end
end
RUBY
end
it "reports an offense when a hard-coded `gcc` is referenced" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
system "/usr/bin/gcc", "foo"
^^^^^^^^^^^^^^ Use "#{ENV.cc}" instead of hard-coding "gcc"
end
end
RUBY
end
it "reports an offense when a hard-coded `g++` is referenced" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
system "/usr/bin/g++", "-o", "foo", "foo.cc"
^^^^^^^^^^^^^^ Use "#{ENV.cxx}" instead of hard-coding "g++"
end
end
RUBY
end
it "reports an offense when a hard-coded `llvm-g++` is set as COMPILER_PATH" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
ENV["COMPILER_PATH"] = "/usr/bin/llvm-g++"
^^^^^^^^^^^^^^^^^^^ Use "#{ENV.cxx}" instead of hard-coding "llvm-g++"
end
end
RUBY
end
it "reports an offense when a hard-coded `gcc` is set as COMPILER_PATH" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
ENV["COMPILER_PATH"] = "/usr/bin/gcc"
^^^^^^^^^^^^^^ Use \"\#{ENV.cc}\" instead of hard-coding \"gcc\"
end
end
RUBY
end
it "reports an offense when the formula path shortcut `man` could be used" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
mv "#{share}/man", share
^^^^ "#{share}/man" should be "#{man}"
end
end
RUBY
end
it "reports an offense when the formula path shortcut `libexec` could be used" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
mv "#{prefix}/libexec", share
^^^^^^^^ "#{prefix}/libexec" should be "#{libexec}"
end
end
RUBY
end
it "reports an offense when the formula path shortcut `info` could be used" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
system "./configure", "--INFODIR=#{prefix}/share/info"
^^^^^^^^^^^ "#{prefix}/share/info" should be "#{info}"
end
end
RUBY
end
it "reports an offense when the formula path shortcut `man8` could be used" do
expect_offense(<<~'RUBY')
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
system "./configure", "--MANDIR=#{prefix}/share/man/man8"
^^^^^^^^^^^^^^^ "#{prefix}/share/man/man8" should be "#{man8}"
end
end
RUBY
end
it "reports an offense when unvendored lua modules are used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "lpeg" => :lua51
^^^^^^ lua modules should be vendored rather than use deprecated `depends_on \"lpeg\" => :lua51`
end
RUBY
end
it "reports an offense when `export` is used to set environment variables" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
system "export", "var=value"
^^^^^^^^ Use ENV instead of invoking 'export' to modify the environment
end
RUBY
end
it "reports an offense when dependencies with invalid options are used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "foo" => "with-bar"
^^^^^^^^^^ Dependency foo should not use option with-bar
end
RUBY
end
it "reports an offense when dependencies with invalid options are used in an array" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "httpd" => [:build, :test]
depends_on "foo" => [:optional, "with-bar"]
^^^^^^^^^^ Dependency foo should not use option with-bar
depends_on "icu4c" => [:optional, "c++11"]
^^^^^^^ Dependency icu4c should not use option c++11
end
RUBY
end
it "reports an offense when `build.head?` could be used instead of checking `version`" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
if version == "HEAD"
^^^^^^^^^^^^^^^^^ Use 'build.head?' instead of inspecting 'version'
foo()
end
end
RUBY
end
it "reports an offense when `ARGV.include? (--HEAD)` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
test do
head = ARGV.include? "--HEAD"
^^^^ Use build instead of ARGV to check options
^^^^^^^^^^^^^^^^^^^^^^ Use "if build.head?" instead
end
end
RUBY
end
it "reports an offense when `needs :openmp` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
needs :openmp
^^^^^^^^^^^^^ 'needs :openmp' should be replaced with 'depends_on \"gcc\"'
end
RUBY
end
it "reports an offense when `MACOS_VERSION` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
test do
version = MACOS_VERSION
^^^^^^^^^^^^^ Use MacOS.version instead of MACOS_VERSION
end
end
RUBY
end
it "reports an offense when `build.with?` is used for a conditional dependency" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "foo" if build.with? "foo"
^^^^^^^^^^^^^^^^ Replace depends_on "foo" if build.with? "foo" with depends_on "foo" => :optional
end
RUBY
end
it "reports an offense when `build.without?` is used for a negated conditional dependency" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on :foo unless build.without? "foo"
^^^^^^^^^^^^^^^ Replace depends_on :foo unless build.without? "foo" with depends_on :foo => :recommended
end
RUBY
end
it "reports an offense when `build.include?` is used for a negated conditional dependency" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on :foo unless build.include? "without-foo"
^^^^^^^^^^^^^^^ Replace depends_on :foo unless build.include? "without-foo" with depends_on :foo => :recommended
end
RUBY
end
end
end

View File

@ -0,0 +1,29 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::MpiCheck do
subject(:cop) { described_class.new }
context "when auditing MPI dependencies" do
it "reports and corrects an offense when using depends_on \"mpich\" in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "mpich"
^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should use 'depends_on "open-mpi"' instead of 'depends_on "mpich"'.
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
depends_on "open-mpi"
end
RUBY
end
end
end

View File

@ -0,0 +1,159 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::OptionDeclarations do
subject(:cop) { described_class.new }
context "when auditing options" do
it "reports an offense when `build.without?` is used in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
build.without? "bar"
^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should not use `build.without?`.
end
end
RUBY
end
it "reports an offense when `build.with?` is used in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def install
build.with? "bar"
^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should not use `build.with?`.
end
end
RUBY
end
it "reports an offense when `build.without?` is used for a conditional dependency" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "bar" if build.without?("baz")
^^^^^^^^^^^^^^^^^^^^^ Use `:optional` or `:recommended` instead of `if build.without?("baz")`
end
RUBY
end
it "reports an offense when `build.without?` is used for a conditional dependency" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "bar" if build.with?("baz")
^^^^^^^^^^^^^^^^^^ Use `:optional` or `:recommended` instead of `if build.with?("baz")`
end
RUBY
end
it "reports an offense when `build.without?` is used with `unless`" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return unless build.without? "bar"
^^^^^^^^^^^^^^^^^^^^ Use if build.with? "bar" instead of unless build.without? "bar"
end
end
RUBY
end
it "reports an offense when `build.with?` is used with `unless`" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return unless build.with? "bar"
^^^^^^^^^^^^^^^^^ Use if build.without? "bar" instead of unless build.with? "bar"
end
end
RUBY
end
it "reports an offense when `build.with?` is negated" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return if !build.with? "bar"
^^^^^^^^^^^^^^^^^^ Don't negate 'build.with?': use 'build.without?'
end
end
RUBY
end
it "reports an offense when `build.without?` is negated" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return if !build.without? "bar"
^^^^^^^^^^^^^^^^^^^^^ Don't negate 'build.without?': use 'build.with?'
end
end
RUBY
end
it "reports an offense when a `build.without?` conditional is unnecessary" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return if build.without? "--without-bar"
^^^^^^^^^^^^^^^ Don't duplicate 'without': Use `build.without? \"bar\"` to check for \"--without-bar\"
end
end
RUBY
end
it "reports an offense when a `build.with?` conditional is unnecessary" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return if build.with? "--with-bar"
^^^^^^^^^^^^ Don't duplicate 'with': Use `build.with? \"bar\"` to check for \"--with-bar\"
end
end
RUBY
end
it "reports an offense when `build.include?` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def post_install
return if build.include? "foo"
^^^^^^^^^^^^^^^^^^^^ `build.include?` is deprecated
end
end
RUBY
end
it "reports an offense when `def option` is used" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url 'https://brew.sh/foo-1.0.tgz'
def options
^^^^^^^^^^^ Use new-style option definitions
[["--bar", "desc"]]
end
end
RUBY
end
end
end

View File

@ -0,0 +1,184 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::PythonVersions do
subject(:cop) { described_class.new }
context "when auditing Python versions" do
it "reports no offenses for Python with no dependency" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
puts "python@3.8"
end
end
RUBY
end
it "reports no offenses for unversioned Python references" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python"
end
end
RUBY
end
it "reports no offenses for Python with no version" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python3"
end
end
RUBY
end
it "reports no offenses when a Python reference matches its dependency" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python@3.9"
end
end
RUBY
end
it "reports no offenses when a Python reference matches its dependency without `@`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python3.9"
end
end
RUBY
end
it "reports no offenses when a Python reference matches its two-digit dependency" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.10"
def install
puts "python@3.10"
end
end
RUBY
end
it "reports no offenses when a Python reference matches its two-digit dependency without `@`" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
depends_on "python@3.10"
def install
puts "python3.10"
end
end
RUBY
end
it "reports and corrects Python references with mismatched versions" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python@3.8"
^^^^^^^^^^^^ References to `python@3.8` should match the specified python dependency (`python@3.9`)
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python@3.9"
end
end
RUBY
end
it "reports and corrects Python references with mismatched versions without `@`" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python3.8"
^^^^^^^^^^^ References to `python3.8` should match the specified python dependency (`python3.9`)
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
depends_on "python@3.9"
def install
puts "python3.9"
end
end
RUBY
end
it "reports and corrects Python references with mismatched two-digit versions" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "python@3.11"
def install
puts "python@3.10"
^^^^^^^^^^^^^ References to `python@3.10` should match the specified python dependency (`python@3.11`)
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
depends_on "python@3.11"
def install
puts "python@3.11"
end
end
RUBY
end
it "reports and corrects Python references with mismatched two-digit versions without `@`" do
expect_offense(<<~RUBY)
class Foo < Formula
depends_on "python@3.11"
def install
puts "python3.10"
^^^^^^^^^^^^ References to `python3.10` should match the specified python dependency (`python3.11`)
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
depends_on "python@3.11"
def install
puts "python3.11"
end
end
RUBY
end
end
end

View File

@ -0,0 +1,59 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::SafePopenCommands do
subject(:cop) { described_class.new }
context "when auditing popen commands" do
it "reports and corrects `Utils.popen_read` usage" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read "foo"
^^^^^^^^^^^^^^^^^^^^^^ Use `Utils.safe_popen_read` instead of `Utils.popen_read`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_read "foo"
end
end
RUBY
end
it "reports and corrects `Utils.popen_write` usage" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_write "foo"
^^^^^^^^^^^^^^^^^^^^^^^ Use `Utils.safe_popen_write` instead of `Utils.popen_write`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_write "foo"
end
end
RUBY
end
it "does not report an offense when `Utils.popen_read` is used in a test block" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install; end
test do
Utils.popen_read "foo"
end
end
RUBY
end
end
end

View File

@ -0,0 +1,212 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAuditStrict::ShellCommands do
subject(:cop) { described_class.new }
context "when auditing shell commands" do
it "reports and corrects an offense when `system` arguments should be separated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
system "foo bar"
^^^^^^^^^ Separate `system` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
system "foo", "bar"
end
end
RUBY
end
it "reports and corrects an offense when `system` arguments with string interpolation should be separated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
system "\#{bin}/foo bar"
^^^^^^^^^^^^^^^^ Separate `system` commands into `\"\#{bin}/foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
system "\#{bin}/foo", "bar"
end
end
RUBY
end
it "reports no offenses when `system` with metacharacter arguments are called" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
system "foo bar > baz"
end
end
RUBY
end
it "reports no offenses when trailing arguments to `system` are unseparated" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
system "foo", "bar baz"
end
end
RUBY
end
it "reports no offenses when `Utils.popen` arguments are unseparated" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
Utils.popen("foo bar")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.popen_read` arguments are unseparated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("foo bar")
^^^^^^^^^ Separate `Utils.popen_read` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("foo", "bar")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.safe_popen_read` arguments are unseparated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_read("foo bar")
^^^^^^^^^ Separate `Utils.safe_popen_read` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_read("foo", "bar")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.popen_write` arguments are unseparated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_write("foo bar")
^^^^^^^^^ Separate `Utils.popen_write` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen_write("foo", "bar")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.safe_popen_write` arguments are unseparated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_write("foo bar")
^^^^^^^^^ Separate `Utils.safe_popen_write` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_write("foo", "bar")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.popen_read` arguments with interpolation are unseparated" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("\#{bin}/foo bar")
^^^^^^^^^^^^^^^^ Separate `Utils.popen_read` commands into `\"\#{bin}/foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("\#{bin}/foo", "bar")
end
end
RUBY
end
it "reports no offenses when `Utils.popen_read` arguments with metacharacters are unseparated" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("foo bar > baz")
end
end
RUBY
end
it "reports no offenses when trailing arguments to `Utils.popen_read` are unseparated" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read("foo", "bar baz")
end
end
RUBY
end
it "reports and corrects an offense when `Utils.popen_read` arguments are unseparated after a shell variable" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read({ "SHELL" => "bash"}, "foo bar")
^^^^^^^^^ Separate `Utils.popen_read` commands into `\"foo\", \"bar\"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen_read({ "SHELL" => "bash"}, "foo", "bar")
end
end
RUBY
end
end
end

View File

@ -0,0 +1,86 @@
# typed: false
# frozen_string_literal: true
require "rubocops/lines"
describe RuboCop::Cop::FormulaAudit::ShellVariables do
subject(:cop) { described_class.new }
context "when auditing shell variables" do
it "reports and corrects unexpanded shell variables in `Utils.popen`" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen "SHELL=bash foo"
^^^^^^^^^^^^^^^^ Use `Utils.popen({ "SHELL" => "bash" }, "foo")` instead of `Utils.popen "SHELL=bash foo"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen { "SHELL" => "bash" }, "foo"
end
end
RUBY
end
it "reports and corrects unexpanded shell variables in `Utils.safe_popen_read`" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_read "SHELL=bash foo"
^^^^^^^^^^^^^^^^ Use `Utils.safe_popen_read({ "SHELL" => "bash" }, "foo")` instead of `Utils.safe_popen_read "SHELL=bash foo"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_read { "SHELL" => "bash" }, "foo"
end
end
RUBY
end
it "reports and corrects unexpanded shell variables in `Utils.safe_popen_write`" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_write "SHELL=bash foo"
^^^^^^^^^^^^^^^^ Use `Utils.safe_popen_write({ "SHELL" => "bash" }, "foo")` instead of `Utils.safe_popen_write "SHELL=bash foo"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.safe_popen_write { "SHELL" => "bash" }, "foo"
end
end
RUBY
end
it "reports and corrects unexpanded shell variables while preserving string interpolation" do
expect_offense(<<~RUBY)
class Foo < Formula
def install
Utils.popen "SHELL=bash \#{bin}/foo"
^^^^^^^^^^^^^^^^^^^^^^^ Use `Utils.popen({ "SHELL" => "bash" }, "\#{bin}/foo")` instead of `Utils.popen "SHELL=bash \#{bin}/foo"`
end
end
RUBY
expect_correction(<<~RUBY)
class Foo < Formula
def install
Utils.popen { "SHELL" => "bash" }, "\#{bin}/foo"
end
end
RUBY
end
end
end

View File

@ -0,0 +1,136 @@
# typed: false
# frozen_string_literal: true
require "rubocops/text"
describe RuboCop::Cop::FormulaAuditStrict::Text do
subject(:cop) { described_class.new }
context "when auditing formula text in homebrew/core" do
it "reports an offense if `env :userpaths` is present" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
env :userpaths
^^^^^^^^^^^^^^ `env :userpaths` in homebrew/core formulae is deprecated
end
RUBY
end
it "reports an offense if `env :std` is present in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
env :std
^^^^^^^^ `env :std` in homebrew/core formulae is deprecated
end
RUBY
end
it %Q(reports an offense if "\#{share}/<formula name>" is present) do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo"
^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foo`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo/bar"
^^^^^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foo`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foolibc++.rb")
class Foolibcxx < Formula
def install
ohai "\#{share}/foolibc++"
^^^^^^^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foolibc++`
end
end
RUBY
end
it 'reports an offense if `share/"<formula name>"` is present' do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo"
^^^^^^^^^^^ Use `pkgshare` instead of `share/"foo"`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo/bar"
^^^^^^^^^^^^^^^ Use `pkgshare` instead of `share/"foo"`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foolibc++.rb")
class Foolibcxx < Formula
def install
ohai share/"foolibc++"
^^^^^^^^^^^^^^^^^ Use `pkgshare` instead of `share/"foolibc++"`
end
end
RUBY
end
it %Q(reports no offenses if "\#{share}/<directory name>" doesn't match formula name) do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo-bar"
end
end
RUBY
end
it 'reports no offenses if `share/"<formula name>"` is not present' do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo-bar"
end
end
RUBY
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"bar"
end
end
RUBY
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"bar/foo"
end
end
RUBY
end
it %Q(reports no offenses if formula name appears afer "\#{share}/<directory name>") do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/bar/foo"
end
end
RUBY
end
end
end

View File

@ -274,135 +274,3 @@ describe RuboCop::Cop::FormulaAudit::Text do
end
end
end
describe RuboCop::Cop::FormulaAuditStrict::Text do
subject(:cop) { described_class.new }
context "when auditing formula text in homebrew/core" do
it "reports an offense if `env :userpaths` is present" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
env :userpaths
^^^^^^^^^^^^^^ `env :userpaths` in homebrew/core formulae is deprecated
end
RUBY
end
it "reports an offense if `env :std` is present in homebrew/core" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
env :std
^^^^^^^^ `env :std` in homebrew/core formulae is deprecated
end
RUBY
end
it %Q(reports an offense if "\#{share}/<formula name>" is present) do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo"
^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foo`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo/bar"
^^^^^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foo`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foolibc++.rb")
class Foolibcxx < Formula
def install
ohai "\#{share}/foolibc++"
^^^^^^^^^^^^^^^^^^^^ Use `\#{pkgshare}` instead of `\#{share}/foolibc++`
end
end
RUBY
end
it 'reports an offense if `share/"<formula name>"` is present' do
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo"
^^^^^^^^^^^ Use `pkgshare` instead of `share/"foo"`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo/bar"
^^^^^^^^^^^^^^^ Use `pkgshare` instead of `share/"foo"`
end
end
RUBY
expect_offense(<<~RUBY, "/homebrew-core/Formula/foolibc++.rb")
class Foolibcxx < Formula
def install
ohai share/"foolibc++"
^^^^^^^^^^^^^^^^^ Use `pkgshare` instead of `share/"foolibc++"`
end
end
RUBY
end
it %Q(reports no offenses if "\#{share}/<directory name>" doesn't match formula name) do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/foo-bar"
end
end
RUBY
end
it 'reports no offenses if `share/"<formula name>"` is not present' do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"foo-bar"
end
end
RUBY
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"bar"
end
end
RUBY
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai share/"bar/foo"
end
end
RUBY
end
it %Q(reports no offenses if formula name appears afer "\#{share}/<directory name>") do
expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb")
class Foo < Formula
def install
ohai "\#{share}/bar/foo"
end
end
RUBY
end
end
end

View File

@ -0,0 +1,119 @@
# typed: false
# frozen_string_literal: true
require "rubocops/urls"
describe RuboCop::Cop::FormulaAudit::GitUrls do
subject(:cop) { described_class.new }
context "when a git URL is used" do
it "reports no offenses with a non-git URL" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
end
RUBY
end
it "reports no offenses with both a tag and a revision" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` before" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
shallow: false,
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` after" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports an offense with no `revision`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a revision for git URLs
tag: "v1.0.0"
end
RUBY
end
it "reports an offense with no `revision` and `shallow`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a revision for git URLs
shallow: false,
tag: "v1.0.0"
end
RUBY
end
it "reports no offenses with no `tag`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with no `tag` and `shallow`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports no offenses with missing arguments in `head`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
head do
url "https://github.com/foo/bar.git"
end
end
RUBY
end
it "reports no offenses for non-core taps" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git"
end
RUBY
end
end
end

View File

@ -0,0 +1,89 @@
# typed: false
# frozen_string_literal: true
require "rubocops/urls"
describe RuboCop::Cop::FormulaAuditStrict::GitUrls do
subject(:cop) { described_class.new }
context "when a git URL is used" do
it "reports no offenses with both a tag and a revision" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` before" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
shallow: false,
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` after" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports an offense with no `tag`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a tag for git URLs
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports an offense with no `tag` and `shallow`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a tag for git URLs
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports no offenses with missing arguments in `head`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
head do
url "https://github.com/foo/bar.git"
end
end
RUBY
end
it "reports no offenses for non-core taps" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git"
end
RUBY
end
end
end

View File

@ -0,0 +1,39 @@
# typed: false
# frozen_string_literal: true
require "rubocops/urls"
describe RuboCop::Cop::FormulaAudit::PyPiUrls do
subject(:cop) { described_class.new }
context "when a pypi URL is used" do
it "reports an offense for pypi.python.org urls" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://pypi.python.org/packages/source/foo/foo-0.1.tar.gz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`)
end
RUBY
end
it "reports an offense for short file.pythonhosted.org urls" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://files.pythonhosted.org/packages/source/f/foo/foo-0.1.tar.gz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`)
end
RUBY
end
it "reports no offenses for long file.pythonhosted.org urls" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://files.pythonhosted.org/packages/a0/b1/a01b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f/foo-0.1.tar.gz"
end
RUBY
end
end
end

View File

@ -240,238 +240,3 @@ describe RuboCop::Cop::FormulaAudit::Urls do
end
end
end
describe RuboCop::Cop::FormulaAudit::PyPiUrls do
subject(:cop) { described_class.new }
context "when a pypi URL is used" do
it "reports an offense for pypi.python.org urls" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://pypi.python.org/packages/source/foo/foo-0.1.tar.gz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`)
end
RUBY
end
it "reports an offense for short file.pythonhosted.org urls" do
expect_offense(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://files.pythonhosted.org/packages/source/f/foo/foo-0.1.tar.gz"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`)
end
RUBY
end
it "reports no offenses for long file.pythonhosted.org urls" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://files.pythonhosted.org/packages/a0/b1/a01b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f/foo-0.1.tar.gz"
end
RUBY
end
end
end
describe RuboCop::Cop::FormulaAudit::GitUrls do
subject(:cop) { described_class.new }
context "when a git URL is used" do
it "reports no offenses with a non-git URL" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
end
RUBY
end
it "reports no offenses with both a tag and a revision" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` before" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
shallow: false,
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` after" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports an offense with no `revision`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a revision for git URLs
tag: "v1.0.0"
end
RUBY
end
it "reports an offense with no `revision` and `shallow`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a revision for git URLs
shallow: false,
tag: "v1.0.0"
end
RUBY
end
it "reports no offenses with no `tag`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with no `tag` and `shallow`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports no offenses with missing arguments in `head`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
head do
url "https://github.com/foo/bar.git"
end
end
RUBY
end
it "reports no offenses for non-core taps" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git"
end
RUBY
end
end
end
describe RuboCop::Cop::FormulaAuditStrict::GitUrls do
subject(:cop) { described_class.new }
context "when a git URL is used" do
it "reports no offenses with both a tag and a revision" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` before" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
shallow: false,
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports no offenses with both a tag, revision and `shallow` after" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
tag: "v1.0.0",
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports an offense with no `tag`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a tag for git URLs
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
end
RUBY
end
it "reports an offense with no `tag` and `shallow`" do
expect_offense(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Formulae in homebrew/core should specify a tag for git URLs
revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
shallow: false
end
RUBY
end
it "reports no offenses with missing arguments in `head`" do
expect_no_offenses(<<~RUBY, "/homebrew-core/")
class Foo < Formula
desc "foo"
url "https://foo.com"
head do
url "https://github.com/foo/bar.git"
end
end
RUBY
end
it "reports no offenses for non-core taps" do
expect_no_offenses(<<~RUBY)
class Foo < Formula
desc "foo"
url "https://github.com/foo/bar.git"
end
RUBY
end
end
end

View File

@ -0,0 +1,51 @@
# typed: false
# frozen_string_literal: true
require "software_spec"
describe BottleSpecification do
subject(:bottle_spec) { described_class.new }
describe "#sha256" do
it "works without cellar" do
checksums = {
snow_leopard_32: "deadbeef" * 8,
snow_leopard: "faceb00c" * 8,
lion: "baadf00d" * 8,
mountain_lion: "8badf00d" * 8,
}
checksums.each_pair do |cat, digest|
bottle_spec.sha256(digest => cat)
checksum, = bottle_spec.checksum_for(cat)
expect(Checksum.new(digest)).to eq(checksum)
end
end
it "works with cellar" do
checksums = [
{ cellar: :any_skip_relocation, tag: :snow_leopard_32, digest: "deadbeef" * 8 },
{ cellar: :any, tag: :snow_leopard, digest: "faceb00c" * 8 },
{ cellar: "/usr/local/Cellar", tag: :lion, digest: "baadf00d" * 8 },
{ cellar: Homebrew::DEFAULT_CELLAR, tag: :mountain_lion, digest: "8badf00d" * 8 },
]
checksums.each do |checksum|
bottle_spec.sha256(checksum[:tag] => checksum[:digest], cellar: checksum[:cellar])
digest, tag, cellar = bottle_spec.checksum_for(checksum[:tag])
expect(Checksum.new(checksum[:digest])).to eq(digest)
expect(checksum[:tag]).to eq(tag)
checksum[:cellar] ||= Homebrew::DEFAULT_CELLAR
expect(checksum[:cellar]).to eq(cellar)
end
end
end
%w[root_url prefix cellar rebuild].each do |method|
specify "##{method}" do
object = Object.new
bottle_spec.public_send(method, object)
expect(bottle_spec.public_send(method)).to eq(object)
end
end
end

View File

@ -0,0 +1,16 @@
# typed: false
# frozen_string_literal: true
require "software_spec"
describe HeadSoftwareSpec do
subject(:head_spec) { described_class.new }
specify "#version" do
expect(head_spec.version).to eq(Version.create("HEAD"))
end
specify "#verify_download_integrity" do
expect(head_spec.verify_download_integrity(Object.new)).to be nil
end
end

View File

@ -173,62 +173,3 @@ describe SoftwareSpec do
end
end
end
describe HeadSoftwareSpec do
subject(:head_spec) { described_class.new }
specify "#version" do
expect(head_spec.version).to eq(Version.create("HEAD"))
end
specify "#verify_download_integrity" do
expect(head_spec.verify_download_integrity(Object.new)).to be nil
end
end
describe BottleSpecification do
subject(:bottle_spec) { described_class.new }
describe "#sha256" do
it "works without cellar" do
checksums = {
snow_leopard_32: "deadbeef" * 8,
snow_leopard: "faceb00c" * 8,
lion: "baadf00d" * 8,
mountain_lion: "8badf00d" * 8,
}
checksums.each_pair do |cat, digest|
bottle_spec.sha256(digest => cat)
checksum, = bottle_spec.checksum_for(cat)
expect(Checksum.new(digest)).to eq(checksum)
end
end
it "works with cellar" do
checksums = [
{ cellar: :any_skip_relocation, tag: :snow_leopard_32, digest: "deadbeef" * 8 },
{ cellar: :any, tag: :snow_leopard, digest: "faceb00c" * 8 },
{ cellar: "/usr/local/Cellar", tag: :lion, digest: "baadf00d" * 8 },
{ cellar: Homebrew::DEFAULT_CELLAR, tag: :mountain_lion, digest: "8badf00d" * 8 },
]
checksums.each do |checksum|
bottle_spec.sha256(checksum[:tag] => checksum[:digest], cellar: checksum[:cellar])
digest, tag, cellar = bottle_spec.checksum_for(checksum[:tag])
expect(Checksum.new(checksum[:digest])).to eq(digest)
expect(checksum[:tag]).to eq(tag)
checksum[:cellar] ||= Homebrew::DEFAULT_CELLAR
expect(checksum[:cellar]).to eq(cellar)
end
end
end
%w[root_url prefix cellar rebuild].each do |method|
specify "##{method}" do
object = Object.new
bottle_spec.public_send(method, object)
expect(bottle_spec.public_send(method)).to eq(object)
end
end
end

View File

@ -452,9 +452,8 @@ describe Tap do
end
end
end
end
describe CoreTap do
describe CoreTap do
subject(:core_tap) { described_class.new }
specify "attributes" do
@ -512,4 +511,5 @@ describe CoreTap do
expect(core_tap.style_exceptions).to eq({ formula_hash: formula_list_file_contents })
expect(core_tap.pypi_formula_mappings).to eq formula_list_file_contents
end
end
end

View File

@ -7,9 +7,8 @@ describe Version do
specify ".formula_optionally_versioned_regex" do
expect(described_class.formula_optionally_versioned_regex("foo")).to match("foo@1.2")
end
end
describe Version::Token do
describe Version::Token do
specify "#inspect" do
expect(described_class.new("foo").inspect).to eq('#<Version::Token "foo">')
end
@ -45,9 +44,9 @@ describe Version::Token do
expect(String.try_convert(described_class.new("foo"))).not_to be nil
end
end
end
end
describe Version::NULL do
describe Version::NULL do
it "is always smaller" do
expect(described_class).to be < Version.create("1")
end
@ -68,9 +67,8 @@ describe Version::NULL do
# Float::NAN is not equal to itself so compare object IDs
expect(described_class.to_f.object_id).to eql(Float::NAN.object_id)
end
end
end
describe Version do
describe "::NULL_TOKEN" do
subject(:null_version) { described_class::NULL_TOKEN }
@ -853,12 +851,12 @@ describe Version do
.to be_detected_from("https://github.com/foo/bar.git", tag: "v1.2.3-beta1")
end
end
end
describe Pathname do
describe Pathname do
specify "#version" do
d = HOMEBREW_CELLAR/"foo-0.1.9"
d.mkpath
expect(d.version).to eq(Version.create("0.1.9"))
end
end
end