1require 'rdoc/test_case'
2
3class TestRDocRIDriver < RDoc::TestCase
4
5  def setup
6    super
7
8    @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_driver_#{$$}"
9    @home_ri = File.join @tmpdir, 'dot_ri'
10
11    FileUtils.mkdir_p @tmpdir
12    FileUtils.mkdir_p @home_ri
13
14    @orig_ri = ENV['RI']
15    @orig_home = ENV['HOME']
16    ENV['HOME'] = @tmpdir
17    ENV.delete 'RI'
18
19    @options = RDoc::RI::Driver.default_options
20    @options[:use_system] = false
21    @options[:use_site]   = false
22    @options[:use_home]   = false
23    @options[:use_gems]   = false
24
25    @options[:home]       = @tmpdir
26    @options[:use_stdout] = true
27    @options[:formatter]  = @RM::ToRdoc
28
29    @driver = RDoc::RI::Driver.new @options
30  end
31
32  def teardown
33    super
34
35    ENV['HOME'] = @orig_home
36    ENV['RI'] = @orig_ri
37    FileUtils.rm_rf @tmpdir
38  end
39
40  DUMMY_PAGER = ":;\n"
41
42  def with_dummy_pager
43    pager_env, ENV['RI_PAGER'] = ENV['RI_PAGER'], DUMMY_PAGER
44    yield
45  ensure
46    ENV['RI_PAGER'] = pager_env
47  end
48
49  def mu_pp(obj)
50    s = ''
51    s = PP.pp obj, s
52    s = s.force_encoding(Encoding.default_external) if defined? Encoding
53    s.chomp
54  end
55
56  def test_self_dump
57    util_store
58
59    out, = capture_io do
60      RDoc::RI::Driver.dump @store1.cache_path
61    end
62
63    assert_match %r%:class_methods%,    out
64    assert_match %r%:modules%,          out
65    assert_match %r%:instance_methods%, out
66    assert_match %r%:ancestors%,        out
67  end
68
69  def test_add_also_in_empty
70    out = @RM::Document.new
71
72    @driver.add_also_in out, []
73
74    assert_empty out
75  end
76
77  def test_add_also_in
78    util_multi_store
79    @store1.type = :system
80    @store2.type = :home
81
82    out = @RM::Document.new
83
84    @driver.add_also_in out, [@store1, @store2]
85
86    expected = @RM::Document.new(
87      @RM::Rule.new(1),
88      @RM::Paragraph.new('Also found in:'),
89      @RM::Verbatim.new("ruby core", "\n",
90                        "~/.rdoc", "\n"))
91
92    assert_equal expected, out
93  end
94
95  def test_add_class
96    util_multi_store
97
98    out = @RM::Document.new
99
100    @driver.add_class out, 'Bar', [@cBar]
101
102    expected = @RM::Document.new(
103      @RM::Heading.new(1, 'Bar < Foo'),
104      @RM::BlankLine.new)
105
106    assert_equal expected, out
107  end
108
109  def test_add_from
110    util_store
111    @store1.type = :system
112
113    out = @RM::Document.new
114
115    @driver.add_from out, @store1
116
117    expected = @RM::Document.new @RM::Paragraph.new("(from ruby core)")
118
119    assert_equal expected, out
120  end
121
122  def test_add_extends
123    util_store
124
125    out = @RM::Document.new
126
127    @driver.add_extends out, [[[@cFooExt], @store1]]
128
129    expected = @RM::Document.new(
130      @RM::Rule.new(1),
131      @RM::Heading.new(1, "Extended by:"),
132      @RM::Paragraph.new("Ext (from #{@store1.friendly_path})"),
133      @RM::BlankLine.new,
134      @RM::Paragraph.new("Extend thingy"),
135      @RM::BlankLine.new)
136
137    assert_equal expected, out
138  end
139
140  def test_add_extension_modules_empty
141    out = @RM::Document.new
142
143    @driver.add_extension_modules out, 'Includes', []
144
145    assert_empty out
146  end
147
148  def test_add_extension_modules_many
149    util_store
150
151    out = @RM::Document.new
152
153    enum = RDoc::Include.new 'Enumerable', nil
154    @cFoo.add_include enum
155
156    @driver.add_extension_modules out, 'Includes', [[[@cFooInc, enum], @store1]]
157
158    expected = @RM::Document.new(
159      @RM::Rule.new(1),
160      @RM::Heading.new(1, "Includes:"),
161      @RM::Paragraph.new("(from #{@store1.friendly_path})"),
162      @RM::BlankLine.new,
163      @RM::Paragraph.new("Inc"),
164      @RM::BlankLine.new,
165      @RM::Paragraph.new("Include thingy"),
166      @RM::BlankLine.new,
167      @RM::Verbatim.new("Enumerable", "\n"))
168
169    assert_equal expected, out
170  end
171
172  def test_add_extension_modules_many_no_doc
173    util_store
174
175    out = @RM::Document.new
176
177    enum = RDoc::Include.new 'Enumerable', nil
178    @cFoo.add_include enum
179    @cFooInc.instance_variable_set :@comment, ''
180
181    @driver.add_extension_modules out, 'Includes', [[[@cFooInc, enum], @store1]]
182
183    expected = @RM::Document.new(
184      @RM::Rule.new(1),
185      @RM::Heading.new(1, "Includes:"),
186      @RM::Paragraph.new("(from #{@store1.friendly_path})"),
187      @RM::Verbatim.new("Inc", "\n",
188                        "Enumerable", "\n"))
189
190    assert_equal expected, out
191  end
192
193  def test_add_extension_modules_one
194    util_store
195
196    out = @RM::Document.new
197
198    @driver.add_extension_modules out, 'Includes', [[[@cFooInc], @store1]]
199
200    expected = @RM::Document.new(
201      @RM::Rule.new(1),
202      @RM::Heading.new(1, "Includes:"),
203      @RM::Paragraph.new("Inc (from #{@store1.friendly_path})"),
204      @RM::BlankLine.new,
205      @RM::Paragraph.new("Include thingy"),
206      @RM::BlankLine.new)
207
208    assert_equal expected, out
209  end
210
211  def test_add_includes
212    util_store
213
214    out = @RM::Document.new
215
216    @driver.add_includes out, [[[@cFooInc], @store1]]
217
218    expected = @RM::Document.new(
219      @RM::Rule.new(1),
220      @RM::Heading.new(1, "Includes:"),
221      @RM::Paragraph.new("Inc (from #{@store1.friendly_path})"),
222      @RM::BlankLine.new,
223      @RM::Paragraph.new("Include thingy"),
224      @RM::BlankLine.new)
225
226    assert_equal expected, out
227  end
228
229  def test_add_method
230    util_store
231
232    out = doc
233
234    @driver.add_method out, 'Foo::Bar#blah'
235
236    expected =
237      doc(
238        head(1, 'Foo::Bar#blah'),
239        blank_line,
240        para('(from ~/.rdoc)'),
241        head(3, 'Implementation from Bar'),
242        rule(1),
243        verb("blah(5) => 5\n",
244             "blah(6) => 6\n"),
245        rule(1),
246        blank_line,
247        blank_line)
248
249    assert_equal expected, out
250  end
251
252  def test_add_method_attribute
253    util_store
254
255    out = doc
256
257    @driver.add_method out, 'Foo::Bar#attr'
258
259    expected =
260      doc(
261        head(1, 'Foo::Bar#attr'),
262        blank_line,
263        para('(from ~/.rdoc)'),
264        rule(1),
265        blank_line,
266        blank_line)
267
268    assert_equal expected, out
269  end
270
271  def test_add_method_inherited
272    util_multi_store
273
274    out = doc
275
276    @driver.add_method out, 'Bar#inherit'
277
278    expected =
279      doc(
280        head(1, 'Bar#inherit'),
281        blank_line,
282        para('(from ~/.rdoc)'),
283        head(3, 'Implementation from Foo'),
284        rule(1),
285        blank_line,
286        blank_line)
287
288    assert_equal expected, out
289  end
290
291  def test_add_method_overriden
292    util_multi_store
293
294    out = doc
295
296    @driver.add_method out, 'Bar#override'
297
298    expected =
299      doc(
300        head(1, 'Bar#override'),
301        blank_line,
302        para("(from #{@store2.path})"),
303        rule(1),
304        blank_line,
305        para('must be displayed'),
306        blank_line,
307        blank_line)
308
309    assert_equal expected, out
310  end
311
312  def test_add_method_documentation
313    util_store
314
315    out = doc()
316
317    missing = RDoc::AnyMethod.new nil, 'missing'
318    @cFoo.add_method missing
319
320    @driver.add_method_documentation out, @cFoo
321
322    expected =
323      doc(
324        head(1, 'Foo#inherit'),
325        blank_line,
326        para('(from ~/.rdoc)'),
327        rule(1),
328        blank_line,
329        blank_line,
330        head(1, 'Foo#override'),
331        blank_line,
332        para('(from ~/.rdoc)'),
333        rule(1),
334        blank_line,
335        para('must not be displayed in Bar#override'),
336        blank_line,
337        blank_line)
338
339    assert_equal expected, out
340  end
341
342  def test_add_method_list
343    out = @RM::Document.new
344
345    @driver.add_method_list out, %w[new parse], 'Class methods'
346
347    expected = @RM::Document.new(
348      @RM::Heading.new(1, 'Class methods:'),
349      @RM::BlankLine.new,
350      @RM::Verbatim.new('new'),
351      @RM::Verbatim.new('parse'),
352      @RM::BlankLine.new)
353
354    assert_equal expected, out
355  end
356
357  def test_add_method_list_interative
358    @options[:interactive] = true
359    driver = RDoc::RI::Driver.new @options
360
361    out = @RM::Document.new
362
363    driver.add_method_list out, %w[new parse], 'Class methods'
364
365    expected = @RM::Document.new(
366      @RM::Heading.new(1, 'Class methods:'),
367      @RM::BlankLine.new,
368      @RM::IndentedParagraph.new(2, 'new, parse'),
369      @RM::BlankLine.new)
370
371    assert_equal expected, out
372  end
373
374  def test_add_method_list_none
375    out = @RM::Document.new
376
377    @driver.add_method_list out, [], 'Class'
378
379    assert_equal @RM::Document.new, out
380  end
381
382  def test_ancestors_of
383    util_ancestors_store
384
385    assert_equal %w[X Mixin Object Foo], @driver.ancestors_of('Foo::Bar')
386  end
387
388  def test_classes
389    util_multi_store
390
391    expected = {
392      'Ambiguous' => [@store1, @store2],
393      'Bar'       => [@store2],
394      'Ext'       => [@store1],
395      'Foo'       => [@store1, @store2],
396      'Foo::Bar'  => [@store1],
397      'Foo::Baz'  => [@store1, @store2],
398      'Inc'       => [@store1],
399    }
400
401    classes = @driver.classes
402
403    assert_equal expected.keys.sort, classes.keys.sort
404
405    expected.each do |klass, stores|
406      assert_equal stores, classes[klass].sort_by { |store| store.path },
407                   "mismatch for #{klass}"
408    end
409  end
410
411  def test_class_document
412    util_store
413
414    tl1 = @store1.add_file 'one.rb'
415    tl2 = @store1.add_file 'two.rb'
416
417    @cFoo.add_comment 'one', tl1
418    @cFoo.add_comment 'two', tl2
419
420    @store1.save_class @cFoo
421
422    found = [
423      [@store1, @store1.load_class(@cFoo.full_name)]
424    ]
425
426    extends  = [[[@cFooExt], @store1]]
427    includes = [[[@cFooInc], @store1]]
428
429    out = @driver.class_document @cFoo.full_name, found, [], includes, extends
430
431    expected = @RM::Document.new
432    @driver.add_class expected, 'Foo', []
433    @driver.add_includes expected, includes
434    @driver.add_extends  expected, extends
435    @driver.add_from expected, @store1
436    expected << @RM::Rule.new(1)
437
438    doc = @RM::Document.new(@RM::Paragraph.new('one'))
439    doc.file = 'one.rb'
440    expected.push doc
441    expected << @RM::BlankLine.new
442    doc = @RM::Document.new(@RM::Paragraph.new('two'))
443    doc.file = 'two.rb'
444    expected.push doc
445
446    expected << @RM::Rule.new(1)
447    expected << @RM::Heading.new(1, 'Instance methods:')
448    expected << @RM::BlankLine.new
449    expected << @RM::Verbatim.new('inherit')
450    expected << @RM::Verbatim.new('override')
451    expected << @RM::BlankLine.new
452
453    assert_equal expected, out
454  end
455
456  def test_complete
457    store = RDoc::RI::Store.new @home_ri
458    store.cache[:ancestors] = {
459      'Foo'      => %w[Object],
460      'Foo::Bar' => %w[Object],
461    }
462    store.cache[:class_methods] = {
463      'Foo' => %w[bar]
464    }
465    store.cache[:instance_methods] = {
466      'Foo' => %w[Bar]
467    }
468    store.cache[:modules] = %w[
469      Foo
470      Foo::Bar
471    ]
472
473    @driver.stores = [store]
474
475    assert_equal %w[Foo         ], @driver.complete('F')
476    assert_equal %w[    Foo::Bar], @driver.complete('Foo::B')
477
478    assert_equal %w[Foo#Bar],           @driver.complete('Foo#'),   'Foo#'
479    assert_equal %w[Foo#Bar  Foo::bar], @driver.complete('Foo.'),   'Foo.'
480    assert_equal %w[Foo::Bar Foo::bar], @driver.complete('Foo::'),  'Foo::'
481
482    assert_equal %w[         Foo::bar], @driver.complete('Foo::b'), 'Foo::b'
483  end
484
485  def test_complete_ancestor
486    util_ancestors_store
487
488    assert_equal %w[Foo::Bar#i_method], @driver.complete('Foo::Bar#')
489
490    assert_equal %w[Foo::Bar#i_method Foo::Bar::c_method Foo::Bar::new],
491                 @driver.complete('Foo::Bar.')
492  end
493
494  def test_complete_classes
495    util_store
496
497    assert_equal %w[                       ], @driver.complete('[')
498    assert_equal %w[                       ], @driver.complete('[::')
499    assert_equal %w[Foo                    ], @driver.complete('F')
500    assert_equal %w[Foo:: Foo::Bar Foo::Baz], @driver.complete('Foo::')
501    assert_equal %w[      Foo::Bar Foo::Baz], @driver.complete('Foo::B')
502  end
503
504  def test_complete_multistore
505    util_multi_store
506
507    assert_equal %w[Bar], @driver.complete('B')
508    assert_equal %w[Foo], @driver.complete('F')
509    assert_equal %w[Foo::Bar Foo::Baz], @driver.complete('Foo::B')
510  end
511
512  def test_display
513    doc = @RM::Document.new(
514            @RM::Paragraph.new('hi'))
515
516    out, = capture_io do
517      @driver.display doc
518    end
519
520    assert_equal "hi\n", out
521  end
522
523  def test_display_class
524    util_store
525
526    out, = capture_io do
527      @driver.display_class 'Foo::Bar'
528    end
529
530    assert_match %r%^= Foo::Bar%, out
531    assert_match %r%^\(from%, out
532
533    assert_match %r%^= Class methods:%, out
534    assert_match %r%^  new%, out
535    assert_match %r%^= Instance methods:%, out
536    assert_match %r%^  blah%, out
537    assert_match %r%^= Attributes:%, out
538    assert_match %r%^  attr_accessor attr%, out
539
540    assert_equal 1, out.scan(/-\n/).length
541
542    refute_match %r%Foo::Bar#blah%, out
543  end
544
545  def test_display_class_all
546    util_store
547
548    @driver.show_all = true
549
550    out, = capture_io do
551      @driver.display_class 'Foo::Bar'
552    end
553
554    assert_match %r%^= Foo::Bar%, out
555    assert_match %r%^\(from%, out
556
557    assert_match %r%^= Class methods:%, out
558    assert_match %r%^  new%, out
559    assert_match %r%^= Instance methods:%, out
560    assert_match %r%^  blah%, out
561    assert_match %r%^= Attributes:%, out
562    assert_match %r%^  attr_accessor attr%, out
563
564    assert_equal 6, out.scan(/-\n/).length
565
566    assert_match %r%Foo::Bar#blah%, out
567  end
568
569  def test_display_class_ambiguous
570    util_multi_store
571
572    out, = capture_io do
573      @driver.display_class 'Ambiguous'
574    end
575
576    assert_match %r%^= Ambiguous < Object$%, out
577  end
578
579  def test_display_class_multi_no_doc
580    util_multi_store
581
582    out, = capture_io do
583      @driver.display_class 'Foo::Baz'
584    end
585
586    assert_match %r%^= Foo::Baz%, out
587    assert_match %r%-\n%, out
588    assert_match %r%Also found in:%, out
589    assert_match %r%#{Regexp.escape @home_ri}%, out
590    assert_match %r%#{Regexp.escape @home_ri2}%, out
591  end
592
593  def test_display_class_superclass
594    util_multi_store
595
596    out, = capture_io do
597      @driver.display_class 'Bar'
598    end
599
600    assert_match %r%^= Bar < Foo%, out
601  end
602
603  def test_display_class_module
604    util_store
605
606    out, = capture_io do
607      @driver.display_class 'Inc'
608    end
609
610    assert_match %r%^= Inc$%, out
611  end
612
613  def test_display_class_page
614    out, = capture_io do
615      @driver.display_class 'ruby:README'
616    end
617
618    assert_empty out
619  end
620
621  def test_display_method
622    util_store
623
624    out, = capture_io do
625      @driver.display_method 'Foo::Bar#blah'
626    end
627
628    assert_match %r%Foo::Bar#blah%, out
629    assert_match %r%blah.5%,        out
630    assert_match %r%blah.6%,        out
631  end
632
633  def test_display_method_attribute
634    util_store
635
636    out, = capture_io do
637      @driver.display_method 'Foo::Bar#attr'
638    end
639
640    assert_match %r%Foo::Bar#attr%, out
641    refute_match %r%Implementation from%, out
642  end
643
644  def test_display_method_inherited
645    util_multi_store
646
647    out, = capture_io do
648      @driver.display_method 'Bar#inherit'
649    end
650
651    assert_match %r%^= Bar#inherit%, out
652    assert_match %r%^=== Implementation from Foo%, out
653  end
654
655  def test_display_method_overriden
656    util_multi_store
657
658    out, = capture_io do
659      @driver.display_method 'Bar#override'
660    end
661
662    refute_match %r%must not be displayed%, out
663  end
664
665  def test_display_name_not_found_class
666    util_store
667
668    out, = capture_io do
669      assert_equal false, @driver.display_name('Foo::B')
670    end
671
672    expected = <<-EXPECTED
673Foo::B not found, maybe you meant:
674
675Foo::Bar
676Foo::Baz
677    EXPECTED
678
679    assert_equal expected, out
680  end
681
682  def test_display_name_not_found_method
683    util_store
684
685    out, = capture_io do
686      assert_equal false, @driver.display_name('Foo::Bar#b')
687    end
688
689    expected = <<-EXPECTED
690Foo::Bar#b not found, maybe you meant:
691
692Foo::Bar#blah
693Foo::Bar#bother
694    EXPECTED
695
696    assert_equal expected, out
697  end
698
699  def test_display_method_params
700    util_store
701
702    out, = capture_io do
703      @driver.display_method 'Foo::Bar#bother'
704    end
705
706    assert_match %r%things.*stuff%, out
707  end
708
709  def test_display_page
710    util_store
711
712    out, = capture_io do
713      @driver.display_page 'home:README.rdoc'
714    end
715
716    assert_match %r%= README%, out
717  end
718
719  def test_display_page_add_extension
720    util_store
721
722    out, = capture_io do
723      @driver.display_page 'home:README'
724    end
725
726    assert_match %r%= README%, out
727  end
728
729  def test_display_page_ambiguous
730    util_store
731
732    other = @store1.add_file 'README.md'
733    other.parser = RDoc::Parser::Simple
734    other.comment =
735      doc(
736        head(1, 'README.md'),
737        para('This is the other README'))
738
739    @store1.save_page other
740
741    out, = capture_io do
742      @driver.display_page 'home:README'
743    end
744
745    assert_match %r%= README pages in ~/\.rdoc%, out
746    assert_match %r%README\.rdoc%,               out
747    assert_match %r%README\.md%,                 out
748  end
749
750  def test_display_page_extension
751    util_store
752
753    other = @store1.add_file 'README.EXT'
754    other.parser = RDoc::Parser::Simple
755    other.comment =
756      doc(
757        head(1, 'README.EXT'),
758        para('This is the other README'))
759
760    @store1.save_page other
761
762    out, = capture_io do
763      @driver.display_page 'home:README.EXT'
764    end
765
766    assert_match 'other README', out
767  end
768
769  def test_display_page_ignore_directory
770    util_store
771
772    other = @store1.add_file 'doc/globals.rdoc'
773    other.parser = RDoc::Parser::Simple
774    other.comment =
775      doc(
776        head(1, 'globals.rdoc'),
777        para('Globals go here'))
778
779    @store1.save_page other
780
781    out, = capture_io do
782      @driver.display_page 'home:globals'
783    end
784
785    assert_match %r%= globals\.rdoc%, out
786  end
787
788  def test_display_page_missing
789    util_store
790
791    out, = capture_io do
792      @driver.display_page 'home:missing'
793    end
794
795    out, = capture_io do
796      @driver.display_page_list @store1
797    end
798
799    assert_match %r%= Pages in ~/\.rdoc%, out
800    assert_match %r%README\.rdoc%,        out
801  end
802
803  def test_display_page_list
804    util_store
805
806    other = @store1.add_file 'OTHER.rdoc'
807    other.parser = RDoc::Parser::Simple
808    other.comment =
809      doc(
810        head(1, 'OTHER'),
811        para('This is OTHER'))
812
813    @store1.save_page other
814
815    out, = capture_io do
816      @driver.display_page_list @store1
817    end
818
819    assert_match %r%= Pages in ~/\.rdoc%, out
820    assert_match %r%README\.rdoc%,        out
821    assert_match %r%OTHER\.rdoc%,         out
822  end
823
824  def test_expand_class
825    util_store
826
827    assert_equal 'Foo',       @driver.expand_class('F')
828    assert_equal 'Foo::Bar',  @driver.expand_class('F::Bar')
829
830    assert_raises RDoc::RI::Driver::NotFoundError do
831      @driver.expand_class 'F::B'
832    end
833  end
834
835  def test_expand_name
836    util_store
837
838    assert_equal '.b',        @driver.expand_name('b')
839    assert_equal 'Foo',       @driver.expand_name('F')
840    assert_equal 'Foo::Bar#', @driver.expand_name('F::Bar#')
841
842    e = assert_raises RDoc::RI::Driver::NotFoundError do
843      @driver.expand_name 'Z'
844    end
845
846    assert_equal 'Z', e.name
847
848    @driver.stores << RDoc::Store.new(nil, :system)
849
850    assert_equal 'ruby:README', @driver.expand_name('ruby:README')
851    assert_equal 'ruby:',       @driver.expand_name('ruby:')
852
853    e = assert_raises RDoc::RI::Driver::NotFoundError do
854      @driver.expand_name 'nonexistent_gem:'
855    end
856
857    assert_equal 'nonexistent_gem', e.name
858  end
859
860  def test_find_methods
861    util_store
862
863    items = []
864
865    @driver.find_methods 'Foo::Bar.' do |store, klass, ancestor, types, method|
866      items << [store, klass, ancestor, types, method]
867    end
868
869    expected = [
870      [@store1, 'Foo::Bar', 'Foo::Bar', :both, nil],
871    ]
872
873    assert_equal expected, items
874  end
875
876  def test_find_methods_method
877    util_store
878
879    items = []
880
881    @driver.find_methods '.blah' do |store, klass, ancestor, types, method|
882      items << [store, klass, ancestor, types, method]
883    end
884
885    expected = [
886      [@store1, 'Ambiguous', 'Ambiguous', :both, 'blah'],
887      [@store1, 'Ext',       'Ext',       :both, 'blah'],
888      [@store1, 'Foo',       'Foo',       :both, 'blah'],
889      [@store1, 'Foo::Bar',  'Foo::Bar',  :both, 'blah'],
890      [@store1, 'Foo::Baz',  'Foo::Baz',  :both, 'blah'],
891      [@store1, 'Inc',       'Inc',       :both, 'blah'],
892    ]
893
894    assert_equal expected, items
895  end
896
897  def test_filter_methods
898    util_multi_store
899
900    name = 'Bar#override'
901
902    found = @driver.load_methods_matching name
903
904    sorted = @driver.filter_methods found, name
905
906    expected = [[@store2, [@override]]]
907
908    assert_equal expected, sorted
909  end
910
911  def test_filter_methods_not_found
912    util_multi_store
913
914    name = 'Bar#inherit'
915
916    found = @driver.load_methods_matching name
917
918    sorted = @driver.filter_methods found, name
919
920    assert_equal found, sorted
921  end
922
923  def test_find_store
924    @driver.stores << RDoc::Store.new(nil,              :system)
925    @driver.stores << RDoc::Store.new('doc/gem-1.0/ri', :gem)
926
927    assert_equal 'ruby',    @driver.find_store('ruby')
928    assert_equal 'gem-1.0', @driver.find_store('gem-1.0')
929    assert_equal 'gem-1.0', @driver.find_store('gem')
930
931    e = assert_raises RDoc::RI::Driver::NotFoundError do
932      @driver.find_store 'nonexistent'
933    end
934
935    assert_equal 'nonexistent', e.name
936  end
937
938  def test_formatter
939    tty = Object.new
940    def tty.tty?() true; end
941
942    driver = RDoc::RI::Driver.new
943
944    assert_instance_of @RM::ToAnsi, driver.formatter(tty)
945
946    assert_instance_of @RM::ToBs, driver.formatter(StringIO.new)
947
948    driver.instance_variable_set :@paging, true
949
950    assert_instance_of @RM::ToBs, driver.formatter(StringIO.new)
951  end
952
953  def test_in_path_eh
954    path = ENV['PATH']
955
956    test_path = File.expand_path '..', __FILE__
957
958    temp_dir do |dir|
959      nonexistent = File.join dir, 'nonexistent'
960      refute @driver.in_path?(nonexistent)
961
962      ENV['PATH'] = test_path
963
964      assert @driver.in_path?(File.basename(__FILE__))
965    end
966  ensure
967    ENV['PATH'] = path
968  end
969
970  def test_method_type
971    assert_equal :both,     @driver.method_type(nil)
972    assert_equal :both,     @driver.method_type('.')
973    assert_equal :instance, @driver.method_type('#')
974    assert_equal :class,    @driver.method_type('::')
975  end
976
977  def test_name_regexp
978    assert_equal %r%^RDoc::AnyMethod#new$%,
979                 @driver.name_regexp('RDoc::AnyMethod#new')
980
981    assert_equal %r%^RDoc::AnyMethod::new$%,
982                 @driver.name_regexp('RDoc::AnyMethod::new')
983
984    assert_equal %r%^RDoc::AnyMethod(#|::)new$%,
985                 @driver.name_regexp('RDoc::AnyMethod.new')
986
987    assert_equal %r%^Hash(#|::)\[\]$%,
988                 @driver.name_regexp('Hash.[]')
989
990    assert_equal %r%^Hash::\[\]$%,
991                 @driver.name_regexp('Hash::[]')
992  end
993
994  def test_list_known_classes
995    util_store
996
997    out, = capture_io do
998      @driver.list_known_classes
999    end
1000
1001    assert_equal "Ambiguous\nExt\nFoo\nFoo::Bar\nFoo::Baz\nInc\n", out
1002  end
1003
1004  def test_list_known_classes_name
1005    util_store
1006
1007    out, = capture_io do
1008      @driver.list_known_classes %w[F I]
1009    end
1010
1011    assert_equal "Foo\nFoo::Bar\nFoo::Baz\nInc\n", out
1012  end
1013
1014  def test_list_methods_matching
1015    util_store
1016
1017    assert_equal %w[
1018        Foo::Bar#attr
1019        Foo::Bar#blah
1020        Foo::Bar#bother
1021        Foo::Bar::new
1022      ],
1023      @driver.list_methods_matching('Foo::Bar.').sort
1024  end
1025
1026  def test_list_methods_matching_inherit
1027    util_multi_store
1028
1029    assert_equal %w[
1030        Bar#baz
1031        Bar#inherit
1032        Bar#override
1033      ],
1034      @driver.list_methods_matching('Bar.').sort
1035  end
1036
1037  def test_list_methods_matching_regexp
1038    util_store
1039
1040    index = RDoc::AnyMethod.new nil, '[]'
1041    index.record_location @top_level
1042    @cFoo.add_method index
1043    @store1.save_method @cFoo, index
1044
1045    c_index = RDoc::AnyMethod.new nil, '[]'
1046    c_index.singleton = true
1047    c_index.record_location @top_level
1048    @cFoo.add_method c_index
1049    @store1.save_method @cFoo, c_index
1050
1051    @store1.save_cache
1052
1053    assert_equal %w[Foo#[]], @driver.list_methods_matching('Foo#[]')
1054    assert_equal %w[Foo::[]], @driver.list_methods_matching('Foo::[]')
1055  end
1056
1057  def test_load_method
1058    util_store
1059
1060    method = @driver.load_method(@store1, :instance_methods, 'Foo', '#',
1061                                 'inherit')
1062
1063    assert_equal @inherit, method
1064  end
1065
1066  def test_load_method_inherited
1067    util_multi_store
1068
1069    method = @driver.load_method(@store2, :instance_methods, 'Bar', '#',
1070                                 'inherit')
1071
1072    assert_equal nil, method
1073  end
1074
1075  def test_load_methods_matching
1076    util_store
1077
1078    expected = [[@store1, [@inherit]]]
1079
1080    assert_equal expected, @driver.load_methods_matching('Foo#inherit')
1081
1082    expected = [[@store1, [@blah]]]
1083
1084    assert_equal expected, @driver.load_methods_matching('.blah')
1085
1086    assert_empty @driver.load_methods_matching('.b')
1087  end
1088
1089  def test_load_methods_matching_inherited
1090    util_multi_store
1091
1092    expected = [[@store1, [@inherit]]]
1093
1094    assert_equal expected, @driver.load_methods_matching('Bar#inherit')
1095  end
1096
1097  def _test_page # this test doesn't do anything anymore :(
1098    @driver.use_stdout = false
1099
1100    with_dummy_pager do
1101      @driver.page do |io|
1102        skip "couldn't find a standard pager" if io == $stdout
1103
1104        assert @driver.paging?
1105      end
1106    end
1107
1108    refute @driver.paging?
1109  end
1110
1111  # this test is too fragile. Perhaps using Process.spawn will make this
1112  # reliable
1113  def _test_page_in_presence_of_child_status
1114    skip 'this test hangs on travis-ci.org' if ENV['CI']
1115    @driver.use_stdout = false
1116
1117    with_dummy_pager do
1118      @driver.page do |io|
1119        refute_equal $stdout, io
1120        assert @driver.paging?
1121      end
1122    end
1123  end
1124
1125  def test_page_stdout
1126    @driver.use_stdout = true
1127
1128    @driver.page do |io|
1129      assert_equal $stdout, io
1130    end
1131
1132    refute @driver.paging?
1133  end
1134
1135  def test_parse_name_method
1136    klass, type, meth = @driver.parse_name 'foo'
1137
1138    assert_equal '',    klass, 'foo class'
1139    assert_equal '.',   type,  'foo type'
1140    assert_equal 'foo', meth,  'foo method'
1141
1142    klass, type, meth = @driver.parse_name '#foo'
1143
1144    assert_equal '',    klass, '#foo class'
1145    assert_equal '#',   type,  '#foo type'
1146    assert_equal 'foo', meth,  '#foo method'
1147
1148    klass, type, meth = @driver.parse_name '::foo'
1149
1150    assert_equal '',    klass, '::foo class'
1151    assert_equal '::',  type,  '::foo type'
1152    assert_equal 'foo', meth,  '::foo method'
1153  end
1154
1155  def test_parse_name_page
1156    klass, type, meth = @driver.parse_name 'ruby:README'
1157
1158    assert_equal 'ruby',   klass, 'ruby project'
1159    assert_equal ':',      type,  'ruby type'
1160    assert_equal 'README', meth,  'ruby page'
1161
1162    klass, type, meth = @driver.parse_name 'ruby:'
1163
1164    assert_equal 'ruby',   klass, 'ruby project'
1165    assert_equal ':',      type,  'ruby type'
1166    assert_equal nil,      meth,  'ruby page'
1167  end
1168
1169  def test_parse_name_page_extenson
1170    klass, type, meth = @driver.parse_name 'ruby:README.EXT'
1171
1172    assert_equal 'ruby',      klass, 'ruby project'
1173    assert_equal ':',         type,  'ruby type'
1174    assert_equal 'README.EXT', meth,  'ruby page'
1175  end
1176
1177  def test_parse_name_single_class
1178    klass, type, meth = @driver.parse_name 'Foo'
1179
1180    assert_equal 'Foo', klass, 'Foo class'
1181    assert_equal nil,   type,  'Foo type'
1182    assert_equal nil,   meth,  'Foo method'
1183
1184    klass, type, meth = @driver.parse_name 'Foo#'
1185
1186    assert_equal 'Foo', klass, 'Foo# class'
1187    assert_equal '#',   type,  'Foo# type'
1188    assert_equal nil,   meth,  'Foo# method'
1189
1190    klass, type, meth = @driver.parse_name 'Foo::'
1191
1192    assert_equal 'Foo', klass, 'Foo:: class'
1193    assert_equal '::',  type,  'Foo:: type'
1194    assert_equal nil,   meth,  'Foo:: method'
1195
1196    klass, type, meth = @driver.parse_name 'Foo.'
1197
1198    assert_equal 'Foo', klass, 'Foo. class'
1199    assert_equal '.',   type,  'Foo. type'
1200    assert_equal nil,   meth,  'Foo. method'
1201
1202    klass, type, meth = @driver.parse_name 'Foo#Bar'
1203
1204    assert_equal 'Foo', klass, 'Foo#Bar class'
1205    assert_equal '#',   type,  'Foo#Bar type'
1206    assert_equal 'Bar', meth,  'Foo#Bar method'
1207
1208    klass, type, meth = @driver.parse_name 'Foo.Bar'
1209
1210    assert_equal 'Foo', klass, 'Foo.Bar class'
1211    assert_equal '.',   type,  'Foo.Bar type'
1212    assert_equal 'Bar', meth,  'Foo.Bar method'
1213
1214    klass, type, meth = @driver.parse_name 'Foo::bar'
1215
1216    assert_equal 'Foo', klass, 'Foo::bar class'
1217    assert_equal '::',  type,  'Foo::bar type'
1218    assert_equal 'bar', meth,  'Foo::bar method'
1219  end
1220
1221  def test_parse_name_namespace
1222    klass, type, meth = @driver.parse_name 'Foo::Bar'
1223
1224    assert_equal 'Foo::Bar', klass, 'Foo::Bar class'
1225    assert_equal nil,        type,  'Foo::Bar type'
1226    assert_equal nil,        meth,  'Foo::Bar method'
1227
1228    klass, type, meth = @driver.parse_name 'Foo::Bar#'
1229
1230    assert_equal 'Foo::Bar', klass, 'Foo::Bar# class'
1231    assert_equal '#',        type,  'Foo::Bar# type'
1232    assert_equal nil,        meth,  'Foo::Bar# method'
1233
1234    klass, type, meth = @driver.parse_name 'Foo::Bar#baz'
1235
1236    assert_equal 'Foo::Bar', klass, 'Foo::Bar#baz class'
1237    assert_equal '#',        type,  'Foo::Bar#baz type'
1238    assert_equal 'baz',      meth,  'Foo::Bar#baz method'
1239  end
1240
1241  def test_parse_name_special
1242    specials = %w[
1243      %
1244      &
1245      *
1246      +
1247      +@
1248      -
1249      -@
1250      /
1251      <
1252      <<
1253      <=
1254      <=>
1255      ==
1256      ===
1257      =>
1258      =~
1259      >
1260      >>
1261      []
1262      []=
1263      ^
1264      `
1265      |
1266      ~
1267      ~@
1268    ]
1269
1270    specials.each do |special|
1271      parsed = @driver.parse_name special
1272
1273      assert_equal ['', '.', special], parsed
1274    end
1275  end
1276
1277  def _test_setup_pager # this test doesn't do anything anymore :(
1278    @driver.use_stdout = false
1279
1280    pager = with_dummy_pager do @driver.setup_pager end
1281
1282    skip "couldn't find a standard pager" unless pager
1283
1284    assert @driver.paging?
1285  ensure
1286    pager.close if pager
1287  end
1288
1289  def util_ancestors_store
1290    store1 = RDoc::RI::Store.new @home_ri
1291    store1.cache[:ancestors] = {
1292      'Foo'      => %w[Object],
1293      'Foo::Bar' => %w[Foo],
1294    }
1295    store1.cache[:class_methods] = {
1296      'Foo'      => %w[c_method new],
1297      'Foo::Bar' => %w[new],
1298    }
1299    store1.cache[:instance_methods] = {
1300      'Foo' => %w[i_method],
1301    }
1302    store1.cache[:modules] = %w[
1303      Foo
1304      Foo::Bar
1305    ]
1306
1307    store2 = RDoc::RI::Store.new @home_ri
1308    store2.cache[:ancestors] = {
1309      'Foo'    => %w[Mixin Object],
1310      'Mixin'  => %w[],
1311      'Object' => %w[X Object],
1312      'X'      => %w[Object],
1313    }
1314    store2.cache[:class_methods] = {
1315      'Foo'    => %w[c_method new],
1316      'Mixin'  => %w[],
1317      'X'      => %w[],
1318      'Object' => %w[],
1319    }
1320    store2.cache[:instance_methods] = {
1321      'Foo'   => %w[i_method],
1322      'Mixin' => %w[],
1323    }
1324    store2.cache[:modules] = %w[
1325      Foo
1326      Mixin
1327      Object
1328      X
1329    ]
1330
1331    @driver.stores = store1, store2
1332  end
1333
1334  def util_multi_store
1335    util_store
1336
1337    @home_ri2 = "#{@home_ri}2"
1338    @store2 = RDoc::RI::Store.new @home_ri2
1339
1340    @top_level = @store2.add_file 'file.rb'
1341
1342    # as if seen in a namespace like class Ambiguous::Other
1343    @mAmbiguous = @top_level.add_module RDoc::NormalModule, 'Ambiguous'
1344
1345    @cFoo = @top_level.add_class RDoc::NormalClass, 'Foo'
1346
1347    @cBar = @top_level.add_class RDoc::NormalClass, 'Bar', 'Foo'
1348    @cFoo_Baz = @cFoo.add_class RDoc::NormalClass, 'Baz'
1349
1350    @baz = @cBar.add_method RDoc::AnyMethod.new(nil, 'baz')
1351    @baz.record_location @top_level
1352
1353    @override = @cBar.add_method RDoc::AnyMethod.new(nil, 'override')
1354    @override.comment = 'must be displayed'
1355    @override.record_location @top_level
1356
1357    @store2.save
1358
1359    @driver.stores = [@store1, @store2]
1360  end
1361
1362  def util_store
1363    @store1 = RDoc::RI::Store.new @home_ri, :home
1364
1365    @top_level = @store1.add_file 'file.rb'
1366
1367    @readme = @store1.add_file 'README.rdoc'
1368    @readme.parser = RDoc::Parser::Simple
1369    @readme.comment =
1370      doc(
1371        head(1, 'README'),
1372        para('This is a README'))
1373
1374    @cFoo = @top_level.add_class RDoc::NormalClass, 'Foo'
1375    @mExt = @top_level.add_module RDoc::NormalModule, 'Ext'
1376    @mInc = @top_level.add_module RDoc::NormalModule, 'Inc'
1377    @cAmbiguous = @top_level.add_class RDoc::NormalClass, 'Ambiguous'
1378
1379    doc = @RM::Document.new @RM::Paragraph.new('Extend thingy')
1380    @cFooExt = @cFoo.add_extend RDoc::Extend.new('Ext', doc)
1381    @cFooExt.record_location @top_level
1382    doc = @RM::Document.new @RM::Paragraph.new('Include thingy')
1383    @cFooInc = @cFoo.add_include RDoc::Include.new('Inc', doc)
1384    @cFooInc.record_location @top_level
1385
1386    @cFoo_Bar = @cFoo.add_class RDoc::NormalClass, 'Bar'
1387
1388    @blah = @cFoo_Bar.add_method RDoc::AnyMethod.new(nil, 'blah')
1389    @blah.call_seq = "blah(5) => 5\nblah(6) => 6\n"
1390    @blah.record_location @top_level
1391
1392    @bother = @cFoo_Bar.add_method RDoc::AnyMethod.new(nil, 'bother')
1393    @bother.block_params = "stuff"
1394    @bother.params = "(things)"
1395    @bother.record_location @top_level
1396
1397    @new = @cFoo_Bar.add_method RDoc::AnyMethod.new nil, 'new'
1398    @new.record_location @top_level
1399    @new.singleton = true
1400
1401    @attr = @cFoo_Bar.add_attribute RDoc::Attr.new nil, 'attr', 'RW', ''
1402    @attr.record_location @top_level
1403
1404    @cFoo_Baz = @cFoo.add_class RDoc::NormalClass, 'Baz'
1405    @cFoo_Baz.record_location @top_level
1406
1407    @inherit = @cFoo.add_method RDoc::AnyMethod.new(nil, 'inherit')
1408    @inherit.record_location @top_level
1409
1410    # overriden by Bar in multi_store
1411    @overriden = @cFoo.add_method RDoc::AnyMethod.new(nil, 'override')
1412    @overriden.comment = 'must not be displayed in Bar#override'
1413    @overriden.record_location @top_level
1414
1415    @store1.save
1416
1417    @driver.stores = [@store1]
1418  end
1419
1420end
1421
1422