diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 81a52f474402b275054cf45ea456c0184a1274c7..11c1a6c5948dbeab7ff39673fa7c7fd326161002 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -207,6 +207,7 @@ case "$HOMEBREW_COMMAND" in up) HOMEBREW_COMMAND="update" ;; ln) HOMEBREW_COMMAND="link" ;; instal) HOMEBREW_COMMAND="install" ;; # gem does the same + uninstal) HOMEBREW_COMMAND="uninstall" ;; rm) HOMEBREW_COMMAND="uninstall" ;; remove) HOMEBREW_COMMAND="uninstall" ;; configure) HOMEBREW_COMMAND="diy" ;; diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 73ab121d2dbf0f9c8855ae9cc9f9d9d88c7d20cb..8e178e3737e7890e2da2004c65ac82785e313cfc 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -37,6 +37,7 @@ module Hbc "-S" => "search", # verb starting with "-" is questionable "up" => "update", "instal" => "install", # gem does the same + "uninstal" => "uninstall", "rm" => "uninstall", "remove" => "uninstall", "abv" => "info", diff --git a/Library/Homebrew/cask/lib/hbc/macos.rb b/Library/Homebrew/cask/lib/hbc/macos.rb index 5c1515d0c7bdd93939dacca54328285f612e73ea..d47e04fb246f7424c02b106f9483fb92077f6cc7 100644 --- a/Library/Homebrew/cask/lib/hbc/macos.rb +++ b/Library/Homebrew/cask/lib/hbc/macos.rb @@ -181,6 +181,7 @@ module OS "/usr/include", "/usr/lib", "/usr/libexec", + "/usr/libexec/cups", "/usr/local", "/usr/local/Cellar", "/usr/local/Frameworks", diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index ea2daf1c42565507b4c40e6cdb0b18af9c89a1b0..bfe9c777674112b77dd04b2d9f354d5dbc80d7ed 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -80,7 +80,8 @@ module Homebrew def fetch_pull_requests(formula) GitHub.issues_for_formula(formula.name, tap: formula.tap).select do |pr| - pr["html_url"].include?("/pull/") + pr["html_url"].include?("/pull/") && + /(^|\s)#{Regexp.quote(formula.name)}(:|\s|$)/i =~ pr["title"] end rescue GitHub::RateLimitExceededError => e opoo e.message diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index 244fbe0270cb9b3ae86b859f49851ab39420d6f4..6276d1c1b7f22e945f6f8764f439a61262a3632a 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -57,9 +57,7 @@ module Homebrew ENV["SEED"] = ARGV.next if ARGV.include? "--seed" files = Dir.glob("test/**/*_{spec,test}.rb") - .reject { |p| !OS.mac? && p.start_with?("test/os/mac/") } - .reject { |p| !OS.mac? && p.start_with?("test/cask/") } - .reject { |p| p.start_with?("test/vendor/bundle/") } + .reject { |p| !OS.mac? && p =~ %r{^test/(os/mac|cask)(/.*|_(test|spec)\.rb)$} } test_args = [] test_args << "--trace" if ARGV.include? "--trace" @@ -84,6 +82,8 @@ module Homebrew "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", "tmp/parallel_runtime_rspec.log" ] + spec_args << "--tag" << "~needs_macos" unless OS.mac? + run_tests "parallel_rspec", spec_files, spec_args if (fs_leak_log = HOMEBREW_LIBRARY_PATH/"tmp/fs_leak.log").file? diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index 7b468574ad30a689fafa723c5ec622faf8870fe6..3b07e0a71ae87e661fc4ced04bd8e16378695585 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -269,7 +269,7 @@ module SharedEnvExtension # @private def gcc_version_formula(name) version = name[GNU_GCC_REGEXP, 1] - gcc_version_name = "gcc#{version.delete(".")}" + gcc_version_name = "gcc@#{version}" gcc = Formulary.factory("gcc") if gcc.version_suffix == version @@ -286,7 +286,6 @@ module SharedEnvExtension rescue FormulaUnavailableError => e raise <<-EOS.undent Homebrew GCC requested, but formula #{e.name} not found! - You may need to: brew tap homebrew/versions EOS end diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index f44a97b31d0eab0eb1aa7daf120c658ef0b0ebd1..476e5da4a472d107d8ef1fecfe4e5123dfff9245 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/extend/os/mac/requirements/java_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb index 451e0001b5efefdf66e00c867333ddc59b7d81cf..5f989bb56e0b45a6a3a5370b2f06df41931502e8 100644 --- a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb +++ b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb @@ -1,4 +1,4 @@ -class JavaRequirement +class JavaRequirement < Requirement cask "java" env do diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index 34b766fde1a5156d9248849e15a9edb5be05a613..28c2a3be85fd37f4530ac75a80301cf47befe201 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -15,7 +15,6 @@ class FormulaVersions @repository = formula.tap.path @entry_name = @path.relative_path_from(repository).to_s @max_depth = options[:max_depth] - @current_formula = formula end def rev_list(branch) @@ -65,33 +64,25 @@ class FormulaVersions attributes.each do |attribute| attributes_map[attribute] ||= {} - # Set the attributes for the current formula in case it's not been - # committed yet. - set_attribute_map(attributes_map[attribute], @current_formula, attribute) end rev_list(branch) do |rev| formula_at_revision(rev) do |f| attributes.each do |attribute| - set_attribute_map(attributes_map[attribute], f, attribute) + map = attributes_map[attribute] + if f.stable + map[:stable] ||= {} + map[:stable][f.stable.version] ||= [] + map[:stable][f.stable.version] << f.send(attribute) + end + next unless f.devel + map[:devel] ||= {} + map[:devel][f.devel.version] ||= [] + map[:devel][f.devel.version] << f.send(attribute) end end end attributes_map end - - private - - def set_attribute_map(map, f, attribute) - if f.stable - map[:stable] ||= {} - map[:stable][f.stable.version] ||= [] - map[:stable][f.stable.version] << f.send(attribute) - end - return unless f.devel - map[:devel] ||= {} - map[:devel][f.devel.version] ||= [] - map[:devel][f.devel.version] << f.send(attribute) - end end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index cf85ba03f61db1dec58ce3dce1016f18e1be2c8d..4a65f87044e9332918bf557fe24828579db28c65 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -4,7 +4,7 @@ require "tap" # The Formulary is responsible for creating instances of Formula. # It is not meant to be used directly from formulae. -class Formulary +module Formulary FORMULAE = {} def self.formula_class_defined?(path) diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index 5e88947c9343eda38bd5d062cc82df898678ae3c..391f5b0121fda46d2583ecb31dc379f0b497d006 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -69,6 +69,7 @@ HOMEBREW_INTERNAL_COMMAND_ALIASES = { "up" => "update", "ln" => "link", "instal" => "install", # gem does the same + "uninstal" => "uninstall", "rm" => "uninstall", "remove" => "uninstall", "configure" => "diy", diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 17ff3bcef8fecb19cbe4c8209f005568b8f13dfd..94e3ff55bf5ff5978b111087d4c9515a254ef49b 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -239,6 +239,10 @@ class Keg def remove_opt_record opt_record.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 @@ -461,9 +465,20 @@ class Keg @oldname_opt_record = nil end + def aliases + Formula[rack.basename.to_s].aliases + rescue FormulaUnavailableError + [] + end + def optlink(mode = OpenStruct.new) opt_record.delete if opt_record.symlink? || opt_record.exist? make_relative_symlink(opt_record, path, mode) + aliases.each do |a| + alias_opt_record = opt_record.parent/a + alias_opt_record.delete if alias_opt_record.symlink? || alias_opt_record.exist? + make_relative_symlink(alias_opt_record, path, mode) + end return unless oldname_opt_record oldname_opt_record.delete diff --git a/Library/Homebrew/requirements/ruby_requirement.rb b/Library/Homebrew/requirements/ruby_requirement.rb index a890435a58389414924c7c9b28704b4ce90124e4..327c131708f459d2ba4db84dffe6a3f7a679f604 100644 --- a/Library/Homebrew/requirements/ruby_requirement.rb +++ b/Library/Homebrew/requirements/ruby_requirement.rb @@ -8,16 +8,14 @@ class RubyRequirement < Requirement super end - satisfy build_env: false do - which_all("ruby").detect do |ruby| - version = /\d\.\d/.match Utils.popen_read(ruby, "--version") - next unless version - Version.create(version.to_s) >= Version.create(@version) - end + satisfy(build_env: false) { new_enough_ruby } + + env do + ENV.prepend_path "PATH", new_enough_ruby end def message - s = "Ruby #{@version} is required to install this formula." + s = "Ruby >= #{@version} is required to install this formula." s += super s end @@ -33,4 +31,28 @@ class RubyRequirement < Requirement name end end + + private + + def new_enough_ruby + rubies.detect { |ruby| new_enough?(ruby) } + end + + def rubies + rubies = which_all("ruby") + ruby_formula = Formula["ruby"] + if ruby_formula && ruby_formula.installed? + rubies.unshift ruby_formula.bin/"ruby" + end + rubies.uniq + end + + def new_enough?(ruby) + version = Utils.popen_read(ruby, "-e", "print RUBY_VERSION").strip + version =~ /^\d+\.\d+/ && Version.create(version) >= min_version + end + + def min_version + @min_version ||= Version.create(@version) + end end diff --git a/Library/Homebrew/test/analytics_test.rb b/Library/Homebrew/test/analytics_test.rb deleted file mode 100644 index 37040f3cd8873fdafb75628173ad469bee244a2c..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/analytics_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestAnalytics < IntegrationCommandTestCase - def test_analytics - HOMEBREW_REPOSITORY.cd do - shutup do - system "git", "init" - end - end - - assert_match "Analytics is disabled (by HOMEBREW_NO_ANALYTICS)", - cmd("analytics", "HOMEBREW_NO_ANALYTICS" => "1") - - cmd("analytics", "off") - assert_match "Analytics is disabled", - cmd("analytics", "HOMEBREW_NO_ANALYTICS" => nil) - - cmd("analytics", "on") - assert_match "Analytics is enabled", cmd("analytics", - "HOMEBREW_NO_ANALYTICS" => nil) - - assert_match "Invalid usage", cmd_fail("analytics", "on", "off") - assert_match "Invalid usage", cmd_fail("analytics", "testball") - cmd("analytics", "regenerate-uuid") - end -end diff --git a/Library/Homebrew/test/blacklist_spec.rb b/Library/Homebrew/test/blacklist_spec.rb index 89d254893fcaeae9e87b199750306d8b66a3b46d..01882167deed9d9f449301adf91489d037503d85 100644 --- a/Library/Homebrew/test/blacklist_spec.rb +++ b/Library/Homebrew/test/blacklist_spec.rb @@ -1,12 +1,8 @@ require "blacklist" -RSpec::Matchers.define :be_blacklisted do - match do |actual| - blacklisted?(actual) - end -end - describe "Blacklist" do + matcher(:be_blacklisted) { match(&method(:blacklisted?)) } + context "rubygems" do %w[gem rubygem rubygems].each do |s| subject { s } @@ -103,9 +99,17 @@ describe "Blacklist" do it { is_expected.to be_blacklisted } end - context "haskell_platform" do + context "haskell-platform" do subject { "haskell-platform" } it { is_expected.to be_blacklisted } end + + context "xcode", :needs_macos do + %w[xcode Xcode].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end end diff --git a/Library/Homebrew/test/cmd/analytics_spec.rb b/Library/Homebrew/test/cmd/analytics_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..aed3a7a33747754d786fcc20c223828fe179b863 --- /dev/null +++ b/Library/Homebrew/test/cmd/analytics_spec.rb @@ -0,0 +1,52 @@ +describe "brew analytics", :integration_test do + before(:each) do + HOMEBREW_REPOSITORY.cd do + shutup do + system "git", "init" + end + end + end + + it "is disabled when HOMEBREW_NO_ANALYTICS is set" do + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => "1" } + .to output(/Analytics is disabled \(by HOMEBREW_NO_ANALYTICS\)/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + context "when HOMEBREW_NO_ANALYTICS is unset" do + it "is disabled after running `brew analytics off`" do + brew "analytics", "off" + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => nil } + .to output(/Analytics is disabled/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "is enabled after running `brew analytics on`" do + brew "analytics", "on" + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => nil } + .to output(/Analytics is enabled/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + + it "fails when running `brew analytics on off`" do + expect { brew "analytics", "on", "off" } + .to output(/Invalid usage/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails when running `brew analytics testball`" do + expect { brew "analytics", "testball" } + .to output(/Invalid usage/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "can generate a new UUID" do + expect { brew "analytics", "regenerate-uuid" }.to be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..99c2cc20b59a397c4cc043a64ac32de94237f70b --- /dev/null +++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb @@ -0,0 +1,19 @@ +require "cmd/search" + +describe Homebrew do + specify "#search_tap" do + json_response = { + "tree" => [ + { + "path" => "Formula/not-a-formula.rb", + "type" => "blob", + }, + ], + } + + allow(GitHub).to receive(:open).and_yield(json_response) + + expect(described_class.search_tap("homebrew", "not-a-tap", "not-a-formula")) + .to eq(["homebrew/not-a-tap/not-a-formula"]) + end +end diff --git a/Library/Homebrew/test/compiler_failure_spec.rb b/Library/Homebrew/test/compiler_failure_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b4fab0b2705278adc95e926fb6f2c5193a88d0b6 --- /dev/null +++ b/Library/Homebrew/test/compiler_failure_spec.rb @@ -0,0 +1,37 @@ +require "compilers" + +RSpec::Matchers.alias_matcher :fail_with, :be_fails_with + +describe CompilerFailure do + describe "::create" do + it "creates a failure when given a symbol" do + failure = described_class.create(:clang) + expect(failure).to fail_with(double("Compiler", name: :clang, version: 425)) + end + + it "can be given a build number in a block" do + failure = described_class.create(:clang) { build 211 } + expect(failure).to fail_with(double("Compiler", name: :clang, version: 210)) + expect(failure).not_to fail_with(double("Compiler", name: :clang, version: 318)) + end + + it "can be given an empty block" do + failure = described_class.create(:clang) {} + expect(failure).to fail_with(double("Compiler", name: :clang, version: 425)) + end + + it "creates a failure when given a hash" do + failure = described_class.create(gcc: "4.8") + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8")) + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.1")) + expect(failure).not_to fail_with(double("Compiler", name: "gcc-4.7", version: "4.7")) + end + + it "creates a failure when given a hash and a block with aversion" do + failure = described_class.create(gcc: "4.8") { version "4.8.1" } + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8")) + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.1")) + expect(failure).not_to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.2")) + end + end +end diff --git a/Library/Homebrew/test/compiler_failure_test.rb b/Library/Homebrew/test/compiler_failure_test.rb deleted file mode 100644 index c0b74d1282266ccb6da6ec2eb33a93cb4e2f578b..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/compiler_failure_test.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "testing_env" -require "compilers" - -class CompilerFailureTests < Homebrew::TestCase - Compiler = Struct.new(:name, :version) - - def assert_fails_with(compiler, failure) - assert_operator failure, :fails_with?, compiler - end - - def refute_fails_with(compiler, failure) - refute_operator failure, :fails_with?, compiler - end - - def compiler(name, version) - Compiler.new(name, version) - end - - def create(spec, &block) - CompilerFailure.create(spec, &block) - end - - def test_create_with_symbol - failure = create(:clang) - assert_fails_with compiler(:clang, 425), failure - end - - def test_create_with_block - failure = create(:clang) { build 211 } - assert_fails_with compiler(:clang, 210), failure - refute_fails_with compiler(:clang, 318), failure - end - - def test_create_with_block_without_build - failure = create(:clang) {} - assert_fails_with compiler(:clang, 425), failure - end - - def test_create_with_hash - failure = create(gcc: "4.8") - assert_fails_with compiler("gcc-4.8", "4.8"), failure - assert_fails_with compiler("gcc-4.8", "4.8.1"), failure - refute_fails_with compiler("gcc-4.7", "4.7"), failure - end - - def test_create_with_hash_and_version - failure = create(gcc: "4.8") { version "4.8.1" } - assert_fails_with compiler("gcc-4.8", "4.8"), failure - assert_fails_with compiler("gcc-4.8", "4.8.1"), failure - refute_fails_with compiler("gcc-4.8", "4.8.2"), failure - end -end diff --git a/Library/Homebrew/test/compiler_selector_spec.rb b/Library/Homebrew/test/compiler_selector_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..0f6f6b5f244c22b93d3f567d0f4f0444158464ee --- /dev/null +++ b/Library/Homebrew/test/compiler_selector_spec.rb @@ -0,0 +1,122 @@ +require "compilers" +require "software_spec" + +describe CompilerSelector do + subject { described_class.new(software_spec, versions, compilers) } + let(:compilers) { [:clang, :gcc, :llvm, :gnu] } + let(:software_spec) { SoftwareSpec.new } + let(:cc) { :clang } + let(:versions) do + double( + gcc_4_0_build_version: Version::NULL, + gcc_build_version: Version.create("5666"), + llvm_build_version: Version::NULL, + clang_build_version: Version.create("425"), + ) + end + + before(:each) do + allow(versions).to receive(:non_apple_gcc_version) do |name| + case name + when "gcc-4.8" then Version.create("4.8.1") + when "gcc-4.7" then Version.create("4.7.1") + else Version::NULL + end + end + end + + describe "#compiler" do + it "raises an error if no matching compiler can be found" do + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + software_spec.fails_with(:gcc) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + + it "defaults to cc" do + expect(subject.compiler).to eq(cc) + end + + it "returns gcc if it fails with clang" do + software_spec.fails_with(:clang) + expect(subject.compiler).to eq(:gcc) + end + + it "returns clang if it fails with llvm" do + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:clang) + end + + it "returns clang if it fails with gcc" do + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq(:clang) + end + + it "returns clang if it fails with non-Apple gcc" do + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq(:clang) + end + + it "still returns gcc-4.8 if it fails with gcc without a specific version" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq("gcc-4.8") + end + + it "returns gcc if it fails with clang and llvm" do + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:gcc) + end + + it "returns clang if it fails with gcc and llvm" do + software_spec.fails_with(:gcc) + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:clang) + end + + example "returns gcc if it fails with a specific gcc version" do + software_spec.fails_with(:clang) + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq(:gcc) + end + + example "returns a lower version of gcc if it fails with the highest version" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + software_spec.fails_with(:llvm) + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq("gcc-4.7") + end + + it "prefers gcc" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq("gcc-4.8") + end + + it "raises an error when gcc is missing" do + allow(versions).to receive(:gcc_build_version).and_return(Version::NULL) + + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + + it "raises an error when llvm and gcc are missing" do + allow(versions).to receive(:gcc_build_version).and_return(Version::NULL) + + software_spec.fails_with(:clang) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + end +end diff --git a/Library/Homebrew/test/compiler_selector_test.rb b/Library/Homebrew/test/compiler_selector_test.rb deleted file mode 100644 index aa1a6f97ec44eef515975594a27a8b495382a9bd..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/compiler_selector_test.rb +++ /dev/null @@ -1,117 +0,0 @@ -require "testing_env" -require "compilers" -require "software_spec" - -class CompilerSelectorTests < Homebrew::TestCase - class Double < SoftwareSpec - def <<(cc) - fails_with(cc) - self - end - end - - class CompilerVersions - attr_accessor :gcc_4_0_build_version, :gcc_build_version, - :clang_build_version - - def initialize - @gcc_4_0_build_version = Version::NULL - @gcc_build_version = Version.create("5666") - @llvm_build_version = Version::NULL - @clang_build_version = Version.create("425") - end - - def non_apple_gcc_version(name) - case name - when "gcc-4.8" then Version.create("4.8.1") - when "gcc-4.7" then Version.create("4.7.1") - else Version::NULL - end - end - end - - def setup - super - @f = Double.new - @cc = :clang - @versions = CompilerVersions.new - @selector = CompilerSelector.new( - @f, @versions, [:clang, :gcc, :llvm, :gnu] - ) - end - - def actual_cc - @selector.compiler - end - - def test_all_compiler_failures - @f << :clang << :llvm << :gcc << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end - - def test_no_compiler_failures - assert_equal @cc, actual_cc - end - - def test_fails_with_clang - @f << :clang - assert_equal :gcc, actual_cc - end - - def test_fails_with_llvm - @f << :llvm - assert_equal :clang, actual_cc - end - - def test_fails_with_gcc - @f << :gcc - assert_equal :clang, actual_cc - end - - def test_fails_with_non_apple_gcc - @f << { gcc: "4.8" } - assert_equal :clang, actual_cc - end - - def test_mixed_failures_1 - @f << :clang << :gcc - assert_equal "gcc-4.8", actual_cc - end - - def test_mixed_failures_2 - @f << :clang << :llvm - assert_equal :gcc, actual_cc - end - - def test_mixed_failures_3 - @f << :gcc << :llvm - assert_equal :clang, actual_cc - end - - def test_mixed_failures_4 - @f << :clang << { gcc: "4.8" } - assert_equal :gcc, actual_cc - end - - def test_mixed_failures_5 - @f << :clang << :gcc << :llvm << { gcc: "4.8" } - assert_equal "gcc-4.7", actual_cc - end - - def test_gcc_precedence - @f << :clang << :gcc - assert_equal "gcc-4.8", actual_cc - end - - def test_missing_gcc - @versions.gcc_build_version = Version::NULL - @f << :clang << :llvm << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end - - def test_missing_llvm_and_gcc - @versions.gcc_build_version = Version::NULL - @f << :clang << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end -end diff --git a/Library/Homebrew/test/dependency_expansion_spec.rb b/Library/Homebrew/test/dependency_expansion_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f955237a971752f67268f93826a201535558fc6e --- /dev/null +++ b/Library/Homebrew/test/dependency_expansion_spec.rb @@ -0,0 +1,136 @@ +require "dependency" + +describe Dependency do + def build_dep(name, tags = [], deps = []) + dep = described_class.new(name.to_s, tags) + allow(dep).to receive(:to_formula).and_return(double(deps: deps, name: name)) + dep + end + + let(:foo) { build_dep(:foo) } + let(:bar) { build_dep(:bar) } + let(:baz) { build_dep(:baz) } + let(:qux) { build_dep(:qux) } + let(:deps) { [foo, bar, baz, qux] } + let(:formula) { double(deps: deps, name: "f") } + + describe "::expand" do + it "yields dependent and dependency pairs" do + i = 0 + described_class.expand(formula) do |dependent, dep| + expect(dependent).to eq(formula) + expect(deps[i]).to eq(dep) + i += 1 + end + end + + it "returns the dependencies" do + expect(described_class.expand(formula)).to eq(deps) + end + + it "prunes all when given a block with ::prune" do + expect(described_class.expand(formula) { described_class.prune }).to be_empty + end + + it "can prune selectively" do + deps = described_class.expand(formula) do |_, dep| + described_class.prune if dep.name == "foo" + end + + expect(deps).to eq([bar, baz, qux]) + end + + it "preserves dependency order" do + allow(foo).to receive(:to_formula).and_return(double(name: "f", deps: [qux, baz])) + expect(described_class.expand(formula)).to eq([qux, baz, foo, bar]) + end + end + + it "skips optionals by default" do + deps = [build_dep(:foo, [:optional]), bar, baz, qux] + f = double(deps: deps, build: double(with?: false), name: "f") + expect(described_class.expand(f)).to eq([bar, baz, qux]) + end + + it "keeps recommended dependencies by default" do + deps = [build_dep(:foo, [:recommended]), bar, baz, qux] + f = double(deps: deps, build: double(with?: true), name: "f") + expect(described_class.expand(f)).to eq(deps) + end + + it "merges repeated dependencies with differing options" do + foo2 = build_dep(:foo, ["option"]) + baz2 = build_dep(:baz, ["option"]) + deps << foo2 << baz2 + deps = [foo2, bar, baz2, qux] + deps.zip(described_class.expand(formula)) do |expected, actual| + expect(expected.tags).to eq(actual.tags) + expect(expected).to eq(actual) + end + end + + it "merges dependencies and perserves env_proc" do + env_proc = double + dep = described_class.new("foo", [], env_proc) + allow(dep).to receive(:to_formula).and_return(double(deps: [], name: "foo")) + deps.replace([dep]) + expect(described_class.expand(formula).first.env_proc).to eq(env_proc) + end + + it "merges tags without duplicating them" do + foo2 = build_dep(:foo, ["option"]) + foo3 = build_dep(:foo, ["option"]) + deps << foo2 << foo3 + + expect(described_class.expand(formula).first.tags).to eq(%w[option]) + end + + it "skips parent but yields children with ::skip" do + f = double( + name: "f", + deps: [ + build_dep(:foo, [], [bar, baz]), + build_dep(:foo, [], [baz]), + ], + ) + + deps = described_class.expand(f) do |_dependent, dep| + described_class.skip if %w[foo qux].include? dep.name + end + + expect(deps).to eq([bar, baz]) + end + + it "keeps dependency but prunes recursive dependencies with ::keep_but_prune_recursive_deps" do + foo = build_dep(:foo, [:build], bar) + baz = build_dep(:baz, [:build]) + f = double(name: "f", deps: [foo, baz]) + + deps = described_class.expand(f) do |_dependent, dep| + described_class.keep_but_prune_recursive_deps if dep.build? + end + + expect(deps).to eq([foo, baz]) + end + + it "returns only the dependencies given as a collection as second argument" do + expect(formula.deps).to eq([foo, bar, baz, qux]) + expect(described_class.expand(formula, [bar, baz])).to eq([bar, baz]) + end + + it "doesn't raise an error when a dependency is cyclic" do + foo = build_dep(:foo) + bar = build_dep(:bar, [], [foo]) + allow(foo).to receive(:to_formula).and_return(double(deps: [bar], name: foo.name)) + f = double(name: "f", deps: [foo, bar]) + expect { described_class.expand(f) }.not_to raise_error + end + + it "cleans the expand stack" do + foo = build_dep(:foo) + allow(foo).to receive(:to_formula).and_raise(FormulaUnavailableError, foo.name) + f = double(name: "f", deps: [foo]) + expect { described_class.expand(f) }.to raise_error(FormulaUnavailableError) + expect(described_class.instance_variable_get(:@expand_stack)).to be_empty + end +end diff --git a/Library/Homebrew/test/dependency_expansion_test.rb b/Library/Homebrew/test/dependency_expansion_test.rb deleted file mode 100644 index 58a731121345ba9721fa9cd52c6598b2dd3b9b40..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/dependency_expansion_test.rb +++ /dev/null @@ -1,138 +0,0 @@ -require "testing_env" -require "dependency" - -class DependencyExpansionTests < Homebrew::TestCase - def build_dep(name, tags = [], deps = []) - dep = Dependency.new(name.to_s, tags) - dep.stubs(:to_formula).returns(stub(deps: deps, name: name)) - dep - end - - def setup - super - @foo = build_dep(:foo) - @bar = build_dep(:bar) - @baz = build_dep(:baz) - @qux = build_dep(:qux) - @deps = [@foo, @bar, @baz, @qux] - @f = stub(deps: @deps, name: "f") - end - - def test_expand_yields_dependent_and_dep_pairs - i = 0 - Dependency.expand(@f) do |dependent, dep| - assert_equal @f, dependent - assert_equal dep, @deps[i] - i += 1 - end - end - - def test_expand_no_block - assert_equal @deps, Dependency.expand(@f) - end - - def test_expand_prune_all - assert_empty Dependency.expand(@f) { Dependency.prune } - end - - def test_expand_selective_pruning - deps = Dependency.expand(@f) do |_, dep| - Dependency.prune if dep.name == "foo" - end - - assert_equal [@bar, @baz, @qux], deps - end - - def test_expand_preserves_dependency_order - @foo.stubs(:to_formula).returns(stub(name: "f", deps: [@qux, @baz])) - assert_equal [@qux, @baz, @foo, @bar], Dependency.expand(@f) - end - - def test_expand_skips_optionals_by_default - deps = [build_dep(:foo, [:optional]), @bar, @baz, @qux] - f = stub(deps: deps, build: stub(with?: false), name: "f") - assert_equal [@bar, @baz, @qux], Dependency.expand(f) - end - - def test_expand_keeps_recommendeds_by_default - deps = [build_dep(:foo, [:recommended]), @bar, @baz, @qux] - f = stub(deps: deps, build: stub(with?: true), name: "f") - assert_equal deps, Dependency.expand(f) - end - - def test_merges_repeated_deps_with_differing_options - @foo2 = build_dep(:foo, ["option"]) - @baz2 = build_dep(:baz, ["option"]) - @deps << @foo2 << @baz2 - deps = [@foo2, @bar, @baz2, @qux] - deps.zip(Dependency.expand(@f)) do |expected, actual| - assert_equal expected.tags, actual.tags - assert_equal expected, actual - end - end - - def test_merger_preserves_env_proc - env_proc = stub - dep = Dependency.new("foo", [], env_proc) - dep.stubs(:to_formula).returns(stub(deps: [], name: "foo")) - @deps.replace [dep] - assert_equal env_proc, Dependency.expand(@f).first.env_proc - end - - def test_merged_tags_no_dupes - @foo2 = build_dep(:foo, ["option"]) - @foo3 = build_dep(:foo, ["option"]) - @deps << @foo2 << @foo3 - - assert_equal %w[option], Dependency.expand(@f).first.tags - end - - def test_skip_skips_parent_but_yields_children - f = stub( - name: "f", - deps: [ - build_dep(:foo, [], [@bar, @baz]), - build_dep(:foo, [], [@baz]), - ], - ) - - deps = Dependency.expand(f) do |_dependent, dep| - Dependency.skip if %w[foo qux].include? dep.name - end - - assert_equal [@bar, @baz], deps - end - - def test_keep_dep_but_prune_recursive_deps - foo = build_dep(:foo, [:build], @bar) - baz = build_dep(:baz, [:build]) - f = stub(name: "f", deps: [foo, baz]) - - deps = Dependency.expand(f) do |_dependent, dep| - Dependency.keep_but_prune_recursive_deps if dep.build? - end - - assert_equal [foo, baz], deps - end - - def test_deps_with_collection_argument - assert_equal [@foo, @bar, @baz, @qux], @f.deps - assert_equal [@bar, @baz], Dependency.expand(@f, [@bar, @baz]) - end - - def test_cyclic_dependency - foo = build_dep(:foo) - bar = build_dep(:bar, [], [foo]) - foo.stubs(:to_formula).returns(stub(deps: [bar], name: "foo")) - f = stub(name: "f", deps: [foo, bar]) - assert_nothing_raised { Dependency.expand(f) } - end - - def test_clean_expand_stack - foo = build_dep(:foo) - foo.stubs(:to_formula).raises(FormulaUnavailableError, "foo") - f = stub(name: "f", deps: [foo]) - assert_raises(FormulaUnavailableError) { Dependency.expand(f) } - assert_empty Dependency.instance_variable_get(:@expand_stack) - end -end diff --git a/Library/Homebrew/test/diagnostic_spec.rb b/Library/Homebrew/test/diagnostic_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..e749a3b0f488af2dcfbd0f407bed945b57886814 --- /dev/null +++ b/Library/Homebrew/test/diagnostic_spec.rb @@ -0,0 +1,188 @@ +require "diagnostic" + +describe Homebrew::Diagnostic::Checks do + specify "#inject_file_list" do + expect(subject.inject_file_list([], "foo:\n")).to eq("foo:\n") + expect(subject.inject_file_list(%w[/a /b], "foo:\n")).to eq("foo:\n /a\n /b\n") + end + + specify "#check_path_for_trailing_slashes" do + ENV["PATH"] += File::PATH_SEPARATOR + "/foo/bar/" + expect(subject.check_path_for_trailing_slashes) + .to match("Some directories in your path end in a slash") + end + + specify "#check_for_anaconda" do + Dir.mktmpdir do |path| + anaconda = "#{path}/anaconda" + python = "#{path}/python" + FileUtils.touch anaconda + File.open(python, "w") do |file| + file.write("#! #{`which bash`}\necho -n '#{python}'\n") + end + FileUtils.chmod 0755, anaconda + FileUtils.chmod 0755, python + + ENV["PATH"] = path + File::PATH_SEPARATOR + ENV["PATH"] + + expect(subject.check_for_anaconda).to match("Anaconda") + end + end + + specify "#check_access_homebrew_repository" do + begin + mode = HOMEBREW_REPOSITORY.stat.mode & 0777 + HOMEBREW_REPOSITORY.chmod 0555 + + expect(subject.check_access_homebrew_repository) + .to match("#{HOMEBREW_REPOSITORY} is not writable.") + ensure + HOMEBREW_REPOSITORY.chmod mode + end + end + + specify "#check_access_logs" do + begin + mode = HOMEBREW_LOGS.stat.mode & 0777 + HOMEBREW_LOGS.chmod 0555 + + expect(subject.check_access_logs) + .to match("#{HOMEBREW_LOGS} isn't writable.") + ensure + HOMEBREW_LOGS.chmod mode + end + end + + specify "#check_access_cache" do + begin + mode = HOMEBREW_CACHE.stat.mode & 0777 + HOMEBREW_CACHE.chmod 0555 + expect(subject.check_access_cache) + .to match("#{HOMEBREW_CACHE} isn't writable.") + ensure + HOMEBREW_CACHE.chmod mode + end + end + + specify "#check_access_cellar" do + begin + mode = HOMEBREW_CELLAR.stat.mode & 0777 + HOMEBREW_CELLAR.chmod 0555 + + expect(subject.check_access_cellar) + .to match("#{HOMEBREW_CELLAR} isn't writable.") + ensure + HOMEBREW_CELLAR.chmod mode + end + end + + specify "#check_homebrew_prefix" do + ENV.delete("JENKINS_HOME") + # the integration tests are run in a special prefix + expect(subject.check_homebrew_prefix) + .to match("Your Homebrew's prefix is not /usr/local.") + end + + specify "#check_user_path_1" do + bin = HOMEBREW_PREFIX/"bin" + sep = File::PATH_SEPARATOR + # ensure /usr/bin is before HOMEBREW_PREFIX/bin in the PATH + ENV["PATH"] = "/usr/bin#{sep}#{bin}#{sep}" + + ENV["PATH"].gsub(%r{(?:^|#{sep})(?:/usr/bin|#{bin})}, "") + + # ensure there's at least one file with the same name in both /usr/bin/ and + # HOMEBREW_PREFIX/bin/ + (bin/File.basename(Dir["/usr/bin/*"].first)).mkpath + + expect(subject.check_user_path_1) + .to match("/usr/bin occurs before #{HOMEBREW_PREFIX}/bin") + end + + specify "#check_user_path_2" do + ENV["PATH"] = ENV["PATH"].gsub \ + %r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}, "" + + expect(subject.check_user_path_1).to be nil + expect(subject.check_user_path_2) + .to match("Homebrew's bin was not found in your PATH.") + end + + specify "#check_user_path_3" do + begin + sbin = HOMEBREW_PREFIX/"sbin" + ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" + + ENV["PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "") + (sbin/"something").mkpath + + expect(subject.check_user_path_1).to be nil + expect(subject.check_user_path_2).to be nil + expect(subject.check_user_path_3) + .to match("Homebrew's sbin was not found in your PATH") + ensure + sbin.rmtree + end + end + + specify "#check_user_curlrc" do + Dir.mktmpdir do |path| + FileUtils.touch "#{path}/.curlrc" + ENV["CURL_HOME"] = path + + expect(subject.check_user_curlrc).to match("You have a curlrc file") + end + end + + specify "#check_for_config_scripts" do + Dir.mktmpdir do |path| + file = "#{path}/foo-config" + FileUtils.touch file + FileUtils.chmod 0755, file + ENV["PATH"] = "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" + + expect(subject.check_for_config_scripts) + .to match('"config" scripts exist') + end + end + + specify "#check_dyld_vars" do + ENV["DYLD_INSERT_LIBRARIES"] = "foo" + expect(subject.check_dyld_vars).to match("Setting DYLD_INSERT_LIBRARIES") + end + + specify "#check_for_symlinked_cellar" do + begin + HOMEBREW_CELLAR.rmtree + + Dir.mktmpdir do |path| + FileUtils.ln_s path, HOMEBREW_CELLAR + + expect(subject.check_for_symlinked_cellar).to match(path) + end + ensure + HOMEBREW_CELLAR.unlink + HOMEBREW_CELLAR.mkpath + end + end + + specify "#check_tmpdir" do + ENV["TMPDIR"] = "/i/don/t/exis/t" + expect(subject.check_tmpdir).to match("doesn't exist") + end + + specify "#check_for_external_cmd_name_conflict" do + Dir.mktmpdir do |path1| + Dir.mktmpdir do |path2| + [path1, path2].each do |path| + cmd = "#{path}/brew-foo" + FileUtils.touch cmd + FileUtils.chmod 0755, cmd + end + + ENV["PATH"] = [path1, path2, ENV["PATH"]].join File::PATH_SEPARATOR + + expect(subject.check_for_external_cmd_name_conflict) + .to match("brew-foo") + end + end + end +end diff --git a/Library/Homebrew/test/diagnostic_test.rb b/Library/Homebrew/test/diagnostic_test.rb deleted file mode 100644 index 7a1fb25f7930bc4a4f7c7b213fcc72342272d859..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/diagnostic_test.rb +++ /dev/null @@ -1,192 +0,0 @@ -require "testing_env" -require "fileutils" -require "pathname" -require "diagnostic" - -class DiagnosticChecksTest < Homebrew::TestCase - def setup - super - @checks = Homebrew::Diagnostic::Checks.new - end - - def test_inject_file_list - assert_equal "foo:\n", - @checks.inject_file_list([], "foo:\n") - assert_equal "foo:\n /a\n /b\n", - @checks.inject_file_list(%w[/a /b], "foo:\n") - end - - def test_check_path_for_trailing_slashes - ENV["PATH"] += File::PATH_SEPARATOR + "/foo/bar/" - assert_match "Some directories in your path end in a slash", - @checks.check_path_for_trailing_slashes - end - - def test_check_for_anaconda - mktmpdir do |path| - anaconda = "#{path}/anaconda" - python = "#{path}/python" - FileUtils.touch anaconda - File.open(python, "w") do |file| - file.write("#! #{`which bash`}\necho -n '#{python}'\n") - end - FileUtils.chmod 0755, anaconda - FileUtils.chmod 0755, python - - ENV["PATH"] = path + File::PATH_SEPARATOR + ENV["PATH"] - - assert_match "Anaconda", - @checks.check_for_anaconda - end - end - - def test_check_access_homebrew_repository - mod = HOMEBREW_REPOSITORY.stat.mode & 0777 - HOMEBREW_REPOSITORY.chmod 0555 - - assert_match "#{HOMEBREW_REPOSITORY} is not writable.", - @checks.check_access_homebrew_repository - ensure - HOMEBREW_REPOSITORY.chmod mod - end - - def test_check_access_logs - mod = HOMEBREW_LOGS.stat.mode & 0777 - HOMEBREW_LOGS.chmod 0555 - - assert_match "#{HOMEBREW_LOGS} isn't writable.", - @checks.check_access_logs - ensure - HOMEBREW_LOGS.chmod mod - end - - def test_check_access_cache - mod = HOMEBREW_CACHE.stat.mode & 0777 - HOMEBREW_CACHE.chmod 0555 - assert_match "#{HOMEBREW_CACHE} isn't writable.", - @checks.check_access_cache - ensure - HOMEBREW_CACHE.chmod mod - end - - def test_check_access_cellar - mod = HOMEBREW_CELLAR.stat.mode & 0777 - HOMEBREW_CELLAR.chmod 0555 - - assert_match "#{HOMEBREW_CELLAR} isn't writable.", - @checks.check_access_cellar - ensure - HOMEBREW_CELLAR.chmod mod - end - - def test_check_homebrew_prefix - ENV.delete("JENKINS_HOME") - # the integration tests are run in a special prefix - assert_match "Your Homebrew's prefix is not /usr/local.", - @checks.check_homebrew_prefix - end - - def test_check_user_path_usr_bin_before_homebrew - bin = HOMEBREW_PREFIX/"bin" - sep = File::PATH_SEPARATOR - # ensure /usr/bin is before HOMEBREW_PREFIX/bin in the PATH - ENV["PATH"] = "/usr/bin#{sep}#{bin}#{sep}" + - ENV["PATH"].gsub(%r{(?:^|#{sep})(?:/usr/bin|#{bin})}, "") - - # ensure there's at least one file with the same name in both /usr/bin/ and - # HOMEBREW_PREFIX/bin/ - (bin/File.basename(Dir["/usr/bin/*"].first)).mkpath - - assert_match "/usr/bin occurs before #{HOMEBREW_PREFIX}/bin", - @checks.check_user_path_1 - end - - def test_check_user_path_bin - ENV["PATH"] = ENV["PATH"].gsub \ - %r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}, "" - - assert_nil @checks.check_user_path_1 - assert_match "Homebrew's bin was not found in your PATH.", - @checks.check_user_path_2 - end - - def test_check_user_path_sbin - sbin = HOMEBREW_PREFIX/"sbin" - ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" + - ENV["PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "") - (sbin/"something").mkpath - - assert_nil @checks.check_user_path_1 - assert_nil @checks.check_user_path_2 - assert_match "Homebrew's sbin was not found in your PATH", - @checks.check_user_path_3 - ensure - sbin.rmtree - end - - def test_check_user_curlrc - mktmpdir do |path| - FileUtils.touch "#{path}/.curlrc" - ENV["CURL_HOME"] = path - - assert_match "You have a curlrc file", - @checks.check_user_curlrc - end - end - - def test_check_for_config_scripts - mktmpdir do |path| - file = "#{path}/foo-config" - FileUtils.touch file - FileUtils.chmod 0755, file - ENV["PATH"] = "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" - - assert_match '"config" scripts exist', - @checks.check_for_config_scripts - end - end - - def test_check_dyld_vars - ENV["DYLD_INSERT_LIBRARIES"] = "foo" - assert_match "Setting DYLD_INSERT_LIBRARIES", - @checks.check_dyld_vars - end - - def test_check_for_symlinked_cellar - HOMEBREW_CELLAR.rmtree - - mktmpdir do |path| - FileUtils.ln_s path, HOMEBREW_CELLAR - - assert_match path, - @checks.check_for_symlinked_cellar - end - - ensure - HOMEBREW_CELLAR.unlink - HOMEBREW_CELLAR.mkpath - end - - def test_check_tmpdir - ENV["TMPDIR"] = "/i/don/t/exis/t" - assert_match "doesn't exist", - @checks.check_tmpdir - end - - def test_check_for_external_cmd_name_conflict - mktmpdir do |path1| - mktmpdir do |path2| - [path1, path2].each do |path| - cmd = "#{path}/brew-foo" - FileUtils.touch cmd - FileUtils.chmod 0755, cmd - end - - ENV["PATH"] = [path1, path2, ENV["PATH"]].join File::PATH_SEPARATOR - - assert_match "brew-foo", - @checks.check_for_external_cmd_name_conflict - end - end - end -end diff --git a/Library/Homebrew/test/formula_lock_spec.rb b/Library/Homebrew/test/formula_lock_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..9b5ece8131157a737fb27044535216a7f3244db3 --- /dev/null +++ b/Library/Homebrew/test/formula_lock_spec.rb @@ -0,0 +1,34 @@ +require "formula_lock" + +describe FormulaLock do + subject { described_class.new("foo") } + + describe "#lock" do + it "does not raise an error when already locked" do + subject.lock + + expect { subject.lock }.not_to raise_error + end + + it "raises an error if a lock already exists" do + subject.lock + + expect { + described_class.new("foo").lock + }.to raise_error(OperationInProgressError) + end + end + + describe "#unlock" do + it "does not raise an error when already unlocked" do + expect { subject.unlock }.not_to raise_error + end + + it "unlocks a locked Formula" do + subject.lock + subject.unlock + + expect { described_class.new("foo").lock }.not_to raise_error + end + end +end diff --git a/Library/Homebrew/test/formula_lock_test.rb b/Library/Homebrew/test/formula_lock_test.rb deleted file mode 100644 index 13244555d08065a2f75cacc837a23bceb0f9d40c..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/formula_lock_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "testing_env" -require "formula_lock" - -class FormulaLockTests < Homebrew::TestCase - def setup - super - @lock = FormulaLock.new("foo") - @lock.lock - end - - def teardown - @lock.unlock - super - end - - def test_locking_file_with_existing_lock_raises_error - assert_raises(OperationInProgressError) { FormulaLock.new("foo").lock } - end - - def test_locking_existing_lock_suceeds - assert_nothing_raised { @lock.lock } - end -end diff --git a/Library/Homebrew/test/formula_pin_spec.rb b/Library/Homebrew/test/formula_pin_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..909bfbc2b3ee59262fd9f0a81f1566c17e1d416a --- /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 7e3c7efa0474cdf5cbd0260f57a02b0b3f7f2305..0000000000000000000000000000000000000000 --- 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/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8e9d2358961b74f7747a408723d0404c96ab679f --- /dev/null +++ b/Library/Homebrew/test/formulary_spec.rb @@ -0,0 +1,219 @@ +require "formula" +require "formula_installer" +require "utils/bottles" + +describe Formulary do + let(:formula_name) { "testball_bottle" } + let(:formula_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } + let(:formula_content) do + <<-EOS.undent + class #{subject.class_s(formula_name)} < Formula + url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" + sha256 TESTBALL_SHA256 + + bottle do + cellar :any_skip_relocation + root_url "file://#{bottle_dir}" + sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag} + end + + def install + prefix.install "bin" + prefix.install "libexec" + end + end + EOS + end + let(:bottle_dir) { Pathname.new("#{TEST_FIXTURE_DIR}/bottles") } + let(:bottle) { bottle_dir/"testball_bottle-0.1.#{Utils::Bottles.tag}.bottle.tar.gz" } + + describe "::class_s" do + it "replaces '+' with 'x'" do + expect(subject.class_s("foo++")).to eq("Fooxx") + end + + it "converts a string to PascalCase" do + expect(subject.class_s("shell.fm")).to eq("ShellFm") + expect(subject.class_s("s-lang")).to eq("SLang") + expect(subject.class_s("pkg-config")).to eq("PkgConfig") + expect(subject.class_s("foo_bar")).to eq("FooBar") + end + + it "replaces '@' with 'AT'" do + expect(subject.class_s("openssl@1.1")).to eq("OpensslAT11") + end + end + + describe "::factory" do + before(:each) do + formula_path.write formula_content + end + + it "returns a Formula" do + expect(subject.factory(formula_name)).to be_kind_of(Formula) + end + + it "returns a Formula when given a fully qualified name" do + expect(subject.factory("homebrew/core/#{formula_name}")).to be_kind_of(Formula) + end + + it "raises an error if the Formula cannot be found" do + expect { + subject.factory("not_existed_formula") + }.to raise_error(FormulaUnavailableError) + end + + context "if the Formula has the wrong class" do + let(:formula_name) { "giraffe" } + let(:formula_content) do + <<-EOS.undent + class Wrong#{subject.class_s(formula_name)} < Formula + end + EOS + end + + it "raises an error" do + expect { + subject.factory(formula_name) + }.to raise_error(FormulaClassUnavailableError) + end + end + + it "returns a Formula when given a path" do + expect(subject.factory(formula_path)).to be_kind_of(Formula) + end + + it "returns a Formula when given a URL" do + formula = shutup do + subject.factory("file://#{formula_path}") + end + + expect(formula).to be_kind_of(Formula) + end + + it "returns a Formula when given a bottle" do + formula = subject.factory(bottle) + expect(formula).to be_kind_of(Formula) + expect(formula.local_bottle_path).to eq(bottle.realpath) + end + + it "returns a Formula when given an alias" do + alias_dir = CoreTap.instance.alias_dir + alias_dir.mkpath + alias_path = alias_dir/"foo" + FileUtils.ln_s formula_path, alias_path + result = subject.factory("foo") + expect(result).to be_kind_of(Formula) + expect(result.alias_path).to eq(alias_path.to_s) + end + + context "with installed Formula" do + let(:formula) { subject.factory(formula_path) } + let(:installer) { FormulaInstaller.new(formula) } + + it "returns a Formula when given a rack" do + shutup do + installer.install + end + + f = subject.from_rack(formula.rack) + expect(f).to be_kind_of(Formula) + expect(f.build).to be_kind_of(Tab) + end + + it "returns a Formula when given a Keg" do + shutup do + installer.install + end + + keg = Keg.new(formula.prefix) + f = subject.from_keg(keg) + expect(f).to be_kind_of(Formula) + expect(f.build).to be_kind_of(Tab) + end + end + + context "from Tap" do + let(:tap) { Tap.new("homebrew", "foo") } + let(:formula_path) { tap.path/"#{formula_name}.rb" } + + it "returns a Formula when given a name" do + expect(subject.factory(formula_name)).to be_kind_of(Formula) + end + + it "returns a Formula from an Alias path" do + alias_dir = tap.path/"Aliases" + alias_dir.mkpath + FileUtils.ln_s formula_path, alias_dir/"bar" + expect(subject.factory("bar")).to be_kind_of(Formula) + end + + it "raises an error when the Formula cannot be found" do + expect { + subject.factory("#{tap}/not_existed_formula") + }.to raise_error(TapFormulaUnavailableError) + end + + it "returns a Formula when given a fully qualified name" do + expect(subject.factory("#{tap}/#{formula_name}")).to be_kind_of(Formula) + end + + it "raises an error if a Formula is in multiple Taps" do + begin + another_tap = Tap.new("homebrew", "bar") + (another_tap.path/"#{formula_name}.rb").write formula_content + expect { + subject.factory(formula_name) + }.to raise_error(TapFormulaAmbiguityError) + ensure + another_tap.path.rmtree + end + end + end + end + + specify "::from_contents" do + expect(subject.from_contents(formula_name, formula_path, formula_content)).to be_kind_of(Formula) + end + + specify "::to_rack" do + expect(subject.to_rack(formula_name)).to eq(HOMEBREW_CELLAR/formula_name) + + (HOMEBREW_CELLAR/formula_name).mkpath + expect(subject.to_rack(formula_name)).to eq(HOMEBREW_CELLAR/formula_name) + + expect { + subject.to_rack("a/b/#{formula_name}") + }.to raise_error(TapFormulaUnavailableError) + end + + describe "::find_with_priority" do + let(:core_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } + let(:tap) { Tap.new("homebrew", "foo") } + let(:tap_path) { tap.path/"#{formula_name}.rb" } + + before(:each) do + core_path.write formula_content + tap_path.write formula_content + end + + it "prioritizes core Formulae" do + formula = subject.find_with_priority(formula_name) + expect(formula).to be_kind_of(Formula) + expect(formula.path).to eq(core_path) + end + + it "prioritizes Formulae from pinned Taps" do + begin + tap.pin + formula = shutup do + subject.find_with_priority(formula_name) + end + expect(formula).to be_kind_of(Formula) + expect(formula.path).to eq(tap_path.realpath) + ensure + tap.pinned_symlink_path.parent.parent.rmtree + end + end + end +end diff --git a/Library/Homebrew/test/formulary_test.rb b/Library/Homebrew/test/formulary_test.rb deleted file mode 100644 index ea7ecf8d0569eb8b03396f63c597a6218e147759..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/formulary_test.rb +++ /dev/null @@ -1,189 +0,0 @@ -require "testing_env" -require "formula" -require "formula_installer" -require "utils/bottles" - -class FormularyTest < Homebrew::TestCase - def test_class_naming - assert_equal "ShellFm", Formulary.class_s("shell.fm") - assert_equal "Fooxx", Formulary.class_s("foo++") - assert_equal "SLang", Formulary.class_s("s-lang") - assert_equal "PkgConfig", Formulary.class_s("pkg-config") - assert_equal "FooBar", Formulary.class_s("foo_bar") - assert_equal "OpensslAT11", Formulary.class_s("openssl@1.1") - end -end - -class FormularyFactoryTest < Homebrew::TestCase - def setup - super - @name = "testball_bottle" - @path = CoreTap.new.formula_dir/"#{@name}.rb" - @bottle_dir = Pathname.new("#{TEST_FIXTURE_DIR}/bottles") - @bottle = @bottle_dir/"testball_bottle-0.1.#{Utils::Bottles.tag}.bottle.tar.gz" - @path.write <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" - sha256 TESTBALL_SHA256 - - bottle do - cellar :any_skip_relocation - root_url "file://#{@bottle_dir}" - sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag} - end - - def install - prefix.install "bin" - prefix.install "libexec" - end - end - EOS - end - - def test_factory - assert_kind_of Formula, Formulary.factory(@name) - end - - def test_factory_with_fully_qualified_name - assert_kind_of Formula, Formulary.factory("homebrew/core/#{@name}") - end - - def test_formula_unavailable_error - assert_raises(FormulaUnavailableError) { Formulary.factory("not_existed_formula") } - end - - def test_formula_class_unavailable_error - name = "giraffe" - path = CoreTap.new.formula_dir/"#{name}.rb" - path.write "class Wrong#{Formulary.class_s(name)} < Formula\nend\n" - - assert_raises(FormulaClassUnavailableError) { Formulary.factory(name) } - end - - def test_factory_from_path - assert_kind_of Formula, Formulary.factory(@path) - end - - def test_factory_from_url - formula = shutup { Formulary.factory("file://#{@path}") } - assert_kind_of Formula, formula - ensure - formula.path.unlink - end - - def test_factory_from_bottle - formula = Formulary.factory(@bottle) - assert_kind_of Formula, formula - assert_equal @bottle.realpath, formula.local_bottle_path - end - - def test_factory_from_alias - alias_dir = CoreTap.instance.alias_dir - alias_dir.mkpath - alias_path = alias_dir/"foo" - FileUtils.ln_s @path, alias_path - result = Formulary.factory("foo") - assert_kind_of Formula, result - assert_equal alias_path.to_s, result.alias_path - end - - def test_factory_from_rack_and_from_keg - formula = Formulary.factory(@path) - installer = FormulaInstaller.new(formula) - shutup { installer.install } - keg = Keg.new(formula.prefix) - f = Formulary.from_rack(formula.rack) - assert_kind_of Formula, f - assert_kind_of Tab, f.build - f = Formulary.from_keg(keg) - assert_kind_of Formula, f - assert_kind_of Tab, f.build - ensure - keg.unlink - end - - def test_load_from_contents - assert_kind_of Formula, Formulary.from_contents(@name, @path, @path.read) - end - - def test_to_rack - assert_equal HOMEBREW_CELLAR/@name, Formulary.to_rack(@name) - (HOMEBREW_CELLAR/@name).mkpath - assert_equal HOMEBREW_CELLAR/@name, Formulary.to_rack(@name) - assert_raises(TapFormulaUnavailableError) { Formulary.to_rack("a/b/#{@name}") } - end -end - -class FormularyTapFactoryTest < Homebrew::TestCase - def setup - super - @name = "foo" - @tap = Tap.new "homebrew", "foo" - @path = @tap.path/"#{@name}.rb" - @code = <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "foo-1.0" - end - EOS - @path.write @code - end - - def test_factory_tap_formula - assert_kind_of Formula, Formulary.factory(@name) - end - - def test_factory_tap_alias - alias_dir = @tap.path/"Aliases" - alias_dir.mkpath - FileUtils.ln_s @path, alias_dir/"bar" - assert_kind_of Formula, Formulary.factory("bar") - end - - def test_tap_formula_unavailable_error - assert_raises(TapFormulaUnavailableError) { Formulary.factory("#{@tap}/not_existed_formula") } - end - - def test_factory_tap_formula_with_fully_qualified_name - assert_kind_of Formula, Formulary.factory("#{@tap}/#{@name}") - end - - def test_factory_ambiguity_tap_formulae - another_tap = Tap.new "homebrew", "bar" - (another_tap.path/"#{@name}.rb").write @code - assert_raises(TapFormulaAmbiguityError) { Formulary.factory(@name) } - ensure - another_tap.path.rmtree - end -end - -class FormularyTapPriorityTest < Homebrew::TestCase - def setup - super - @name = "foo" - @core_path = CoreTap.new.formula_dir/"#{@name}.rb" - @tap = Tap.new "homebrew", "foo" - @tap_path = @tap.path/"#{@name}.rb" - code = <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "foo-1.0" - end - EOS - @core_path.write code - @tap_path.write code - end - - def test_find_with_priority_core_formula - formula = Formulary.find_with_priority(@name) - assert_kind_of Formula, formula - assert_equal @core_path, formula.path - end - - def test_find_with_priority_tap_formula - @tap.pin - formula = shutup { Formulary.find_with_priority(@name) } - assert_kind_of Formula, formula - assert_equal @tap_path.realpath, formula.path - ensure - @tap.pinned_symlink_path.parent.parent.rmtree - end -end diff --git a/Library/Homebrew/test/gpg2_requirement_spec.rb b/Library/Homebrew/test/gpg2_requirement_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f46b31196fbd09cad9fe954381600cf4df059fd3 --- /dev/null +++ b/Library/Homebrew/test/gpg2_requirement_spec.rb @@ -0,0 +1,23 @@ +require "requirements/gpg2_requirement" +require "fileutils" + +describe GPG2Requirement do + let(:dir) { @dir = Pathname.new(Dir.mktmpdir) } + + after(:each) do + FileUtils.rm_rf dir unless @dir.nil? + end + + describe "#satisfied?" do + it "returns true if GPG2 is installed" do + ENV["PATH"] = dir/"bin" + (dir/"bin/gpg").write <<-EOS.undent + #!/bin/bash + echo 2.0.30 + EOS + FileUtils.chmod 0755, dir/"bin/gpg" + + expect(subject).to be_satisfied + end + end +end diff --git a/Library/Homebrew/test/gpg2_requirement_test.rb b/Library/Homebrew/test/gpg2_requirement_test.rb deleted file mode 100644 index 3297c28512b39ef85eea42d33cc85ab11e6c9aa1..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/gpg2_requirement_test.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "testing_env" -require "requirements/gpg2_requirement" -require "fileutils" - -class GPG2RequirementTests < Homebrew::TestCase - def setup - super - @dir = Pathname.new(mktmpdir) - (@dir/"bin/gpg").write <<-EOS.undent - #!/bin/bash - echo 2.0.30 - EOS - FileUtils.chmod 0755, @dir/"bin/gpg" - end - - def teardown - FileUtils.rm_rf @dir - super - end - - def test_satisfied - ENV["PATH"] = @dir/"bin" - assert_predicate GPG2Requirement.new, :satisfied? - end -end diff --git a/Library/Homebrew/test/inreplace_spec.rb b/Library/Homebrew/test/inreplace_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5be44f50db8bf864f430b5aba3021cc7b2d43ef0 --- /dev/null +++ b/Library/Homebrew/test/inreplace_spec.rb @@ -0,0 +1,251 @@ +require "extend/string" +require "tempfile" +require "utils/inreplace" + +describe StringInreplaceExtension do + subject { string.extend(described_class) } + + describe "#change_make_var!" do + context "flag" do + context "with spaces" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + + it "is successfully appended" do + subject.change_make_var! "FLAG", "\\1 def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=abc def + FLAG2=abc + EOS + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "CFLAGS", "-O3" + expect(subject).to eq <<-EOS.undent + CFLAGS=-O3 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + end + end + + context "empty flag between other flags" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + end + + context "empty flag" do + let(:string) do + <<-EOS.undent + FLAG = + mv file_a file_b + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + FLAG=def + mv file_a file_b + EOS + end + end + + context "shell-style variable" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG=abc + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + end + end + + describe "#remove_make_var!" do + context "flag" do + context "with spaces" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2 = def + EOS + end + + it "is successfully removed" do + subject.remove_make_var! "FLAG" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG2 = def + EOS + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "is successfully removed" do + subject.remove_make_var! "LDFLAGS" + expect(subject).to eq <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + EOS + end + end + end + + context "multiple flags" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2 = def + OTHER2=def + EOS + end + + specify "are be successfully removed" do + subject.remove_make_var! ["FLAG", "FLAG2"] + expect(subject).to eq <<-EOS.undent + OTHER=def + OTHER2=def + EOS + end + end + end + + describe "#get_make_var" do + context "with spaces" do + let(:string) do + <<-EOS.undent + CFLAGS = -Wall -O2 + LDFLAGS = -lcrypto -lssl + EOS + end + + it "extracts the value for a given variable" do + expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "extracts the value for a given variable" do + expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + end + end + end + + describe "#sub!" do + let(:string) { "foo" } + + it "replaces the first occurence" do + subject.sub!("o", "e") + expect(subject).to eq("feo") + end + end + + describe "#gsub!" do + let(:string) { "foo" } + + it "replaces the all occurences" do + subject.gsub!("o", "e") # rubocop:disable Performance/StringReplacement + expect(subject).to eq("fee") + end + end +end + +describe Utils::Inreplace do + let(:file) { Tempfile.new("test") } + + before(:each) do + file.write <<-EOS.undent + a + b + c + EOS + end + + after(:each) { file.unlink } + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace file.path, "d", "f" + }.to raise_error(Utils::InreplaceError) + end + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace(file.path) do |s| + s.gsub!("d", "f") # rubocop:disable Performance/StringReplacement + end + }.to raise_error(Utils::InreplaceError) + end + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace(file.path) do |s| + s.change_make_var! "VAR", "value" + s.remove_make_var! "VAR2" + end + }.to raise_error(Utils::InreplaceError) + end +end diff --git a/Library/Homebrew/test/inreplace_test.rb b/Library/Homebrew/test/inreplace_test.rb deleted file mode 100644 index 0e62f9d3f9691ddcc93b8f48138db9bfe283f29e..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/inreplace_test.rb +++ /dev/null @@ -1,119 +0,0 @@ -require "testing_env" -require "extend/string" -require "utils/inreplace" - -class InreplaceTest < Homebrew::TestCase - def test_change_make_var - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_change_make_var_empty - # Replace empty flag - s1 = "OTHER=def\nFLAG = \nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_change_make_var_empty_2 - # Replace empty flag - s1 = "FLAG = \nmv file_a file_b" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "FLAG=def\nmv file_a file_b", s1 - end - - def test_change_make_var_append - # Append to flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "\\1 def" - assert_equal "OTHER=def\nFLAG=abc def\nFLAG2=abc", s1 - end - - def test_change_make_var_shell_style - # Shell variables have no spaces around = - s1 = "OTHER=def\nFLAG=abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_remove_make_var - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2 = def" - s1.extend(StringInreplaceExtension) - s1.remove_make_var! "FLAG" - assert_equal "OTHER=def\nFLAG2 = def", s1 - end - - def test_remove_make_vars - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2 = def\nOTHER2=def" - s1.extend(StringInreplaceExtension) - s1.remove_make_var! ["FLAG", "FLAG2"] - assert_equal "OTHER=def\nOTHER2=def", s1 - end - - def test_get_make_var - s = "CFLAGS = -Wall -O2\nLDFLAGS = -lcrypto -lssl" - s.extend(StringInreplaceExtension) - assert_equal "-Wall -O2", s.get_make_var("CFLAGS") - end - - def test_change_make_var_with_tabs - s = "CFLAGS\t=\t-Wall -O2\nLDFLAGS\t=\t-lcrypto -lssl" - s.extend(StringInreplaceExtension) - - assert_equal "-Wall -O2", s.get_make_var("CFLAGS") - - s.change_make_var! "CFLAGS", "-O3" - assert_equal "CFLAGS=-O3\nLDFLAGS\t=\t-lcrypto -lssl", s - - s.remove_make_var! "LDFLAGS" - assert_equal "CFLAGS=-O3\n", s - end - - def test_sub_gsub - s = "foo" - s.extend(StringInreplaceExtension) - - s.sub!("f", "b") - assert_equal "boo", s - - # Under current context, we are testing `String#gsub!`, so let's disable rubocop temporarily. - s.gsub!("o", "e") # rubocop:disable Performance/StringReplacement - assert_equal "bee", s - end - - def test_inreplace_errors - require "tempfile" - extend(Utils::Inreplace) - - file = Tempfile.new("test") - - file.write "a\nb\nc\n" - - assert_raises(Utils::InreplaceError) do - inreplace file.path, "d", "f" - end - - assert_raises(Utils::InreplaceError) do - # Under current context, we are testing `String#gsub!`, so let's disable rubocop temporarily. - inreplace(file.path) { |s| s.gsub!("d", "f") } # rubocop:disable Performance/StringReplacement - end - - assert_raises(Utils::InreplaceError) do - inreplace(file.path) do |s| - s.change_make_var! "VAR", "value" - s.remove_make_var! "VAR2" - end - end - ensure - file.unlink - end -end diff --git a/Library/Homebrew/test/java_requirement_spec.rb b/Library/Homebrew/test/java_requirement_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5adf64c7c2d943630b520f11ea3b21c2f5a4a69a --- /dev/null +++ b/Library/Homebrew/test/java_requirement_spec.rb @@ -0,0 +1,107 @@ +require "requirements/java_requirement" + +describe JavaRequirement do + subject { described_class.new([]) } + + before(:each) do + ENV["JAVA_HOME"] = nil + end + + describe "#message" do + its(:message) { is_expected.to match(/Java is required to install this formula./) } + end + + describe "#inspect" do + subject { described_class.new(%w[1.7+]) } + its(:inspect) { is_expected.to eq('#<JavaRequirement: "java" [] version="1.7+">') } + end + + describe "#display_s" do + context "without specific version" do + its(:display_s) { is_expected.to eq("java") } + end + + context "with version 1.8" do + subject { described_class.new(%w[1.8]) } + its(:display_s) { is_expected.to eq("java = 1.8") } + end + + context "with version 1.8+" do + subject { described_class.new(%w[1.8+]) } + its(:display_s) { is_expected.to eq("java >= 1.8") } + end + end + + describe "#satisfied?" do + subject { described_class.new(%w[1.8]) } + + it "returns false if no `java` executable can be found" do + allow(File).to receive(:executable?).and_return(false) + expect(subject).not_to be_satisfied + end + + it "returns true if #preferred_java returns a path" do + allow(subject).to receive(:preferred_java).and_return(Pathname.new("/usr/bin/java")) + expect(subject).to be_satisfied + end + + context "when #possible_javas contains paths" do + let(:path) { Pathname.new(Dir.mktmpdir) } + let(:java) { path/"java" } + + def setup_java_with_version(version) + IO.write java, <<-EOS.undent + #!/bin/sh + echo 'java version "#{version}"' + EOS + FileUtils.chmod "+x", java + end + + before(:each) do + allow(subject).to receive(:possible_javas).and_return([java]) + end + + after(:each) do + path.rmtree + end + + context "and 1.7 is required" do + subject { described_class.new(%w[1.7]) } + + it "returns false if all are lower" do + setup_java_with_version "1.6.0_5" + expect(subject).not_to be_satisfied + end + + it "returns true if one is equal" do + setup_java_with_version "1.7.0_5" + expect(subject).to be_satisfied + end + + it "returns false if all are higher" do + setup_java_with_version "1.8.0_5" + expect(subject).not_to be_satisfied + end + end + + context "and 1.7+ is required" do + subject { described_class.new(%w[1.7+]) } + + it "returns false if all are lower" do + setup_java_with_version "1.6.0_5" + expect(subject).not_to be_satisfied + end + + it "returns true if one is equal" do + setup_java_with_version "1.7.0_5" + expect(subject).to be_satisfied + end + + it "returns true if one is higher" do + setup_java_with_version "1.8.0_5" + expect(subject).to be_satisfied + end + end + end + end +end diff --git a/Library/Homebrew/test/java_requirement_test.rb b/Library/Homebrew/test/java_requirement_test.rb deleted file mode 100644 index d0b51f92cfe72357bb500af330b88119eee9b826..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/java_requirement_test.rb +++ /dev/null @@ -1,50 +0,0 @@ -require "testing_env" -require "requirements/java_requirement" - -class JavaRequirementTests < Homebrew::TestCase - def setup - super - ENV["JAVA_HOME"] = nil - end - - def test_message - a = JavaRequirement.new([]) - assert_match(/Java is required to install this formula./, a.message) - end - - def test_inspect - a = JavaRequirement.new(%w[1.7+]) - assert_equal a.inspect, '#<JavaRequirement: "java" [] version="1.7+">' - end - - def test_display_s - x = JavaRequirement.new([]) - assert_equal x.display_s, "java" - y = JavaRequirement.new(%w[1.8]) - assert_equal y.display_s, "java = 1.8" - z = JavaRequirement.new(%w[1.8+]) - assert_equal z.display_s, "java >= 1.8" - end - - def test_satisfied? - a = JavaRequirement.new(%w[1.8]) - File.stubs(:executable?).returns(false) - refute_predicate a, :satisfied? - - b = JavaRequirement.new([]) - b.stubs(:preferred_java).returns(Pathname.new("/usr/bin/java")) - assert_predicate b, :satisfied? - - c = JavaRequirement.new(%w[1.7+]) - c.stubs(:possible_javas).returns([Pathname.new("/usr/bin/java")]) - Utils.stubs(:popen_read).returns('java version "1.6.0_5"') - refute_predicate c, :satisfied? - Utils.stubs(:popen_read).returns('java version "1.8.0_5"') - assert_predicate c, :satisfied? - - d = JavaRequirement.new(%w[1.7]) - d.stubs(:possible_javas).returns([Pathname.new("/usr/bin/java")]) - Utils.stubs(:popen_read).returns('java version "1.8.0_5"') - refute_predicate d, :satisfied? - end -end diff --git a/Library/Homebrew/test/os/mac/blacklist_test.rb b/Library/Homebrew/test/os/mac/blacklist_test.rb deleted file mode 100644 index 26dd84ed9f888992fdc5bda51df6f501ac4e3c9e..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/blacklist_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" -require "blacklist" - -class OSMacBlacklistTests < Homebrew::TestCase - def assert_blacklisted(s) - assert blacklisted?(s), "'#{s}' should be blacklisted" - end - - def test_xcode - %w[xcode Xcode].each { |s| assert_blacklisted s } - end -end diff --git a/Library/Homebrew/test/os/mac/bottle_tag_test.rb b/Library/Homebrew/test/os/mac/bottle_tag_test.rb deleted file mode 100644 index 996bd4d536468ffb4fe18b698de78c7e40285850..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/bottle_tag_test.rb +++ /dev/null @@ -1,79 +0,0 @@ -require "testing_env" -require "utils/bottles" - -class OSMacBottleTagTests < Homebrew::TestCase - def test_tag_tiger_ppc - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:foo) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :tiger_foo, Utils::Bottles.tag - end - - def test_tag_tiger_intel - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :tiger, Utils::Bottles.tag - end - - def test_tag_tiger_ppc_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:g5) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :tiger_g5_64, Utils::Bottles.tag - end - - # Note that this will probably never be used - def test_tag_tiger_intel_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :tiger_64, Utils::Bottles.tag - end - - def test_tag_leopard_intel - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :leopard, Utils::Bottles.tag - end - - def test_tag_leopard_ppc_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:g5) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :leopard_g5_64, Utils::Bottles.tag - end - - def test_tag_leopard_intel_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :leopard_64, Utils::Bottles.tag - end - - def test_tag_snow_leopard_32 - MacOS.stubs(:version).returns(MacOS::Version.new("10.6")) - Hardware::CPU.stubs(:is_64_bit?).returns(false) - assert_equal :snow_leopard_32, Utils::Bottles.tag - end - - def test_tag_snow_leopard_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.6")) - Hardware::CPU.stubs(:is_64_bit?).returns(true) - assert_equal :snow_leopard, Utils::Bottles.tag - end - - def test_tag_lion - MacOS.stubs(:version).returns(MacOS::Version.new("10.7")) - assert_equal :lion, Utils::Bottles.tag - end - - def test_tag_mountain_lion - MacOS.stubs(:version).returns(MacOS::Version.new("10.8")) - assert_equal :mountain_lion, Utils::Bottles.tag - end -end diff --git a/Library/Homebrew/test/os/mac/java_requirement_spec.rb b/Library/Homebrew/test/os/mac/java_requirement_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f6404db926c4311ff8505bc7ada6362a5c422088 --- /dev/null +++ b/Library/Homebrew/test/os/mac/java_requirement_spec.rb @@ -0,0 +1,34 @@ +require "requirements/java_requirement" +require "fileutils" + +describe JavaRequirement do + subject { described_class.new(%w[1.8]) } + let(:java_home) { Dir.mktmpdir } + let(:java_home_path) { Pathname.new(java_home) } + + before(:each) do + FileUtils.mkdir java_home_path/"bin" + FileUtils.touch java_home_path/"bin/java" + allow(subject).to receive(:preferred_java).and_return(java_home_path/"bin/java") + expect(subject).to be_satisfied + end + + after(:each) { java_home_path.rmtree } + + specify "Apple Java environment" do + expect(ENV).to receive(:prepend_path) + expect(ENV).to receive(:append_to_cflags) + + subject.modify_build_environment + expect(ENV["JAVA_HOME"]).to eq(java_home) + end + + specify "Oracle Java environment" do + FileUtils.mkdir java_home_path/"include" + expect(ENV).to receive(:prepend_path) + expect(ENV).to receive(:append_to_cflags).twice + + subject.modify_build_environment + expect(ENV["JAVA_HOME"]).to eq(java_home) + end +end diff --git a/Library/Homebrew/test/os/mac/java_requirement_test.rb b/Library/Homebrew/test/os/mac/java_requirement_test.rb deleted file mode 100644 index 83c1af95ca3c0715fc0a821c92fa5332379a0af4..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/java_requirement_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -require "testing_env" -require "requirements/java_requirement" -require "fileutils" - -class OSMacJavaRequirementTests < Homebrew::TestCase - def setup - super - @java_req = JavaRequirement.new(%w[1.8]) - @tmp_java_home = mktmpdir - @tmp_pathname = Pathname.new(@tmp_java_home) - FileUtils.mkdir @tmp_pathname/"bin" - FileUtils.touch @tmp_pathname/"bin/java" - @java_req.stubs(:preferred_java).returns(@tmp_pathname/"bin/java") - @java_req.satisfied? - end - - def test_java_env_apple - ENV.expects(:prepend_path) - ENV.expects(:append_to_cflags) - @java_req.modify_build_environment - assert_equal ENV["JAVA_HOME"], @tmp_java_home - end - - def test_java_env_oracle - FileUtils.mkdir @tmp_pathname/"include" - ENV.expects(:prepend_path) - ENV.expects(:append_to_cflags).twice - @java_req.modify_build_environment - assert_equal ENV["JAVA_HOME"], @tmp_java_home - end -end diff --git a/Library/Homebrew/test/os/mac/keg_spec.rb b/Library/Homebrew/test/os/mac/keg_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..562c2ba6a69152388b6131a5b97d040a5ac0d9c2 --- /dev/null +++ b/Library/Homebrew/test/os/mac/keg_spec.rb @@ -0,0 +1,32 @@ +require "keg" + +describe Keg do + include FileUtils + + subject { described_class.new(keg_path) } + + describe "#mach_o_files" do + let(:keg_path) { HOMEBREW_CELLAR/"a/1.0" } + + before(:each) { (keg_path/"lib").mkpath } + + after(:each) { subject.unlink } + + it "skips hardlinks" do + cp dylib_path("i386"), keg_path/"lib/i386.dylib" + ln keg_path/"lib/i386.dylib", keg_path/"lib/i386_hardlink.dylib" + + subject.link + expect(subject.mach_o_files.count).to eq(1) + end + + it "isn't confused by symlinks" do + cp dylib_path("i386"), keg_path/"lib/i386.dylib" + ln keg_path/"lib/i386.dylib", keg_path/"lib/i386_hardlink.dylib" + ln_s keg_path/"lib/i386.dylib", keg_path/"lib/i386_symlink.dylib" + + subject.link + expect(subject.mach_o_files.count).to eq(1) + end + end +end diff --git a/Library/Homebrew/test/os/mac/keg_test.rb b/Library/Homebrew/test/os/mac/keg_test.rb deleted file mode 100644 index d1103415dece628c685ee42d6471407bbea01fe1..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/keg_test.rb +++ /dev/null @@ -1,69 +0,0 @@ -require "testing_env" -require "keg" -require "stringio" - -class OSMacLinkTests < Homebrew::TestCase - include FileUtils - - def setup - super - - keg = HOMEBREW_CELLAR.join("foo", "1.0") - keg.join("bin").mkpath - - %w[hiworld helloworld goodbye_cruel_world].each do |file| - touch keg.join("bin", file) - end - - @keg = Keg.new(keg) - @dst = HOMEBREW_PREFIX.join("bin", "helloworld") - @nonexistent = Pathname.new("/some/nonexistent/path") - - @mode = OpenStruct.new - - @old_stdout = $stdout - $stdout = StringIO.new - - mkpath HOMEBREW_PREFIX/"bin" - mkpath HOMEBREW_PREFIX/"lib" - end - - def teardown - @keg.unlink - - $stdout = @old_stdout - - rmtree HOMEBREW_PREFIX/"lib" - - super - end - - def test_mach_o_files_skips_hardlinks - a = HOMEBREW_CELLAR/"a/1.0" - (a/"lib").mkpath - FileUtils.cp dylib_path("i386"), a/"lib/i386.dylib" - FileUtils.ln a/"lib/i386.dylib", a/"lib/i386_link.dylib" - - keg = Keg.new(a) - keg.link - - assert_equal 1, keg.mach_o_files.size - ensure - keg.unlink - end - - def test_mach_o_files_isnt_confused_by_symlinks - a = HOMEBREW_CELLAR/"a/1.0" - (a/"lib").mkpath - FileUtils.cp dylib_path("i386"), a/"lib/i386.dylib" - FileUtils.ln a/"lib/i386.dylib", a/"lib/i386_link.dylib" - FileUtils.ln_s a/"lib/i386.dylib", a/"lib/1.dylib" - - keg = Keg.new(a) - keg.link - - assert_equal 1, keg.mach_o_files.size - ensure - keg.unlink - end -end diff --git a/Library/Homebrew/test/os/mac/language_test.rb b/Library/Homebrew/test/os/mac/language_test.rb deleted file mode 100644 index e328db5e00d3d060c795356ee2dd2edaf53d1918..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/language_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" -require "locale" -require "os/mac" - -class OSMacLanguageTests < Homebrew::TestCase - def test_languages_format - OS::Mac.languages.each do |language| - assert_nothing_raised do - Locale.parse(language) - end - end - end - - def test_language_format - assert_nothing_raised do - Locale.parse(OS::Mac.language) - end - 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 0000000000000000000000000000000000000000..5c9aafcbb9e3ab4675b8f182e744e8ca285bc0c5 --- /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 ed0424be6595f14703b4a21d9684830686d71355..0000000000000000000000000000000000000000 --- 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/os/mac/version_spec.rb b/Library/Homebrew/test/os/mac/version_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..797207b6788b44c34d6ac1825771ae3a5fc11242 --- /dev/null +++ b/Library/Homebrew/test/os/mac/version_spec.rb @@ -0,0 +1,51 @@ +require "version" +require "os/mac/version" + +describe OS::Mac::Version do + subject { described_class.new("10.7") } + + specify "comparison with Symbol" do + expect(subject).to be > :snow_leopard + expect(subject).to be == :lion + expect(subject).to be === :lion # rubocop:disable Style/CaseEquality + expect(subject).to be < :mountain_lion + end + + specify "comparison with Fixnum" do + expect(subject).to be > 10 + expect(subject).to be < 11 + end + + specify "comparison with Float" do + expect(subject).to be > 10.6 + expect(subject).to be == 10.7 + expect(subject).to be === 10.7 # rubocop:disable Style/CaseEquality + expect(subject).to be < 10.8 + end + + specify "comparison with String" do + expect(subject).to be > "10.6" + expect(subject).to be == "10.7" + expect(subject).to be === "10.7" # rubocop:disable Style/CaseEquality + expect(subject).to be < "10.8" + end + + specify "comparison with Version" do + expect(subject).to be > Version.create("10.6") + expect(subject).to be == Version.create("10.7") + expect(subject).to be === Version.create("10.7") # rubocop:disable Style/CaseEquality + expect(subject).to be < Version.create("10.8") + end + + specify "#from_symbol" do + expect(described_class.from_symbol(:lion)).to eq(subject) + expect { described_class.from_symbol(:foo) } + .to raise_error(ArgumentError) + end + + specify "#pretty_name" do + expect(described_class.new("10.11").pretty_name).to eq("El Capitan") + expect(described_class.new("10.8").pretty_name).to eq("Mountain Lion") + expect(described_class.new("10.10").pretty_name).to eq("Yosemite") + end +end diff --git a/Library/Homebrew/test/os/mac/version_test.rb b/Library/Homebrew/test/os/mac/version_test.rb deleted file mode 100644 index ba42176917a71f0542b4c6eca435cdcba79cd12a..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/os/mac/version_test.rb +++ /dev/null @@ -1,54 +0,0 @@ -require "testing_env" -require "version" -require "os/mac/version" - -class OSMacVersionTests < Homebrew::TestCase - def setup - super - @v = MacOS::Version.new("10.7") - end - - def test_compare_with_symbol - assert_operator @v, :>, :snow_leopard - assert_operator @v, :==, :lion - assert_operator @v, :===, :lion - assert_operator @v, :<, :mountain_lion - end - - def test_compare_with_fixnum - assert_operator @v, :>, 10 - assert_operator @v, :<, 11 - end - - def test_compare_with_float - assert_operator @v, :>, 10.6 - assert_operator @v, :==, 10.7 - assert_operator @v, :===, 10.7 - assert_operator @v, :<, 10.8 - end - - def test_compare_with_string - assert_operator @v, :>, "10.6" - assert_operator @v, :==, "10.7" - assert_operator @v, :===, "10.7" - assert_operator @v, :<, "10.8" - end - - def test_compare_with_version - assert_operator @v, :>, Version.create("10.6") - assert_operator @v, :==, Version.create("10.7") - assert_operator @v, :===, Version.create("10.7") - assert_operator @v, :<, Version.create("10.8") - end - - def test_from_symbol - assert_equal @v, MacOS::Version.from_symbol(:lion) - assert_raises(ArgumentError) { MacOS::Version.from_symbol(:foo) } - end - - def test_pretty_name - assert_equal "El Capitan", MacOS::Version.new("10.11").pretty_name - assert_equal "Mountain Lion", MacOS::Version.new("10.8").pretty_name - assert_equal "Yosemite", MacOS::Version.new("10.10").pretty_name - end -end diff --git a/Library/Homebrew/test/os/mac_spec.rb b/Library/Homebrew/test/os/mac_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..64178245112d47dc8bb6b52afff92b6ce7a8f94b --- /dev/null +++ b/Library/Homebrew/test/os/mac_spec.rb @@ -0,0 +1,22 @@ +require "locale" +require "os/mac" + +describe OS::Mac do + describe "::languages" do + specify "all languages can be parsed by Locale::parse" do + subject.languages.each do |language| + expect { Locale.parse(language) }.not_to raise_error + end + end + end + + describe "::language" do + it "returns the first item from #languages" do + expect(subject.language).to eq(subject.languages.first) + end + + it "can be parsed by Locale::parse" do + expect { Locale.parse(subject.language) }.not_to raise_error + end + end +end diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..da12d4347a852dbc8fb19a441bed42b31eb1222a --- /dev/null +++ b/Library/Homebrew/test/pathname_spec.rb @@ -0,0 +1,300 @@ +require "tmpdir" +require "extend/pathname" +require "install_renamed" + +describe Pathname do + include FileUtils + + let(:src) { Pathname.new(Dir.mktmpdir) } + let(:dst) { Pathname.new(Dir.mktmpdir) } + let(:file) { src/"foo" } + let(:dir) { src/"bar" } + + after(:each) { rm_rf [src, dst] } + + describe DiskUsageExtension do + before(:each) do + mkdir_p dir/"a-directory" + touch [dir/".DS_Store", dir/"a-file"] + File.truncate(dir/"a-file", 1_048_576) + ln_s dir/"a-file", dir/"a-symlink" + ln dir/"a-file", dir/"a-hardlink" + end + + describe "#file_count" do + it "returns the number of files in a directory" do + expect(dir.file_count).to eq(3) + end + end + + describe "#abv" do + context "when called on a directory" do + it "returns a string with the file count and disk usage" do + expect(dir.abv).to eq("3 files, 1M") + end + end + + context "when called on a file" do + it "returns the disk usage" do + expect((dir/"a-file").abv).to eq("1M") + end + end + end + end + + describe "#rmdir_if_possible" do + before(:each) { mkdir_p dir } + + it "returns true and removes a directory if it doesn't contain files" do + expect(dir.rmdir_if_possible).to be true + expect(dir).not_to exist + end + + it "returns false and doesn't delete a directory if it contains files" do + touch dir/"foo" + expect(dir.rmdir_if_possible).to be false + expect(dir).to be_a_directory + end + + it "ignores .DS_Store files" do + touch dir/".DS_Store" + expect(dir.rmdir_if_possible).to be true + expect(dir).not_to exist + end + end + + describe "#write" do + it "creates a file and writes to it" do + expect(file).not_to exist + file.write("CONTENT") + expect(File.read(file)).to eq("CONTENT") + end + + it "raises an error if the file already exists" do + touch file + expect { file.write("CONTENT") }.to raise_error(RuntimeError) + end + end + + describe "#append_lines" do + it "appends lines to a file" do + touch file + + file.append_lines("CONTENT") + expect(File.read(file)).to eq <<-EOS.undent + CONTENT + EOS + + file.append_lines("CONTENTS") + expect(File.read(file)).to eq <<-EOS.undent + CONTENT + CONTENTS + EOS + end + + it "raises an error if the file does not exist" do + expect(file).not_to exist + expect { file.append_lines("CONTENT") }.to raise_error(RuntimeError) + end + end + + describe "#atomic_write" do + it "atomically replaces a file" do + touch file + file.atomic_write("CONTENT") + expect(File.read(file)).to eq("CONTENT") + end + + it "preserves permissions" do + File.open(file, "w", 0100777).close + file.atomic_write("CONTENT") + expect(file.stat.mode).to eq(0100777 & ~File.umask) + end + + it "preserves default permissions" do + file.atomic_write("CONTENT") + sentinel = file.parent.join("sentinel") + touch sentinel + expect(file.stat.mode).to eq(sentinel.stat.mode) + end + end + + describe "#ensure_writable" do + it "makes a file writable and restores permissions afterwards" do + touch file + chmod 0555, file + expect(file).not_to be_writable + file.ensure_writable do + expect(file).to be_writable + end + expect(file).not_to be_writable + end + end + + describe "#extname" do + it "supports common multi-level archives" do + expect(Pathname.new("foo-0.1.tar.gz").extname).to eq(".tar.gz") + expect(Pathname.new("foo-0.1.cpio.gz").extname).to eq(".cpio.gz") + end + end + + describe "#stem" do + it "returns the basename without double extensions" do + expect(Pathname("foo-0.1.tar.gz").stem).to eq("foo-0.1") + expect(Pathname("foo-0.1.cpio.gz").stem).to eq("foo-0.1") + end + end + + describe "#install" do + before(:each) do + (src/"a.txt").write "This is sample file a." + (src/"b.txt").write "This is sample file b." + end + + it "raises an error if the file doesn't exist" do + expect { dst.install "non_existent_file" }.to raise_error(Errno::ENOENT) + end + + it "installs a file to a directory with its basename" do + touch file + dst.install(file) + expect(dst/file.basename).to exist + expect(file).not_to exist + end + + it "creates intermediate directories" do + touch file + expect(dir).not_to be_a_directory + dir.install(file) + expect(dir).to be_a_directory + end + + it "can install a file" do + dst.install src/"a.txt" + expect(dst/"a.txt").to exist, "a.txt was not installed" + expect(dst/"b.txt").not_to exist, "b.txt was installed." + end + + it "can install an array of files" do + dst.install [src/"a.txt", src/"b.txt"] + + expect(dst/"a.txt").to exist, "a.txt was not installed" + expect(dst/"b.txt").to exist, "b.txt was not installed" + end + + it "can install a directory" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install bin + + expect(dst/"bin/a.txt").to exist, "a.txt was not installed" + expect(dst/"bin/b.txt").to exist, "b.txt was not installed" + end + + it "supports renaming files" do + dst.install src/"a.txt" => "c.txt" + + expect(dst/"c.txt").to exist, "c.txt was not installed" + expect(dst/"a.txt").not_to exist, "a.txt was installed but not renamed" + expect(dst/"b.txt").not_to exist, "b.txt was installed" + end + + it "supports renaming multiple files" do + dst.install(src/"a.txt" => "c.txt", src/"b.txt" => "d.txt") + + expect(dst/"c.txt").to exist, "c.txt was not installed" + expect(dst/"d.txt").to exist, "d.txt was not installed" + expect(dst/"a.txt").not_to exist, "a.txt was installed but not renamed" + expect(dst/"b.txt").not_to exist, "b.txt was installed but not renamed" + end + + it "supports renaming directories" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install bin => "libexec" + + expect(dst/"bin").not_to exist, "bin was installed but not renamed" + expect(dst/"libexec/a.txt").to exist, "a.txt was not installed" + expect(dst/"libexec/b.txt").to exist, "b.txt was not installed" + end + + it "can install directories as relative symlinks" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install_symlink bin + + expect(dst/"bin").to be_a_symlink + expect(dst/"bin").to be_a_directory + expect(dst/"bin/a.txt").to exist + expect(dst/"bin/b.txt").to exist + expect((dst/"bin").readlink).to be_relative + end + + it "can install relative paths as symlinks" do + dst.install_symlink "foo" => "bar" + expect((dst/"bar").readlink).to eq(Pathname.new("foo")) + end + end + + describe InstallRenamed do + before(:each) do + dst.extend(InstallRenamed) + end + + it "renames the installed file if it already exists" do + file.write "a" + dst.install file + + file.write "b" + dst.install file + + expect(File.read(dst/file.basename)).to eq("a") + expect(File.read(dst/"#{file.basename}.default")).to eq("b") + end + + it "renames the installed directory" do + file.write "a" + dst.install src + expect(File.read(dst/src.basename/file.basename)).to eq("a") + end + + it "recursively renames directories" do + (dst/dir.basename).mkpath + (dst/dir.basename/"another_file").write "a" + dir.mkpath + (dir/"another_file").write "b" + dst.install dir + expect(File.read(dst/dir.basename/"another_file.default")).to eq("b") + end + end + + describe "#cp_path_sub" do + it "copies a file and replaces the given pattern" do + file.write "a" + file.cp_path_sub src, dst + expect(File.read(dst/file.basename)).to eq("a") + end + + it "copies a directory and replaces the given pattern" do + dir.mkpath + dir.cp_path_sub src, dst + expect(dst/dir.basename).to be_a_directory + end + end +end + +describe FileUtils do + let(:dst) { Pathname.new(Dir.mktmpdir) } + + describe "#mkdir" do + it "creates indermediate directories" do + described_class.mkdir dst/"foo/bar/baz" do + expect(dst/"foo/bar/baz").to exist, "foo/bar/baz was not created" + expect(dst/"foo/bar/baz").to be_a_directory, "foo/bar/baz was not a directory structure" + end + end + end +end diff --git a/Library/Homebrew/test/pathname_test.rb b/Library/Homebrew/test/pathname_test.rb deleted file mode 100644 index b48a26fbd3dadce56bffb2e0c6b8af2809ab5b61..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/pathname_test.rb +++ /dev/null @@ -1,263 +0,0 @@ -require "testing_env" -require "tmpdir" -require "extend/pathname" -require "install_renamed" - -module PathnameTestExtension - include FileUtils - - def setup - super - @src = Pathname.new(mktmpdir) - @dst = Pathname.new(mktmpdir) - @file = @src/"foo" - @dir = @src/"bar" - end -end - -class PathnameTests < Homebrew::TestCase - include PathnameTestExtension - - def test_disk_usage_extension - mkdir_p @dir/"a-directory" - touch @dir/".DS_Store" - touch @dir/"a-file" - File.truncate(@dir/"a-file", 1_048_576) - ln_s @dir/"a-file", @dir/"a-symlink" - ln @dir/"a-file", @dir/"a-hardlink" - assert_equal 3, @dir.file_count - assert_equal "3 files, 1M", @dir.abv - assert_equal "1M", (@dir/"a-file").abv - end - - def test_rmdir_if_possible - mkdir_p @dir - touch @dir/"foo" - - assert !@dir.rmdir_if_possible - assert_predicate @dir, :directory? - - rm_f @dir/"foo" - assert @dir.rmdir_if_possible - refute_predicate @dir, :exist? - end - - def test_rmdir_if_possible_ignore_ds_store - mkdir_p @dir - touch @dir/".DS_Store" - assert @dir.rmdir_if_possible - refute_predicate @dir, :exist? - end - - def test_write - @file.write("CONTENT") - assert_equal "CONTENT", File.read(@file) - end - - def test_write_does_not_overwrite - touch @file - assert_raises(RuntimeError) { @file.write("CONTENT") } - end - - def test_append_lines - touch @file - @file.append_lines("CONTENT") - assert_equal "CONTENT\n", File.read(@file) - @file.append_lines("CONTENTS") - assert_equal "CONTENT\nCONTENTS\n", File.read(@file) - end - - def test_append_lines_does_not_create - assert_raises(RuntimeError) { @file.append_lines("CONTENT") } - end - - def test_atomic_write - touch @file - @file.atomic_write("CONTENT") - assert_equal "CONTENT", File.read(@file) - end - - def test_atomic_write_preserves_permissions - File.open(@file, "w", 0100777) {} - @file.atomic_write("CONTENT") - assert_equal 0100777 & ~File.umask, @file.stat.mode - end - - def test_atomic_write_preserves_default_permissions - @file.atomic_write("CONTENT") - sentinel = @file.parent.join("sentinel") - touch sentinel - assert_equal sentinel.stat.mode, @file.stat.mode - end - - def test_ensure_writable - touch @file - chmod 0555, @file - @file.ensure_writable { assert_predicate @file, :writable? } - refute_predicate @file, :writable? - end - - def test_extname - assert_equal ".tar.gz", Pathname("foo-0.1.tar.gz").extname - assert_equal ".cpio.gz", Pathname("foo-0.1.cpio.gz").extname - end - - def test_stem - assert_equal "foo-0.1", Pathname("foo-0.1.tar.gz").stem - assert_equal "foo-0.1", Pathname("foo-0.1.cpio.gz").stem - end - - def test_install_missing_file - assert_raises(Errno::ENOENT) { @dst.install "non_existent_file" } - end - - def test_install_removes_original - touch @file - @dst.install(@file) - - assert_predicate @dst/@file.basename, :exist? - refute_predicate @file, :exist? - end - - def test_install_creates_intermediate_directories - touch @file - refute_predicate @dir, :directory? - @dir.install(@file) - assert_predicate @dir, :directory? - end - - def test_install_renamed - @dst.extend(InstallRenamed) - - @file.write "a" - @dst.install @file - @file.write "b" - @dst.install @file - - assert_equal "a", File.read(@dst/@file.basename) - assert_equal "b", File.read(@dst/"#{@file.basename}.default") - end - - def test_install_renamed_directory - @dst.extend(InstallRenamed) - @file.write "a" - @dst.install @src - assert_equal "a", File.read(@dst/@src.basename/@file.basename) - end - - def test_install_renamed_directory_recursive - @dst.extend(InstallRenamed) - (@dst/@dir.basename).mkpath - (@dst/@dir.basename/"another_file").write "a" - @dir.mkpath - (@dir/"another_file").write "b" - @dst.install @dir - assert_equal "b", File.read(@dst/@dir.basename/"another_file.default") - end - - def test_cp_path_sub_file - @file.write "a" - @file.cp_path_sub @src, @dst - assert_equal "a", File.read(@dst/"foo") - end - - def test_cp_path_sub_directory - @dir.mkpath - @dir.cp_path_sub @src, @dst - assert_predicate @dst/@dir.basename, :directory? - end -end - -class PathnameInstallTests < Homebrew::TestCase - include PathnameTestExtension - - def setup - super - (@src/"a.txt").write "This is sample file a." - (@src/"b.txt").write "This is sample file b." - end - - def test_install - @dst.install @src/"a.txt" - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed." - end - - def test_install_list - @dst.install [@src/"a.txt", @src/"b.txt"] - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"b.txt", :exist?, "b.txt was not installed" - end - - def test_install_glob - @dst.install Dir[@src/"*.txt"] - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"b.txt", :exist?, "b.txt was not installed" - end - - def test_install_directory - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install bin - - assert_predicate @dst/"bin/a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"bin/b.txt", :exist?, "b.txt was not installed" - end - - def test_install_rename - @dst.install @src/"a.txt" => "c.txt" - - assert_predicate @dst/"c.txt", :exist?, "c.txt was not installed" - refute_predicate @dst/"a.txt", :exist?, "a.txt was installed but not renamed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed" - end - - def test_install_rename_more - @dst.install(@src/"a.txt" => "c.txt", @src/"b.txt" => "d.txt") - - assert_predicate @dst/"c.txt", :exist?, "c.txt was not installed" - assert_predicate @dst/"d.txt", :exist?, "d.txt was not installed" - refute_predicate @dst/"a.txt", :exist?, "a.txt was installed but not renamed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed but not renamed" - end - - def test_install_rename_directory - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install bin => "libexec" - - refute_predicate @dst/"bin", :exist?, "bin was installed but not renamed" - assert_predicate @dst/"libexec/a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"libexec/b.txt", :exist?, "b.txt was not installed" - end - - def test_install_symlink - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install_symlink bin - - assert_predicate @dst/"bin", :symlink? - assert_predicate @dst/"bin", :directory? - assert_predicate @dst/"bin/a.txt", :exist? - assert_predicate @dst/"bin/b.txt", :exist? - assert_predicate((@dst/"bin").readlink, :relative?) - end - - def test_install_relative_symlink - @dst.install_symlink "foo" => "bar" - assert_equal Pathname.new("foo"), (@dst/"bar").readlink - end - - def test_mkdir_creates_intermediate_directories - mkdir @dst/"foo/bar/baz" do - assert_predicate @dst/"foo/bar/baz", :exist?, "foo/bar/baz was not created" - assert_predicate @dst/"foo/bar/baz", :directory?, "foo/bar/baz was not a directory structure" - end - end -end diff --git a/Library/Homebrew/test/resource_spec.rb b/Library/Homebrew/test/resource_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..6a04195389f93188bf98678b5050816749742caa --- /dev/null +++ b/Library/Homebrew/test/resource_spec.rb @@ -0,0 +1,147 @@ +require "resource" + +describe Resource do + subject { described_class.new("test") } + + describe "#url" do + it "sets the URL" do + subject.url("foo") + expect(subject.url).to eq("foo") + end + + it "can set the URL with specifications" do + subject.url("foo", branch: "master") + expect(subject.url).to eq("foo") + expect(subject.specs).to eq(branch: "master") + end + + it "can set the URL with a custom download strategy class" do + strategy = Class.new(AbstractDownloadStrategy) + subject.url("foo", using: strategy) + expect(subject.url).to eq("foo") + expect(subject.download_strategy).to eq(strategy) + end + + it "can set the URL with specifications and a custom download strategy class" do + strategy = Class.new(AbstractDownloadStrategy) + subject.url("foo", using: strategy, branch: "master") + expect(subject.url).to eq("foo") + expect(subject.specs).to eq(branch: "master") + expect(subject.download_strategy).to eq(strategy) + end + + it "can set the URL with a custom download strategy symbol" do + subject.url("foo", using: :git) + expect(subject.url).to eq("foo") + expect(subject.download_strategy).to eq(GitDownloadStrategy) + end + + it "raises an error if the download strategy class is unkown" do + expect { subject.url("foo", using: Class.new) }.to raise_error(TypeError) + end + + it "does not mutate the specifications hash" do + specs = { using: :git, branch: "master" } + subject.url("foo", specs) + expect(subject.specs).to eq(branch: "master") + expect(subject.using).to eq(:git) + expect(specs).to eq(using: :git, branch: "master") + end + end + + describe "#version" do + it "sets the version" do + subject.version("1.0") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).not_to be_detected_from_url + end + + it "can detect the version from a URL" do + subject.url("http://example.com/foo-1.0.tar.gz") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).to be_detected_from_url + end + + it "can set the version with a scheme" do + klass = Class.new(Version) + subject.version klass.new("1.0") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).to be_a(klass) + end + + it "can set the version from a tag" do + subject.url("http://example.com/foo-1.0.tar.gz", tag: "v1.0.2") + expect(subject.version).to eq(Version.parse("1.0.2")) + expect(subject.version).to be_detected_from_url + end + + it "rejects non-string versions" do + expect { subject.version(1) }.to raise_error(TypeError) + expect { subject.version(2.0) }.to raise_error(TypeError) + expect { subject.version(Object.new) }.to raise_error(TypeError) + end + + it "returns nil if unset" do + expect(subject.version).to be nil + end + end + + describe "#mirrors" do + it "is empty by defaults" do + expect(subject.mirrors).to be_empty + end + + it "returns an array of mirrors added with #mirror" do + subject.mirror("foo") + subject.mirror("bar") + expect(subject.mirrors).to eq(%w[foo bar]) + end + end + + describe "#checksum" do + it "returns nil if unset" do + expect(subject.checksum).to be nil + end + + it "returns the checksum set with #sha256" do + subject.sha256(TEST_SHA256) + expect(subject.checksum).to eq(Checksum.new(:sha256, TEST_SHA256)) + end + end + + describe "#download_strategy" do + it "returns the download strategy" do + strategy = Object.new + expect(DownloadStrategyDetector) + .to receive(:detect).with("foo", nil).and_return(strategy) + subject.url("foo") + expect(subject.download_strategy).to eq(strategy) + end + end + + specify "#verify_download_integrity_missing" do + fn = Pathname.new("test") + + allow(fn).to receive(:file?).and_return(true) + expect(fn).to receive(:verify_checksum).and_raise(ChecksumMissingError) + expect(fn).to receive(:sha256) + + shutup do + subject.verify_download_integrity(fn) + end + end + + specify "#verify_download_integrity_mismatch" do + fn = double(file?: true) + checksum = subject.sha256(TEST_SHA256) + + expect(fn).to receive(:verify_checksum).with(checksum) + .and_raise(ChecksumMismatchError.new(fn, checksum, Object.new)) + + shutup do + expect { + subject.verify_download_integrity(fn) + }.to raise_error(ChecksumMismatchError) + end + end +end diff --git a/Library/Homebrew/test/resource_test.rb b/Library/Homebrew/test/resource_test.rb deleted file mode 100644 index d982a7c3373f4220e8b9a82fe87aa4000bf570c6..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/resource_test.rb +++ /dev/null @@ -1,133 +0,0 @@ -require "testing_env" -require "resource" - -class ResourceTests < Homebrew::TestCase - def setup - super - @resource = Resource.new("test") - end - - def test_url - @resource.url("foo") - assert_equal "foo", @resource.url - end - - def test_url_with_specs - @resource.url("foo", branch: "master") - assert_equal "foo", @resource.url - assert_equal({ branch: "master" }, @resource.specs) - end - - def test_url_with_custom_download_strategy_class - strategy = Class.new(AbstractDownloadStrategy) - @resource.url("foo", using: strategy) - assert_equal "foo", @resource.url - assert_equal strategy, @resource.download_strategy - end - - def test_url_with_specs_and_download_strategy - strategy = Class.new(AbstractDownloadStrategy) - @resource.url("foo", using: strategy, branch: "master") - assert_equal "foo", @resource.url - assert_equal({ branch: "master" }, @resource.specs) - assert_equal strategy, @resource.download_strategy - end - - def test_url_with_custom_download_strategy_symbol - @resource.url("foo", using: :git) - assert_equal "foo", @resource.url - assert_equal GitDownloadStrategy, @resource.download_strategy - end - - def test_raises_for_unknown_download_strategy_class - assert_raises(TypeError) { @resource.url("foo", using: Class.new) } - end - - def test_does_not_mutate_specs_hash - specs = { using: :git, branch: "master" } - @resource.url("foo", specs) - assert_equal({ branch: "master" }, @resource.specs) - assert_equal(:git, @resource.using) - assert_equal({ using: :git, branch: "master" }, specs) - end - - def test_version - @resource.version("1.0") - assert_version_equal "1.0", @resource.version - refute_predicate @resource.version, :detected_from_url? - end - - def test_version_from_url - @resource.url("http://example.com/foo-1.0.tar.gz") - assert_version_equal "1.0", @resource.version - assert_predicate @resource.version, :detected_from_url? - end - - def test_version_with_scheme - klass = Class.new(Version) - @resource.version klass.new("1.0") - assert_version_equal "1.0", @resource.version - assert_instance_of klass, @resource.version - end - - def test_version_from_tag - @resource.url("http://example.com/foo-1.0.tar.gz", tag: "v1.0.2") - assert_version_equal "1.0.2", @resource.version - assert_predicate @resource.version, :detected_from_url? - end - - def test_rejects_non_string_versions - assert_raises(TypeError) { @resource.version(1) } - assert_raises(TypeError) { @resource.version(2.0) } - assert_raises(TypeError) { @resource.version(Object.new) } - end - - def test_version_when_url_is_not_set - assert_nil @resource.version - end - - def test_mirrors - assert_empty @resource.mirrors - @resource.mirror("foo") - @resource.mirror("bar") - assert_equal %w[foo bar], @resource.mirrors - end - - def test_checksum_setters - assert_nil @resource.checksum - @resource.sha256(TEST_SHA256) - assert_equal Checksum.new(:sha256, TEST_SHA256), @resource.checksum - end - - def test_download_strategy - strategy = Object.new - DownloadStrategyDetector - .expects(:detect).with("foo", nil).returns(strategy) - @resource.url("foo") - assert_equal strategy, @resource.download_strategy - end - - def test_verify_download_integrity_missing - fn = Pathname.new("test") - - fn.stubs(file?: true) - fn.expects(:verify_checksum).raises(ChecksumMissingError) - fn.expects(:sha256) - - shutup { @resource.verify_download_integrity(fn) } - end - - def test_verify_download_integrity_mismatch - fn = stub(file?: true) - checksum = @resource.sha256(TEST_SHA256) - - fn.expects(:verify_checksum).with(checksum) - .raises(ChecksumMismatchError.new(fn, checksum, Object.new)) - - shutup do - assert_raises(ChecksumMismatchError) do - @resource.verify_download_integrity(fn) - end - end - end -end diff --git a/Library/Homebrew/test/search_remote_tap_test.rb b/Library/Homebrew/test/search_remote_tap_test.rb deleted file mode 100644 index 9dd9ee6544413d67de0cd3d75824229a941896a4..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/search_remote_tap_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" -require "cmd/search" - -class SearchRemoteTapTests < Homebrew::TestCase - def test_search_remote_tap - json_response = { - "tree" => [ - { - "path" => "Formula/not-a-formula.rb", - "type" => "blob", - }, - ], - } - - GitHub.stubs(:open).yields(json_response) - - assert_equal ["homebrew/not-a-tap/not-a-formula"], Homebrew.search_tap("homebrew", "not-a-tap", "not-a-formula") - end -end diff --git a/Library/Homebrew/test/shell_test.rb b/Library/Homebrew/test/shell_test.rb deleted file mode 100644 index 97048970285e2833d0d3b977c46462bed5676c37..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/shell_test.rb +++ /dev/null @@ -1,56 +0,0 @@ -require "testing_env" -require "utils/shell" - -class ShellSmokeTest < Homebrew::TestCase - def test_path_to_shell - # raw command name - assert_equal :bash, Utils::Shell.path_to_shell("bash") - # full path - assert_equal :bash, Utils::Shell.path_to_shell("/bin/bash") - # versions - assert_equal :zsh, Utils::Shell.path_to_shell("zsh-5.2") - # strip newline too - assert_equal :zsh, Utils::Shell.path_to_shell("zsh-5.2\n") - end - - def test_path_to_shell_failure - assert_nil Utils::Shell.path_to_shell("") - assert_nil Utils::Shell.path_to_shell("@@@@@@") - assert_nil Utils::Shell.path_to_shell("invalid_shell-4.2") - end - - def test_sh_quote - assert_equal "''", Utils::Shell.sh_quote("") - assert_equal "\\\\", Utils::Shell.sh_quote("\\") - assert_equal "'\n'", Utils::Shell.sh_quote("\n") - assert_equal "\\$", Utils::Shell.sh_quote("$") - assert_equal "word", Utils::Shell.sh_quote("word") - end - - def test_csh_quote - assert_equal "''", Utils::Shell.csh_quote("") - assert_equal "\\\\", Utils::Shell.csh_quote("\\") - # note this test is different than for sh - assert_equal "'\\\n'", Utils::Shell.csh_quote("\n") - assert_equal "\\$", Utils::Shell.csh_quote("$") - assert_equal "word", Utils::Shell.csh_quote("word") - end - - def prepend_path_shell(shell, path, fragment) - ENV["SHELL"] = shell - - prepend_message = Utils::Shell.prepend_path_in_shell_profile(path) - assert( - prepend_message.start_with?(fragment), - "#{shell}: expected #{prepend_message} to match #{fragment}", - ) - end - - def test_prepend_path_in_shell_profile - prepend_path_shell "/bin/tcsh", "/path", "echo 'setenv PATH /path" - - prepend_path_shell "/bin/bash", "/path", "echo 'export PATH=\"/path" - - prepend_path_shell "/usr/local/bin/fish", "/path", "echo 'set -g fish_user_paths \"/path\" $fish_user_paths' >>" - 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 0000000000000000000000000000000000000000..5fd4f598a978eb2c13f0ce6e4d47158b3c185dc4 --- /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 026265a4a12379b4a70c148c48ed643af1f6b6e4..0000000000000000000000000000000000000000 --- 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 diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index 67e5f555a182155f0f29a5a6eb01456e92546532..e4349c8a00853f79439e4f4bf7815d830cf602ee 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -15,6 +15,8 @@ require "global" require "tap" require "test/support/helper/shutup" +require "test/support/helper/fixtures" +require "test/support/helper/spec/shared_context/integration_test" TEST_DIRECTORIES = [ CoreTap.instance.path/"Formula", @@ -29,9 +31,10 @@ TEST_DIRECTORIES = [ RSpec.configure do |config| config.order = :random config.include(Test::Helper::Shutup) + config.include(Test::Helper::Fixtures) config.before(:each) do |example| if example.metadata[:needs_macos] - skip "not on macOS" unless OS.mac? + skip "Not on macOS." unless OS.mac? end if example.metadata[:needs_python] @@ -42,6 +45,8 @@ RSpec.configure do |config| begin TEST_DIRECTORIES.each(&:mkpath) + @__homebrew_failed = Homebrew.failed? + @__files_before_test = Find.find(TEST_TMPDIR).map { |f| f.sub(TEST_TMPDIR, "") } @__argv = ARGV.dup @@ -81,6 +86,10 @@ RSpec.configure do |config| file leak detected: #{diff.map { |f| " #{f}" }.join("\n")} EOS + + Homebrew.failed = @__homebrew_failed end end end + +RSpec::Matchers.alias_matcher :have_failed, :be_failed diff --git a/Library/Homebrew/test/string_spec.rb b/Library/Homebrew/test/string_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..d1b820b66107f5dc2904819d58802c35a5d98dff --- /dev/null +++ b/Library/Homebrew/test/string_spec.rb @@ -0,0 +1,49 @@ +require "extend/string" + +describe String do + describe "#undent" do + it "removes leading whitespace, taking the first line as reference" do + string = <<-EOS.undent + hi +........my friend over + there + EOS + + expect(string).to eq("hi\n........my friend over\n there\n") + end + + it "removes nothing if the text is not indented" do + string = <<-EOS.undent +hi +I'm not indented + EOS + + expect(string).to eq("hi\nI'm not indented\n") + end + + it "can be nested" do + nested_string = <<-EOS.undent + goodbye + EOS + + string = <<-EOS.undent + hello + #{nested_string} + EOS + + expect(string).to eq("hello\ngoodbye\n\n") + end + end +end + +describe StringInreplaceExtension do + subject { string.extend(described_class) } + let(:string) { "foobar" } + + describe "#sub!" do + it "adds an error to #errors when no replacement was made" do + subject.sub! "not here", "test" + expect(subject.errors).to eq(['expected replacement of "not here" with "test"']) + end + end +end diff --git a/Library/Homebrew/test/string_test.rb b/Library/Homebrew/test/string_test.rb deleted file mode 100644 index 497c4badb15b021e238279ad3b5e786ded90739c..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/string_test.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "testing_env" -require "extend/string" - -class StringTest < Homebrew::TestCase - def test_undent - undented = <<-EOS.undent - hi -....my friend over - there - EOS - assert_equal "hi\n....my friend over\nthere\n", undented - end - - def test_undent_not_indented - undented = <<-EOS.undent -hi -I'm not indented - EOS - assert_equal "hi\nI'm not indented\n", undented - end - - def test_undent_nested - nest = <<-EOS.undent - goodbye - EOS - - undented = <<-EOS.undent - hello - #{nest} - EOS - - assert_equal "hello\ngoodbye\n\n", undented - end - - def test_inreplace_sub_failure - s = "foobar".extend StringInreplaceExtension - s.sub! "not here", "test" - assert_equal ['expected replacement of "not here" with "test"'], s.errors - end -end diff --git a/Library/Homebrew/test/support/helper/fixtures.rb b/Library/Homebrew/test/support/helper/fixtures.rb new file mode 100644 index 0000000000000000000000000000000000000000..716fe200816e5889d937bc0e5ee63f9b14bc9d46 --- /dev/null +++ b/Library/Homebrew/test/support/helper/fixtures.rb @@ -0,0 +1,13 @@ +module Test + module Helper + module Fixtures + def dylib_path(name) + Pathname.new("#{TEST_FIXTURE_DIR}/mach/#{name}.dylib") + end + + def bundle_path(name) + Pathname.new("#{TEST_FIXTURE_DIR}/mach/#{name}.bundle") + end + end + end +end diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..dd2271a3a41cf96e9458c0286a220968b894e7ec --- /dev/null +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -0,0 +1,94 @@ +require "rspec" +require "open3" + +RSpec::Matchers.define_negated_matcher :not_to_output, :output +RSpec::Matchers.define_negated_matcher :be_a_failure, :be_a_success + +RSpec.shared_context "integration test" do + extend RSpec::Matchers::DSL + + matcher :be_a_success do + match do |actual| + status = actual.is_a?(Proc) ? actual.call : actual + status.respond_to?(:success?) && status.success? + end + + def supports_block_expectations? + true + end + + # It needs to be nested like this: + # + # expect { + # expect { + # # command + # }.to be_a_success + # }.to output(something).to_stdout + # + # rather than this: + # + # expect { + # expect { + # # command + # }.to output(something).to_stdout + # }.to be_a_success + # + def expects_call_stack_jump? + true + end + end + + before(:each) do + (HOMEBREW_PREFIX/"bin").mkpath + FileUtils.touch HOMEBREW_PREFIX/"bin/brew" + end + + after(:each) do + FileUtils.rm HOMEBREW_PREFIX/"bin/brew" + FileUtils.rmdir HOMEBREW_PREFIX/"bin" + end + + # Generate unique ID to be able to + # properly merge coverage results. + def command_id_from_args(args) + @command_count ||= 0 + pretty_args = args.join(" ").gsub(TEST_TMPDIR, "@TMPDIR@") + file_and_line = caller[1].sub(/(.*\d+):.*/, '\1') + .sub("#{HOMEBREW_LIBRARY_PATH}/test/", "") + "#{file_and_line}:brew #{pretty_args}:#{@command_count += 1}" + end + + # Runs a `brew` command with the test configuration + # and with coverage reporting enabled. + def brew(*args) + env = args.last.is_a?(Hash) ? args.pop : {} + + env.merge!( + "HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew", + "HOMEBREW_INTEGRATION_TEST" => command_id_from_args(args), + "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, + "HOMEBREW_DEVELOPER" => ENV["HOMEBREW_DEVELOPER"], + ) + + ruby_args = [ + "-W0", + "-I", "#{HOMEBREW_LIBRARY_PATH}/test/support/lib", + "-I", HOMEBREW_LIBRARY_PATH.to_s, + "-rconfig" + ] + ruby_args << "-rsimplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] + ruby_args << "-rtest/support/helper/integration_mocks" + ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s + + Bundler.with_original_env do + stdout, stderr, status = Open3.capture3(env, RUBY_PATH, *ruby_args, *args) + $stdout.print stdout + $stderr.print stderr + status + end + end +end + +RSpec.configure do |config| + config.include_context "integration test", :integration_test +end diff --git a/Library/Homebrew/test/utils/bottles/bintray_spec.rb b/Library/Homebrew/test/utils/bottles/bintray_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..a7dfc00eabe1eaddcc1c20dcf792fb41f27d51a1 --- /dev/null +++ b/Library/Homebrew/test/utils/bottles/bintray_spec.rb @@ -0,0 +1,18 @@ +require "utils/bottles" + +describe Utils::Bottles::Bintray do + describe "::package" do + it "converts a Formula name to a package name" do + expect(described_class.package("openssl@1.1")).to eq("openssl:1.1") + expect(described_class.package("gtk+")).to eq("gtkx") + expect(described_class.package("llvm")).to eq("llvm") + end + end + + describe "::repository" do + it "returns the repository for a given Tap" do + expect(described_class.repository(Tap.new("homebrew", "bintray-test"))) + .to eq("bottles-bintray-test") + end + end +end diff --git a/Library/Homebrew/test/utils/bottles/bottles_spec.rb b/Library/Homebrew/test/utils/bottles/bottles_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8b54b0b3449c2f5acb26f51e60cd4567caf426b7 --- /dev/null +++ b/Library/Homebrew/test/utils/bottles/bottles_spec.rb @@ -0,0 +1,80 @@ +require "utils/bottles" + +describe Utils::Bottles do + describe "#tag", :needs_macos do + it "returns :tiger_foo on Tiger PowerPC" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:foo) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:tiger_foo) + end + + it "returns :tiger on Tiger Intel" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:tiger) + end + + it "returns :tiger_g5_64 on Tiger PowerPC 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:g5) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:tiger_g5_64) + end + + # Note that this will probably never be used + it "returns :tiger_64 on Tiger Intel 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:tiger_64) + end + + it "returns :leopard on Leopard Intel" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:leopard) + end + + it "returns :leopard_g5_64 on Leopard PowerPC 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:g5) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:leopard_g5_64) + end + + it "returns :leopard_64 on Leopard Intel 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:leopard_64) + end + + it "returns :snow_leopard_32 on Snow Leopard 32-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.6")) + allow(Hardware::CPU).to receive(:is_64_bit?).and_return(false) + expect(described_class.tag).to eq(:snow_leopard_32) + end + + it "returns :snow_leopard on Snow Leopard 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.6")) + allow(Hardware::CPU).to receive(:is_64_bit?).and_return(true) + expect(described_class.tag).to eq(:snow_leopard) + end + + it "returns :lion on Lion" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.7")) + expect(described_class.tag).to eq(:lion) + end + + it "returns :mountain_lion on Mountain Lion" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.8")) + expect(described_class.tag).to eq(:mountain_lion) + end + end +end diff --git a/Library/Homebrew/test/utils/popen_spec.rb b/Library/Homebrew/test/utils/popen_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..e3704a876ad8e6433289c348ba86390c2bbf3dc0 --- /dev/null +++ b/Library/Homebrew/test/utils/popen_spec.rb @@ -0,0 +1,28 @@ +require "utils/popen" + +describe Utils do + describe "::popen_read" do + it "reads the standard output of a given command" do + expect(subject.popen_read("sh", "-c", "echo success").chomp).to eq("success") + expect($?).to be_a_success + end + + it "can be given a block to manually read from the pipe" do + expect( + subject.popen_read("sh", "-c", "echo success") do |pipe| + pipe.read.chomp + end, + ).to eq("success") + expect($?).to be_a_success + end + end + + describe "::popen_write" do + it "with supports writing to a command's standard input" do + subject.popen_write("grep", "-q", "success") do |pipe| + pipe.write("success\n") + end + expect($?).to be_a_success + end + end +end diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c44bd82533f793b65a7a3b81de4d49238fd3057b --- /dev/null +++ b/Library/Homebrew/test/utils/shell_spec.rb @@ -0,0 +1,93 @@ +require "utils/shell" + +describe Utils::Shell do + describe "::shell_profile" do + it "returns ~/.bash_profile by default" do + ENV["SHELL"] = "/bin/another_shell" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.bash_profile for Sh" do + ENV["SHELL"] = "/bin/another_shell" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.bash_profile for Bash" do + ENV["SHELL"] = "/bin/bash" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.zshrc for Zsh" do + ENV["SHELL"] = "/bin/zsh" + expect(subject.shell_profile).to eq("~/.zshrc") + end + + it "returns ~/.kshrc for Ksh" do + ENV["SHELL"] = "/bin/ksh" + expect(subject.shell_profile).to eq("~/.kshrc") + end + end + + describe "::path_to_shell" do + it "supports a raw command name" do + expect(subject.path_to_shell("bash")).to eq(:bash) + end + + it "supports full paths" do + expect(subject.path_to_shell("/bin/bash")).to eq(:bash) + end + + it "supports versions" do + expect(subject.path_to_shell("zsh-5.2")).to eq(:zsh) + end + + it "strips newlines" do + expect(subject.path_to_shell("zsh-5.2\n")).to eq(:zsh) + end + + it "returns nil when input is invalid" do + expect(subject.path_to_shell("")).to be nil + expect(subject.path_to_shell("@@@@@@")).to be nil + expect(subject.path_to_shell("invalid_shell-4.2")).to be nil + end + end + + specify "::sh_quote" do + expect(subject.sh_quote("")).to eq("''") + expect(subject.sh_quote("\\")).to eq("\\\\") + expect(subject.sh_quote("\n")).to eq("'\n'") + expect(subject.sh_quote("$")).to eq("\\$") + expect(subject.sh_quote("word")).to eq("word") + end + + specify "::csh_quote" do + expect(subject.csh_quote("")).to eq("''") + expect(subject.csh_quote("\\")).to eq("\\\\") + # note this test is different than for sh + expect(subject.csh_quote("\n")).to eq("'\\\n'") + expect(subject.csh_quote("$")).to eq("\\$") + expect(subject.csh_quote("word")).to eq("word") + end + + describe "::prepend_path_in_shell_profile" do + let(:path) { "/my/path" } + + it "supports Tcsh" do + ENV["SHELL"] = "/bin/tcsh" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'setenv PATH #{path}:$") + end + + it "supports Bash" do + ENV["SHELL"] = "/bin/bash" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'export PATH=\"#{path}:$") + end + + it "supports Fish" do + ENV["SHELL"] = "/usr/local/bin/fish" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'set -g fish_user_paths \"#{path}\" $fish_user_paths' >>") + end + end +end diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..040ad630bea05ae0c603c447617787061723631d --- /dev/null +++ b/Library/Homebrew/test/utils_spec.rb @@ -0,0 +1,277 @@ +require "utils" + +describe "globally-scoped helper methods" do + let(:dir) { @dir = Pathname.new(Dir.mktmpdir) } + + after(:each) { dir.rmtree unless @dir.nil? } + + def esc(code) + /(\e\[\d+m)*\e\[#{code}m/ + end + + describe "#ofail" do + it "sets Homebrew.failed to true" do + expect { + ofail "foo" + }.to output("Error: foo\n").to_stderr + + expect(Homebrew).to have_failed + end + end + + describe "#odie" do + it "exits with 1" do + expect(self).to receive(:exit).and_return(1) + expect { + odie "foo" + }.to output("Error: foo\n").to_stderr + end + end + + describe "#pretty_installed" do + subject { pretty_installed("foo") } + + context "when $stdout is a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + + context "with HOMEBREW_NO_EMOJI unset" do + before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + + it "returns a string with a colored checkmark" do + expect(subject) + .to match(/#{esc 1}foo #{esc 32}✔#{esc 0}/) + end + end + + context "with HOMEBREW_NO_EMOJI set" do + before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + + it "returns a string with colored info" do + expect(subject) + .to match(/#{esc 1}foo \(installed\)#{esc 0}/) + end + end + end + + context "when $stdout is not a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + + it "returns plain text" do + expect(subject).to eq("foo") + end + end + end + + describe "#pretty_uninstalled" do + subject { pretty_uninstalled("foo") } + + context "when $stdout is a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + + context "with HOMEBREW_NO_EMOJI unset" do + before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + + it "returns a string with a colored checkmark" do + expect(subject) + .to match(/#{esc 1}foo #{esc 31}✘#{esc 0}/) + end + end + + context "with HOMEBREW_NO_EMOJI set" do + before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + + it "returns a string with colored info" do + expect(subject) + .to match(/#{esc 1}foo \(uninstalled\)#{esc 0}/) + end + end + end + + context "when $stdout is not a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + + it "returns plain text" do + expect(subject).to eq("foo") + end + end + end + + describe "#interactive_shell" do + let(:shell) { dir/"myshell" } + + it "starts an interactive shell session" do + IO.write shell, <<-EOS.undent + #!/bin/sh + echo called > "#{dir}/called" + EOS + + FileUtils.chmod 0755, shell + + ENV["SHELL"] = shell + + expect { interactive_shell }.not_to raise_error + expect(dir/"called").to exist + end + end + + describe "#with_custom_locale" do + it "temporarily overrides the system locale" do + ENV["LC_ALL"] = "en_US.UTF-8" + + with_custom_locale("C") do + expect(ENV["LC_ALL"]).to eq("C") + end + + expect(ENV["LC_ALL"]).to eq("en_US.UTF-8") + end + end + + describe "#run_as_not_developer" do + it "temporarily unsets HOMEBREW_DEVELOPER" do + ENV["HOMEBREW_DEVELOPER"] = "foo" + + run_as_not_developer do + expect(ENV["HOMEBREW_DEVELOPER"]).to be nil + end + + expect(ENV["HOMEBREW_DEVELOPER"]).to eq("foo") + end + end + + describe "#which" do + let(:cmd) { dir/"foo" } + + before(:each) { FileUtils.touch cmd } + + it "returns the first executable that is found" do + cmd.chmod 0744 + expect(which(File.basename(cmd), File.dirname(cmd))).to eq(cmd) + end + + it "skips non-executables" do + expect(which(File.basename(cmd), File.dirname(cmd))).to be nil + end + + it "skips malformed path and doesn't fail" do + # 'which' should not fail if a path is malformed + # see https://github.com/Homebrew/legacy-homebrew/issues/32789 for an example + cmd.chmod 0744 + + # ~~ will fail because ~foo resolves to foo's home and there is no '~' user + path = ["~~", File.dirname(cmd)].join(File::PATH_SEPARATOR) + expect(which(File.basename(cmd), path)).to eq(cmd) + end + end + + describe "#which_all" do + let(:cmd1) { dir/"foo" } + let(:cmd2) { dir/"bar/foo" } + let(:cmd3) { dir/"bar/baz/foo" } + + before(:each) do + (dir/"bar/baz").mkpath + + FileUtils.touch cmd2 + + [cmd1, cmd3].each do |cmd| + FileUtils.touch cmd + cmd.chmod 0744 + end + end + + it "returns an array of all executables that are found" do + path = [ + "#{dir}/bar/baz", + "#{dir}/baz:#{dir}", + "~baduserpath", + ].join(File::PATH_SEPARATOR) + expect(which_all("foo", path)).to eq([cmd3, cmd1]) + end + end + + specify "#which_editor" do + ENV["HOMEBREW_EDITOR"] = "vemate" + expect(which_editor).to eq("vemate") + end + + specify "#gzip" do + Dir.mktmpdir do |path| + path = Pathname.new(path) + somefile = path/"somefile" + FileUtils.touch somefile + expect(gzip(somefile)[0].to_s).to eq("#{somefile}.gz") + expect(Pathname.new("#{somefile}.gz")).to exist + end + end + + specify "#capture_stderr" do + err = capture_stderr do + $stderr.print "test" + end + + expect(err).to eq("test") + end + + describe "#pretty_duration" do + it "converts seconds to a human-readable string" do + expect(pretty_duration(1)).to eq("1 second") + expect(pretty_duration(2.5)).to eq("2 seconds") + expect(pretty_duration(42)).to eq("42 seconds") + expect(pretty_duration(240)).to eq("4 minutes") + expect(pretty_duration(252.45)).to eq("4 minutes 12 seconds") + end + end + + specify "#plural" do + expect(plural(1)).to eq("") + expect(plural(0)).to eq("s") + expect(plural(42)).to eq("s") + expect(plural(42, "")).to eq("") + end + + specify "#disk_usage_readable" do + expect(disk_usage_readable(1)).to eq("1B") + expect(disk_usage_readable(1000)).to eq("1000B") + expect(disk_usage_readable(1024)).to eq("1K") + expect(disk_usage_readable(1025)).to eq("1K") + expect(disk_usage_readable(4_404_020)).to eq("4.2M") + expect(disk_usage_readable(4_509_715_660)).to eq("4.2G") + end + + describe "#number_readable" do + it "returns a string with thousands separators" do + expect(number_readable(1)).to eq("1") + expect(number_readable(1_000)).to eq("1,000") + expect(number_readable(1_000_000)).to eq("1,000,000") + end + end + + specify "#truncate_text_to_approximate_size" do + glue = "\n[...snip...]\n" # hard-coded copy from truncate_text_to_approximate_size + n = 20 + long_s = "x" * 40 + + s = truncate_text_to_approximate_size(long_s, n) + expect(s.length).to eq(n) + expect(s).to match(/^x+#{Regexp.escape(glue)}x+$/) + + s = truncate_text_to_approximate_size(long_s, n, front_weight: 0.0) + expect(s).to eq(glue + ("x" * (n - glue.length))) + + s = truncate_text_to_approximate_size(long_s, n, front_weight: 1.0) + expect(s).to eq(("x" * (n - glue.length)) + glue) + end + + describe "#odeprecated" do + it "raises a MethodDeprecatedError" do + ENV.delete("HOMEBREW_DEVELOPER") + expect { + odeprecated( + "method", "replacement", + caller: ["#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/"], + disable: true + ) + }.to raise_error(MethodDeprecatedError, %r{method.*replacement.*homebrew/homebrew-core.*homebrew/core}m) + end + end +end diff --git a/Library/Homebrew/test/utils_test.rb b/Library/Homebrew/test/utils_test.rb deleted file mode 100644 index 1f2fb7b55f7f50511e2658d287dc8c1a6d9c3af7..0000000000000000000000000000000000000000 --- a/Library/Homebrew/test/utils_test.rb +++ /dev/null @@ -1,252 +0,0 @@ -require "testing_env" -require "utils" -require "tempfile" -require "utils/shell" - -class UtilTests < Homebrew::TestCase - def setup - super - @dir = Pathname.new(mktmpdir) - end - - def esc(code) - /(\e\[\d+m)*\e\[#{code}m/ - end - - def test_ofail - shutup { ofail "foo" } - assert Homebrew.failed? - ensure - Homebrew.failed = false - end - - def test_odie - expects(:exit).returns 1 - shutup { odie "foo" } - end - - def test_pretty_installed - $stdout.stubs(:tty?).returns true - ENV.delete("HOMEBREW_NO_EMOJI") - tty_with_emoji_output = /\A#{esc 1}foo #{esc 32}✔#{esc 0}\Z/ - assert_match tty_with_emoji_output, pretty_installed("foo") - - ENV["HOMEBREW_NO_EMOJI"] = "1" - tty_no_emoji_output = /\A#{esc 1}foo \(installed\)#{esc 0}\Z/ - assert_match tty_no_emoji_output, pretty_installed("foo") - - $stdout.stubs(:tty?).returns false - assert_equal "foo", pretty_installed("foo") - end - - def test_pretty_uninstalled - $stdout.stubs(:tty?).returns true - ENV.delete("HOMEBREW_NO_EMOJI") - tty_with_emoji_output = /\A#{esc 1}foo #{esc 31}✘#{esc 0}\Z/ - assert_match tty_with_emoji_output, pretty_uninstalled("foo") - - ENV["HOMEBREW_NO_EMOJI"] = "1" - tty_no_emoji_output = /\A#{esc 1}foo \(uninstalled\)#{esc 0}\Z/ - assert_match tty_no_emoji_output, pretty_uninstalled("foo") - - $stdout.stubs(:tty?).returns false - assert_equal "foo", pretty_uninstalled("foo") - end - - def test_interactive_shell - mktmpdir do |path| - shell = "#{path}/myshell" - File.open(shell, "w") do |file| - file.write "#!/bin/sh\necho called > #{path}/called\n" - end - FileUtils.chmod 0755, shell - ENV["SHELL"] = shell - assert_nothing_raised { interactive_shell } - assert File.exist? "#{path}/called" - end - end - - def test_with_custom_locale - ENV["LC_ALL"] = "en_US.UTF-8" - with_custom_locale("C") do - assert_equal "C", ENV["LC_ALL"] - end - assert_equal "en_US.UTF-8", ENV["LC_ALL"] - end - - def test_run_as_not_developer - ENV["HOMEBREW_DEVELOPER"] = "foo" - run_as_not_developer do - assert_nil ENV["HOMEBREW_DEVELOPER"] - end - assert_equal "foo", ENV["HOMEBREW_DEVELOPER"] - end - - def test_put_columns_empty - out, err = capture_io do - puts Formatter.columns([]) - end - - assert_equal out, "\n" - assert_equal err, "" - end - - def test_which - cmd = @dir/"foo" - FileUtils.touch cmd - cmd.chmod 0744 - assert_equal Pathname.new(cmd), - which(File.basename(cmd), File.dirname(cmd)) - end - - def test_which_skip_non_executables - cmd = @dir/"foo" - FileUtils.touch cmd - assert_nil which(File.basename(cmd), File.dirname(cmd)) - end - - def test_which_skip_malformed_path - # 'which' should not fail if a path is malformed - # see https://github.com/Homebrew/legacy-homebrew/issues/32789 for an example - cmd = @dir/"foo" - FileUtils.touch cmd - cmd.chmod 0744 - - # ~~ will fail because ~foo resolves to foo's home and there is no '~' user - # here - assert_equal Pathname.new(cmd), - which(File.basename(cmd), "~~#{File::PATH_SEPARATOR}#{File.dirname(cmd)}") - end - - def test_which_all - (@dir/"bar/baz").mkpath - cmd1 = @dir/"foo" - cmd2 = @dir/"bar/foo" - cmd3 = @dir/"bar/baz/foo" - FileUtils.touch cmd2 - [cmd1, cmd3].each do |cmd| - FileUtils.touch cmd - cmd.chmod 0744 - end - assert_equal [cmd3, cmd1], - which_all("foo", "#{@dir}/bar/baz:#{@dir}/baz:#{@dir}:~baduserpath") - end - - def test_which_editor - ENV["HOMEBREW_EDITOR"] = "vemate" - assert_equal "vemate", which_editor - end - - def test_gzip - mktmpdir do |path| - somefile = "#{path}/somefile" - FileUtils.touch somefile - assert_equal "#{somefile}.gz", - gzip(somefile)[0].to_s - assert File.exist?("#{somefile}.gz") - end - end - - def test_capture_stderr - assert_equal "test\n", capture_stderr { $stderr.puts "test" } - end - - def test_shell_profile - ENV["SHELL"] = "/bin/sh" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/bash" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/another_shell" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/zsh" - assert_equal "~/.zshrc", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/ksh" - assert_equal "~/.kshrc", Utils::Shell.shell_profile - end - - def test_popen_read - out = Utils.popen_read("sh", "-c", "echo success").chomp - assert_equal "success", out - assert_predicate $?, :success? - end - - def test_popen_read_with_block - out = Utils.popen_read("sh", "-c", "echo success") do |pipe| - pipe.read.chomp - end - assert_equal "success", out - assert_predicate $?, :success? - end - - def test_popen_write_with_block - Utils.popen_write("grep", "-q", "success") do |pipe| - pipe.write("success\n") - end - assert_predicate $?, :success? - end - - def test_pretty_duration - assert_equal "1 second", pretty_duration(1) - assert_equal "2 seconds", pretty_duration(2.5) - assert_equal "42 seconds", pretty_duration(42) - assert_equal "4 minutes", pretty_duration(240) - assert_equal "4 minutes 12 seconds", pretty_duration(252.45) - end - - def test_plural - assert_equal "", plural(1) - assert_equal "s", plural(0) - assert_equal "s", plural(42) - assert_equal "", plural(42, "") - end - - def test_disk_usage_readable - assert_equal "1B", disk_usage_readable(1) - assert_equal "1000B", disk_usage_readable(1000) - assert_equal "1K", disk_usage_readable(1024) - assert_equal "1K", disk_usage_readable(1025) - assert_equal "4.2M", disk_usage_readable(4_404_020) - assert_equal "4.2G", disk_usage_readable(4_509_715_660) - end - - def test_number_readable - assert_equal "1", number_readable(1) - assert_equal "1,000", number_readable(1_000) - assert_equal "1,000,000", number_readable(1_000_000) - end - - def test_truncate_text_to_approximate_size - glue = "\n[...snip...]\n" # hard-coded copy from truncate_text_to_approximate_size - n = 20 - long_s = "x" * 40 - s = truncate_text_to_approximate_size(long_s, n) - assert_equal n, s.length - assert_match(/^x+#{Regexp.escape(glue)}x+$/, s) - s = truncate_text_to_approximate_size(long_s, n, front_weight: 0.0) - assert_equal glue + ("x" * (n - glue.length)), s - s = truncate_text_to_approximate_size(long_s, n, front_weight: 1.0) - assert_equal(("x" * (n - glue.length)) + glue, s) - end - - def test_odeprecated - ENV.delete("HOMEBREW_DEVELOPER") - e = assert_raises(MethodDeprecatedError) do - odeprecated("method", "replacement", - caller: ["#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/"], - disable: true) - end - assert_match "method", e.message - assert_match "replacement", e.message - assert_match "homebrew/homebrew-core", e.message - assert_match "homebrew/core", e.message - end - - def test_bottles_bintray - assert_equal "openssl:1.1", Utils::Bottles::Bintray.package("openssl@1.1") - assert_equal "gtkx", Utils::Bottles::Bintray.package("gtk+") - assert_equal "llvm", Utils::Bottles::Bintray.package("llvm") - - tap = Tap.new("homebrew", "bintray-test") - assert_equal "bottles-bintray-test", Utils::Bottles::Bintray.repository(tap) - end -end