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