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