1require File.expand_path('../helper', __FILE__)
2require 'fileutils'
3
4class TestRakeFileTask < Rake::TestCase
5  include Rake
6
7  def setup
8    super
9
10    Task.clear
11    @runs = Array.new
12    FileUtils.rm_f NEWFILE
13    FileUtils.rm_f OLDFILE
14  end
15
16  def test_file_need
17    name = "dummy"
18    file name
19
20    ftask = Task[name]
21
22    assert_equal name.to_s, ftask.name
23    File.delete(ftask.name) rescue nil
24
25    assert ftask.needed?, "file should be needed"
26
27    open(ftask.name, "w") { |f| f.puts "HI" }
28
29    assert_equal nil, ftask.prerequisites.collect{|n| Task[n].timestamp}.max
30    assert ! ftask.needed?, "file should not be needed"
31  ensure
32    File.delete(ftask.name) rescue nil
33  end
34
35  def test_file_times_new_depends_on_old
36    create_timed_files(OLDFILE, NEWFILE)
37
38    t1 = Rake.application.intern(FileTask, NEWFILE).enhance([OLDFILE])
39    t2 = Rake.application.intern(FileTask, OLDFILE)
40    assert ! t2.needed?, "Should not need to build old file"
41    assert ! t1.needed?, "Should not need to rebuild new file because of old"
42  end
43
44  def test_file_times_new_depend_on_regular_task_timestamps
45    load_phony
46
47    name = "dummy"
48    task name
49
50    create_timed_files(NEWFILE)
51
52    t1 = Rake.application.intern(FileTask, NEWFILE).enhance([name])
53
54    assert t1.needed?, "depending on non-file task uses Time.now"
55
56    task(name => :phony)
57
58    assert ! t1.needed?, "unless the non-file task has a timestamp"
59  end
60
61  def test_file_times_old_depends_on_new
62    create_timed_files(OLDFILE, NEWFILE)
63
64    t1 = Rake.application.intern(FileTask,OLDFILE).enhance([NEWFILE])
65    t2 = Rake.application.intern(FileTask, NEWFILE)
66    assert ! t2.needed?, "Should not need to build new file"
67    preq_stamp = t1.prerequisites.collect{|t| Task[t].timestamp}.max
68    assert_equal t2.timestamp, preq_stamp
69    assert t1.timestamp < preq_stamp, "T1 should be older"
70    assert t1.needed?, "Should need to rebuild old file because of new"
71  end
72
73  def test_file_depends_on_task_depend_on_file
74    create_timed_files(OLDFILE, NEWFILE)
75
76    file NEWFILE => [:obj] do |t| @runs << t.name end
77    task :obj => [OLDFILE] do |t| @runs << t.name end
78    file OLDFILE           do |t| @runs << t.name end
79
80    Task[:obj].invoke
81    Task[NEWFILE].invoke
82    assert ! @runs.include?(NEWFILE)
83  end
84
85  def test_existing_file_depends_on_non_existing_file
86    @ran = false
87
88    create_file(OLDFILE)
89    delete_file(NEWFILE)
90    file NEWFILE do
91      @ran = true
92    end
93
94    file OLDFILE => NEWFILE
95
96    Task[OLDFILE].invoke
97
98    assert @ran
99  end
100
101  # I have currently disabled this test.  I'm not convinced that
102  # deleting the file target on failure is always the proper thing to
103  # do.  I'm willing to hear input on this topic.
104  def ztest_file_deletes_on_failure
105    task :obj
106    file NEWFILE => [:obj] do |t|
107      FileUtils.touch NEWFILE
108      fail "Ooops"
109    end
110    assert Task[NEWFILE]
111    begin
112      Task[NEWFILE].invoke
113    rescue Exception
114    end
115    assert( ! File.exist?(NEWFILE), "NEWFILE should be deleted")
116  end
117
118  def load_phony
119    load File.join(@rake_lib, "rake/phony.rb")
120  end
121
122end
123