require 'test/unit' require 'tutil' $testDir ||= File.expand_path(File.dirname(__FILE__)) class TestSourceNode < Test::Unit::TestCase def setup # Ensure we run in test directory. Dir.chdir $testDir end def teardown Dir.chdir $testDir FileUtils.rm_rf Dir["*.t"] end def tmp_rf(content = @rf, fn = "rf.t") open(fn, "w") { |f| f.write content } yield ensure FileUtils.rm_f fn end def test_invoke @rf = <<-EOF gen SourceNode, "a.t" EOF tmp_rf do out, err = assert_rant("-frf.t") assert(!test(?f, "a.t")) assert(out.strip.empty?) assert(err.strip.empty?) end tmp_rf do out, err = assert_rant("-frf.t", "a.t") assert(out.strip.empty?) assert(err.strip.empty?) end end def test_deps_empty_array @rf = <<-EOF gen SourceNode, "a.t" => [] EOF tmp_rf do assert_rant("-frf.t") end end def test_with_deps @rf = <<-EOF gen SourceNode, "a.t" => %w(b.t c.t) EOF tmp_rf do assert_rant("-frf.t") end tmp_rf do assert_rant(:fail, "-frf.t", "b.t") end end def test_as_dependency @rf = <<-EOF file "a.t" => "b.t" do |t| sys.touch t.name end gen SourceNode, "b.t" => "c.t" EOF tmp_rf do out, err = assert_rant(:fail, "-frf.t") assert(out.strip.empty?) assert_match(/\[ERROR\].*no such file.*b\.t/m, err) end assert(!test(?e, "a.t")) FileUtils.touch "b.t" tmp_rf do out, err = assert_rant(:fail, "-frf.t") assert(out.strip.empty?) assert_match(/\[ERROR\].*no such file.*c\.t/m, err) end assert(!test(?e, "a.t")) FileUtils.touch "c.t" tmp_rf do out, err = assert_rant("-frf.t") end assert(test(?f, "a.t")) end def test_timestamps @rf = <<-EOF file "a.t" => "b.t" do |t| sys.touch t.name end gen SourceNode, "b.t" => %w(c.t d.t) EOF FileUtils.touch %w(b.t c.t d.t) tmp_rf do assert_rant("-frf.t") assert(test(?f, "a.t")) out, err = assert_rant("-frf.t") assert(out.strip.empty?, "no source changed, no update required") old_mtime = File.mtime "a.t" timeout FileUtils.touch "b.t" assert_rant("-frf.t") assert(File.mtime("a.t") > old_mtime) old_mtime = File.mtime "a.t" timeout FileUtils.touch "c.t" assert_rant("-frf.t") assert(File.mtime("a.t") > old_mtime) end end def test_with_block @rf = <<-EOF gen SourceNode, "a.t" do end EOF tmp_rf do out, err = assert_rant(:fail, "-frf.t") assert_match(/\[ERROR\].*SourceNode.*block/m, err) end end def test_with_autoclean @rf = <<-EOF import "autoclean" gen SourceNode, "a.t" => %w(b.t c.t) gen AutoClean EOF tmp_rf do assert_rant("-frf.t", "autoclean") FileUtils.touch %w(a.t b.t c.t) assert_rant("-frf.t", "autoclean") assert(test(?f, "a.t")) assert(test(?f, "b.t")) assert(test(?f, "c.t")) end end def test_sourcenode_depends_on_sourcenode @rf = <<-EOF file "a.t" => "b.t" do |t| sys.touch t.name end gen SourceNode, "b.t" => %w(c.t d.t) gen SourceNode, "d.t" => "e.t" EOF FileUtils.touch %w(b.t c.t d.t e.t) tmp_rf do assert_rant("-frf.t") assert(test(?f, "a.t")) timeout FileUtils.touch "e.t" old_mtime = File.mtime "a.t" assert_rant("-frf.t") assert(File.mtime("a.t") > old_mtime) end end def test_circular_dep @rf = <<-EOF gen SourceNode, "a.t" => "b.t" gen SourceNode, "b.t" => "a.t" EOF FileUtils.touch %w(a.t b.t) tmp_rf do th = Thread.new{ assert_rant("-frf.t") } assert_equal(th, th.join(0.5)) end end def test_file_pre @rf = <<-EOF import "autoclean" file "f.t" => "a.t" do |t| sys.touch t.name end gen SourceNode, "a.t" => ["b.t", "c.t"] file "b.t" do |t| sys.touch t.name end gen AutoClean EOF FileUtils.touch "c.t" FileUtils.touch "a.t" tmp_rf do out, err = assert_rant("-frf.t") assert(err.empty?) assert(!out.empty?) assert(test(?f, "f.t")) assert(test(?f, "b.t")) out, err = assert_rant("-frf.t") assert(err.empty?) assert(out.empty?) assert_rant("-frf.t", "autoclean") assert(!test(?f, "f.t")) assert(!test(?f, "b.t")) assert(test(?f, "a.t")) assert(test(?f, "c.t")) end end end