######################################################################
# test_file_find.rb
#
# Test case for the File::Find package. You should run this via the
# 'rake test' task.
######################################################################
require 'rubygems'
gem 'test-unit'

require 'test/unit'
require 'fileutils'
require 'file/find'
require 'rbconfig'
require 'sys/admin'
include Config

class TC_File_Find < Test::Unit::TestCase
   def self.startup
      Dir.chdir('test') unless File.basename(Dir.pwd) == 'test'
      @@windows = CONFIG['host_os'] =~ /windows|mswin/i
      @@loguser = Sys::Admin.get_user(Admin.get_login) unless @@windows
      @@logroup = Sys::Admin.get_group(@@loguser.gid) unless @@windows
   end

   def setup
      @file1 = 'test1.rb'
      @file2 = 'test1.txt'
      @file3 = 'foo.txt'
      @file4 = 'foo.doc'
      @dir1  = 'dir1'
      @dir2  = 'dir2'

      File.open(@file1, 'w'){}
      File.open(@file2, 'w'){}
      File.open(@file3, 'w'){}
      File.open(@file4, 'w'){}

      unless @@windows
         @link1 = 'link1'
         File.symlink(@file1, @link1)
      end

      Dir.mkdir(@dir1) unless File.exists?(@dir1)
      Dir.mkdir(@dir2) unless File.exists?(@dir2)

      File.open(File.join(@dir1, 'bar.txt'), 'w'){}
      File.open(File.join(@dir2, 'baz.txt'), 'w'){}

      @rule1 = File::Find.new(:name => '*.txt')
      @rule2 = File::Find.new
   end

   def test_version
      assert_equal('0.2.2', File::Find::VERSION)
   end

   def test_path
      assert_respond_to(@rule1, :path)
      assert_respond_to(@rule1, :path=)
      assert_equal(Dir.pwd, @rule1.path)
   end

   def test_options
      assert_respond_to(@rule1, :options)
      assert_respond_to(@rule1, :options=)
      assert_equal({:name => '*.txt'}, @rule1.options)
   end

   def test_atime_basic
      assert_respond_to(@rule1, :atime)
      assert_respond_to(@rule1, :atime=)
      assert_nil(@rule1.atime)
   end

   def test_atime
      rule1 = File::Find.new(:name => "*.rb", :atime => 0)
      rule2 = File::Find.new(:name => "*.rb", :atime => 1)

      assert_equal(false, rule1.find.empty?)
      assert_equal(true, rule2.find.empty?)
   end

   def test_ctime_basic
      assert_respond_to(@rule1, :ctime)
      assert_respond_to(@rule1, :ctime=)
      assert_nil(@rule1.ctime)
   end

   def test_ctime
      rule1 = File::Find.new(:name => "*.rb", :ctime => 0)
      rule2 = File::Find.new(:name => "*.rb", :ctime => 1)

      assert_equal(false, rule1.find.empty?)
      assert_equal(true, rule2.find.empty?)
   end

   def test_ftype_basic
      assert_respond_to(@rule1, :ftype)
      assert_respond_to(@rule1, :ftype=)
      assert_nil(@rule1.ftype)
   end

   def test_ftype
      rule1 = File::Find.new(:name => "*.rb", :ftype => "file")
      rule2 = File::Find.new(:name => "*.rb", :ftype => "characterSpecial")

      assert_equal(false, rule1.find.empty?)
      assert_equal(true, rule2.find.empty?)
   end

   def test_group_basic
      assert_respond_to(@rule1, :group)
      assert_respond_to(@rule1, :group=)
      assert_nil(@rule1.group)
   end

   def test_group_with_numeric_id
      omit_if(@@windows, 'group test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :group => @@loguser.gid)
      assert_equal([File.expand_path(@file4)], @rule1.find)
   end

   def test_group_with_string
      omit_if(@@windows, 'group test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :group => @@logroup.name)
      assert_equal([File.expand_path(@file4)], @rule1.find)
   end

   def test_group_with_bad_id
      omit_if(@@windows, 'group test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :group => 'totallybogus')
      @rule2 = File::Find.new(:name => '*.doc', :group => 99999999)
      assert_equal([], @rule1.find)
      assert_equal([], @rule2.find)
   end

   def test_inum_basic
      assert_respond_to(@rule1, :inum)
      assert_respond_to(@rule1, :inum=)
      assert_nil(@rule1.inum)
   end

   def test_follow_basic
      assert_respond_to(@rule1, :follow)
      assert_respond_to(@rule1, :follow=)
      assert_equal(true, @rule1.follow)
   end

   def test_name_basic
      assert_respond_to(@rule1, :name)
      assert_respond_to(@rule1, :name=)
      assert_equal('*.txt', @rule1.name)
   end

   def test_pattern_alias
      assert_respond_to(@rule1, :pattern)
      assert_respond_to(@rule1, :pattern=)
      assert_true(@rule1.method(:name) == @rule1.method(:pattern))
      assert_true(@rule1.method(:name=) == @rule1.method(:pattern=))
   end

   def test_perm_basic
      assert_respond_to(@rule1, :perm)
      assert_respond_to(@rule1, :perm=)
      assert_nil(@rule1.perm)
   end

   def test_perm
      omit_if(@@windows, 'perm test skipped on MS Windows')
      File.chmod(0664, @file1) 
      File.chmod(0644, @file2) 
      results = File::Find.new(:name => "test1*", :perm => 664).find

      assert_equal(1, results.length)
      assert_equal('test1.rb', File.basename(results.first))
   end

   def test_prune_basic
      assert_respond_to(@rule1, :prune)
      assert_respond_to(@rule1, :prune=)
      assert_nil(@rule1.prune)
   end

   def test_prune
      rule = File::Find.new(:name => "*.txt", :prune => 'foo')
      assert_equal('test1.txt', File.basename(rule.find.first))
   end

   def test_size_basic
      assert_respond_to(@rule1, :size)
      assert_respond_to(@rule1, :size=)
      assert_nil(@rule1.size)
   end

   def test_user_basic
      assert_respond_to(@rule1, :user)
      assert_respond_to(@rule1, :user=)
      assert_nil(@rule1.user)
   end

   def test_user_with_numeric_id
      omit_if(@@windows, 'user test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.uid)
      assert_equal([File.expand_path(@file4)], @rule1.find)
   end

   def test_user_with_string
      omit_if(@@windows, 'user test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :user => @@loguser.name)
      assert_equal([File.expand_path(@file4)], @rule1.find)
   end

   def test_user_with_bad_id
      omit_if(@@windows, 'user test skipped on MS Windows')
      @rule1 = File::Find.new(:name => '*.doc', :user => 'totallybogus')
      @rule2 = File::Find.new(:name => '*.doc', :user => 99999999)
      assert_equal([], @rule1.find)
      assert_equal([], @rule2.find)
   end

   def test_previous_basic
      assert_respond_to(@rule1, :previous)
   end

   def test_expected_errors
      assert_raises(Errno::ENOENT){ File::Find.new(:path => '/bogus/dir').find }
   end

   def teardown
      FileUtils.rm_rf(@file1)
      FileUtils.rm_rf(@file2)
      FileUtils.rm_rf(@file3)
      FileUtils.rm_rf(@file4)
      FileUtils.rm_rf(@dir1)
      FileUtils.rm_rf(@dir2)
      FileUtils.rm_rf(@link1) unless @@windows

      @rule1 = nil
      @rule2 = nil
      @file1 = nil
      @file2 = nil
      @file3 = nil
      @file4 = nil
   end

   def self.shutdown
      @@windows = nil
      @@loguser = nil unless @@windows
      @@logroup = nil unless @@windows
   end
end