1require 'rdoc/test_case'
2
3class TestRDocOptions < RDoc::TestCase
4
5  def setup
6    super
7
8    @options = RDoc::Options.new
9    @generators = RDoc::RDoc::GENERATORS.dup
10  end
11
12  def teardown
13    super
14
15    RDoc::RDoc::GENERATORS.replace @generators
16  end
17
18  def mu_pp obj
19    s = ''
20    s = PP.pp obj, s
21    s = s.force_encoding Encoding.default_external if defined? Encoding
22    s.chomp
23  end
24
25  def test_check_files
26    skip "assumes UNIX permission model" if /mswin|mingw/ =~ RUBY_PLATFORM
27
28    out, err = capture_io do
29      temp_dir do
30        FileUtils.touch 'unreadable'
31        FileUtils.chmod 0, 'unreadable'
32
33        @options.files = %w[nonexistent unreadable]
34
35        @options.check_files
36      end
37    end
38
39    assert_empty @options.files
40
41    assert_empty out
42    assert_empty err
43  end
44
45  def test_check_files_warn
46    @options.verbosity = 2
47
48    out, err = verbose_capture_io do
49      @options.files = %w[nonexistent]
50
51      @options.check_files
52    end
53
54    assert_empty out
55    assert_equal "file 'nonexistent' not found\n", err
56    assert_empty @options.files
57  end
58
59  def test_dry_run_default
60    refute @options.dry_run
61  end
62
63  def test_encode_with
64    coder = {}
65    class << coder; alias add []=; end
66
67    @options.encode_with coder
68
69    encoding = Object.const_defined?(:Encoding) ? 'UTF-8' : nil
70
71    expected = {
72      'charset'        => 'UTF-8',
73      'encoding'       => encoding,
74      'exclude'        => [],
75      'hyperlink_all'  => false,
76      'line_numbers'   => false,
77      'main_page'      => nil,
78      'markup'         => 'rdoc',
79      'page_dir'       => nil,
80      'rdoc_include'   => [],
81      'show_hash'      => false,
82      'static_path'    => [],
83      'tab_width'      => 8,
84      'title'          => nil,
85      'visibility'     => :protected,
86      'webcvs'         => nil,
87    }
88
89    assert_equal expected, coder
90  end
91
92  def test_encode_with_trim_paths
93    subdir = nil
94    coder = {}
95    class << coder; alias add []=; end
96
97    temp_dir do |dir|
98      FileUtils.mkdir 'project'
99      FileUtils.mkdir 'dir'
100      FileUtils.touch 'file'
101
102      Dir.chdir 'project' do
103        subdir = File.expand_path 'subdir'
104        FileUtils.mkdir 'subdir'
105        @options.parse %w[
106          --copy subdir
107          --copy ../file
108          --copy ../
109          --copy /
110          --include subdir
111          --include ../dir
112          --include ../
113          --include /
114        ]
115
116        @options.encode_with coder
117      end
118    end
119
120    assert_equal [subdir], coder['rdoc_include']
121
122    assert_equal [subdir], coder['static_path']
123  end
124
125  def test_encoding_default
126    skip "Encoding not implemented" unless Object.const_defined? :Encoding
127
128    assert_equal Encoding::UTF_8, @options.encoding
129  end
130
131  def test_generator_descriptions
132    # HACK autotest/isolate should take care of this
133    RDoc::RDoc::GENERATORS.clear
134    RDoc::RDoc::GENERATORS['darkfish'] = RDoc::Generator::Darkfish
135    RDoc::RDoc::GENERATORS['ri']       = RDoc::Generator::RI
136
137    expected = <<-EXPECTED.chomp
138  darkfish - HTML generator, written by Michael Granger
139  ri       - creates ri data files
140    EXPECTED
141
142    assert_equal expected, @options.generator_descriptions
143  end
144
145  def test_init_with_encoding
146    skip "Encoding not implemented" unless Object.const_defined? :Encoding
147    RDoc.load_yaml
148
149    @options.encoding = Encoding::IBM437
150
151    options = YAML.load YAML.dump @options
152
153    assert_equal Encoding::IBM437, options.encoding
154  end
155
156  def test_init_with_trim_paths
157    RDoc.load_yaml
158
159    yaml = <<-YAML
160--- !ruby/object:RDoc::Options
161static_path:
162- /etc
163rdoc_include:
164- /etc
165    YAML
166
167    options = YAML.load yaml
168
169    assert_empty options.rdoc_include
170    assert_empty options.static_path
171  end
172
173  def test_parse_copy_files_file_relative
174    file = File.basename __FILE__
175    expected = File.expand_path __FILE__
176
177    Dir.chdir File.expand_path('..', __FILE__) do
178      @options.parse %W[--copy-files #{file}]
179
180      assert_equal [expected], @options.static_path
181    end
182  end
183
184  def test_parse_copy_files_file_absolute
185    @options.parse %W[--copy-files #{File.expand_path __FILE__}]
186
187    assert_equal [File.expand_path(__FILE__)], @options.static_path
188  end
189
190  def test_parse_copy_files_directory_relative
191    @options.parse %w[--copy-files .]
192
193    assert_equal [@pwd], @options.static_path
194  end
195
196  def test_parse_copy_files_directory_absolute
197    @options.parse %w[--copy-files /]
198
199    assert_equal 1, @options.static_path.length
200
201    assert_match %r%^([A-Z]:)?/$%i, @options.static_path.first
202  end
203
204  def test_parse_coverage
205    @options.parse %w[--dcov]
206
207    assert @options.coverage_report
208    assert @options.force_update
209  end
210
211  def test_parse_coverage_no
212    @options.parse %w[--no-dcov]
213
214    refute @options.coverage_report
215  end
216
217  def test_parse_coverage_level_1
218    @options.parse %w[--dcov=1]
219
220    assert_equal 1, @options.coverage_report
221  end
222
223  def test_parse_dash_p
224    out, err = capture_io do
225      @options.parse %w[-p]
226    end
227
228    assert @options.pipe
229    refute_match %r%^Usage: %, err
230    refute_match %r%^invalid options%, err
231
232    assert_empty out
233  end
234
235  def test_parse_dash_p_files
236    out, err = capture_io do
237      @options.parse ['-p', File.expand_path(__FILE__)]
238    end
239
240    refute @options.pipe
241    refute_match %r%^Usage: %, err
242    assert_match %r%^invalid options: -p .with files.%, err
243
244    assert_empty out
245  end
246
247  def test_parse_default
248    @options.parse []
249
250    assert_equal RDoc::Generator::Darkfish,             @options.generator
251    assert_equal 'darkfish',                            @options.template
252    assert_match %r%rdoc/generator/template/darkfish$%, @options.template_dir
253  end
254
255  def test_parse_deprecated
256    dep_hash = RDoc::Options::DEPRECATED
257    options = dep_hash.keys.sort
258
259    out, err = capture_io do
260      @options.parse options
261    end
262
263    dep_hash.each_pair do |opt, message|
264      assert_match %r%.*#{opt}.+#{message}%, err
265    end
266
267    assert_empty out
268  end
269
270  def test_parse_dry_run
271    @options.parse %w[--dry-run]
272
273    assert @options.dry_run
274  end
275
276  def test_parse_encoding
277    skip "Encoding not implemented" unless Object.const_defined? :Encoding
278
279    @options.parse %w[--encoding Big5]
280
281    assert_equal Encoding::Big5, @options.encoding
282    assert_equal 'Big5',         @options.charset
283  end
284
285  def test_parse_encoding_invalid
286    skip "Encoding not implemented" unless Object.const_defined? :Encoding
287
288    out, err = capture_io do
289      @options.parse %w[--encoding invalid]
290    end
291
292    assert_match %r%^invalid options: --encoding invalid%, err
293
294    assert_empty out
295  end
296
297  def test_parse_formatter
298    e = assert_raises OptionParser::InvalidOption do
299      @options.parse %w[--format darkfish --format ri]
300    end
301
302    assert_equal 'invalid option: --format generator already set to darkfish',
303                 e.message
304  end
305
306  def test_parse_formatter_ri
307    e = assert_raises OptionParser::InvalidOption do
308      @options.parse %w[--format darkfish --ri]
309    end
310
311    assert_equal 'invalid option: --ri generator already set to darkfish',
312                 e.message
313
314    @options = RDoc::Options.new
315
316    e = assert_raises OptionParser::InvalidOption do
317      @options.parse %w[--format darkfish -r]
318    end
319
320    assert_equal 'invalid option: -r generator already set to darkfish',
321                 e.message
322  end
323
324  def test_parse_formatter_ri_site
325    e = assert_raises OptionParser::InvalidOption do
326      @options.parse %w[--format darkfish --ri-site]
327    end
328
329    assert_equal 'invalid option: --ri-site generator already set to darkfish',
330                 e.message
331
332    @options = RDoc::Options.new
333
334    e = assert_raises OptionParser::InvalidOption do
335      @options.parse %w[--format darkfish -R]
336    end
337
338    assert_equal 'invalid option: -R generator already set to darkfish',
339                 e.message
340  end
341
342  def test_parse_help
343    out, = capture_io do
344      begin
345        @options.parse %w[--help]
346      rescue SystemExit
347      end
348    end
349
350    assert_equal 1, out.scan(/HTML generator options:/).length
351    assert_equal 1, out.scan(/ri generator options:/).  length
352  end
353
354  def test_parse_help_extra_generator
355    RDoc::RDoc::GENERATORS['test'] = Class.new do
356      def self.setup_options options
357        op = options.option_parser
358
359        op.separator 'test generator options:'
360      end
361    end
362
363    out, = capture_io do
364      begin
365        @options.parse %w[--help]
366      rescue SystemExit
367      end
368    end
369
370    assert_equal 1, out.scan(/HTML generator options:/).length
371    assert_equal 1, out.scan(/ri generator options:/).  length
372    assert_equal 1, out.scan(/test generator options:/).length
373  end
374
375  def test_parse_ignore_invalid
376    out, err = capture_io do
377      @options.parse %w[--ignore-invalid --bogus]
378    end
379
380    refute_match %r%^Usage: %, err
381    assert_match %r%^invalid options: --bogus%, err
382
383    assert_empty out
384  end
385
386  def test_parse_ignore_invalid_default
387    out, err = capture_io do
388      @options.parse %w[--bogus --main BLAH]
389    end
390
391    refute_match %r%^Usage: %, err
392    assert_match %r%^invalid options: --bogus%, err
393
394    assert_equal 'BLAH', @options.main_page
395
396    assert_empty out
397  end
398
399  def test_parse_ignore_invalid_no
400    out, err = capture_io do
401      assert_raises SystemExit do
402        @options.parse %w[--no-ignore-invalid --bogus=arg --bobogus --visibility=extended]
403      end
404    end
405
406    assert_match %r%^Usage: %, err
407    assert_match %r%^invalid options: --bogus=arg, --bobogus, --visibility=extended%, err
408
409    assert_empty out
410  end
411
412  def test_parse_main
413    out, err = capture_io do
414      @options.parse %w[--main MAIN]
415    end
416
417    assert_empty out
418    assert_empty err
419
420    assert_equal 'MAIN', @options.main_page
421  end
422
423  def test_parse_markup
424    out, err = capture_io do
425      @options.parse %w[--markup tomdoc]
426    end
427
428    assert_empty out
429    assert_empty err
430
431    assert_equal 'tomdoc', @options.markup
432  end
433
434  def test_parse_page_dir
435    assert_nil @options.page_dir
436
437    out, err = capture_io do
438      @options.parse %W[--page-dir #{Dir.tmpdir}]
439    end
440
441    assert_empty out
442    assert_empty err
443
444    expected =
445      Pathname(Dir.tmpdir).expand_path.relative_path_from @options.root
446
447    assert_equal expected,     @options.page_dir
448    assert_equal [Dir.tmpdir], @options.files
449  end
450
451  def test_parse_page_dir_root
452    assert_nil @options.page_dir
453
454    Dir.mktmpdir do |dir|
455      abs_root     = dir
456      abs_page_dir = File.join dir, 'pages'
457      FileUtils.mkdir abs_page_dir
458
459      out, err = capture_io do
460        @options.parse %W[--page-dir #{abs_page_dir} --root #{abs_root}]
461      end
462
463      assert_empty out
464      assert_empty err
465
466      assert_equal Pathname('pages'), @options.page_dir
467      assert_equal [abs_page_dir],    @options.files
468    end
469  end
470
471  def test_parse_root
472    assert_equal Pathname(Dir.pwd), @options.root
473
474    out, err = capture_io do
475      @options.parse %W[--root #{Dir.tmpdir}]
476    end
477
478    assert_empty out
479    assert_empty err
480
481    assert_equal Pathname(Dir.tmpdir), @options.root
482  end
483
484  def test_parse_template
485    out, err = capture_io do
486      @options.parse %w[--template darkfish]
487    end
488
489    assert_empty out
490    assert_empty err
491
492    assert_equal 'darkfish', @options.template
493
494    assert_match %r%rdoc/generator/template/darkfish$%, @options.template_dir
495  end
496
497  def test_parse_template_nonexistent
498    out, err = capture_io do
499      @options.parse %w[--template NONEXISTENT]
500    end
501
502    assert_empty out
503    assert_equal "could not find template NONEXISTENT\n", err
504
505    assert_equal 'darkfish', @options.template
506    assert_match %r%rdoc/generator/template/darkfish$%, @options.template_dir
507  end
508
509  def test_parse_template_load_path
510    orig_LOAD_PATH = $LOAD_PATH.dup
511
512    template_dir = nil
513
514    Dir.mktmpdir do |dir|
515      $LOAD_PATH << dir
516
517      template_dir = File.join dir, 'rdoc', 'generator', 'template', 'load_path'
518
519      FileUtils.mkdir_p template_dir
520
521      out, err = capture_io do
522        @options.parse %w[--template load_path]
523      end
524
525      assert_empty out
526      assert_empty err
527    end
528
529    assert_equal 'load_path',  @options.template
530    assert_equal template_dir, @options.template_dir
531  ensure
532    $LOAD_PATH.replace orig_LOAD_PATH
533  end
534
535  def test_parse_write_options
536    tmpdir = File.join Dir.tmpdir, "test_rdoc_options_#{$$}"
537    FileUtils.mkdir_p tmpdir
538
539    Dir.chdir tmpdir do
540      e = assert_raises SystemExit do
541        @options.parse %w[--write-options]
542      end
543
544      assert_equal 0, e.status
545
546      assert File.exist? '.rdoc_options'
547    end
548  ensure
549    FileUtils.rm_rf tmpdir
550  end
551
552  def test_parse_extension_alias
553    out, err = capture_io do
554      @options.parse %w[--extension foobar=rdoc]
555    end
556
557    assert_includes RDoc::Parser.parsers, [/\.foobar$/, RDoc::Parser::Simple]
558
559    assert_empty out
560    assert_empty err
561  end
562
563  def test_setup_generator
564    test_generator = Class.new do
565      def self.setup_options op
566        @op = op
567      end
568
569      def self.op() @op end
570    end
571
572    RDoc::RDoc::GENERATORS['test'] = test_generator
573
574    @options.setup_generator 'test'
575
576    assert_equal test_generator, @options.generator
577    assert_equal [test_generator], @options.generator_options
578
579    assert_equal @options, test_generator.op
580  ensure
581    RDoc::RDoc::GENERATORS.delete 'test'
582  end
583
584  def test_setup_generator_no_option_parser
585    test_generator = Class.new do
586      def self.setup_options op
587        op.option_parser.separator nil
588        @op = op
589      end
590
591      def self.op() @op end
592    end
593
594    RDoc::RDoc::GENERATORS['test'] = test_generator
595
596    @options.setup_generator 'test'
597
598    assert_equal test_generator, @options.generator
599    assert_equal [test_generator], @options.generator_options
600
601    assert_equal @options, test_generator.op
602  ensure
603    RDoc::RDoc::GENERATORS.delete 'test'
604  end
605
606  def test_update_output_dir
607    assert @options.update_output_dir
608
609    @options.update_output_dir = false
610
611    refute @options.update_output_dir
612  end
613
614  def test_warn
615    out, err = capture_io do
616      @options.warn "warnings off"
617    end
618
619    assert_empty out
620    assert_empty err
621
622    @options.verbosity = 2
623
624    out, err = verbose_capture_io do
625      @options.warn "warnings on"
626    end
627
628    assert_empty out
629    assert_equal "warnings on\n", err
630  end
631
632  def test_write_options
633    temp_dir do |dir|
634      @options.write_options
635
636      assert File.exist? '.rdoc_options'
637
638      assert_equal @options, YAML.load(File.read('.rdoc_options'))
639    end
640  end
641
642end
643
644