Merge pull request #2230 from reitermarkus/spec-audit-cmd
Convert FormulaAuditor test to spec.
This commit is contained in:
commit
afb68d235b
@ -1,464 +0,0 @@
|
|||||||
require "testing_env"
|
|
||||||
require "fileutils"
|
|
||||||
require "pathname"
|
|
||||||
require "formulary"
|
|
||||||
require "dev-cmd/audit"
|
|
||||||
|
|
||||||
class FormulaAuditorTests < Homebrew::TestCase
|
|
||||||
def setup
|
|
||||||
super
|
|
||||||
@dir = mktmpdir
|
|
||||||
end
|
|
||||||
|
|
||||||
def formula_auditor(name, text, options = {})
|
|
||||||
path = Pathname.new "#{@dir}/#{name}.rb"
|
|
||||||
path.open("w") do |f|
|
|
||||||
f.write text
|
|
||||||
end
|
|
||||||
FormulaAuditor.new Formulary.factory(path), options
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_init_no_problems
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_permissions
|
|
||||||
File.stubs(:umask).returns 022
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
path = fa.formula.path
|
|
||||||
path.chmod 0400
|
|
||||||
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["Incorrect file permissions (400): chmod 644 #{path}"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_data_no_end
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
patch :DATA
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["'DATA' was found, but no '__END__'"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_end_no_data
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
__END__
|
|
||||||
a patch goes here
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["'__END__' was found, but 'DATA' is not used"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_no_trailing_newline
|
|
||||||
fa = formula_auditor "foo", 'class Foo<Formula; url "file:///foo-1.0.tgz";end'
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["File should end with a newline"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_not_strict_no_issue
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
homepage "http://example.com"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_ordering_issue
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
homepage "http://example.com"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["`homepage` (line 3) should be put before `url` (line 2)"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_resource_placement
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "https://example.com/foo-1.0.tgz"
|
|
||||||
|
|
||||||
resource "foo2" do
|
|
||||||
url "https://example.com/foo-2.0.tgz"
|
|
||||||
end
|
|
||||||
|
|
||||||
depends_on "openssl"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["`depends_on` (line 8) should be put before `resource` (line 4)"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_plist_placement
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "https://example.com/foo-1.0.tgz"
|
|
||||||
|
|
||||||
test do
|
|
||||||
assert_match "Dogs are terrific", shell_output("./dogs")
|
|
||||||
end
|
|
||||||
|
|
||||||
def plist
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["`plist block` (line 8) should be put before `test block` (line 4)"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_url_outside_of_stable_block
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
stable do
|
|
||||||
# stuff
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["`url` should be put inside `stable block`"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_head_and_head_do
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
head "http://example.com/foo.git"
|
|
||||||
head do
|
|
||||||
# stuff
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["Should not have both `head` and `head do`"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_file_strict_bottle_and_bottle_do
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
bottle do
|
|
||||||
# bottles go here
|
|
||||||
end
|
|
||||||
bottle :unneeded
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_file
|
|
||||||
assert_equal ["Should not have `bottle :unneeded/:disable` and `bottle do`"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_class_no_test
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_class
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_class
|
|
||||||
assert_equal ["A `test do` test block should be added"], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_class_github_gist_formula
|
|
||||||
needs_compat
|
|
||||||
require "compat/formula_specialties"
|
|
||||||
|
|
||||||
ENV.delete("HOMEBREW_DEVELOPER")
|
|
||||||
fa = shutup do
|
|
||||||
formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < GithubGistFormula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
end
|
|
||||||
fa.audit_class
|
|
||||||
assert_equal ["GithubGistFormula is deprecated, use Formula instead"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_class_script_file_formula
|
|
||||||
needs_compat
|
|
||||||
require "compat/formula_specialties"
|
|
||||||
|
|
||||||
ENV.delete("HOMEBREW_DEVELOPER")
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < ScriptFileFormula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_class
|
|
||||||
assert_equal ["ScriptFileFormula is deprecated, use Formula instead"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_class_aws_formula
|
|
||||||
needs_compat
|
|
||||||
require "compat/formula_specialties"
|
|
||||||
|
|
||||||
ENV.delete("HOMEBREW_DEVELOPER")
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < AmazonWebServicesFormula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_class
|
|
||||||
assert_equal ["AmazonWebServicesFormula is deprecated, use Formula instead"],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_line_pkgshare
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
fa.audit_line 'ohai "#{share}/foo"', 3
|
|
||||||
assert_equal "Use \#{pkgshare} instead of \#{share}/foo", fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai "#{share}/foo/bar"', 3
|
|
||||||
assert_equal "Use \#{pkgshare} instead of \#{share}/foo", fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai share/"foo"', 3
|
|
||||||
assert_equal 'Use pkgshare instead of (share/"foo")', fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai share/"foo/bar"', 3
|
|
||||||
assert_equal 'Use pkgshare instead of (share/"foo")', fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai "#{share}/foo-bar"', 3
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
fa.audit_line 'ohai share/"foo-bar"', 3
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
fa.audit_line 'ohai share/"bar"', 3
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
# Regression test for https://github.com/Homebrew/legacy-homebrew/pull/48744
|
|
||||||
# Formulae with "++" in their name would break various audit regexps:
|
|
||||||
# Error: nested *?+ in regexp: /^libxml++3\s/
|
|
||||||
def test_audit_plus_plus_name
|
|
||||||
fa = formula_auditor "foolibc++", <<-EOS.undent, strict: true
|
|
||||||
class Foolibcxx < Formula
|
|
||||||
desc "foolibc++ is a test"
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_desc
|
|
||||||
assert_equal "Description shouldn't include the formula name",
|
|
||||||
fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai "#{share}/foolibc++"', 3
|
|
||||||
assert_equal "Use \#{pkgshare} instead of \#{share}/foolibc++", fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line 'ohai share/"foolibc++"', 3
|
|
||||||
assert_equal 'Use pkgshare instead of (share/"foolibc++")', fa.problems.shift
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_line_space_in_class_inheritance
|
|
||||||
fa = formula_auditor "foo", "class Foo<Formula; url '/foo-1.0.tgz'; end"
|
|
||||||
fa.audit_line "class Foo<Formula", 1
|
|
||||||
assert_equal "Use a space in class inheritance: class Foo < Formula",
|
|
||||||
fa.problems.shift
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_line_default_template
|
|
||||||
fa = formula_auditor "foo", "class Foo < Formula; url '/foo-1.0.tgz'; end"
|
|
||||||
|
|
||||||
fa.audit_line '# system "cmake", ".", *std_cmake_args', 3
|
|
||||||
assert_equal "Commented cmake call found",
|
|
||||||
fa.problems.shift
|
|
||||||
|
|
||||||
fa.audit_line "# PLEASE REMOVE", 3
|
|
||||||
assert_equal "Please remove default template comments",
|
|
||||||
fa.problems.shift
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_github_repository_no_api
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, strict: true, online: true
|
|
||||||
class Foo < Formula
|
|
||||||
homepage "https://github.com/example/example"
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
ENV["HOMEBREW_NO_GITHUB_API"] = "1"
|
|
||||||
|
|
||||||
fa.audit_github_repository
|
|
||||||
assert_equal [], fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_caveats
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
homepage "http://example.com/foo"
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
|
|
||||||
def caveats
|
|
||||||
"setuid"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_caveats
|
|
||||||
assert_equal ["Don't recommend setuid in the caveats, suggest sudo instead."],
|
|
||||||
fa.problems
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_desc
|
|
||||||
formula_descriptions = [
|
|
||||||
{ name: "foo", desc: nil,
|
|
||||||
problem: "Formula should have a desc" },
|
|
||||||
{ name: "bar", desc: "bar" * 30,
|
|
||||||
problem: "Description is too long" },
|
|
||||||
{ name: "baz", desc: "Baz commandline tool",
|
|
||||||
problem: "Description should use \"command-line\"" },
|
|
||||||
{ name: "qux", desc: "A tool called Qux",
|
|
||||||
problem: "Description shouldn't start with an indefinite article" },
|
|
||||||
]
|
|
||||||
|
|
||||||
formula_descriptions.each do |formula|
|
|
||||||
content = <<-EOS.undent
|
|
||||||
class #{Formulary.class_s(formula[:name])} < Formula
|
|
||||||
url "http://example.com/#{formula[:name]}-1.0.tgz"
|
|
||||||
desc "#{formula[:desc]}"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa = formula_auditor formula[:name], content, strict: true
|
|
||||||
fa.audit_desc
|
|
||||||
assert_match formula[:problem], fa.problems.first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_homepage
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, online: true
|
|
||||||
class Foo < Formula
|
|
||||||
homepage "ftp://example.com/foo"
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_homepage
|
|
||||||
assert_equal ["The homepage should start with http or https (URL is #{fa.formula.homepage})."],
|
|
||||||
fa.problems
|
|
||||||
|
|
||||||
formula_homepages = {
|
|
||||||
"bar" => "http://www.freedesktop.org/wiki/bar",
|
|
||||||
"baz" => "http://www.freedesktop.org/wiki/Software/baz",
|
|
||||||
"qux" => "https://code.google.com/p/qux",
|
|
||||||
"quux" => "http://github.com/quux",
|
|
||||||
"corge" => "http://savannah.nongnu.org/corge",
|
|
||||||
"grault" => "http://grault.github.io/",
|
|
||||||
"garply" => "http://www.gnome.org/garply",
|
|
||||||
"sf1" => "http://foo.sourceforge.net/",
|
|
||||||
"sf2" => "http://foo.sourceforge.net",
|
|
||||||
"sf3" => "http://foo.sf.net/",
|
|
||||||
"sf4" => "http://foo.sourceforge.io/",
|
|
||||||
"waldo" => "http://www.gnu.org/waldo",
|
|
||||||
}
|
|
||||||
|
|
||||||
formula_homepages.each do |name, homepage|
|
|
||||||
fa = formula_auditor name, <<-EOS.undent
|
|
||||||
class #{Formulary.class_s(name)} < Formula
|
|
||||||
homepage "#{homepage}"
|
|
||||||
url "http://example.com/#{name}-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_homepage
|
|
||||||
if homepage =~ %r{http:\/\/www\.freedesktop\.org}
|
|
||||||
if homepage =~ /Software/
|
|
||||||
assert_match "#{homepage} should be styled " \
|
|
||||||
"`https://wiki.freedesktop.org/www/Software/project_name`",
|
|
||||||
fa.problems.first
|
|
||||||
else
|
|
||||||
assert_match "#{homepage} should be styled " \
|
|
||||||
"`https://wiki.freedesktop.org/project_name`",
|
|
||||||
fa.problems.first
|
|
||||||
end
|
|
||||||
elsif homepage =~ %r{https:\/\/code\.google\.com}
|
|
||||||
assert_match "#{homepage} should end with a slash", fa.problems.first
|
|
||||||
elsif homepage =~ /foo\.(sf|sourceforge)\.net/
|
|
||||||
assert_match "#{homepage} should be `https://foo.sourceforge.io/`", fa.problems.first
|
|
||||||
else
|
|
||||||
assert_match "Please use https:// for #{homepage}", fa.problems.first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_without_homepage
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent, online: true
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_homepage
|
|
||||||
assert_match "Formula should have a homepage.", fa.problems.first
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_xcodebuild_suggests_symroot
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
homepage "http://example.com"
|
|
||||||
|
|
||||||
def install
|
|
||||||
xcodebuild "-project", "meow.xcodeproject"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_text
|
|
||||||
|
|
||||||
assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_audit_bare_xcodebuild_suggests_symroot_also
|
|
||||||
fa = formula_auditor "foo", <<-EOS.undent
|
|
||||||
class Foo < Formula
|
|
||||||
url "http://example.com/foo-1.0.tgz"
|
|
||||||
homepage "http://example.com"
|
|
||||||
|
|
||||||
def install
|
|
||||||
xcodebuild
|
|
||||||
end
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
|
|
||||||
fa.audit_text
|
|
||||||
|
|
||||||
assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first
|
|
||||||
end
|
|
||||||
end
|
|
@ -59,3 +59,501 @@ describe FormulaText do
|
|||||||
expect(ft.without_patch).to eq("class End < Formula\n \nend")
|
expect(ft.without_patch).to eq("class End < Formula\n \nend")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe FormulaAuditor do
|
||||||
|
def formula_auditor(name, text, options = {})
|
||||||
|
path = Pathname.new "#{dir}/#{name}.rb"
|
||||||
|
path.open("w") do |f|
|
||||||
|
f.write text
|
||||||
|
end
|
||||||
|
|
||||||
|
described_class.new(Formulary.factory(path), options)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:dir) { @dir = Pathname.new(Dir.mktmpdir) }
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
dir.rmtree unless @dir.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#problems" do
|
||||||
|
it "is empty by default" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
expect(fa.problems).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_file" do
|
||||||
|
specify "file permissions" do
|
||||||
|
allow(File).to receive(:umask).and_return(022)
|
||||||
|
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
path = fa.formula.path
|
||||||
|
path.chmod 0400
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["Incorrect file permissions (400): chmod 644 #{path}"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "DATA but no __END__" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
patch :DATA
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq(["'DATA' was found, but no '__END__'"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "__END__ but no DATA" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
__END__
|
||||||
|
a patch goes here
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq(["'__END__' was found, but 'DATA' is not used"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "no trailing newline" do
|
||||||
|
fa = formula_auditor "foo", 'class Foo<Formula; url "file:///foo-1.0.tgz";end'
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq(["File should end with a newline"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "no issue" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
homepage "http://example.com"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: ordering issue" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
homepage "http://example.com"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["`homepage` (line 3) should be put before `url` (line 2)"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: resource placement" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://example.com/foo-1.0.tgz"
|
||||||
|
|
||||||
|
resource "foo2" do
|
||||||
|
url "https://example.com/foo-2.0.tgz"
|
||||||
|
end
|
||||||
|
|
||||||
|
depends_on "openssl"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["`depends_on` (line 8) should be put before `resource` (line 4)"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: plist placement" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "https://example.com/foo-1.0.tgz"
|
||||||
|
|
||||||
|
test do
|
||||||
|
expect(shell_output("./dogs")).to match("Dogs are terrific")
|
||||||
|
end
|
||||||
|
|
||||||
|
def plist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["`plist block` (line 8) should be put before `test block` (line 4)"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: url outside of stable block" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
stable do
|
||||||
|
# stuff
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq(["`url` should be put inside `stable block`"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: head and head do" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
head "http://example.com/foo.git"
|
||||||
|
head do
|
||||||
|
# stuff
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems).to eq(["Should not have both `head` and `head do`"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "strict: bottle and bottle do" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
bottle do
|
||||||
|
# bottles go here
|
||||||
|
end
|
||||||
|
bottle :unneeded
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_file
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["Should not have `bottle :unneeded/:disable` and `bottle do`"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_class" do
|
||||||
|
specify "missing test" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_class
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_class
|
||||||
|
expect(fa.problems).to eq(["A `test do` test block should be added"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "GithubGistFormula", :needs_compat do
|
||||||
|
ENV.delete("HOMEBREW_DEVELOPER")
|
||||||
|
|
||||||
|
fa = shutup do
|
||||||
|
formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < GithubGistFormula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
fa.audit_class
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["GithubGistFormula is deprecated, use Formula instead"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "ScriptFileFormula", :needs_compat do
|
||||||
|
ENV.delete("HOMEBREW_DEVELOPER")
|
||||||
|
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < ScriptFileFormula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_class
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["ScriptFileFormula is deprecated, use Formula instead"])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "AmazonWebServicesFormula", :needs_compat do
|
||||||
|
ENV.delete("HOMEBREW_DEVELOPER")
|
||||||
|
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < AmazonWebServicesFormula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_class
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["AmazonWebServicesFormula is deprecated, use Formula instead"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_line" do
|
||||||
|
specify "pkgshare" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_line 'ohai "#{share}/foo"', 3
|
||||||
|
expect(fa.problems.shift).to eq("Use \#{pkgshare} instead of \#{share}/foo")
|
||||||
|
|
||||||
|
fa.audit_line 'ohai "#{share}/foo/bar"', 3
|
||||||
|
expect(fa.problems.shift).to eq("Use \#{pkgshare} instead of \#{share}/foo")
|
||||||
|
|
||||||
|
fa.audit_line 'ohai share/"foo"', 3
|
||||||
|
expect(fa.problems.shift).to eq('Use pkgshare instead of (share/"foo")')
|
||||||
|
|
||||||
|
fa.audit_line 'ohai share/"foo/bar"', 3
|
||||||
|
expect(fa.problems.shift).to eq('Use pkgshare instead of (share/"foo")')
|
||||||
|
|
||||||
|
fa.audit_line 'ohai "#{share}/foo-bar"', 3
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
|
||||||
|
fa.audit_line 'ohai share/"foo-bar"', 3
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
|
||||||
|
fa.audit_line 'ohai share/"bar"', 3
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Regression test for https://github.com/Homebrew/legacy-homebrew/pull/48744
|
||||||
|
# Formulae with "++" in their name would break various audit regexps:
|
||||||
|
# Error: nested *?+ in regexp: /^libxml++3\s/
|
||||||
|
specify "++ in name" do
|
||||||
|
fa = formula_auditor "foolibc++", <<-EOS.undent, strict: true
|
||||||
|
class Foolibcxx < Formula
|
||||||
|
desc "foolibc++ is a test"
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_desc
|
||||||
|
expect(fa.problems.shift)
|
||||||
|
.to eq("Description shouldn't include the formula name")
|
||||||
|
|
||||||
|
fa.audit_line 'ohai "#{share}/foolibc++"', 3
|
||||||
|
expect(fa.problems.shift)
|
||||||
|
.to eq("Use \#{pkgshare} instead of \#{share}/foolibc++")
|
||||||
|
|
||||||
|
fa.audit_line 'ohai share/"foolibc++"', 3
|
||||||
|
expect(fa.problems.shift)
|
||||||
|
.to eq('Use pkgshare instead of (share/"foolibc++")')
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "no space in class inheritance" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo<Formula
|
||||||
|
url '/foo-1.0.tgz'
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_line "class Foo<Formula", 1
|
||||||
|
expect(fa.problems.shift)
|
||||||
|
.to eq("Use a space in class inheritance: class Foo < Formula")
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "default template" do
|
||||||
|
fa = formula_auditor "foo", "class Foo < Formula; url '/foo-1.0.tgz'; end"
|
||||||
|
|
||||||
|
fa.audit_line '# system "cmake", ".", *std_cmake_args', 3
|
||||||
|
expect(fa.problems.shift).to eq("Commented cmake call found")
|
||||||
|
|
||||||
|
fa.audit_line "# PLEASE REMOVE", 3
|
||||||
|
expect(fa.problems.shift).to eq("Please remove default template comments")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_github_repository" do
|
||||||
|
specify "#audit_github_repository when HOMEBREW_NO_GITHUB_API is set" do
|
||||||
|
ENV["HOMEBREW_NO_GITHUB_API"] = "1"
|
||||||
|
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, strict: true, online: true
|
||||||
|
class Foo < Formula
|
||||||
|
homepage "https://github.com/example/example"
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_github_repository
|
||||||
|
expect(fa.problems).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "#audit_caveats" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
homepage "http://example.com/foo"
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
|
||||||
|
def caveats
|
||||||
|
"setuid"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_caveats
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["Don't recommend setuid in the caveats, suggest sudo instead."])
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "#audit_desc" do
|
||||||
|
formula_descriptions = [
|
||||||
|
{ name: "foo", desc: nil,
|
||||||
|
problem: "Formula should have a desc" },
|
||||||
|
{ name: "bar", desc: "bar" * 30,
|
||||||
|
problem: "Description is too long" },
|
||||||
|
{ name: "baz", desc: "Baz commandline tool",
|
||||||
|
problem: "Description should use \"command-line\"" },
|
||||||
|
{ name: "qux", desc: "A tool called Qux",
|
||||||
|
problem: "Description shouldn't start with an indefinite article" },
|
||||||
|
]
|
||||||
|
|
||||||
|
formula_descriptions.each do |formula|
|
||||||
|
content = <<-EOS.undent
|
||||||
|
class #{Formulary.class_s(formula[:name])} < Formula
|
||||||
|
url "http://example.com/#{formula[:name]}-1.0.tgz"
|
||||||
|
desc "#{formula[:desc]}"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa = formula_auditor formula[:name], content, strict: true
|
||||||
|
fa.audit_desc
|
||||||
|
expect(fa.problems.first).to match(formula[:problem])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_homepage" do
|
||||||
|
specify "homepage URLs" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, online: true
|
||||||
|
class Foo < Formula
|
||||||
|
homepage "ftp://example.com/foo"
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_homepage
|
||||||
|
expect(fa.problems)
|
||||||
|
.to eq(["The homepage should start with http or https (URL is #{fa.formula.homepage})."])
|
||||||
|
|
||||||
|
formula_homepages = {
|
||||||
|
"bar" => "http://www.freedesktop.org/wiki/bar",
|
||||||
|
"baz" => "http://www.freedesktop.org/wiki/Software/baz",
|
||||||
|
"qux" => "https://code.google.com/p/qux",
|
||||||
|
"quux" => "http://github.com/quux",
|
||||||
|
"corge" => "http://savannah.nongnu.org/corge",
|
||||||
|
"grault" => "http://grault.github.io/",
|
||||||
|
"garply" => "http://www.gnome.org/garply",
|
||||||
|
"sf1" => "http://foo.sourceforge.net/",
|
||||||
|
"sf2" => "http://foo.sourceforge.net",
|
||||||
|
"sf3" => "http://foo.sf.net/",
|
||||||
|
"sf4" => "http://foo.sourceforge.io/",
|
||||||
|
"waldo" => "http://www.gnu.org/waldo",
|
||||||
|
}
|
||||||
|
|
||||||
|
formula_homepages.each do |name, homepage|
|
||||||
|
fa = formula_auditor name, <<-EOS.undent
|
||||||
|
class #{Formulary.class_s(name)} < Formula
|
||||||
|
homepage "#{homepage}"
|
||||||
|
url "http://example.com/#{name}-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_homepage
|
||||||
|
if homepage =~ %r{http:\/\/www\.freedesktop\.org}
|
||||||
|
if homepage =~ /Software/
|
||||||
|
expect(fa.problems.first).to match(
|
||||||
|
"#{homepage} should be styled " \
|
||||||
|
"`https://wiki.freedesktop.org/www/Software/project_name`",
|
||||||
|
)
|
||||||
|
else
|
||||||
|
expect(fa.problems.first).to match(
|
||||||
|
"#{homepage} should be styled " \
|
||||||
|
"`https://wiki.freedesktop.org/project_name`",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
elsif homepage =~ %r{https:\/\/code\.google\.com}
|
||||||
|
expect(fa.problems.first)
|
||||||
|
.to match("#{homepage} should end with a slash")
|
||||||
|
elsif homepage =~ /foo\.(sf|sourceforge)\.net/
|
||||||
|
expect(fa.problems.first)
|
||||||
|
.to match("#{homepage} should be `https://foo.sourceforge.io/`")
|
||||||
|
else
|
||||||
|
expect(fa.problems.first)
|
||||||
|
.to match("Please use https:// for #{homepage}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "missing homepage" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent, online: true
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_homepage
|
||||||
|
expect(fa.problems.first).to match("Formula should have a homepage.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#audit_text" do
|
||||||
|
specify "xcodebuild suggests symroot" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
homepage "http://example.com"
|
||||||
|
|
||||||
|
def install
|
||||||
|
xcodebuild "-project", "meow.xcodeproject"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_text
|
||||||
|
expect(fa.problems.first)
|
||||||
|
.to match('xcodebuild should be passed an explicit "SYMROOT"')
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "bare xcodebuild also suggests symroot" do
|
||||||
|
fa = formula_auditor "foo", <<-EOS.undent
|
||||||
|
class Foo < Formula
|
||||||
|
url "http://example.com/foo-1.0.tgz"
|
||||||
|
homepage "http://example.com"
|
||||||
|
|
||||||
|
def install
|
||||||
|
xcodebuild
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
|
||||||
|
fa.audit_text
|
||||||
|
expect(fa.problems.first)
|
||||||
|
.to match('xcodebuild should be passed an explicit "SYMROOT"')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -36,6 +36,10 @@ RSpec.configure do |config|
|
|||||||
config.include(Test::Helper::Fixtures)
|
config.include(Test::Helper::Fixtures)
|
||||||
config.include(Test::Helper::Formula)
|
config.include(Test::Helper::Formula)
|
||||||
|
|
||||||
|
config.before(:each, :needs_compat) do
|
||||||
|
skip "Requires compatibility layer." if ENV["HOMEBREW_NO_COMPAT"]
|
||||||
|
end
|
||||||
|
|
||||||
config.before(:each, :needs_official_cmd_taps) do
|
config.before(:each, :needs_official_cmd_taps) do
|
||||||
skip "Needs official command Taps." unless ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"]
|
skip "Needs official command Taps." unless ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"]
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user