diff --git a/Library/Homebrew/test/keg_spec.rb b/Library/Homebrew/test/keg_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f40002dd263dc995ded6e6bce0a17cc600988735
--- /dev/null
+++ b/Library/Homebrew/test/keg_spec.rb
@@ -0,0 +1,486 @@
+require "keg"
+require "stringio"
+
+describe Keg do
+  include FileUtils
+
+  def setup_test_keg(name, version)
+    path = HOMEBREW_CELLAR/name/version
+    (path/"bin").mkpath
+
+    %w[hiworld helloworld goodbye_cruel_world].each do |file|
+      touch path/"bin"/file
+    end
+
+    keg = described_class.new(path)
+    kegs << keg
+    keg
+  end
+
+  around(:each) do |example|
+    begin
+      @old_stdout = $stdout
+      $stdout = StringIO.new
+
+      example.run
+    ensure
+      $stdout = @old_stdout
+    end
+  end
+
+  let(:dst) { HOMEBREW_PREFIX/"bin"/"helloworld" }
+  let(:nonexistent) { Pathname.new("/some/nonexistent/path") }
+  let(:mode) { OpenStruct.new }
+  let!(:keg) { setup_test_keg("foo", "1.0") }
+  let(:kegs) { [] }
+
+  before(:each) do
+    (HOMEBREW_PREFIX/"bin").mkpath
+    (HOMEBREW_PREFIX/"lib").mkpath
+  end
+
+  after(:each) do
+    kegs.each(&:unlink)
+    rmtree HOMEBREW_PREFIX/"lib"
+  end
+
+  specify "::all" do
+    Formula.clear_racks_cache
+    expect(described_class.all).to eq([keg])
+  end
+
+  specify "#empty_installation?" do
+    %w[.DS_Store INSTALL_RECEIPT.json LICENSE.txt].each do |file|
+      touch keg/file
+    end
+
+    expect(keg).to exist
+    expect(keg).to be_a_directory
+    expect(keg).not_to be_an_empty_installation
+
+    (keg/"bin").rmtree
+    expect(keg).to be_an_empty_installation
+  end
+
+  specify "#oldname_opt_record" do
+    expect(keg.oldname_opt_record).to be nil
+    oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
+    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
+    expect(keg.oldname_opt_record).to eq(oldname_opt_record)
+  end
+
+  specify "#remove_oldname_opt_record" do
+    oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
+    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/2.0")
+    keg.remove_oldname_opt_record
+    expect(oldname_opt_record).to be_a_symlink
+    oldname_opt_record.unlink
+    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
+    keg.remove_oldname_opt_record
+    expect(oldname_opt_record).not_to be_a_symlink
+  end
+
+  describe "#link" do
+    it "links a Keg" do
+      expect(keg.link).to eq(3)
+      (HOMEBREW_PREFIX/"bin").children.each do |c|
+        expect(c.readlink).to be_relative
+      end
+    end
+
+    context "with dry run set to true" do
+      it "only prints what would be done" do
+        mode.dry_run = true
+
+        expect(keg.link(mode)).to eq(0)
+        expect(keg).not_to be_linked
+
+        ["hiworld", "helloworld", "goodbye_cruel_world"].each do |file|
+          expect($stdout.string).to match("#{HOMEBREW_PREFIX}/bin/#{file}")
+        end
+        expect($stdout.string.lines.count).to eq(3)
+      end
+    end
+
+    it "fails when already linked" do
+      keg.link
+
+      expect { keg.link }.to raise_error(Keg::AlreadyLinkedError)
+    end
+
+    it "fails when files exist" do
+      touch dst
+
+      expect { keg.link }.to raise_error(Keg::ConflictError)
+    end
+
+    it "ignores broken symlinks at target" do
+      src = keg/"bin"/"helloworld"
+      dst.make_symlink(nonexistent)
+      keg.link
+      expect(dst.readlink).to eq(src.relative_path_from(dst.dirname))
+    end
+
+    context "with overwrite set to true" do
+      it "overwrite existing files" do
+        touch dst
+        mode.overwrite = true
+        expect(keg.link(mode)).to eq(3)
+        expect(keg).to be_linked
+      end
+
+      it "overwrites broken symlinks" do
+        dst.make_symlink "nowhere"
+        mode.overwrite = true
+        expect(keg.link(mode)).to eq(3)
+        expect(keg).to be_linked
+      end
+
+      it "still supports dryrun" do
+        touch dst
+        mode.overwrite = true
+        mode.dry_run = true
+
+        expect(keg.link(mode)).to eq(0)
+        expect(keg).not_to be_linked
+
+        expect($stdout.string).to eq("#{dst}\n")
+      end
+    end
+
+    it "also creates an opt link" do
+      expect(keg).not_to be_optlinked
+      keg.link
+      expect(keg).to be_optlinked
+    end
+
+    specify "pkgconfig directory is created" do
+      link = HOMEBREW_PREFIX/"lib"/"pkgconfig"
+      (keg/"lib"/"pkgconfig").mkpath
+      keg.link
+      expect(link.lstat).to be_a_directory
+    end
+
+    specify "cmake directory is created" do
+      link = HOMEBREW_PREFIX/"lib"/"cmake"
+      (keg/"lib"/"cmake").mkpath
+      keg.link
+      expect(link.lstat).to be_a_directory
+    end
+
+    specify "symlinks are linked directly" do
+      link = HOMEBREW_PREFIX/"lib"/"pkgconfig"
+
+      (keg/"lib"/"example").mkpath
+      (keg/"lib"/"pkgconfig").make_symlink "example"
+      keg.link
+
+      expect(link.resolved_path).to be_a_symlink
+      expect(link.lstat).to be_a_symlink
+    end
+  end
+
+  describe "#unlink" do
+    it "unlinks a Keg" do
+      keg.link
+      expect(dst).to be_a_symlink
+      expect(keg.unlink).to eq(3)
+      expect(dst).not_to be_a_symlink
+    end
+
+    it "prunes empty top-level directories" do
+      mkpath HOMEBREW_PREFIX/"lib/foo/bar"
+      mkpath keg/"lib/foo/bar"
+      touch keg/"lib/foo/bar/file1"
+
+      keg.unlink
+
+      expect(HOMEBREW_PREFIX/"lib/foo").not_to be_a_directory
+    end
+
+    it "ignores .DS_Store when pruning empty directories" do
+      mkpath HOMEBREW_PREFIX/"lib/foo/bar"
+      touch HOMEBREW_PREFIX/"lib/foo/.DS_Store"
+      mkpath keg/"lib/foo/bar"
+      touch keg/"lib/foo/bar/file1"
+
+      keg.unlink
+
+      expect(HOMEBREW_PREFIX/"lib/foo").not_to be_a_directory
+      expect(HOMEBREW_PREFIX/"lib/foo/.DS_Store").not_to exist
+    end
+
+    it "doesn't remove opt link" do
+      keg.link
+      keg.unlink
+      expect(keg).to be_optlinked
+    end
+
+    it "preverves broken symlinks pointing outside the Keg" do
+      keg.link
+      dst.delete
+      dst.make_symlink(nonexistent)
+      keg.unlink
+      expect(dst).to be_a_symlink
+    end
+
+    it "preverves broken symlinks pointing into the Keg" do
+      keg.link
+      dst.resolved_path.delete
+      keg.unlink
+      expect(dst).to be_a_symlink
+    end
+
+    it "preverves symlinks pointing outside the Keg" do
+      keg.link
+      dst.delete
+      dst.make_symlink(Pathname.new("/bin/sh"))
+      keg.unlink
+      expect(dst).to be_a_symlink
+    end
+
+    it "preserves real files" do
+      keg.link
+      dst.delete
+      touch dst
+      keg.unlink
+      expect(dst).to be_a_file
+    end
+
+    it "ignores nonexistent file" do
+      keg.link
+      dst.delete
+      expect(keg.unlink).to eq(2)
+    end
+
+    it "doesn't remove links to symlinks" do
+      a = HOMEBREW_CELLAR/"a"/"1.0"
+      b = HOMEBREW_CELLAR/"b"/"1.0"
+
+      (a/"lib"/"example").mkpath
+      (a/"lib"/"example2").make_symlink "example"
+      (b/"lib"/"example2").mkpath
+
+      a = described_class.new(a)
+      b = described_class.new(b)
+      a.link
+
+      lib = HOMEBREW_PREFIX/"lib"
+      expect(lib.children.length).to eq(2)
+      expect { b.link }.to raise_error(Keg::ConflictError)
+      expect(lib.children.length).to eq(2)
+    end
+
+    it "removes broken symlinks that conflict with directories" do
+      a = HOMEBREW_CELLAR/"a"/"1.0"
+      (a/"lib"/"foo").mkpath
+
+      keg = described_class.new(a)
+
+      link = HOMEBREW_PREFIX/"lib"/"foo"
+      link.parent.mkpath
+      link.make_symlink(nonexistent)
+
+      keg.link
+    end
+  end
+
+  describe "#optlink" do
+    it "creates an opt link" do
+      oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
+      oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
+      keg_record = HOMEBREW_CELLAR/"foo"/"2.0"
+      (keg_record/"bin").mkpath
+      keg = described_class.new(keg_record)
+      keg.optlink
+      expect(keg_record).to eq(oldname_opt_record.resolved_path)
+      keg.uninstall
+      expect(oldname_opt_record).not_to be_a_symlink
+    end
+
+    it "doesn't fail if already opt-linked" do
+      keg.opt_record.make_relative_symlink Pathname.new(keg)
+      keg.optlink
+      expect(keg).to be_optlinked
+    end
+
+    it "replaces an existing directory" do
+      keg.opt_record.mkpath
+      keg.optlink
+      expect(keg).to be_optlinked
+    end
+
+    it "replaces an existing file" do
+      keg.opt_record.parent.mkpath
+      keg.opt_record.write("foo")
+      keg.optlink
+      expect(keg).to be_optlinked
+    end
+  end
+
+  specify "#link and #unlink" do
+    expect(keg).not_to be_linked
+    keg.link
+    expect(keg).to be_linked
+    keg.unlink
+    expect(keg).not_to be_linked
+  end
+
+  describe "::find_some_installed_dependents" do
+    def stub_formula_name(name)
+      f = formula(name) { url "foo-1.0" }
+      stub_formula_loader f
+      stub_formula_loader f, "homebrew/core/#{f}"
+      f
+    end
+
+    def setup_test_keg(name, version)
+      f = stub_formula_name(name)
+      keg = super
+      Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write
+      keg
+    end
+
+    before(:each) do
+      keg.link
+    end
+
+    def alter_tab(keg = dependent)
+      tab = Tab.for_keg(keg)
+      yield tab
+      tab.write
+    end
+
+    # 1.1.6 is the earliest version of Homebrew that generates correct runtime
+    # dependency lists in Tabs.
+    def dependencies(deps, homebrew_version: "1.1.6")
+      alter_tab do |tab|
+        tab.homebrew_version = homebrew_version
+        tab.tabfile = dependent/Tab::FILENAME
+        tab.runtime_dependencies = deps
+      end
+    end
+
+    def unreliable_dependencies(deps)
+      # 1.1.5 is (hopefully!) the last version of Homebrew that generates
+      # incorrect runtime dependency lists in Tabs.
+      dependencies(deps, homebrew_version: "1.1.5")
+    end
+
+    let(:dependent) { setup_test_keg("bar", "1.0") }
+
+    # Test with a keg whose formula isn't known.
+    # This can happen if e.g. a formula is installed
+    # from a file path or URL.
+    specify "unknown Formula" do
+      allow(Formulary).to receive(:loader_for).and_call_original
+      alter_tab(keg) do |t|
+        t.source["tap"] = "some/tap"
+        t.source["path"] = nil
+      end
+
+      dependencies [{ "full_name" => "some/tap/foo", "version" => "1.0" }]
+      expect(keg.installed_dependents).to eq([dependent])
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]])
+
+      dependencies nil
+      # It doesn't make sense for a keg with no formula to have any dependents,
+      # so that can't really be tested.
+      expect(described_class.find_some_installed_dependents([keg])).to be nil
+    end
+
+    specify "a dependency with no Tap in Tab" do
+      tap_dep = setup_test_keg("baz", "1.0")
+
+      alter_tab(keg) { |t| t.source["tap"] = nil }
+
+      dependencies nil
+      Formula["bar"].class.depends_on "foo"
+      Formula["bar"].class.depends_on "baz"
+
+      result = described_class.find_some_installed_dependents([keg, tap_dep])
+      expect(result).to eq([[keg, tap_dep], ["bar"]])
+    end
+
+    specify "no dependencies anywhere" do
+      dependencies nil
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to be nil
+    end
+
+    specify "missing Formula dependency" do
+      dependencies nil
+      Formula["bar"].class.depends_on "foo"
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
+    end
+
+    specify "uninstalling dependent and dependency" do
+      dependencies nil
+      Formula["bar"].class.depends_on "foo"
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg, dependent])).to be nil
+    end
+
+    specify "renamed dependency" do
+      dependencies nil
+
+      stub_formula_loader Formula["foo"], "homebrew/core/foo-old"
+      renamed_path = HOMEBREW_CELLAR/"foo-old"
+      (HOMEBREW_CELLAR/"foo").rename(renamed_path)
+      renamed_keg = described_class.new(renamed_path/"1.0")
+
+      Formula["bar"].class.depends_on "foo"
+
+      result = described_class.find_some_installed_dependents([renamed_keg])
+      expect(result).to eq([[renamed_keg], ["bar"]])
+    end
+
+    specify "empty dependencies in Tab" do
+      dependencies []
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to be nil
+    end
+
+    specify "same name but different version in Tab" do
+      dependencies [{ "full_name" => "foo", "version" => "1.1" }]
+      expect(keg.installed_dependents).to eq([dependent])
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]])
+    end
+
+    specify "different name and same version in Tab" do
+      stub_formula_name("baz")
+      dependencies [{ "full_name" => "baz", "version" => keg.version.to_s }]
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to be nil
+    end
+
+    specify "same name and version in Tab" do
+      dependencies [{ "full_name" => "foo", "version" => "1.0" }]
+      expect(keg.installed_dependents).to eq([dependent])
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]])
+    end
+
+    specify "fallback for old versions" do
+      unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }]
+      Formula["bar"].class.depends_on "foo"
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]])
+    end
+
+    specify "non-opt-linked" do
+      keg.remove_opt_record
+      dependencies [{ "full_name" => "foo", "version" => "1.0" }]
+      expect(keg.installed_dependents).to be_empty
+      expect(described_class.find_some_installed_dependents([keg])).to be nil
+    end
+
+    specify "keg-only" do
+      keg.unlink
+      Formula["foo"].class.keg_only "a good reason"
+      dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version
+      expect(keg.installed_dependents).to eq([dependent])
+      expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]])
+    end
+  end
+end
diff --git a/Library/Homebrew/test/keg_test.rb b/Library/Homebrew/test/keg_test.rb
deleted file mode 100644
index bd42320383d6bfc9a6177598620d402563455874..0000000000000000000000000000000000000000
--- a/Library/Homebrew/test/keg_test.rb
+++ /dev/null
@@ -1,475 +0,0 @@
-require "testing_env"
-require "keg"
-require "stringio"
-
-class LinkTestCase < Homebrew::TestCase
-  include FileUtils
-
-  def setup_test_keg(name, version)
-    path = HOMEBREW_CELLAR.join(name, version)
-    path.join("bin").mkpath
-
-    %w[hiworld helloworld goodbye_cruel_world].each do |file|
-      touch path.join("bin", file)
-    end
-
-    keg = Keg.new(path)
-    @kegs ||= []
-    @kegs << keg
-    keg
-  end
-
-  def setup
-    super
-
-    @keg = setup_test_keg("foo", "1.0")
-    @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
-    @kegs.each(&:unlink)
-    $stdout = @old_stdout
-    rmtree HOMEBREW_PREFIX/"lib"
-    super
-  end
-end
-
-class LinkTests < LinkTestCase
-  def test_all
-    Formula.clear_racks_cache
-    assert_equal [@keg], Keg.all
-  end
-
-  def test_empty_installation
-    %w[.DS_Store INSTALL_RECEIPT.json LICENSE.txt].each do |file|
-      touch @keg/file
-    end
-    assert_predicate @keg, :exist?
-    assert_predicate @keg, :directory?
-    refute_predicate @keg, :empty_installation?
-
-    (@keg/"bin").rmtree
-    assert_predicate @keg, :empty_installation?
-  end
-
-  def test_linking_keg
-    assert_equal 3, @keg.link
-    (HOMEBREW_PREFIX/"bin").children.each { |c| assert_predicate c.readlink, :relative? }
-  end
-
-  def test_unlinking_keg
-    @keg.link
-    assert_predicate @dst, :symlink?
-    assert_equal 3, @keg.unlink
-    refute_predicate @dst, :symlink?
-  end
-
-  def test_oldname_opt_record
-    assert_nil @keg.oldname_opt_record
-    oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
-    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
-    assert_equal oldname_opt_record, @keg.oldname_opt_record
-  end
-
-  def test_optlink_relink
-    oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
-    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
-    keg_record = HOMEBREW_CELLAR.join("foo", "2.0")
-    keg_record.join("bin").mkpath
-    keg = Keg.new(keg_record)
-    keg.optlink
-    assert_equal keg_record, oldname_opt_record.resolved_path
-    keg.uninstall
-    refute_predicate oldname_opt_record, :symlink?
-  end
-
-  def test_remove_oldname_opt_record
-    oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo"
-    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/2.0")
-    @keg.remove_oldname_opt_record
-    assert_predicate oldname_opt_record, :symlink?
-    oldname_opt_record.unlink
-    oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0")
-    @keg.remove_oldname_opt_record
-    refute_predicate oldname_opt_record, :symlink?
-  end
-
-  def test_link_dry_run
-    @mode.dry_run = true
-
-    assert_equal 0, @keg.link(@mode)
-    refute_predicate @keg, :linked?
-
-    ["hiworld", "helloworld", "goodbye_cruel_world"].each do |file|
-      assert_match "#{HOMEBREW_PREFIX}/bin/#{file}", $stdout.string
-    end
-    assert_equal 3, $stdout.string.lines.count
-  end
-
-  def test_linking_fails_when_already_linked
-    @keg.link
-    assert_raises(Keg::AlreadyLinkedError) { @keg.link }
-  end
-
-  def test_linking_fails_when_files_exist
-    touch @dst
-    assert_raises(Keg::ConflictError) { @keg.link }
-  end
-
-  def test_link_ignores_broken_symlinks_at_target
-    src = @keg.join("bin", "helloworld")
-    @dst.make_symlink(@nonexistent)
-    @keg.link
-    assert_equal src.relative_path_from(@dst.dirname), @dst.readlink
-  end
-
-  def test_link_overwrite
-    touch @dst
-    @mode.overwrite = true
-    assert_equal 3, @keg.link(@mode)
-    assert_predicate @keg, :linked?
-  end
-
-  def test_link_overwrite_broken_symlinks
-    @dst.make_symlink "nowhere"
-    @mode.overwrite = true
-    assert_equal 3, @keg.link(@mode)
-    assert_predicate @keg, :linked?
-  end
-
-  def test_link_overwrite_dryrun
-    touch @dst
-    @mode.overwrite = true
-    @mode.dry_run = true
-
-    assert_equal 0, @keg.link(@mode)
-    refute_predicate @keg, :linked?
-
-    assert_equal "#{@dst}\n", $stdout.string
-  end
-
-  def test_unlink_prunes_empty_toplevel_directories
-    mkpath HOMEBREW_PREFIX/"lib/foo/bar"
-    mkpath @keg/"lib/foo/bar"
-    touch @keg/"lib/foo/bar/file1"
-
-    @keg.unlink
-
-    refute_predicate HOMEBREW_PREFIX/"lib/foo", :directory?
-  end
-
-  def test_unlink_ignores_ds_store_when_pruning_empty_dirs
-    mkpath HOMEBREW_PREFIX/"lib/foo/bar"
-    touch HOMEBREW_PREFIX/"lib/foo/.DS_Store"
-    mkpath @keg/"lib/foo/bar"
-    touch @keg/"lib/foo/bar/file1"
-
-    @keg.unlink
-
-    refute_predicate HOMEBREW_PREFIX/"lib/foo", :directory?
-    refute_predicate HOMEBREW_PREFIX/"lib/foo/.DS_Store", :exist?
-  end
-
-  def test_linking_creates_opt_link
-    refute_predicate @keg, :optlinked?
-    @keg.link
-    assert_predicate @keg, :optlinked?
-  end
-
-  def test_unlinking_does_not_remove_opt_link
-    @keg.link
-    @keg.unlink
-    assert_predicate @keg, :optlinked?
-  end
-
-  def test_existing_opt_link
-    @keg.opt_record.make_relative_symlink Pathname.new(@keg)
-    @keg.optlink
-    assert_predicate @keg, :optlinked?
-  end
-
-  def test_existing_opt_link_directory
-    @keg.opt_record.mkpath
-    @keg.optlink
-    assert_predicate @keg, :optlinked?
-  end
-
-  def test_existing_opt_link_file
-    @keg.opt_record.parent.mkpath
-    @keg.opt_record.write("foo")
-    @keg.optlink
-    assert_predicate @keg, :optlinked?
-  end
-
-  def test_linked_keg
-    refute_predicate @keg, :linked?
-    @keg.link
-    assert_predicate @keg, :linked?
-    @keg.unlink
-    refute_predicate @keg, :linked?
-  end
-
-  def test_unlink_preserves_broken_symlink_pointing_outside_the_keg
-    @keg.link
-    @dst.delete
-    @dst.make_symlink(@nonexistent)
-    @keg.unlink
-    assert_predicate @dst, :symlink?
-  end
-
-  def test_unlink_preserves_broken_symlink_pointing_into_the_keg
-    @keg.link
-    @dst.resolved_path.delete
-    @keg.unlink
-    assert_predicate @dst, :symlink?
-  end
-
-  def test_unlink_preserves_symlink_pointing_outside_of_keg
-    @keg.link
-    @dst.delete
-    @dst.make_symlink(Pathname.new("/bin/sh"))
-    @keg.unlink
-    assert_predicate @dst, :symlink?
-  end
-
-  def test_unlink_preserves_real_file
-    @keg.link
-    @dst.delete
-    touch @dst
-    @keg.unlink
-    assert_predicate @dst, :file?
-  end
-
-  def test_unlink_ignores_nonexistent_file
-    @keg.link
-    @dst.delete
-    assert_equal 2, @keg.unlink
-  end
-
-  def test_pkgconfig_is_mkpathed
-    link = HOMEBREW_PREFIX.join("lib", "pkgconfig")
-    @keg.join("lib", "pkgconfig").mkpath
-    @keg.link
-    assert_predicate link.lstat, :directory?
-  end
-
-  def test_cmake_is_mkpathed
-    link = HOMEBREW_PREFIX.join("lib", "cmake")
-    @keg.join("lib", "cmake").mkpath
-    @keg.link
-    assert_predicate link.lstat, :directory?
-  end
-
-  def test_symlinks_are_linked_directly
-    link = HOMEBREW_PREFIX.join("lib", "pkgconfig")
-
-    @keg.join("lib", "example").mkpath
-    @keg.join("lib", "pkgconfig").make_symlink "example"
-    @keg.link
-
-    assert_predicate link.resolved_path, :symlink?
-    assert_predicate link.lstat, :symlink?
-  end
-
-  def test_links_to_symlinks_are_not_removed
-    a = HOMEBREW_CELLAR.join("a", "1.0")
-    b = HOMEBREW_CELLAR.join("b", "1.0")
-
-    a.join("lib", "example").mkpath
-    a.join("lib", "example2").make_symlink "example"
-    b.join("lib", "example2").mkpath
-
-    a = Keg.new(a)
-    b = Keg.new(b)
-    a.link
-
-    lib = HOMEBREW_PREFIX.join("lib")
-    assert_equal 2, lib.children.length
-    assert_raises(Keg::ConflictError) { b.link }
-    assert_equal 2, lib.children.length
-  ensure
-    a.unlink
-  end
-
-  def test_removes_broken_symlinks_that_conflict_with_directories
-    a = HOMEBREW_CELLAR.join("a", "1.0")
-    a.join("lib", "foo").mkpath
-
-    keg = Keg.new(a)
-
-    link = HOMEBREW_PREFIX.join("lib", "foo")
-    link.parent.mkpath
-    link.make_symlink(@nonexistent)
-
-    keg.link
-  ensure
-    keg.unlink
-  end
-end
-
-class InstalledDependantsTests < LinkTestCase
-  def stub_formula_name(name)
-    f = formula(name) { url "foo-1.0" }
-    stub_formula_loader f
-    stub_formula_loader f, "homebrew/core/#{f}"
-    f
-  end
-
-  def setup_test_keg(name, version)
-    f = stub_formula_name(name)
-    keg = super
-    Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write
-    keg
-  end
-
-  def setup
-    super
-    @dependent = setup_test_keg("bar", "1.0")
-    @keg.link
-  end
-
-  def alter_tab(keg = @dependent)
-    tab = Tab.for_keg(keg)
-    yield tab
-    tab.write
-  end
-
-  # 1.1.6 is the earliest version of Homebrew that generates correct runtime
-  # dependency lists in tabs.
-  def dependencies(deps, homebrew_version: "1.1.6")
-    alter_tab do |tab|
-      tab.homebrew_version = homebrew_version
-      tab.tabfile = @dependent.join("INSTALL_RECEIPT.json")
-      tab.runtime_dependencies = deps
-    end
-  end
-
-  def unreliable_dependencies(deps)
-    # 1.1.5 is (hopefully!) the last version of Homebrew that generates
-    # incorrect runtime dependency lists in tabs.
-    dependencies(deps, homebrew_version: "1.1.5")
-  end
-
-  # Test with a keg whose formula isn't known.
-  # This can happen if e.g. a formula is installed
-  # from a file path or URL.
-  def test_unknown_formula
-    Formulary.unstub(:loader_for)
-    alter_tab(@keg) do |t|
-      t.source["tap"] = "some/tap"
-      t.source["path"] = nil
-    end
-
-    dependencies [{ "full_name" => "some/tap/foo", "version" => "1.0" }]
-    assert_equal [@dependent], @keg.installed_dependents
-    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
-
-    dependencies nil
-    # It doesn't make sense for a keg with no formula to have any dependents,
-    # so that can't really be tested.
-    assert_nil Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_a_dependency_with_no_tap_in_tab
-    @tap_dep = setup_test_keg("baz", "1.0")
-
-    alter_tab(@keg) { |t| t.source["tap"] = nil }
-
-    dependencies nil
-    Formula["bar"].class.depends_on "foo"
-    Formula["bar"].class.depends_on "baz"
-
-    result = Keg.find_some_installed_dependents([@keg, @tap_dep])
-    assert_equal [[@keg, @tap_dep], ["bar"]], result
-  end
-
-  def test_no_dependencies_anywhere
-    dependencies nil
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_missing_formula_dependency
-    dependencies nil
-    Formula["bar"].class.depends_on "foo"
-    assert_empty @keg.installed_dependents
-    assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_uninstalling_dependent_and_dependency
-    dependencies nil
-    Formula["bar"].class.depends_on "foo"
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg, @dependent])
-  end
-
-  def test_renamed_dependency
-    dependencies nil
-
-    stub_formula_loader Formula["foo"], "homebrew/core/foo-old"
-    renamed_path = HOMEBREW_CELLAR/"foo-old"
-    (HOMEBREW_CELLAR/"foo").rename(renamed_path)
-    renamed_keg = Keg.new(renamed_path.join("1.0"))
-
-    Formula["bar"].class.depends_on "foo"
-
-    result = Keg.find_some_installed_dependents([renamed_keg])
-    assert_equal [[renamed_keg], ["bar"]], result
-  end
-
-  def test_empty_dependencies_in_tab
-    dependencies []
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_same_name_different_version_in_tab
-    dependencies [{ "full_name" => "foo", "version" => "1.1" }]
-    assert_equal [@dependent], @keg.installed_dependents
-    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_different_name_same_version_in_tab
-    stub_formula_name("baz")
-    dependencies [{ "full_name" => "baz", "version" => @keg.version.to_s }]
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_same_name_and_version_in_tab
-    dependencies [{ "full_name" => "foo", "version" => "1.0" }]
-    assert_equal [@dependent], @keg.installed_dependents
-    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_fallback_for_old_versions
-    unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }]
-    Formula["bar"].class.depends_on "foo"
-    assert_empty @keg.installed_dependents
-    assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_nonoptlinked
-    @keg.remove_opt_record
-    dependencies [{ "full_name" => "foo", "version" => "1.0" }]
-    assert_empty @keg.installed_dependents
-    assert_nil Keg.find_some_installed_dependents([@keg])
-  end
-
-  def test_keg_only
-    @keg.unlink
-    Formula["foo"].class.keg_only "a good reason"
-    dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version
-    assert_equal [@dependent], @keg.installed_dependents
-    assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg])
-  end
-end