aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/test
diff options
context:
space:
mode:
Diffstat (limited to 'Library/Homebrew/test')
-rw-r--r--Library/Homebrew/test/analytics_test.rb26
-rw-r--r--Library/Homebrew/test/blacklist_spec.rb18
-rw-r--r--Library/Homebrew/test/cmd/analytics_spec.rb52
-rw-r--r--Library/Homebrew/test/cmd/search_remote_tap_spec.rb19
-rw-r--r--Library/Homebrew/test/compiler_failure_spec.rb37
-rw-r--r--Library/Homebrew/test/compiler_failure_test.rb52
-rw-r--r--Library/Homebrew/test/compiler_selector_spec.rb122
-rw-r--r--Library/Homebrew/test/compiler_selector_test.rb117
-rw-r--r--Library/Homebrew/test/dependency_expansion_spec.rb136
-rw-r--r--Library/Homebrew/test/dependency_expansion_test.rb138
-rw-r--r--Library/Homebrew/test/diagnostic_spec.rb188
-rw-r--r--Library/Homebrew/test/diagnostic_test.rb192
-rw-r--r--Library/Homebrew/test/formula_lock_spec.rb34
-rw-r--r--Library/Homebrew/test/formula_lock_test.rb23
-rw-r--r--Library/Homebrew/test/formula_pin_spec.rb41
-rw-r--r--Library/Homebrew/test/formula_pin_test.rb51
-rw-r--r--Library/Homebrew/test/formulary_spec.rb219
-rw-r--r--Library/Homebrew/test/formulary_test.rb189
-rw-r--r--Library/Homebrew/test/gpg2_requirement_spec.rb23
-rw-r--r--Library/Homebrew/test/gpg2_requirement_test.rb25
-rw-r--r--Library/Homebrew/test/inreplace_spec.rb251
-rw-r--r--Library/Homebrew/test/inreplace_test.rb119
-rw-r--r--Library/Homebrew/test/java_requirement_spec.rb107
-rw-r--r--Library/Homebrew/test/java_requirement_test.rb50
-rw-r--r--Library/Homebrew/test/os/mac/blacklist_test.rb12
-rw-r--r--Library/Homebrew/test/os/mac/bottle_tag_test.rb79
-rw-r--r--Library/Homebrew/test/os/mac/java_requirement_spec.rb34
-rw-r--r--Library/Homebrew/test/os/mac/java_requirement_test.rb31
-rw-r--r--Library/Homebrew/test/os/mac/keg_spec.rb32
-rw-r--r--Library/Homebrew/test/os/mac/keg_test.rb69
-rw-r--r--Library/Homebrew/test/os/mac/language_test.rb19
-rw-r--r--Library/Homebrew/test/os/mac/mach_spec.rb198
-rw-r--r--Library/Homebrew/test/os/mac/mach_test.rb211
-rw-r--r--Library/Homebrew/test/os/mac/version_spec.rb51
-rw-r--r--Library/Homebrew/test/os/mac/version_test.rb54
-rw-r--r--Library/Homebrew/test/os/mac_spec.rb22
-rw-r--r--Library/Homebrew/test/pathname_spec.rb300
-rw-r--r--Library/Homebrew/test/pathname_test.rb263
-rw-r--r--Library/Homebrew/test/resource_spec.rb147
-rw-r--r--Library/Homebrew/test/resource_test.rb133
-rw-r--r--Library/Homebrew/test/search_remote_tap_test.rb19
-rw-r--r--Library/Homebrew/test/shell_test.rb56
-rw-r--r--Library/Homebrew/test/software_spec_spec.rb184
-rw-r--r--Library/Homebrew/test/software_spec_test.rb184
-rw-r--r--Library/Homebrew/test/spec_helper.rb11
-rw-r--r--Library/Homebrew/test/string_spec.rb49
-rw-r--r--Library/Homebrew/test/string_test.rb40
-rw-r--r--Library/Homebrew/test/support/helper/fixtures.rb13
-rw-r--r--Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb94
-rw-r--r--Library/Homebrew/test/utils/bottles/bintray_spec.rb18
-rw-r--r--Library/Homebrew/test/utils/bottles/bottles_spec.rb80
-rw-r--r--Library/Homebrew/test/utils/popen_spec.rb28
-rw-r--r--Library/Homebrew/test/utils/shell_spec.rb93
-rw-r--r--Library/Homebrew/test/utils_spec.rb277
-rw-r--r--Library/Homebrew/test/utils_test.rb252
55 files changed, 2870 insertions, 2412 deletions
diff --git a/Library/Homebrew/test/analytics_test.rb b/Library/Homebrew/test/analytics_test.rb
deleted file mode 100644
index 37040f3cd..000000000
--- 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 89d254893..01882167d 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 000000000..aed3a7a33
--- /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 000000000..99c2cc20b
--- /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 000000000..b4fab0b27
--- /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 c0b74d128..000000000
--- 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 000000000..0f6f6b5f2
--- /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 aa1a6f97e..000000000
--- 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 000000000..f955237a9
--- /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 58a731121..000000000
--- 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 000000000..e749a3b0f
--- /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 7a1fb25f7..000000000
--- 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 000000000..9b5ece813
--- /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 13244555d..000000000
--- 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 000000000..909bfbc2b
--- /dev/null
+++ b/Library/Homebrew/test/formula_pin_spec.rb
@@ -0,0 +1,41 @@
+require "formula_pin"
+
+describe FormulaPin do
+ subject { described_class.new(formula) }
+ let(:name) { "double" }
+ let(:formula) { double(Formula, name: name, rack: HOMEBREW_CELLAR/name) }
+
+ before(:each) do
+ formula.rack.mkpath
+
+ allow(formula).to receive(:installed_prefixes) do
+ formula.rack.directory? ? formula.rack.subdirs : []
+ end
+
+ allow(formula).to receive(:installed_kegs) do
+ formula.installed_prefixes.map { |prefix| Keg.new(prefix) }
+ end
+ end
+
+ it "is not pinnable by default" do
+ expect(subject).not_to be_pinnable
+ end
+
+ it "is pinnable if the Keg exists" do
+ (formula.rack/"0.1").mkpath
+ expect(subject).to be_pinnable
+ end
+
+ specify "#pin and #unpin" do
+ (formula.rack/"0.1").mkpath
+
+ subject.pin
+ expect(subject).to be_pinned
+ expect(HOMEBREW_PINNED_KEGS/name).to be_a_directory
+ expect(HOMEBREW_PINNED_KEGS.children.count).to eq(1)
+
+ subject.unpin
+ expect(subject).not_to be_pinned
+ expect(HOMEBREW_PINNED_KEGS).not_to be_a_directory
+ end
+end
diff --git a/Library/Homebrew/test/formula_pin_test.rb b/Library/Homebrew/test/formula_pin_test.rb
deleted file mode 100644
index 7e3c7efa0..000000000
--- a/Library/Homebrew/test/formula_pin_test.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require "testing_env"
-require "formula_pin"
-
-class FormulaPinTests < Homebrew::TestCase
- class FormulaDouble
- def name
- "double"
- end
-
- def rack
- HOMEBREW_CELLAR/name
- end
-
- def installed_prefixes
- rack.directory? ? rack.subdirs : []
- end
-
- def installed_kegs
- installed_prefixes.map { |d| Keg.new d }
- end
- end
-
- def setup
- super
- @f = FormulaDouble.new
- @pin = FormulaPin.new(@f)
- @f.rack.mkpath
- end
-
- def test_not_pinnable
- refute_predicate @pin, :pinnable?
- end
-
- def test_pinnable_if_kegs_exist
- (@f.rack/"0.1").mkpath
- assert_predicate @pin, :pinnable?
- end
-
- def test_unpin
- (@f.rack/"0.1").mkpath
- @pin.pin
-
- assert_predicate @pin, :pinned?
- assert_equal 1, HOMEBREW_PINNED_KEGS.children.length
-
- @pin.unpin
-
- refute_predicate @pin, :pinned?
- refute_predicate HOMEBREW_PINNED_KEGS, :directory?
- end
-end
diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb
new file mode 100644
index 000000000..8e9d23589
--- /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 ea7ecf8d0..000000000
--- 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 000000000..f46b31196
--- /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 3297c2851..000000000
--- 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 000000000..5be44f50d
--- /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 0e62f9d3f..000000000
--- 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 000000000..5adf64c7c
--- /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 d0b51f92c..000000000
--- 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 26dd84ed9..000000000
--- 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 996bd4d53..000000000
--- 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 000000000..f6404db92
--- /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 83c1af95c..000000000
--- 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 000000000..562c2ba6a
--- /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 d1103415d..000000000
--- 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 e328db5e0..000000000
--- 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 000000000..5c9aafcbb
--- /dev/null
+++ b/Library/Homebrew/test/os/mac/mach_spec.rb
@@ -0,0 +1,198 @@
+describe "Mach-O Pathname tests" do
+ specify "fat dylib" do
+ pn = dylib_path("fat")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn.arch).to eq(:universal)
+ end
+
+ specify "i386 dylib" do
+ pn = dylib_path("i386")
+ expect(pn).not_to be_universal
+ expect(pn).to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "x86_64 dylib" do
+ pn = dylib_path("x86_64")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "Mach-O executable" do
+ pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ end
+
+ specify "fat bundle" do
+ pn = bundle_path("fat")
+ expect(pn).to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "i386 bundle" do
+ pn = bundle_path("i386")
+ expect(pn).not_to be_universal
+ expect(pn).to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "x86_64 bundle" do
+ pn = bundle_path("x86_64")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).to be_mach_o_bundle
+ end
+
+ specify "non-Mach-O" do
+ pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz")
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn).not_to be_mach_o_bundle
+ expect(pn.arch).to eq(:dunno)
+ end
+end
+
+describe ArchitectureListExtension do
+ let(:archs) { [:i386, :x86_64, :ppc7400, :ppc64].extend(described_class) }
+
+ specify "universal checks" do
+ expect(archs).to be_universal
+ expect(archs).to be_intel_universal
+ expect(archs).to be_ppc_universal
+ expect(archs).to be_cross_universal
+ expect(archs).to be_fat
+
+ non_universal = [:i386].extend(described_class)
+ expect(non_universal).not_to be_universal
+
+ intel_only = [:i386, :x86_64].extend(described_class)
+ expect(intel_only).to be_universal
+ expect(intel_only).not_to be_ppc_universal
+ expect(intel_only).not_to be_cross_universal
+
+ ppc_only = [:ppc970, :ppc64].extend(described_class)
+ expect(ppc_only).to be_universal
+ expect(ppc_only).not_to be_intel_universal
+ expect(ppc_only).not_to be_cross_universal
+
+ cross = [:ppc7400, :i386].extend(described_class)
+ expect(cross).to be_universal
+ expect(cross).not_to be_intel_universal
+ expect(cross).not_to be_ppc_universal
+ end
+
+ specify "messaging flags" do
+ archs.remove_ppc!
+ expect(archs.length).to eq(2)
+ expect(archs.as_arch_flags).to match(/-arch i386/)
+ expect(archs.as_arch_flags).to match(/-arch x86_64/)
+ end
+
+ specify "architecture flags" do
+ pn = dylib_path("fat")
+ expect(pn.archs).to be_intel_universal
+ expect(pn.archs.as_arch_flags).to eq("-arch x86_64 -arch i386")
+ expect(pn.archs.as_cmake_arch_flags).to eq("x86_64;i386")
+ end
+end
+
+describe "text executables" do
+ let(:pn) { HOMEBREW_PREFIX/"an_executable" }
+
+ after(:each) { pn.unlink }
+
+ specify "simple shebang" do
+ pn.write "#!/bin/sh"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+
+ specify "shebang with options" do
+ pn.write "#! /usr/bin/perl -w"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+
+ specify "malformed shebang" do
+ pn.write " #!"
+ expect(pn).not_to be_universal
+ expect(pn).not_to be_i386
+ expect(pn).not_to be_x86_64
+ expect(pn).not_to be_ppc7400
+ expect(pn).not_to be_ppc64
+ expect(pn).not_to be_dylib
+ expect(pn).not_to be_mach_o_executable
+ expect(pn).not_to be_text_executable
+ expect(pn.archs).to eq([])
+ expect(pn.arch).to eq(:dunno)
+ end
+end
diff --git a/Library/Homebrew/test/os/mac/mach_test.rb b/Library/Homebrew/test/os/mac/mach_test.rb
deleted file mode 100644
index ed0424be6..000000000
--- a/Library/Homebrew/test/os/mac/mach_test.rb
+++ /dev/null
@@ -1,211 +0,0 @@
-require "testing_env"
-
-class MachOPathnameTests < Homebrew::TestCase
- def test_fat_dylib
- pn = dylib_path("fat")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_equal :universal, pn.arch
- end
-
- def test_i386_dylib
- pn = dylib_path("i386")
- refute_predicate pn, :universal?
- assert_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_x86_64_dylib
- pn = dylib_path("x86_64")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- assert_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- assert_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_mach_o_executable
- pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- assert_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- end
-
- def test_fat_bundle
- pn = bundle_path("fat")
- assert_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_i386_bundle
- pn = bundle_path("i386")
- refute_predicate pn, :universal?
- assert_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_x86_64_bundle
- pn = bundle_path("x86_64")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- assert_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_predicate pn, :mach_o_bundle?
- end
-
- def test_non_mach_o
- pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz")
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- refute_predicate pn, :mach_o_bundle?
- assert_equal :dunno, pn.arch
- end
-end
-
-class ArchitectureListExtensionTests < MachOPathnameTests
- def setup
- super
- @archs = [:i386, :x86_64, :ppc7400, :ppc64].extend(ArchitectureListExtension)
- end
-
- def test_architecture_list_extension_universal_checks
- assert_predicate @archs, :universal?
- assert_predicate @archs, :intel_universal?
- assert_predicate @archs, :ppc_universal?
- assert_predicate @archs, :cross_universal?
- assert_predicate @archs, :fat?
-
- non_universal = [:i386].extend ArchitectureListExtension
- refute_predicate non_universal, :universal?
-
- intel_only = [:i386, :x86_64].extend ArchitectureListExtension
- assert_predicate intel_only, :universal?
- refute_predicate intel_only, :ppc_universal?
- refute_predicate intel_only, :cross_universal?
-
- ppc_only = [:ppc970, :ppc64].extend ArchitectureListExtension
- assert_predicate ppc_only, :universal?
- refute_predicate ppc_only, :intel_universal?
- refute_predicate ppc_only, :cross_universal?
-
- cross = [:ppc7400, :i386].extend ArchitectureListExtension
- assert_predicate cross, :universal?
- refute_predicate cross, :intel_universal?
- refute_predicate cross, :ppc_universal?
- end
-
- def test_architecture_list_extension_massaging_flags
- @archs.remove_ppc!
- assert_equal 2, @archs.length
- assert_match(/-arch i386/, @archs.as_arch_flags)
- assert_match(/-arch x86_64/, @archs.as_arch_flags)
- end
-
- def test_architecture_list_arch_flags_methods
- pn = dylib_path("fat")
- assert_predicate pn.archs, :intel_universal?
- assert_equal "-arch x86_64 -arch i386", pn.archs.as_arch_flags
- assert_equal "x86_64;i386", pn.archs.as_cmake_arch_flags
- end
-end
-
-class TextExecutableTests < Homebrew::TestCase
- attr_reader :pn
-
- def setup
- super
- @pn = HOMEBREW_PREFIX.join("an_executable")
- end
-
- def teardown
- HOMEBREW_PREFIX.join("an_executable").unlink
- super
- end
-
- def test_simple_shebang
- pn.write "#!/bin/sh"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- assert_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-
- def test_shebang_with_options
- pn.write "#! /usr/bin/perl -w"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- assert_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-
- def test_malformed_shebang
- pn.write " #!"
- refute_predicate pn, :universal?
- refute_predicate pn, :i386?
- refute_predicate pn, :x86_64?
- refute_predicate pn, :ppc7400?
- refute_predicate pn, :ppc64?
- refute_predicate pn, :dylib?
- refute_predicate pn, :mach_o_executable?
- refute_predicate pn, :text_executable?
- assert_equal [], pn.archs
- assert_equal :dunno, pn.arch
- end
-end
diff --git a/Library/Homebrew/test/os/mac/version_spec.rb b/Library/Homebrew/test/os/mac/version_spec.rb
new file mode 100644
index 000000000..797207b67
--- /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 ba4217691..000000000
--- 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 000000000..641782451
--- /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 000000000..da12d4347
--- /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 b48a26fbd..000000000
--- 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 000000000..6a0419538
--- /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 d982a7c33..000000000
--- 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 9dd9ee654..000000000
--- 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 970489702..000000000
--- 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 000000000..5fd4f598a
--- /dev/null
+++ b/Library/Homebrew/test/software_spec_spec.rb
@@ -0,0 +1,184 @@
+require "software_spec"
+
+RSpec::Matchers.alias_matcher :have_defined_resource, :be_resource_defined
+RSpec::Matchers.alias_matcher :have_defined_option, :be_option_defined
+
+describe SoftwareSpec do
+ let(:owner) { double(name: "some_name", full_name: "some_name", tap: "homebrew/core") }
+
+ describe "#resource" do
+ it "defines a resource" do
+ subject.resource("foo") { url "foo-1.0" }
+ expect(subject).to have_defined_resource("foo")
+ end
+
+ it "sets itself to be the resource's owner" do
+ subject.resource("foo") { url "foo-1.0" }
+ subject.owner = owner
+ subject.resources.each_value do |r|
+ expect(r.owner).to eq(subject)
+ end
+ end
+
+ it "receives the owner's version if it has no own version" do
+ subject.url("foo-42")
+ subject.resource("bar") { url "bar" }
+ subject.owner = owner
+
+ expect(subject.resource("bar").version).to eq("42")
+ end
+
+ it "raises an error when duplicate resources are defined" do
+ subject.resource("foo") { url "foo-1.0" }
+ expect {
+ subject.resource("foo") { url "foo-1.0" }
+ }.to raise_error(DuplicateResourceError)
+ end
+
+ it "raises an error when accessing missing resources" do
+ subject.owner = owner
+ expect {
+ subject.resource("foo")
+ }.to raise_error(ResourceMissingError)
+ end
+ end
+
+ describe "#owner" do
+ it "sets the owner" do
+ subject.owner = owner
+ expect(subject.owner).to eq(owner)
+ end
+
+ it "sets the name" do
+ subject.owner = owner
+ expect(subject.name).to eq(owner.name)
+ end
+ end
+
+ describe "#option" do
+ it "defines an option" do
+ subject.option("foo")
+ expect(subject).to have_defined_option("foo")
+ end
+
+ it "raises an error when it begins with dashes" do
+ expect {
+ subject.option("--foo")
+ }.to raise_error(ArgumentError)
+ end
+
+ it "raises an error when name is empty" do
+ expect {
+ subject.option("")
+ }.to raise_error(ArgumentError)
+ end
+
+ it "special cases the cxx11 option" do
+ subject.option(:cxx11)
+ expect(subject).to have_defined_option("c++11")
+ expect(subject).not_to have_defined_option("cxx11")
+ end
+
+ it "supports options with descriptions" do
+ subject.option("bar", "description")
+ expect(subject.options.first.description).to eq("description")
+ end
+
+ it "defaults to an empty string when no description is given" do
+ subject.option("foo")
+ expect(subject.options.first.description).to eq("")
+ end
+ end
+
+ describe "#deprecated_option" do
+ it "allows specifying deprecated options" do
+ subject.deprecated_option("foo" => "bar")
+ expect(subject.deprecated_options).not_to be_empty
+ expect(subject.deprecated_options.first.old).to eq("foo")
+ expect(subject.deprecated_options.first.current).to eq("bar")
+ end
+
+ it "allows specifying deprecated options as a Hash from an Array/String to an Array/String" do
+ subject.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"])
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo1", "bar1"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo2", "bar1"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar2"))
+ expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar3"))
+ end
+
+ it "raises an error when empty" do
+ expect {
+ subject.deprecated_option({})
+ }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe "#depends_on" do
+ it "allows specifying dependencies" do
+ subject.depends_on("foo")
+ expect(subject.deps.first.name).to eq("foo")
+ end
+
+ it "allows specifying optional dependencies" do
+ subject.depends_on "foo" => :optional
+ expect(subject).to have_defined_option("with-foo")
+ end
+
+ it "allows specifying recommended dependencies" do
+ subject.depends_on "bar" => :recommended
+ expect(subject).to have_defined_option("without-bar")
+ end
+ end
+
+ specify "explicit options override defaupt depends_on option description" do
+ subject.option("with-foo", "blah")
+ subject.depends_on("foo" => :optional)
+ expect(subject.options.first.description).to eq("blah")
+ end
+
+ describe "#patch" do
+ it "adds a patch" do
+ subject.patch(:p1, :DATA)
+ expect(subject.patches.count).to eq(1)
+ expect(subject.patches.first.strip).to eq(:p1)
+ end
+ end
+end
+
+describe HeadSoftwareSpec do
+ specify "#version" do
+ expect(subject.version).to eq(Version.create("HEAD"))
+ end
+
+ specify "#verify_download_integrity" do
+ expect(subject.verify_download_integrity(Object.new)).to be nil
+ end
+end
+
+describe BottleSpecification do
+ specify "#sha256" do
+ checksums = {
+ snow_leopard_32: "deadbeef" * 8,
+ snow_leopard: "faceb00c" * 8,
+ lion: "baadf00d" * 8,
+ mountain_lion: "8badf00d" * 8,
+ }
+
+ checksums.each_pair do |cat, digest|
+ subject.sha256(digest => cat)
+ end
+
+ checksums.each_pair do |cat, digest|
+ checksum, = subject.checksum_for(cat)
+ expect(Checksum.new(:sha256, digest)).to eq(checksum)
+ end
+ end
+
+ %w[root_url prefix cellar rebuild].each do |method|
+ specify "##{method}" do
+ object = Object.new
+ subject.public_send(method, object)
+ expect(subject.public_send(method)).to eq(object)
+ end
+ end
+end
diff --git a/Library/Homebrew/test/software_spec_test.rb b/Library/Homebrew/test/software_spec_test.rb
deleted file mode 100644
index 026265a4a..000000000
--- a/Library/Homebrew/test/software_spec_test.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-require "testing_env"
-require "software_spec"
-
-class SoftwareSpecTests < Homebrew::TestCase
- def setup
- super
- @spec = SoftwareSpec.new
- end
-
- def test_resource
- @spec.resource("foo") { url "foo-1.0" }
- assert @spec.resource_defined?("foo")
- end
-
- def test_raises_when_duplicate_resources_are_defined
- @spec.resource("foo") { url "foo-1.0" }
- assert_raises(DuplicateResourceError) do
- @spec.resource("foo") { url "foo-1.0" }
- end
- end
-
- def test_raises_when_accessing_missing_resources
- @spec.owner = Class.new do
- def name
- "test"
- end
-
- def full_name
- "test"
- end
-
- def tap
- "homebrew/core"
- end
- end.new
- assert_raises(ResourceMissingError) { @spec.resource("foo") }
- end
-
- def test_set_owner
- owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- @spec.owner = owner
- assert_equal owner, @spec.owner
- end
-
- def test_resource_owner
- @spec.resource("foo") { url "foo-1.0" }
- @spec.owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- assert_equal "some_name", @spec.name
- @spec.resources.each_value { |r| assert_equal @spec, r.owner }
- end
-
- def test_resource_without_version_receives_owners_version
- @spec.url("foo-42")
- @spec.resource("bar") { url "bar" }
- @spec.owner = stub name: "some_name",
- full_name: "some_name",
- tap: "homebrew/core"
- assert_version_equal "42", @spec.resource("bar").version
- end
-
- def test_option
- @spec.option("foo")
- assert @spec.option_defined?("foo")
- end
-
- def test_option_raises_when_begins_with_dashes
- assert_raises(ArgumentError) { @spec.option("--foo") }
- end
-
- def test_option_raises_when_name_empty
- assert_raises(ArgumentError) { @spec.option("") }
- end
-
- def test_cxx11_option_special_case
- @spec.option(:cxx11)
- assert @spec.option_defined?("c++11")
- refute @spec.option_defined?("cxx11")
- end
-
- def test_option_description
- @spec.option("bar", "description")
- assert_equal "description", @spec.options.first.description
- end
-
- def test_option_description_defaults_to_empty_string
- @spec.option("foo")
- assert_equal "", @spec.options.first.description
- end
-
- def test_deprecated_option
- @spec.deprecated_option("foo" => "bar")
- refute_empty @spec.deprecated_options
- assert_equal "foo", @spec.deprecated_options.first.old
- assert_equal "bar", @spec.deprecated_options.first.current
- end
-
- def test_deprecated_options
- @spec.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"])
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo1", "bar1")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo2", "bar1")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar2")
- assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar3")
- end
-
- def test_deprecated_option_raises_when_empty
- assert_raises(ArgumentError) { @spec.deprecated_option({}) }
- end
-
- def test_depends_on
- @spec.depends_on("foo")
- assert_equal "foo", @spec.deps.first.name
- end
-
- def test_dependency_option_integration
- @spec.depends_on "foo" => :optional
- @spec.depends_on "bar" => :recommended
- assert @spec.option_defined?("with-foo")
- assert @spec.option_defined?("without-bar")
- end
-
- def test_explicit_options_override_default_dep_option_description
- @spec.option("with-foo", "blah")
- @spec.depends_on("foo" => :optional)
- assert_equal "blah", @spec.options.first.description
- end
-
- def test_patch
- @spec.patch :p1, :DATA
- assert_equal 1, @spec.patches.length
- assert_equal :p1, @spec.patches.first.strip
- end
-end
-
-class HeadSoftwareSpecTests < Homebrew::TestCase
- def setup
- super
- @spec = HeadSoftwareSpec.new
- end
-
- def test_version
- assert_version_equal "HEAD", @spec.version
- end
-
- def test_verify_download_integrity
- assert_nil @spec.verify_download_integrity(Object.new)
- end
-end
-
-class BottleSpecificationTests < Homebrew::TestCase
- def setup
- super
- @spec = BottleSpecification.new
- end
-
- def test_checksum_setters
- checksums = {
- snow_leopard_32: "deadbeef"*8,
- snow_leopard: "faceb00c"*8,
- lion: "baadf00d"*8,
- mountain_lion: "8badf00d"*8,
- }
-
- checksums.each_pair do |cat, digest|
- @spec.sha256(digest => cat)
- end
-
- checksums.each_pair do |cat, digest|
- checksum, = @spec.checksum_for(cat)
- assert_equal Checksum.new(:sha256, digest), checksum
- end
- end
-
- def test_other_setters
- double = Object.new
- %w[root_url prefix cellar rebuild].each do |method|
- @spec.send(method, double)
- assert_equal double, @spec.send(method)
- end
- end
-end
diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb
index 67e5f555a..e4349c8a0 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 000000000..d1b820b66
--- /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 497c4badb..000000000
--- 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 000000000..716fe2008
--- /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 000000000..dd2271a3a
--- /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 000000000..a7dfc00ea
--- /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 000000000..8b54b0b34
--- /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 000000000..e3704a876
--- /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 000000000..c44bd8253
--- /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 000000000..040ad630b
--- /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 1f2fb7b55..000000000
--- 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