aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb34
-rw-r--r--Library/Homebrew/extend/os/mac/keg_relocate.rb8
-rw-r--r--Library/Homebrew/keg.rb5
-rw-r--r--Library/Homebrew/readall.rb19
-rw-r--r--Library/Homebrew/test/formula_pin_spec.rb41
-rw-r--r--Library/Homebrew/test/formula_pin_test.rb51
-rw-r--r--Library/Homebrew/test/os/mac/mach_spec.rb198
-rw-r--r--Library/Homebrew/test/os/mac/mach_test.rb211
-rw-r--r--Library/Homebrew/test/software_spec_spec.rb184
-rw-r--r--Library/Homebrew/test/software_spec_test.rb184
10 files changed, 451 insertions, 484 deletions
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 9da5d28b4..d4d6a6d72 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -295,27 +295,6 @@ class FormulaAuditor
problem "File should end with a newline" unless text.trailing_newline?
- versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]
- needs_versioned_alias = !versioned_formulae.empty? &&
- formula.tap &&
- formula.aliases.grep(/.@\d/).empty?
- if needs_versioned_alias
- _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first)
- .gsub(/\.rb$/, "")
- .split("@")
- major, minor, = formula.version.to_s.split(".")
- alias_name = if last_alias_version.split(".").length == 1
- "#{formula.name}@#{major}"
- else
- "#{formula.name}@#{major}.#{minor}"
- end
- problem <<-EOS.undent
- Formula has other versions so create an alias:
- cd #{formula.tap.alias_dir}
- ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
- EOS
- end
-
return unless @strict
present = audit_components
@@ -431,8 +410,7 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'."
end
- if @@aliases.include?(dep.name) &&
- (core_formula? || !dep_f.versioned_formula?)
+ if @@aliases.include?(dep.name)
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
end
@@ -816,10 +794,12 @@ class FormulaAuditor
return if formula.revision.zero?
if formula.stable
- revision_map = attributes_map[:revision][:stable]
- stable_revisions = revision_map[formula.stable.version] if revision_map
- if !stable_revisions || stable_revisions.empty?
- problem "'revision #{formula.revision}' should be removed"
+ if revision_map = attributes_map[:revision][:stable]
+ stable_revisions = revision_map[formula.stable.version]
+ stable_revisions -= [formula.revision]
+ if stable_revisions.empty?
+ problem "'revision #{formula.revision}' should be removed"
+ end
end
else # head/devel-only formula
problem "'revision #{formula.revision}' should be removed"
diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb
index f44a97b31..476e5da4a 100644
--- a/Library/Homebrew/extend/os/mac/keg_relocate.rb
+++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb
@@ -78,13 +78,19 @@ class Keg
end
end
+ def filename_contains_metavariable?(fn)
+ fn =~ /^@(loader_|executable_|r)path/
+ end
+
def each_install_name_for(file, &block)
dylibs = file.dynamically_linked_libraries
- dylibs.reject! { |fn| fn =~ /^@(loader_|executable_|r)path/ }
+ dylibs.reject! { |fn| filename_contains_metavariable?(fn) }
dylibs.each(&block)
end
def dylib_id_for(file)
+ return file.dylib_id if filename_contains_metavariable?(file.dylib_id)
+
# The new dylib ID should have the same basename as the old dylib ID, not
# the basename of the file itself.
basename = File.basename(file.dylib_id)
diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb
index b31997d5a..94e3ff55b 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -239,7 +239,10 @@ class Keg
def remove_opt_record
opt_record.unlink
- aliases.each { |a| (opt_record.parent/a).unlink }
+ aliases.each do |a|
+ next if !opt_record.symlink? && !opt_record.exist?
+ (opt_record.parent/a).delete
+ end
opt_record.parent.rmdir_if_possible
end
diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb
index 52addfa87..3dd7075ec 100644
--- a/Library/Homebrew/readall.rb
+++ b/Library/Homebrew/readall.rb
@@ -24,15 +24,16 @@ module Readall
!failed
end
- def valid_aliases?(alias_dir, formula_dir)
- return false unless alias_dir.directory?
-
+ def valid_aliases?(alias_dirs)
failed = false
- alias_dir.each_child do |f|
- next unless f.symlink?
- next if f.file? && !(formula_dir/"#{f.basename}.rb").exist?
- onoe "Broken alias: #{f}"
- failed = true
+ alias_dirs.each do |alias_dir|
+ next unless alias_dir.directory?
+ alias_dir.children.each do |f|
+ next unless f.symlink?
+ next if f.file?
+ onoe "Broken alias: #{f}"
+ failed = true
+ end
end
!failed
end
@@ -56,7 +57,7 @@ module Readall
def valid_tap?(tap, options = {})
failed = false
if options[:aliases]
- valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
+ valid_aliases = valid_aliases?([tap.alias_dir])
failed = true unless valid_aliases
end
valid_formulae = valid_formulae?(tap.formula_files)
diff --git a/Library/Homebrew/test/formula_pin_spec.rb b/Library/Homebrew/test/formula_pin_spec.rb
new file mode 100644
index 000000000..909bfbc2b
--- /dev/null
+++ b/Library/Homebrew/test/formula_pin_spec.rb
@@ -0,0 +1,41 @@
+require "formula_pin"
+
+describe FormulaPin do
+ subject { described_class.new(formula) }
+ let(:name) { "double" }
+ let(:formula) { double(Formula, name: name, rack: HOMEBREW_CELLAR/name) }
+
+ before(:each) do
+ formula.rack.mkpath
+
+ allow(formula).to receive(:installed_prefixes) do
+ formula.rack.directory? ? formula.rack.subdirs : []
+ end
+
+ allow(formula).to receive(:installed_kegs) do
+ formula.installed_prefixes.map { |prefix| Keg.new(prefix) }
+ end
+ end
+
+ it "is not pinnable by default" do
+ expect(subject).not_to be_pinnable
+ end
+
+ it "is pinnable if the Keg exists" do
+ (formula.rack/"0.1").mkpath
+ expect(subject).to be_pinnable
+ end
+
+ specify "#pin and #unpin" do
+ (formula.rack/"0.1").mkpath
+
+ subject.pin
+ expect(subject).to be_pinned
+ expect(HOMEBREW_PINNED_KEGS/name).to be_a_directory
+ expect(HOMEBREW_PINNED_KEGS.children.count).to eq(1)
+
+ subject.unpin
+ expect(subject).not_to be_pinned
+ expect(HOMEBREW_PINNED_KEGS).not_to be_a_directory
+ end
+end
diff --git a/Library/Homebrew/test/formula_pin_test.rb b/Library/Homebrew/test/formula_pin_test.rb
deleted file mode 100644
index 7e3c7efa0..000000000
--- a/Library/Homebrew/test/formula_pin_test.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require "testing_env"
-require "formula_pin"
-
-class FormulaPinTests < Homebrew::TestCase
- class FormulaDouble
- def name
- "double"
- end
-
- def rack
- HOMEBREW_CELLAR/name
- end
-
- def installed_prefixes
- rack.directory? ? rack.subdirs : []
- end
-
- def installed_kegs
- installed_prefixes.map { |d| Keg.new d }
- end
- end
-
- def setup
- super
- @f = FormulaDouble.new
- @pin = FormulaPin.new(@f)
- @f.rack.mkpath
- end
-
- def test_not_pinnable
- refute_predicate @pin, :pinnable?
- end
-
- def test_pinnable_if_kegs_exist
- (@f.rack/"0.1").mkpath
- assert_predicate @pin, :pinnable?
- end
-
- def test_unpin
- (@f.rack/"0.1").mkpath
- @pin.pin
-
- assert_predicate @pin, :pinned?
- assert_equal 1, HOMEBREW_PINNED_KEGS.children.length
-
- @pin.unpin
-
- refute_predicate @pin, :pinned?
- refute_predicate HOMEBREW_PINNED_KEGS, :directory?
- end
-end
diff --git a/Library/Homebrew/test/os/mac/mach_spec.rb b/Library/Homebrew/test/os/mac/mach_spec.rb
new file mode 100644
index 000000000..5c9aafcbb
--- /dev/null
+++ b/Library/Homebrew/test/os/mac/mach_spec.rb
@@ -0,0 +1,198 @@
+describe "Mach-O Pathname tests" do
+ specify "fat dylib" do
+ pn = dylib_path("fat")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn.arch).to eq(:universal)
+ end
+
+ specify "i386 dylib" do
+ pn = dylib_path("i386")
+ expect(pn).not_to be_universal
+ expect(pn).to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "x86_64 dylib" do
+ pn = dylib_path("x86_64")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "Mach-O executable" do
+ pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "fat bundle" do
+ pn = bundle_path("fat")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "i386 bundle" do
+ pn = bundle_path("i386")
+ expect(pn).not_to be_universal
+ expect(pn).to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "x86_64 bundle" do
+ pn = bundle_path("x86_64")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "non-Mach-O" do
+ pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ expect(pn.arch).to eq(:dunno)
+ end
+end
+
+describe ArchitectureListExtension do
+ let(:archs) { [:i386, :x86_64, :ppc7400, :ppc64].extend(described_class) }
+
+ specify "universal checks" do
+ expect(archs).to be_universal
+ expect(archs).to be_intel_universal
+ expect(archs).to be_ppc_universal
+ expect(archs).to be_cross_universal
+ expect(archs).to be_fat
+
+ non_universal = [:i386].extend(described_class)
+ expect(non_universal).not_to be_universal
+
+ intel_only = [:i386, :x86_64].extend(described_class)
+ expect(intel_only).to be_universal
+ expect(intel_only).not_to be_ppc_universal
+ expect(intel_only).not_to be_cross_universal
+
+ ppc_only = [:ppc970, :ppc64].extend(described_class)
+ expect(ppc_only).to be_universal
+ expect(ppc_only).not_to be_intel_universal
+ expect(ppc_only).not_to be_cross_universal
+
+ cross = [:ppc7400, :i386].extend(described_class)
+ expect(cross).to be_universal
+ expect(cross).not_to be_intel_universal
+ expect(cross).not_to be_ppc_universal
+ end
+
+ specify "messaging flags" do
+ archs.remove_ppc!
+ expect(archs.length).to eq(2)
+ expect(archs.as_arch_flags).to match(/-arch i386/)
+ expect(archs.as_arch_flags).to match(/-arch x86_64/)
+ end
+
+ specify "architecture flags" do
+ pn = dylib_path("fat")
+ expect(pn.archs).to be_intel_universal
+ expect(pn.archs.as_arch_flags).to eq("-arch x86_64 -arch i386")
+ expect(pn.archs.as_cmake_arch_flags).to eq("x86_64;i386")
+ end
+end
+
+describe "text executables" do
+ let(:pn) { HOMEBREW_PREFIX/"an_executable" }
+
+ after(:each) { pn.unlink }
+
+ specify "simple shebang" do
+ pn.write "#!/bin/sh"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+
+ specify "shebang with options" do
+ pn.write "#! /usr/bin/perl -w"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+
+ specify "malformed shebang" do
+ pn.write " #!"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+end
diff --git a/Library/Homebrew/test/os/mac/mach_test.rb b/Library/Homebrew/test/os/mac/mach_test.rb
deleted file mode 100644
index ed0424be6..000000000
--- a/Library/Homebrew/test/os/mac/mach_test.rb
+++ /dev/null
@@ -1,211 +0,0 @@
-require "testing_env"
-
-class MachOPathnameTests < Homebrew::TestCase
- def test_fat_dylib
- pn = dylib_path("fat")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_equal :universal, pn.arch
- end
-
- def test_i386_dylib
- pn = dylib_path("i386")
- refute_predicate pn, :universal?
- assert_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_x86_64_dylib
- pn = dylib_path("x86_64")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- assert_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_mach_o_executable
- pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- assert_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_fat_bundle
- pn = bundle_path("fat")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_i386_bundle
- pn = bundle_path("i386")
- refute_predicate pn, :universal?
- assert_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_x86_64_bundle
- pn = bundle_path("x86_64")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- assert_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_non_mach_o
- pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- assert_equal :dunno, pn.arch
- end
-end
-
-class ArchitectureListExtensionTests < MachOPathnameTests
- def setup
- super
- @archs = [:i386, :x86_64, :ppc7400, :ppc64].extend(ArchitectureListExtension)
- end
-
- def test_architecture_list_extension_universal_checks
- assert_predicate @archs, :universal?
- assert_predicate @archs, :intel_universal?
- assert_predicate @archs, :ppc_universal?
- assert_predicate @archs, :cross_universal?
- assert_predicate @archs, :fat?
-
- non_universal = [:i386].extend ArchitectureListExtension
- refute_predicate non_universal, :universal?
-
- intel_only = [:i386, :x86_64].extend ArchitectureListExtension
- assert_predicate intel_only, :universal?
- refute_predicate intel_only, :ppc_universal?
- refute_predicate intel_only, :cross_universal?
-
- ppc_only = [:ppc970, :ppc64].extend ArchitectureListExtension
- assert_predicate ppc_only, :universal?
- refute_predicate ppc_only, :intel_universal?
- refute_predicate ppc_only, :cross_universal?
-
- cross = [:ppc7400, :i386].extend ArchitectureListExtension
- assert_predicate cross, :universal?
- refute_predicate cross, :intel_universal?
- refute_predicate cross, :ppc_universal?
- end
-
- def test_architecture_list_extension_massaging_flags
- @archs.remove_ppc!
- assert_equal 2, @archs.length
- assert_match(/-arch i386/, @archs.as_arch_flags)
- assert_match(/-arch x86_64/, @archs.as_arch_flags)
- end
-
- def test_architecture_list_arch_flags_methods
- pn = dylib_path("fat")
- assert_predicate pn.archs, :intel_universal?
- assert_equal "-arch x86_64 -arch i386", pn.archs.as_arch_flags
- assert_equal "x86_64;i386", pn.archs.as_cmake_arch_flags
- end
-end
-
-class TextExecutableTests < Homebrew::TestCase
- attr_reader :pn
-
- def setup
- super
- @pn = HOMEBREW_PREFIX.join("an_executable")
- end
-
- def teardown
- HOMEBREW_PREFIX.join("an_executable").unlink
- super
- end
-
- def test_simple_shebang
- pn.write "#!/bin/sh"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- assert_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-
- def test_shebang_with_options
- pn.write "#! /usr/bin/perl -w"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- assert_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-
- def test_malformed_shebang
- pn.write " #!"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-end
diff --git a/Library/Homebrew/test/software_spec_spec.rb b/Library/Homebrew/test/software_spec_spec.rb
new file mode 100644
index 000000000..5fd4f598a
--- /dev/null
+++ b/Library/Homebrew/test/software_spec_spec.rb
@@ -0,0 +1,184 @@
+require "software_spec"
+
+RSpec::Matchers.alias_matcher :have_defined_resource, :be_resource_defined
+RSpec::Matchers.alias_matcher :have_defined_option, :be_option_defined
+
+describe SoftwareSpec do
+ let(:owner) { double(name: "some_name", full_name: "some_name", tap: "homebrew/core") }
+
+ describe "#resource" do
+ it "defines a resource" do
+ subject.resource("foo") { url "foo-1.0" }
+ expect(subject).to have_defined_resource("foo")
+ end
+
+ it "sets itself to be the resource's owner" do
+ subject.resource("foo") { url "foo-1.0" }
+ subject.owner = owner
+ subject.resources.each_value do |r|
+ expect(r.owner).to eq(subject)
+ end
+ end
+
+ it "receives the owner's version if it has no own version" do
+ subject.url("foo-42")
+ subject.resource("bar") { url "bar" }
+ subject.owner = owner
+
+ expect(subject.resource("bar").version).to eq("42")
+ end
+
+ it "raises an error when duplicate resources are defined" do
+ subject.resource("foo") { url "foo-1.0" }
+ expect {
+ subject.resource("foo") { url "foo-1.0" }
+ }.to raise_error(DuplicateResourceError)
+ end
+
+ it "raises an error when accessing missing resources" do
+ subject.owner = owner
+ expect {
+ subject.resource("foo")
+ }.to raise_error(ResourceMissingError)
+ end
+ end
+
+ describe "#owner" do
+ it "sets the owner" do
+ subject.owner = owner
+ expect(subject.owner).to eq(owner)
+ end
+
+ it "sets the name" do
+ subject.owner = owner
+ expect(subject.name).to eq(owner.name)
+ end
+ end
+
+ describe "#option" do
+ it "defines an option" do
+ subject.option("foo")
+ expect(subject).to have_defined_option("foo")
+ end
+
+ it "raises an error when it begins with dashes" do
+ expect {
+ subject.option("--foo")
+ }.to raise_error(ArgumentError)
+ end
+
+ it "raises an error when name is empty" do
+ expect {
+ subject.option("")
+ }.to raise_error(ArgumentError)
+ end
+
+ it "special cases the cxx11 option" do
+ subject.option(:cxx11)
+ expect(subject).to have_defined_option("c++11")
+ expect(subject).not_to have_defined_option("cxx11")
+ end
+
+ it "supports options with descriptions" do
+ subject.option("bar", "description")
+ expect(subject.options.first.description).to eq("description")
+ end
+
+ it "defaults to an empty string when no description is given" do
+ subject.option("foo")
+ expect(subject.options.first.description).to eq("")
+ end
+ end
+
+ describe "#deprecated_option" do
+ it "allows specifying deprecated options" do
+ subject.deprecated_option("foo" => "bar")
+ expect(subject.deprecated_options).not_to be_empty
+ expect(subject.deprecated_options.first.old).to eq("foo")
+ expect(subject.deprecated_options.first.current).to eq("bar")
+ end
+
+ it "allows specifying deprecated options as a Hash from an Array/String to an Array/String" do
+ subject.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"])
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo1", "bar1"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo2", "bar1"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar2"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar3"))
+ end
+
+ it "raises an error when empty" do
+ expect {
+ subject.deprecated_option({})
+ }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe "#depends_on" do
+ it "allows specifying dependencies" do
+ subject.depends_on("foo")
+ expect(subject.deps.first.name).to eq("foo")
+ end
+
+ it "allows specifying optional dependencies" do
+ subject.depends_on "foo" => :optional
+ expect(subject).to have_defined_option("with-foo")
+ end
+
+ it "allows specifying recommended dependencies" do
+ subject.depends_on "bar" => :recommended
+ expect(subject).to have_defined_option("without-bar")
+ end
+ end
+
+ specify "explicit options override defaupt depends_on option description" do
+ subject.option("with-foo", "blah")
+ subject.depends_on("foo" => :optional)
+ expect(subject.options.first.description).to eq("blah")
+ end
+
+ describe "#patch" do
+ it "adds a patch" do
+ subject.patch(:p1, :DATA)
+ expect(subject.patches.count).to eq(1)
+ expect(subject.patches.first.strip).to eq(:p1)
+ end
+ end
+end
+
+describe HeadSoftwareSpec do
+ specify "#version" do
+ expect(subject.version).to eq(Version.create("HEAD"))
+ end
+
+ specify "#verify_download_integrity" do
+ expect(subject.verify_download_integrity(Object.new)).to be nil
+ end
+end
+
+describe BottleSpecification do
+ specify "#sha256" do
+ checksums = {
+ snow_leopard_32: "deadbeef" * 8,
+ snow_leopard: "faceb00c" * 8,
+ lion: "baadf00d" * 8,
+ mountain_lion: "8badf00d" * 8,
+ }
+
+ checksums.each_pair do |cat, digest|
+ subject.sha256(digest => cat)
+ end
+
+ checksums.each_pair do |cat, digest|
+ checksum, = subject.checksum_for(cat)
+ expect(Checksum.new(:sha256, digest)).to eq(checksum)
+ end
+ end
+
+ %w[root_url prefix cellar rebuild].each do |method|
+ specify "##{method}" do
+ object = Object.new
+ subject.public_send(method, object)
+ expect(subject.public_send(method)).to eq(object)
+ end
+ end
+end
diff --git a/Library/Homebrew/test/software_spec_test.rb b/Library/Homebrew/test/software_spec_test.rb
deleted file mode 100644
index 026265a4a..000000000
--- a/Library/Homebrew/test/software_spec_test.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-require "testing_env"
-require "software_spec"
-
-class SoftwareSpecTests < Homebrew::TestCase
- def setup
- super
- @spec = SoftwareSpec.new
- end
-
- def test_resource
- @spec.resource("foo") { url "foo-1.0" }
- assert @spec.resource_defined?("foo")
- end
-
- def test_raises_when_duplicate_resources_are_defined
- @spec.resource("foo") { url "foo-1.0" }
- assert_raises(DuplicateResourceError) do
- @spec.resource("foo") { url "foo-1.0" }
- end
- end
-
- def test_raises_when_accessing_missing_resources
- @spec.owner = Class.new do
- def name
- "test"
- end
-
- def full_name
- "test"
- end
-
- def tap
- "homebrew/core"
- end
- end.new
- assert_raises(ResourceMissingError) { @spec.resource("foo") }
- end
-
- def test_set_owner
- owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- @spec.owner = owner
- assert_equal owner, @spec.owner
- end
-
- def test_resource_owner
- @spec.resource("foo") { url "foo-1.0" }
- @spec.owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- assert_equal "some_name", @spec.name
- @spec.resources.each_value { |r| assert_equal @spec, r.owner }
- end
-
- def test_resource_without_version_receives_owners_version
- @spec.url("foo-42")
- @spec.resource("bar") { url "bar" }
- @spec.owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- assert_version_equal "42", @spec.resource("bar").version
- end
-
- def test_option
- @spec.option("foo")
- assert @spec.option_defined?("foo")
- end
-
- def test_option_raises_when_begins_with_dashes
- assert_raises(ArgumentError) { @spec.option("--foo") }
- end
-
- def test_option_raises_when_name_empty
- assert_raises(ArgumentError) { @spec.option("") }
- end
-
- def test_cxx11_option_special_case
- @spec.option(:cxx11)
- assert @spec.option_defined?("c++11")
- refute @spec.option_defined?("cxx11")
- end
-
- def test_option_description
- @spec.option("bar", "description")
- assert_equal "description", @spec.options.first.description
- end
-
- def test_option_description_defaults_to_empty_string
- @spec.option("foo")
- assert_equal "", @spec.options.first.description
- end
-
- def test_deprecated_option
- @spec.deprecated_option("foo" => "bar")
- refute_empty @spec.deprecated_options
- assert_equal "foo", @spec.deprecated_options.first.old
- assert_equal "bar", @spec.deprecated_options.first.current
- end
-
- def test_deprecated_options
- @spec.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"])
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo1", "bar1")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo2", "bar1")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar2")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar3")
- end
-
- def test_deprecated_option_raises_when_empty
- assert_raises(ArgumentError) { @spec.deprecated_option({}) }
- end
-
- def test_depends_on
- @spec.depends_on("foo")
- assert_equal "foo", @spec.deps.first.name
- end
-
- def test_dependency_option_integration
- @spec.depends_on "foo" => :optional
- @spec.depends_on "bar" => :recommended
- assert @spec.option_defined?("with-foo")
- assert @spec.option_defined?("without-bar")
- end
-
- def test_explicit_options_override_default_dep_option_description
- @spec.option("with-foo", "blah")
- @spec.depends_on("foo" => :optional)
- assert_equal "blah", @spec.options.first.description
- end
-
- def test_patch
- @spec.patch :p1, :DATA
- assert_equal 1, @spec.patches.length
- assert_equal :p1, @spec.patches.first.strip
- end
-end
-
-class HeadSoftwareSpecTests < Homebrew::TestCase
- def setup
- super
- @spec = HeadSoftwareSpec.new
- end
-
- def test_version
- assert_version_equal "HEAD", @spec.version
- end
-
- def test_verify_download_integrity
- assert_nil @spec.verify_download_integrity(Object.new)
- end
-end
-
-class BottleSpecificationTests < Homebrew::TestCase
- def setup
- super
- @spec = BottleSpecification.new
- end
-
- def test_checksum_setters
- checksums = {
- snow_leopard_32: "deadbeef"*8,
- snow_leopard: "faceb00c"*8,
- lion: "baadf00d"*8,
- mountain_lion: "8badf00d"*8,
- }
-
- checksums.each_pair do |cat, digest|
- @spec.sha256(digest => cat)
- end
-
- checksums.each_pair do |cat, digest|
- checksum, = @spec.checksum_for(cat)
- assert_equal Checksum.new(:sha256, digest), checksum
- end
- end
-
- def test_other_setters
- double = Object.new
- %w[root_url prefix cellar rebuild].each do |method|
- @spec.send(method, double)
- assert_equal double, @spec.send(method)
- end
- end
-end