1require File.expand_path('../helper', __FILE__) 2require 'fileutils' 3require 'open3' 4 5class TestRakeFunctional < Rake::TestCase 6 7 def setup 8 super 9 10 @ruby_options = ["-I#{@rake_lib}", "-I."] 11 @verbose = ENV['VERBOSE'] 12 13 if @verbose 14 puts 15 puts 16 puts '-' * 80 17 puts @__name__ 18 puts '-' * 80 19 end 20 end 21 22 def test_rake_default 23 rakefile_default 24 25 rake 26 27 assert_match(/^DEFAULT$/, @out) 28 end 29 30 def test_rake_error_on_bad_task 31 rakefile_default 32 33 rake '-t', 'xyz' 34 35 assert_match(/rake aborted/, @err) 36 end 37 38 def test_env_available_at_top_scope 39 rakefile_default 40 41 rake "TESTTOPSCOPE=1" 42 43 assert_match(/^TOPSCOPE$/, @out) 44 end 45 46 def test_env_available_at_task_scope 47 rakefile_default 48 49 rake 'TESTTASKSCOPE=1', 'task_scope' 50 51 assert_match(/^TASKSCOPE$/, @out) 52 end 53 54 def test_multi_desc 55 ENV['RAKE_COLUMNS'] = '80' 56 rakefile_multidesc 57 58 rake "-T" 59 60 assert_match %r{^rake a *# A / A2 *$}, @out 61 assert_match %r{^rake b *# B *$}, @out 62 refute_match %r{^rake c}, @out 63 assert_match %r{^rake d *# x{65}\.\.\.$}, @out 64 end 65 66 def test_long_description 67 rakefile_multidesc 68 69 rake "--describe" 70 71 assert_match %r{^rake a\n *A / A2 *$}m, @out 72 assert_match %r{^rake b\n *B *$}m, @out 73 assert_match %r{^rake d\n *x{80}}m, @out 74 refute_match %r{^rake c\n}m, @out 75 end 76 77 def test_proper_namespace_access 78 rakefile_access 79 80 rake 81 82 refute_match %r{^BAD:}, @out 83 end 84 85 def test_rbext 86 rakefile_rbext 87 88 rake "-N" 89 90 assert_match %r{^OK$}, @out 91 end 92 93 def test_system 94 rake_system_dir 95 96 rake '-g', "sys1" 97 98 assert_match %r{^SYS1}, @out 99 end 100 101 def test_system_excludes_rakelib_files_too 102 rake_system_dir 103 104 rake '-g', "sys1", '-T', 'extra' 105 106 refute_match %r{extra:extra}, @out 107 end 108 109 def test_by_default_rakelib_files_are_included 110 rake_system_dir 111 rakefile_extra 112 113 rake '-T', 'extra', '--trace' 114 115 assert_match %r{extra:extra}, @out 116 end 117 118 def test_implicit_system 119 rake_system_dir 120 Dir.chdir @tempdir 121 122 rake "sys1", "--trace" 123 124 assert_match %r{^SYS1}, @out 125 end 126 127 def test_no_system 128 rake_system_dir 129 rakefile_extra 130 131 rake '-G', "sys1" 132 133 assert_match %r{^Don't know how to build task}, @err # emacs wart: ' 134 end 135 136 def test_nosearch_with_rakefile_uses_local_rakefile 137 rakefile_default 138 139 rake "--nosearch" 140 141 assert_match %r{^DEFAULT}, @out 142 end 143 144 def test_nosearch_without_rakefile_finds_system 145 rakefile_nosearch 146 rake_system_dir 147 148 rake "--nosearch", "sys1" 149 150 assert_match %r{^SYS1}, @out 151 end 152 153 def test_nosearch_without_rakefile_and_no_system_fails 154 rakefile_nosearch 155 ENV['RAKE_SYSTEM'] = 'not_exist' 156 157 rake "--nosearch" 158 159 assert_match %r{^No Rakefile found}, @err 160 end 161 162 def test_invalid_command_line_options 163 rakefile_default 164 165 rake "--bad-options" 166 167 assert_match %r{invalid +option}i, @err 168 end 169 170 def test_inline_verbose_default_should_show_command 171 rakefile_verbose 172 173 rake "inline_verbose_default" 174 175 assert_match(/#{Regexp.quote(RUBY)} -e/, @err) 176 end 177 178 def test_inline_verbose_true_should_show_command 179 rakefile_verbose 180 181 rake "inline_verbose_true" 182 183 assert_match(/#{Regexp.quote(RUBY)} -e/, @err) 184 end 185 186 def test_inline_verbose_false_should_not_show_command 187 rakefile_verbose 188 189 rake "inline_verbose_false" 190 191 refute_match(/#{Regexp.quote(RUBY)} -e/, @err) 192 end 193 194 def test_block_verbose_false_should_not_show_command 195 rakefile_verbose 196 197 rake "block_verbose_false" 198 199 refute_match(/#{Regexp.quote(RUBY)} -e/, @err) 200 end 201 202 def test_block_verbose_true_should_show_command 203 rakefile_verbose 204 205 rake "block_verbose_true" 206 207 assert_match(/#{Regexp.quote(RUBY)} -e/, @err) 208 end 209 210 def test_standalone_verbose_true_should_show_command 211 rakefile_verbose 212 213 rake "standalone_verbose_true" 214 215 assert_match(/#{Regexp.quote(RUBY)} -e/, @err) 216 end 217 218 def test_standalone_verbose_false_should_not_show_command 219 rakefile_verbose 220 221 rake "standalone_verbose_false" 222 223 refute_match(/#{Regexp.quote(RUBY)} -e/, @err) 224 end 225 226 def test_dry_run 227 rakefile_default 228 229 rake "-n", "other" 230 231 assert_match %r{Execute \(dry run\) default}, @err 232 assert_match %r{Execute \(dry run\) other}, @err 233 refute_match %r{DEFAULT}, @out 234 refute_match %r{OTHER}, @out 235 end 236 237 # Test for the trace/dry_run bug found by Brian Chandler 238 def test_dry_run_bug 239 rakefile_dryrun 240 241 rake 242 243 FileUtils.rm_f 'temp_one' 244 245 rake "--dry-run" 246 247 refute_match(/No such file/, @out) 248 end 249 250 # Test for the trace/dry_run bug found by Brian Chandler 251 def test_trace_bug 252 rakefile_dryrun 253 254 rake 255 256 FileUtils.rm_f 'temp_one' 257 258 rake "--trace" 259 260 refute_match(/No such file/, @out) 261 end 262 263 def test_imports 264 rakefile_imports 265 266 rake 267 268 assert File.exist?(File.join(@tempdir, 'dynamic_deps')), 269 "'dynamic_deps' file should exist" 270 assert_match(/^FIRST$\s+^DYNAMIC$\s+^STATIC$\s+^OTHER$/, @out) 271 end 272 273 def test_rules_chaining_to_file_task 274 rakefile_chains 275 276 rake 277 278 assert File.exist?(File.join(@tempdir, 'play.app')), 279 "'play.app' file should exist" 280 end 281 282 def test_file_creation_task 283 rakefile_file_creation 284 285 rake "prep" 286 rake "run" 287 rake "run" 288 289 assert(@err !~ /^cp src/, "Should not recopy data") 290 end 291 292 def test_dash_f_with_no_arg_foils_rakefile_lookup 293 rakefile_rakelib 294 295 rake '-I', 'rakelib', '-rtest1', '-f' 296 297 assert_match(/^TEST1$/, @out) 298 end 299 300 def test_dot_rake_files_can_be_loaded_with_dash_r 301 rakefile_rakelib 302 303 rake '-I', 'rakelib', '-rtest2', '-f' 304 305 assert_empty @err 306 assert_match(/^TEST2$/, @out) 307 end 308 309 def test_can_invoke_task_in_toplevel_namespace 310 rakefile_namespace 311 312 rake "copy" 313 314 assert_match(/^COPY$/, @out) 315 end 316 317 def test_can_invoke_task_in_nested_namespace 318 rakefile_namespace 319 320 rake "nest:copy" 321 322 assert_match(/^NEST COPY$/, @out) 323 end 324 325 def test_tasks_can_reference_task_in_same_namespace 326 rakefile_namespace 327 328 rake "nest:xx" 329 330 assert_match(/^NEST COPY$/m, @out) 331 end 332 333 def test_tasks_can_reference_task_in_other_namespaces 334 rakefile_namespace 335 336 rake "b:run" 337 338 assert_match(/^IN A\nIN B$/m, @out) 339 end 340 341 def test_anonymous_tasks_can_be_invoked_indirectly 342 rakefile_namespace 343 344 rake "anon" 345 346 assert_match(/^ANON COPY$/m, @out) 347 end 348 349 def test_rake_namespace_refers_to_toplevel 350 rakefile_namespace 351 352 rake "very:nested:run" 353 354 assert_match(/^COPY$/m, @out) 355 end 356 357 def test_file_task_are_not_scoped_by_namespaces 358 rakefile_namespace 359 360 rake "xyz.rb" 361 362 assert_match(/^XYZ1\nXYZ2$/m, @out) 363 end 364 365 def test_file_task_dependencies_scoped_by_namespaces 366 rakefile_namespace 367 368 rake "scopedep.rb" 369 370 assert_match(/^PREPARE\nSCOPEDEP$/m, @out) 371 end 372 373 def test_comment_before_task_acts_like_desc 374 rakefile_comments 375 376 rake "-T" 377 378 refute_match(/comment for t1/, @out) 379 end 380 381 def test_comment_separated_from_task_by_blank_line_is_not_picked_up 382 rakefile_comments 383 384 rake "-T" 385 386 refute_match("t2", @out) 387 end 388 389 def test_comment_after_desc_is_ignored 390 rakefile_comments 391 392 rake "-T" 393 394 assert_match("override comment for t3", @out) 395 end 396 397 def test_comment_before_desc_is_ignored 398 rakefile_comments 399 400 rake "-T" 401 402 assert_match("override comment for t4", @out) 403 end 404 405 def test_correct_number_of_tasks_reported 406 rakefile_comments 407 408 rake "-T" 409 410 assert_equal(2, @out.split(/\n/).grep(/t\d/).size) 411 end 412 413 def test_file_list_is_requirable_separately 414 ruby '-rrake/file_list', '-e', 'puts Rake::FileList["a"].size' 415 assert_equal "1\n", @out 416 end 417 418 def can_detect_signals? 419 system "ruby -e 'Process.kill \"TERM\", $$'" 420 status = $? 421 if @verbose 422 puts " SIG status = #{$?.inspect}" 423 puts " SIG status.respond_to?(:signaled?) = #{$?.respond_to?(:signaled?).inspect}" 424 puts " SIG status.signaled? = #{status.signaled?}" if status.respond_to?(:signaled?) 425 end 426 status.respond_to?(:signaled?) && status.signaled? 427 end 428 429 def test_signal_propagation_in_tests 430 if can_detect_signals? 431 rakefile_test_signal 432 rake 433 assert_match(/ATEST/, @out) 434 refute_match(/BTEST/, @out) 435 else 436 skip "Signal detect seems broken on this system" 437 end 438 end 439 440 def test_failing_test_sets_exit_status 441 skip if uncertain_exit_status? 442 rakefile_failing_test_task 443 rake 444 assert @exit.exitstatus > 0, "should be non-zero" 445 end 446 447 def test_stand_alone_filelist 448 rakefile_stand_alone_filelist 449 450 run_ruby @ruby_options + ["stand_alone_filelist.rb"] 451 452 assert_match(/^stand_alone_filelist\.rb$/, @out) 453 assert_equal 0, @exit.exitstatus unless uncertain_exit_status? 454 end 455 456 private 457 458 # We are unable to accurately verify that Rake returns a proper 459 # error exit status using popen3 in Ruby 1.8.7 and JRuby. This 460 # predicate function can be used to skip tests or assertions as 461 # needed. 462 def uncertain_exit_status? 463 RUBY_VERSION < "1.9" || defined?(JRUBY_VERSION) 464 end 465 466 # Run a shell Ruby command with command line options (using the 467 # default test options). Output is captured in @out and @err 468 def ruby(*option_list) 469 run_ruby(@ruby_options + option_list) 470 end 471 472 # Run a command line rake with the give rake options. Default 473 # command line ruby options are included. Output is captured in 474 # @out and @err 475 def rake(*rake_options) 476 run_ruby @ruby_options + [@rake_exec] + rake_options 477 end 478 479 # Low level ruby command runner ... 480 def run_ruby(option_list) 481 puts "COMMAND: [#{RUBY} #{option_list.join ' '}]" if @verbose 482 483 inn, out, err, wait = Open3.popen3(RUBY, *option_list) 484 inn.close 485 486 @exit = wait ? wait.value : $? 487 @out = out.read 488 @err = err.read 489 490 puts "OUTPUT: [#{@out}]" if @verbose 491 puts "ERROR: [#{@err}]" if @verbose 492 puts "EXIT: [#{@exit.inspect}]" if @verbose 493 puts "PWD: [#{Dir.pwd}]" if @verbose 494 end 495 496end 497