require "testing_env"
require "cleaner"
require "formula"

class CleanerTests < Homebrew::TestCase
  include FileUtils

  def setup
    @f = formula("cleaner_test") { url "foo-1.0" }
    @f.prefix.mkpath
  end

  def teardown
    @f.rack.rmtree if @f.rack.exist?
  end

  def test_clean_file
    @f.bin.mkpath
    @f.lib.mkpath
    cp "#{TEST_DIRECTORY}/mach/a.out", @f.bin
    cp Dir["#{TEST_DIRECTORY}/mach/*.dylib"], @f.lib

    Cleaner.new(@f).clean

    dylib_perm = OS.mac? ? 0100444 : 0100555
    assert_equal 0100555, (@f.bin/"a.out").stat.mode
    assert_equal dylib_perm, (@f.lib/"fat.dylib").stat.mode
    assert_equal dylib_perm, (@f.lib/"x86_64.dylib").stat.mode
    assert_equal dylib_perm, (@f.lib/"i386.dylib").stat.mode
  end

  def test_prunes_prefix_if_empty
    Cleaner.new(@f).clean
    refute_predicate @f.prefix, :directory?
  end

  def test_prunes_empty_directories
    subdir = @f.bin/"subdir"
    subdir.mkpath

    Cleaner.new(@f).clean

    refute_predicate @f.bin, :directory?
    refute_predicate subdir, :directory?
  end

  def test_skip_clean_empty_directory
    @f.class.skip_clean "bin"
    @f.bin.mkpath

    Cleaner.new(@f).clean

    assert_predicate @f.bin, :directory?
  end

  def test_skip_clean_directory_with_empty_subdir
    @f.class.skip_clean "bin"
    subdir = @f.bin/"subdir"
    subdir.mkpath

    Cleaner.new(@f).clean

    assert_predicate @f.bin, :directory?
    assert_predicate subdir, :directory?
  end

  def test_removes_symlink_when_target_was_pruned_first
    dir = @f.prefix/"b"
    symlink = @f.prefix/"a"

    dir.mkpath
    ln_s dir.basename, symlink

    Cleaner.new(@f).clean

    refute_predicate dir, :exist?
    refute_predicate symlink, :symlink?
    refute_predicate symlink, :exist?
  end

  def test_removes_symlink_pointing_to_empty_directory
    dir = @f.prefix/"b"
    symlink = @f.prefix/"c"

    dir.mkpath
    ln_s dir.basename, symlink

    Cleaner.new(@f).clean

    refute_predicate dir, :exist?
    refute_predicate symlink, :symlink?
    refute_predicate symlink, :exist?
  end

  def test_removes_broken_symlinks
    symlink = @f.prefix/"symlink"
    ln_s "target", symlink

    Cleaner.new(@f).clean

    refute_predicate symlink, :symlink?
  end

  def test_skip_clean_broken_symlink
    @f.class.skip_clean "symlink"
    symlink = @f.prefix/"symlink"
    ln_s "target", symlink

    Cleaner.new(@f).clean

    assert_predicate symlink, :symlink?
  end

  def test_skip_clean_symlink_pointing_to_empty_directory
    @f.class.skip_clean "c"
    dir = @f.prefix/"b"
    symlink = @f.prefix/"c"

    dir.mkpath
    ln_s dir.basename, symlink

    Cleaner.new(@f).clean

    refute_predicate dir, :exist?
    assert_predicate symlink, :symlink?
    refute_predicate symlink, :exist?
  end

  def test_skip_clean_symlink_when_target_pruned
    @f.class.skip_clean "a"
    dir = @f.prefix/"b"
    symlink = @f.prefix/"a"

    dir.mkpath
    ln_s dir.basename, symlink

    Cleaner.new(@f).clean

    refute_predicate dir, :exist?
    assert_predicate symlink, :symlink?
    refute_predicate symlink, :exist?
  end

  def test_removes_la_files
    file = @f.lib/"foo.la"

    @f.lib.mkpath
    touch file

    Cleaner.new(@f).clean

    refute_predicate file, :exist?
  end

  def test_skip_clean_la
    file = @f.lib/"foo.la"

    @f.class.skip_clean :la
    @f.lib.mkpath
    touch file

    Cleaner.new(@f).clean

    assert_predicate file, :exist?
  end

  def test_remove_charset_alias
    file = @f.lib/"charset.alias"

    @f.lib.mkpath
    touch file

    Cleaner.new(@f).clean

    refute_predicate file, :exist?
  end

  def test_skip_clean_subdir
    dir = @f.lib/"subdir"
    @f.class.skip_clean "lib/subdir"

    dir.mkpath

    Cleaner.new(@f).clean

    assert_predicate dir, :directory?
  end

  def test_skip_clean_paths_are_anchored_to_prefix
    dir1 = @f.bin/"a"
    dir2 = @f.lib/"bin/a"

    @f.class.skip_clean "bin/a"
    dir1.mkpath
    dir2.mkpath

    Cleaner.new(@f).clean

    assert_predicate dir1, :exist?
    refute_predicate dir2, :exist?
  end
end
