summaryrefslogtreecommitdiff
path: root/trunk/test
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/test')
-rw-r--r--trunk/test/csv/line_endings.gzbin0 -> 59 bytes
-rw-r--r--trunk/test/csv/tc_csv_parsing.rb164
-rw-r--r--trunk/test/csv/tc_csv_writing.rb96
-rw-r--r--trunk/test/csv/tc_data_converters.rb260
-rw-r--r--trunk/test/csv/tc_features.rb177
-rw-r--r--trunk/test/csv/tc_headers.rb261
-rw-r--r--trunk/test/csv/tc_interface.rb235
-rw-r--r--trunk/test/csv/tc_row.rb289
-rw-r--r--trunk/test/csv/tc_serialization.rb155
-rw-r--r--trunk/test/csv/tc_table.rb392
-rw-r--r--trunk/test/csv/ts_all.rb19
-rw-r--r--trunk/test/dbm/test_dbm.rb562
-rw-r--r--trunk/test/digest/test_digest.rb120
-rw-r--r--trunk/test/digest/test_digest_hmac.rb3
-rw-r--r--trunk/test/drb/drbtest.rb352
-rw-r--r--trunk/test/drb/ignore_test_drb.rb24
-rw-r--r--trunk/test/drb/test_acl.rb195
-rw-r--r--trunk/test/drb/test_drb.rb301
-rw-r--r--trunk/test/drb/test_drbssl.rb62
-rw-r--r--trunk/test/drb/test_drbunix.rb46
-rw-r--r--trunk/test/drb/ut_array.rb15
-rw-r--r--trunk/test/drb/ut_array_drbssl.rb24
-rw-r--r--trunk/test/drb/ut_array_drbunix.rb15
-rw-r--r--trunk/test/drb/ut_drb.rb160
-rw-r--r--trunk/test/drb/ut_drb_drbssl.rb25
-rw-r--r--trunk/test/drb/ut_drb_drbunix.rb16
-rw-r--r--trunk/test/drb/ut_eval.rb31
-rw-r--r--trunk/test/drb/ut_large.rb38
-rw-r--r--trunk/test/drb/ut_port.rb14
-rw-r--r--trunk/test/drb/ut_safe1.rb15
-rw-r--r--trunk/test/drb/ut_timerholder.rb49
-rw-r--r--trunk/test/erb/hello.erb4
-rw-r--r--trunk/test/erb/test_erb.rb446
-rw-r--r--trunk/test/etc/test_etc.rb139
-rw-r--r--trunk/test/fileutils/fileasserts.rb100
-rw-r--r--trunk/test/fileutils/test_dryrun.rb25
-rw-r--r--trunk/test/fileutils/test_fileutils.rb1081
-rw-r--r--trunk/test/fileutils/test_nowrite.rb99
-rw-r--r--trunk/test/fileutils/test_verbose.rb25
-rw-r--r--trunk/test/gdbm/test_gdbm.rb715
-rw-r--r--trunk/test/iconv/test_basic.rb49
-rw-r--r--trunk/test/iconv/test_option.rb43
-rw-r--r--trunk/test/iconv/test_partial.rb41
-rw-r--r--trunk/test/iconv/utils.rb26
-rw-r--r--trunk/test/inlinetest.rb55
-rw-r--r--trunk/test/io/nonblock/test_flush.rb36
-rw-r--r--trunk/test/json/fixtures/fail1.json1
-rw-r--r--trunk/test/json/fixtures/fail10.json1
-rw-r--r--trunk/test/json/fixtures/fail11.json1
-rw-r--r--trunk/test/json/fixtures/fail12.json1
-rw-r--r--trunk/test/json/fixtures/fail13.json1
-rw-r--r--trunk/test/json/fixtures/fail14.json1
-rw-r--r--trunk/test/json/fixtures/fail18.json1
-rw-r--r--trunk/test/json/fixtures/fail19.json1
-rw-r--r--trunk/test/json/fixtures/fail2.json1
-rw-r--r--trunk/test/json/fixtures/fail20.json1
-rw-r--r--trunk/test/json/fixtures/fail21.json1
-rw-r--r--trunk/test/json/fixtures/fail22.json1
-rw-r--r--trunk/test/json/fixtures/fail23.json1
-rw-r--r--trunk/test/json/fixtures/fail24.json1
-rw-r--r--trunk/test/json/fixtures/fail25.json1
-rw-r--r--trunk/test/json/fixtures/fail27.json2
-rw-r--r--trunk/test/json/fixtures/fail28.json2
-rw-r--r--trunk/test/json/fixtures/fail3.json1
-rw-r--r--trunk/test/json/fixtures/fail4.json1
-rw-r--r--trunk/test/json/fixtures/fail5.json1
-rw-r--r--trunk/test/json/fixtures/fail6.json1
-rw-r--r--trunk/test/json/fixtures/fail7.json1
-rw-r--r--trunk/test/json/fixtures/fail8.json1
-rw-r--r--trunk/test/json/fixtures/fail9.json1
-rw-r--r--trunk/test/json/fixtures/pass1.json56
-rw-r--r--trunk/test/json/fixtures/pass15.json1
-rw-r--r--trunk/test/json/fixtures/pass16.json1
-rw-r--r--trunk/test/json/fixtures/pass17.json1
-rw-r--r--trunk/test/json/fixtures/pass2.json1
-rw-r--r--trunk/test/json/fixtures/pass26.json1
-rw-r--r--trunk/test/json/fixtures/pass3.json6
-rwxr-xr-xtrunk/test/json/runner.rb26
-rwxr-xr-xtrunk/test/json/test_json.rb255
-rwxr-xr-xtrunk/test/json/test_json_addition.rb143
-rwxr-xr-xtrunk/test/json/test_json_fixtures.rb29
-rw-r--r--trunk/test/json/test_json_generate.rb80
-rw-r--r--trunk/test/json/test_json_rails.rb113
-rwxr-xr-xtrunk/test/json/test_json_unicode.rb61
-rw-r--r--trunk/test/logger/test_logger.rb376
-rw-r--r--trunk/test/monitor/test_monitor.rb163
-rw-r--r--trunk/test/net/http/test_http.rb320
-rw-r--r--trunk/test/net/http/test_httpheader.rb317
-rw-r--r--trunk/test/net/http/test_https.rb97
-rw-r--r--trunk/test/net/http/test_https_proxy.rb37
-rw-r--r--trunk/test/net/http/utils.rb96
-rw-r--r--trunk/test/net/imap/cacert.pem62
-rw-r--r--trunk/test/net/imap/server.crt12
-rw-r--r--trunk/test/net/imap/server.key15
-rw-r--r--trunk/test/net/imap/test_imap.rb195
-rw-r--r--trunk/test/nkf/test_kconv.rb74
-rw-r--r--trunk/test/nkf/test_nkf.rb16
-rw-r--r--trunk/test/openssl/ssl_server.rb81
-rw-r--r--trunk/test/openssl/test_asn1.rb197
-rw-r--r--trunk/test/openssl/test_cipher.rb95
-rw-r--r--trunk/test/openssl/test_digest.rb88
-rw-r--r--trunk/test/openssl/test_ec.rb113
-rw-r--r--trunk/test/openssl/test_hmac.rb34
-rw-r--r--trunk/test/openssl/test_ns_spki.rb59
-rw-r--r--trunk/test/openssl/test_pair.rb149
-rw-r--r--trunk/test/openssl/test_pkcs7.rb154
-rw-r--r--trunk/test/openssl/test_pkey_rsa.rb49
-rw-r--r--trunk/test/openssl/test_ssl.rb557
-rw-r--r--trunk/test/openssl/test_x509cert.rb175
-rw-r--r--trunk/test/openssl/test_x509crl.rb218
-rw-r--r--trunk/test/openssl/test_x509ext.rb74
-rw-r--r--trunk/test/openssl/test_x509name.rb266
-rw-r--r--trunk/test/openssl/test_x509req.rb140
-rw-r--r--trunk/test/openssl/test_x509store.rb218
-rw-r--r--trunk/test/openssl/utils.rb135
-rw-r--r--trunk/test/optparse/test_getopts.rb31
-rw-r--r--trunk/test/optparse/test_noarg.rb57
-rw-r--r--trunk/test/optparse/test_optarg.rb44
-rw-r--r--trunk/test/optparse/test_optparse.rb46
-rw-r--r--trunk/test/optparse/test_placearg.rb45
-rw-r--r--trunk/test/optparse/test_reqarg.rb63
-rw-r--r--trunk/test/ostruct/test_ostruct.rb23
-rw-r--r--trunk/test/pathname/test_pathname.rb517
-rw-r--r--trunk/test/rdoc/test_rdoc_info_formatting.rb175
-rw-r--r--trunk/test/rdoc/test_rdoc_info_sections.rb136
-rw-r--r--trunk/test/rdoc/test_rdoc_markup.rb613
-rw-r--r--trunk/test/rdoc/test_rdoc_markup_attribute_manager.rb224
-rw-r--r--trunk/test/rdoc/test_rdoc_markup_to_html.rb30
-rw-r--r--trunk/test/rdoc/test_rdoc_markup_to_html_crossref.rb18
-rw-r--r--trunk/test/rdoc/test_rdoc_parser_c.rb258
-rw-r--r--trunk/test/rdoc/test_rdoc_parser_ruby.rb539
-rw-r--r--trunk/test/rdoc/test_rdoc_ri_attribute_formatter.rb42
-rw-r--r--trunk/test/rdoc/test_rdoc_ri_default_display.rb296
-rw-r--r--trunk/test/rdoc/test_rdoc_ri_driver.rb92
-rw-r--r--trunk/test/rdoc/test_rdoc_ri_formatter.rb318
-rw-r--r--trunk/test/rdoc/test_rdoc_ri_overstrike_formatter.rb69
-rw-r--r--trunk/test/readline/test_readline.rb233
-rw-r--r--trunk/test/readline/test_readline_history.rb313
-rw-r--r--trunk/test/rinda/test_rinda.rb544
-rw-r--r--trunk/test/rinda/test_tuplebag.rb172
-rw-r--r--trunk/test/ripper/dummyparser.rb571
-rw-r--r--trunk/test/ripper/test_files.rb25
-rw-r--r--trunk/test/ripper/test_parser_events.rb498
-rw-r--r--trunk/test/ripper/test_scanner_events.rb807
-rw-r--r--trunk/test/rss/dot.pngbin0 -> 111 bytes
-rw-r--r--trunk/test/rss/rss-assertions.rb2086
-rw-r--r--trunk/test/rss/rss-testcase.rb478
-rw-r--r--trunk/test/rss/test_1.0.rb296
-rw-r--r--trunk/test/rss/test_2.0.rb410
-rw-r--r--trunk/test/rss/test_accessor.rb103
-rw-r--r--trunk/test/rss/test_atom.rb683
-rw-r--r--trunk/test/rss/test_content.rb104
-rw-r--r--trunk/test/rss/test_dublincore.rb279
-rw-r--r--trunk/test/rss/test_image.rb214
-rw-r--r--trunk/test/rss/test_inherit.rb40
-rw-r--r--trunk/test/rss/test_itunes.rb347
-rw-r--r--trunk/test/rss/test_maker_0.9.rb439
-rw-r--r--trunk/test/rss/test_maker_1.0.rb485
-rw-r--r--trunk/test/rss/test_maker_2.0.rb706
-rw-r--r--trunk/test/rss/test_maker_atom_entry.rb367
-rw-r--r--trunk/test/rss/test_maker_atom_feed.rb389
-rw-r--r--trunk/test/rss/test_maker_content.rb47
-rw-r--r--trunk/test/rss/test_maker_dc.rb149
-rw-r--r--trunk/test/rss/test_maker_image.rb62
-rw-r--r--trunk/test/rss/test_maker_itunes.rb471
-rw-r--r--trunk/test/rss/test_maker_slash.rb37
-rw-r--r--trunk/test/rss/test_maker_sy.rb44
-rw-r--r--trunk/test/rss/test_maker_taxo.rb81
-rw-r--r--trunk/test/rss/test_maker_trackback.rb41
-rw-r--r--trunk/test/rss/test_maker_xml-stylesheet.rb83
-rw-r--r--trunk/test/rss/test_parser.rb62
-rw-r--r--trunk/test/rss/test_parser_1.0.rb512
-rw-r--r--trunk/test/rss/test_parser_2.0.rb122
-rw-r--r--trunk/test/rss/test_parser_atom_entry.rb163
-rw-r--r--trunk/test/rss/test_parser_atom_feed.rb276
-rw-r--r--trunk/test/rss/test_setup_maker_0.9.rb246
-rw-r--r--trunk/test/rss/test_setup_maker_1.0.rb550
-rw-r--r--trunk/test/rss/test_setup_maker_2.0.rb308
-rw-r--r--trunk/test/rss/test_setup_maker_atom_entry.rb409
-rw-r--r--trunk/test/rss/test_setup_maker_atom_feed.rb445
-rw-r--r--trunk/test/rss/test_setup_maker_itunes.rb144
-rw-r--r--trunk/test/rss/test_setup_maker_slash.rb38
-rw-r--r--trunk/test/rss/test_slash.rb64
-rw-r--r--trunk/test/rss/test_syndication.rb125
-rw-r--r--trunk/test/rss/test_taxonomy.rb172
-rw-r--r--trunk/test/rss/test_to_s.rb670
-rw-r--r--trunk/test/rss/test_trackback.rb135
-rw-r--r--trunk/test/rss/test_version.rb9
-rw-r--r--trunk/test/rss/test_xml-stylesheet.rb108
-rw-r--r--trunk/test/ruby/allpairs.rb103
-rw-r--r--trunk/test/ruby/beginmainend.rb80
-rw-r--r--trunk/test/ruby/enc/test_big5.rb28
-rw-r--r--trunk/test/ruby/enc/test_cp949.rb28
-rw-r--r--trunk/test/ruby/enc/test_euc_jp.rb20
-rw-r--r--trunk/test/ruby/enc/test_euc_kr.rb28
-rw-r--r--trunk/test/ruby/enc/test_euc_tw.rb28
-rw-r--r--trunk/test/ruby/enc/test_gb18030.rb125
-rw-r--r--trunk/test/ruby/enc/test_gbk.rb28
-rw-r--r--trunk/test/ruby/enc/test_iso_8859.rb163
-rw-r--r--trunk/test/ruby/enc/test_koi8.rb22
-rw-r--r--trunk/test/ruby/enc/test_shift_jis.rb27
-rw-r--r--trunk/test/ruby/enc/test_utf16.rb358
-rw-r--r--trunk/test/ruby/enc/test_utf32.rb93
-rw-r--r--trunk/test/ruby/enc/test_windows_1251.rb16
-rw-r--r--trunk/test/ruby/endblockwarn_rb12
-rw-r--r--trunk/test/ruby/envutil.rb176
-rw-r--r--trunk/test/ruby/lbtest.rb48
-rw-r--r--trunk/test/ruby/marshaltestlib.rb499
-rw-r--r--trunk/test/ruby/sentence.rb668
-rw-r--r--trunk/test/ruby/test_alias.rb64
-rw-r--r--trunk/test/ruby/test_argf.rb701
-rw-r--r--trunk/test/ruby/test_array.rb1603
-rw-r--r--trunk/test/ruby/test_assignment.rb687
-rw-r--r--trunk/test/ruby/test_basicinstructions.rb628
-rw-r--r--trunk/test/ruby/test_beginendblock.rb101
-rw-r--r--trunk/test/ruby/test_bignum.rb390
-rw-r--r--trunk/test/ruby/test_call.rb19
-rw-r--r--trunk/test/ruby/test_case.rb49
-rw-r--r--trunk/test/ruby/test_class.rb147
-rw-r--r--trunk/test/ruby/test_clone.rb28
-rw-r--r--trunk/test/ruby/test_comparable.rb66
-rw-r--r--trunk/test/ruby/test_complex.rb1147
-rw-r--r--trunk/test/ruby/test_condition.rb16
-rw-r--r--trunk/test/ruby/test_const.rb48
-rw-r--r--trunk/test/ruby/test_continuation.rb81
-rw-r--r--trunk/test/ruby/test_defined.rb81
-rw-r--r--trunk/test/ruby/test_dir.rb170
-rw-r--r--trunk/test/ruby/test_econv.rb524
-rw-r--r--trunk/test/ruby/test_encoding.rb54
-rw-r--r--trunk/test/ruby/test_enum.rb259
-rw-r--r--trunk/test/ruby/test_enumerator.rb125
-rw-r--r--trunk/test/ruby/test_env.rb350
-rw-r--r--trunk/test/ruby/test_eval.rb394
-rw-r--r--trunk/test/ruby/test_exception.rb226
-rw-r--r--trunk/test/ruby/test_fiber.rb164
-rw-r--r--trunk/test/ruby/test_file.rb122
-rw-r--r--trunk/test/ruby/test_file_exhaustive.rb726
-rw-r--r--trunk/test/ruby/test_fixnum.rb241
-rw-r--r--trunk/test/ruby/test_float.rb433
-rw-r--r--trunk/test/ruby/test_fnmatch.rb104
-rw-r--r--trunk/test/ruby/test_gc.rb54
-rw-r--r--trunk/test/ruby/test_hash.rb851
-rw-r--r--trunk/test/ruby/test_ifunless.rb14
-rw-r--r--trunk/test/ruby/test_integer.rb193
-rw-r--r--trunk/test/ruby/test_integer_comb.rb620
-rw-r--r--trunk/test/ruby/test_io.rb1276
-rw-r--r--trunk/test/ruby/test_io_m17n.rb1334
-rw-r--r--trunk/test/ruby/test_iterator.rb497
-rw-r--r--trunk/test/ruby/test_lambda.rb68
-rw-r--r--trunk/test/ruby/test_literal.rb241
-rw-r--r--trunk/test/ruby/test_m17n.rb1290
-rw-r--r--trunk/test/ruby/test_m17n_comb.rb1623
-rw-r--r--trunk/test/ruby/test_marshal.rb194
-rw-r--r--trunk/test/ruby/test_math.rb239
-rw-r--r--trunk/test/ruby/test_method.rb224
-rw-r--r--trunk/test/ruby/test_mixed_unicode_escapes.rb25
-rw-r--r--trunk/test/ruby/test_module.rb720
-rw-r--r--trunk/test/ruby/test_numeric.rb217
-rw-r--r--trunk/test/ruby/test_object.rb401
-rw-r--r--trunk/test/ruby/test_objectspace.rb67
-rw-r--r--trunk/test/ruby/test_optimization.rb140
-rw-r--r--trunk/test/ruby/test_pack.rb448
-rw-r--r--trunk/test/ruby/test_parse.rb826
-rw-r--r--trunk/test/ruby/test_path.rb224
-rw-r--r--trunk/test/ruby/test_pipe.rb16
-rw-r--r--trunk/test/ruby/test_prec.rb21
-rw-r--r--trunk/test/ruby/test_primitive.rb397
-rw-r--r--trunk/test/ruby/test_proc.rb312
-rw-r--r--trunk/test/ruby/test_process.rb1007
-rw-r--r--trunk/test/ruby/test_rand.rb167
-rw-r--r--trunk/test/ruby/test_range.rb270
-rw-r--r--trunk/test/ruby/test_rational.rb1074
-rw-r--r--trunk/test/ruby/test_rational2.rb1360
-rw-r--r--trunk/test/ruby/test_readpartial.rb70
-rw-r--r--trunk/test/ruby/test_regexp.rb758
-rw-r--r--trunk/test/ruby/test_require.rb194
-rw-r--r--trunk/test/ruby/test_rubyoptions.rb283
-rw-r--r--trunk/test/ruby/test_settracefunc.rb184
-rw-r--r--trunk/test/ruby/test_signal.rb166
-rw-r--r--trunk/test/ruby/test_sleep.rb10
-rw-r--r--trunk/test/ruby/test_sprintf.rb273
-rw-r--r--trunk/test/ruby/test_sprintf_comb.rb548
-rw-r--r--trunk/test/ruby/test_string.rb1717
-rw-r--r--trunk/test/ruby/test_stringchar.rb166
-rw-r--r--trunk/test/ruby/test_struct.rb215
-rw-r--r--trunk/test/ruby/test_super.rb134
-rw-r--r--trunk/test/ruby/test_symbol.rb135
-rw-r--r--trunk/test/ruby/test_system.rb76
-rw-r--r--trunk/test/ruby/test_thread.rb507
-rw-r--r--trunk/test/ruby/test_time.rb394
-rw-r--r--trunk/test/ruby/test_trace.rb49
-rw-r--r--trunk/test/ruby/test_transcode.rb398
-rw-r--r--trunk/test/ruby/test_unicode_escape.rb267
-rw-r--r--trunk/test/ruby/test_variable.rb83
-rw-r--r--trunk/test/ruby/test_whileuntil.rb82
-rw-r--r--trunk/test/ruby/test_yield.rb355
-rw-r--r--trunk/test/ruby/ut_eof.rb128
-rw-r--r--trunk/test/rubygems/bogussources.rb8
-rw-r--r--trunk/test/rubygems/data/gem-private_key.pem27
-rw-r--r--trunk/test/rubygems/data/gem-public_cert.pem20
-rw-r--r--trunk/test/rubygems/fake_certlib/openssl.rb7
-rw-r--r--trunk/test/rubygems/functional.rb95
-rw-r--r--trunk/test/rubygems/gem_installer_test_case.rb86
-rw-r--r--trunk/test/rubygems/gem_package_tar_test_case.rb146
-rw-r--r--trunk/test/rubygems/gemutilities.rb441
-rw-r--r--trunk/test/rubygems/insure_session.rb51
-rw-r--r--trunk/test/rubygems/mockgemui.rb43
-rw-r--r--trunk/test/rubygems/private_key.pem27
-rw-r--r--trunk/test/rubygems/public_cert.pem20
-rw-r--r--trunk/test/rubygems/simple_gem.rb72
-rw-r--r--trunk/test/rubygems/test_config.rb21
-rw-r--r--trunk/test/rubygems/test_gem.rb449
-rw-r--r--trunk/test/rubygems/test_gem_builder.rb34
-rw-r--r--trunk/test/rubygems/test_gem_command.rb196
-rw-r--r--trunk/test/rubygems/test_gem_command_manager.rb213
-rw-r--r--trunk/test/rubygems/test_gem_commands_build_command.rb75
-rw-r--r--trunk/test/rubygems/test_gem_commands_cert_command.rb126
-rw-r--r--trunk/test/rubygems/test_gem_commands_check_command.rb25
-rw-r--r--trunk/test/rubygems/test_gem_commands_contents_command.rb92
-rw-r--r--trunk/test/rubygems/test_gem_commands_dependency_command.rb227
-rw-r--r--trunk/test/rubygems/test_gem_commands_environment_command.rb134
-rw-r--r--trunk/test/rubygems/test_gem_commands_fetch_command.rb55
-rw-r--r--trunk/test/rubygems/test_gem_commands_generate_index_command.rb32
-rw-r--r--trunk/test/rubygems/test_gem_commands_install_command.rb166
-rw-r--r--trunk/test/rubygems/test_gem_commands_mirror_command.rb61
-rw-r--r--trunk/test/rubygems/test_gem_commands_outdated_command.rb43
-rw-r--r--trunk/test/rubygems/test_gem_commands_pristine_command.rb109
-rw-r--r--trunk/test/rubygems/test_gem_commands_query_command.rb288
-rw-r--r--trunk/test/rubygems/test_gem_commands_server_command.rb27
-rw-r--r--trunk/test/rubygems/test_gem_commands_sources_command.rb275
-rw-r--r--trunk/test/rubygems/test_gem_commands_specification_command.rb97
-rw-r--r--trunk/test/rubygems/test_gem_commands_stale_command.rb39
-rw-r--r--trunk/test/rubygems/test_gem_commands_unpack_command.rb115
-rw-r--r--trunk/test/rubygems/test_gem_commands_update_command.rb165
-rw-r--r--trunk/test/rubygems/test_gem_config_file.rb276
-rw-r--r--trunk/test/rubygems/test_gem_dependency.rb140
-rw-r--r--trunk/test/rubygems/test_gem_dependency_installer.rb637
-rw-r--r--trunk/test/rubygems/test_gem_dependency_list.rb212
-rwxr-xr-xtrunk/test/rubygems/test_gem_digest.rb44
-rw-r--r--trunk/test/rubygems/test_gem_doc_manager.rb32
-rw-r--r--trunk/test/rubygems/test_gem_ext_configure_builder.rb86
-rw-r--r--trunk/test/rubygems/test_gem_ext_ext_conf_builder.rb122
-rw-r--r--trunk/test/rubygems/test_gem_ext_rake_builder.rb76
-rw-r--r--trunk/test/rubygems/test_gem_format.rb69
-rw-r--r--trunk/test/rubygems/test_gem_gem_path_searcher.rb60
-rw-r--r--trunk/test/rubygems/test_gem_gem_runner.rb35
-rw-r--r--trunk/test/rubygems/test_gem_indexer.rb263
-rw-r--r--trunk/test/rubygems/test_gem_install_update_options.rb61
-rw-r--r--trunk/test/rubygems/test_gem_installer.rb868
-rw-r--r--trunk/test/rubygems/test_gem_local_remote_options.rb85
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_header.rb137
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_input.rb119
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_output.rb104
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_reader.rb53
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_reader_entry.rb116
-rw-r--r--trunk/test/rubygems/test_gem_package_tar_writer.rb151
-rw-r--r--trunk/test/rubygems/test_gem_platform.rb259
-rw-r--r--trunk/test/rubygems/test_gem_remote_fetcher.rb692
-rw-r--r--trunk/test/rubygems/test_gem_requirement.rb223
-rw-r--r--trunk/test/rubygems/test_gem_server.rb301
-rw-r--r--trunk/test/rubygems/test_gem_source_index.rb834
-rw-r--r--trunk/test/rubygems/test_gem_source_info_cache.rb448
-rw-r--r--trunk/test/rubygems/test_gem_source_info_cache_entry.rb79
-rw-r--r--trunk/test/rubygems/test_gem_spec_fetcher.rb303
-rw-r--r--trunk/test/rubygems/test_gem_specification.rb954
-rw-r--r--trunk/test/rubygems/test_gem_stream_ui.rb117
-rw-r--r--trunk/test/rubygems/test_gem_uninstaller.rb66
-rw-r--r--trunk/test/rubygems/test_gem_validator.rb70
-rw-r--r--trunk/test/rubygems/test_gem_version.rb215
-rw-r--r--trunk/test/rubygems/test_gem_version_option.rb77
-rw-r--r--trunk/test/rubygems/test_kernel.rb65
-rw-r--r--trunk/test/runner.rb9
-rw-r--r--trunk/test/scanf/data.txt6
-rw-r--r--trunk/test/scanf/test_scanf.rb313
-rw-r--r--trunk/test/scanf/test_scanfblocks.rb81
-rw-r--r--trunk/test/scanf/test_scanfio.rb19
-rw-r--r--trunk/test/sdbm/test_sdbm.rb563
-rw-r--r--trunk/test/socket/test_nonblock.rb179
-rw-r--r--trunk/test/socket/test_socket.rb100
-rw-r--r--trunk/test/socket/test_tcp.rb24
-rw-r--r--trunk/test/socket/test_udp.rb32
-rw-r--r--trunk/test/socket/test_unix.rb149
-rw-r--r--trunk/test/stringio/test_stringio.rb382
-rw-r--r--trunk/test/strscan/test_stringscanner.rb674
-rw-r--r--trunk/test/test_delegate.rb20
-rw-r--r--trunk/test/test_ipaddr.rb4
-rw-r--r--trunk/test/test_pp.rb4
-rw-r--r--trunk/test/test_prettyprint.rb4
-rw-r--r--trunk/test/test_pstore.rb74
-rw-r--r--trunk/test/test_set.rb4
-rw-r--r--trunk/test/test_shellwords.rb39
-rw-r--r--trunk/test/test_singleton.rb15
-rw-r--r--trunk/test/test_tempfile.rb14
-rw-r--r--trunk/test/test_time.rb4
-rw-r--r--trunk/test/test_timeout.rb13
-rw-r--r--trunk/test/test_tsort.rb4
-rw-r--r--trunk/test/testunit/collector/test_dir.rb411
-rw-r--r--trunk/test/testunit/collector/test_objectspace.rb98
-rw-r--r--trunk/test/testunit/test_assertions.rb543
-rw-r--r--trunk/test/testunit/test_error.rb26
-rw-r--r--trunk/test/testunit/test_failure.rb33
-rw-r--r--trunk/test/testunit/test_testcase.rb275
-rw-r--r--trunk/test/testunit/test_testresult.rb104
-rw-r--r--trunk/test/testunit/test_testsuite.rb129
-rw-r--r--trunk/test/testunit/util/test_backtracefilter.rb41
-rw-r--r--trunk/test/testunit/util/test_observable.rb102
-rw-r--r--trunk/test/testunit/util/test_procwrapper.rb36
-rw-r--r--trunk/test/uri/test_common.rb55
-rw-r--r--trunk/test/uri/test_ftp.rb62
-rw-r--r--trunk/test/uri/test_generic.rb739
-rw-r--r--trunk/test/uri/test_http.rb63
-rw-r--r--trunk/test/uri/test_ldap.rb100
-rw-r--r--trunk/test/uri/test_mailto.rb122
-rw-r--r--trunk/test/webrick/.htaccess1
-rw-r--r--trunk/test/webrick/test_cgi.rb101
-rw-r--r--trunk/test/webrick/test_cookie.rb104
-rw-r--r--trunk/test/webrick/test_filehandler.rb204
-rw-r--r--trunk/test/webrick/test_httpauth.rb82
-rw-r--r--trunk/test/webrick/test_httpproxy.rb281
-rw-r--r--trunk/test/webrick/test_httprequest.rb349
-rw-r--r--trunk/test/webrick/test_httpserver.rb260
-rw-r--r--trunk/test/webrick/test_httputils.rb96
-rw-r--r--trunk/test/webrick/test_httpversion.rb40
-rw-r--r--trunk/test/webrick/test_server.rb64
-rw-r--r--trunk/test/webrick/test_utils.rb64
-rw-r--r--trunk/test/webrick/utils.rb56
-rw-r--r--trunk/test/webrick/webrick.cgi36
-rw-r--r--trunk/test/webrick/webrick_long_filename.cgi36
-rw-r--r--trunk/test/win32ole/err_in_callback.rb11
-rw-r--r--trunk/test/win32ole/test_err_in_callback.rb82
-rw-r--r--trunk/test/win32ole/test_folderitem2_invokeverb.rb89
-rw-r--r--trunk/test/win32ole/test_nil2vtempty.rb36
-rw-r--r--trunk/test/win32ole/test_ole_methods.rb36
-rw-r--r--trunk/test/win32ole/test_propertyputref.rb30
-rw-r--r--trunk/test/win32ole/test_win32ole.rb445
-rw-r--r--trunk/test/win32ole/test_win32ole_event.rb333
-rw-r--r--trunk/test/win32ole/test_win32ole_method.rb138
-rw-r--r--trunk/test/win32ole/test_win32ole_param.rb91
-rw-r--r--trunk/test/win32ole/test_win32ole_type.rb249
-rw-r--r--trunk/test/win32ole/test_win32ole_typelib.rb110
-rw-r--r--trunk/test/win32ole/test_win32ole_variable.rb61
-rw-r--r--trunk/test/win32ole/test_win32ole_variant.rb638
-rw-r--r--trunk/test/win32ole/test_win32ole_variant_m.rb35
-rw-r--r--trunk/test/win32ole/test_win32ole_variant_with_ie.rb53
-rw-r--r--trunk/test/win32ole/test_word.rb72
-rw-r--r--trunk/test/xmlrpc/data/bug_bool.expected3
-rw-r--r--trunk/test/xmlrpc/data/bug_bool.xml8
-rw-r--r--trunk/test/xmlrpc/data/bug_cdata.expected3
-rw-r--r--trunk/test/xmlrpc/data/bug_cdata.xml8
-rw-r--r--trunk/test/xmlrpc/data/bug_covert.expected10
-rw-r--r--trunk/test/xmlrpc/data/bug_covert.xml6
-rw-r--r--trunk/test/xmlrpc/data/datetime_iso8601.xml8
-rw-r--r--trunk/test/xmlrpc/data/fault.xml16
-rw-r--r--trunk/test/xmlrpc/data/value.expected7
-rw-r--r--trunk/test/xmlrpc/data/value.xml22
-rw-r--r--trunk/test/xmlrpc/data/xml1.expected243
-rw-r--r--trunk/test/xmlrpc/data/xml1.xml1
-rw-r--r--trunk/test/xmlrpc/test_cookie.rb96
-rw-r--r--trunk/test/xmlrpc/test_datetime.rb159
-rw-r--r--trunk/test/xmlrpc/test_features.rb48
-rw-r--r--trunk/test/xmlrpc/test_marshal.rb93
-rw-r--r--trunk/test/xmlrpc/test_parser.rb85
-rw-r--r--trunk/test/xmlrpc/test_webrick_server.rb98
-rw-r--r--trunk/test/xmlrpc/webrick_testing.rb38
-rw-r--r--trunk/test/yaml/test_yaml.rb1298
-rw-r--r--trunk/test/yaml/test_yamlstore.rb74
-rw-r--r--trunk/test/zlib/test_zlib.rb638
467 files changed, 93549 insertions, 0 deletions
diff --git a/trunk/test/csv/line_endings.gz b/trunk/test/csv/line_endings.gz
new file mode 100644
index 0000000000..39e1729ee4
--- /dev/null
+++ b/trunk/test/csv/line_endings.gz
Binary files differ
diff --git a/trunk/test/csv/tc_csv_parsing.rb b/trunk/test/csv/tc_csv_parsing.rb
new file mode 100644
index 0000000000..965af929f3
--- /dev/null
+++ b/trunk/test/csv/tc_csv_parsing.rb
@@ -0,0 +1,164 @@
+#!/usr/local/bin/ruby -w
+
+# tc_csv_parsing.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+#
+# Following tests are my interpretation of the
+# {CSV RCF}[http://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that
+# document in one place (intentionally) and that is to make the default row
+# separator <tt>$/</tt>.
+#
+class TestCSVParsing < Test::Unit::TestCase
+ def test_mastering_regex_example
+ ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
+ assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
+ "It's \"10 Grand\", baby", "10K" ],
+ CSV.parse_line(ex) )
+ end
+
+ # Old Ruby 1.8 CSV library tests.
+ def test_std_lib_csv
+ [ ["\t", ["\t"]],
+ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
+ ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
+ ["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
+ ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
+ ["\"\"", [""]],
+ ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
+ ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
+ ["foo,\"\r\",baz", ["foo", "\r", "baz"]],
+ ["foo,\"\",baz", ["foo", "", "baz"]],
+ ["\",\"", [","]],
+ ["foo", ["foo"]],
+ [",,", [nil, nil, nil]],
+ [",", [nil, nil]],
+ ["foo,\"\n\",baz", ["foo", "\n", "baz"]],
+ ["foo,,baz", ["foo", nil, "baz"]],
+ ["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
+ ["\",\",\",\"", [",", ","]],
+ ["foo,bar,", ["foo", "bar", nil]],
+ [",foo,bar", [nil, "foo", "bar"]],
+ ["foo,bar", ["foo", "bar"]],
+ [";", [";"]],
+ ["\t,\t", ["\t", "\t"]],
+ ["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
+ ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
+ ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
+ [";,;", [";", ";"]] ].each do |csv_test|
+ assert_equal(csv_test.last, CSV.parse_line(csv_test.first))
+ end
+
+ [ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
+ ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
+ ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
+ ["\"\"", [""]],
+ ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
+ ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
+ ["foo,\"\r\",baz", ["foo", "\r", "baz"]],
+ ["foo,\"\",baz", ["foo", "", "baz"]],
+ ["foo", ["foo"]],
+ [",,", [nil, nil, nil]],
+ [",", [nil, nil]],
+ ["foo,\"\n\",baz", ["foo", "\n", "baz"]],
+ ["foo,,baz", ["foo", nil, "baz"]],
+ ["foo,bar", ["foo", "bar"]],
+ ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
+ ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]] ].each do |csv_test|
+ assert_equal(csv_test.last, CSV.parse_line(csv_test.first))
+ end
+ end
+
+ # From: http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-core/6496
+ def test_aras_edge_cases
+ [ [%Q{a,b}, ["a", "b"]],
+ [%Q{a,"""b"""}, ["a", "\"b\""]],
+ [%Q{a,"""b"}, ["a", "\"b"]],
+ [%Q{a,"b"""}, ["a", "b\""]],
+ [%Q{a,"\nb"""}, ["a", "\nb\""]],
+ [%Q{a,"""\nb"}, ["a", "\"\nb"]],
+ [%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
+ [%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]],
+ [%Q{a,,,}, ["a", nil, nil, nil]],
+ [%Q{,}, [nil, nil]],
+ [%Q{"",""}, ["", ""]],
+ [%Q{""""}, ["\""]],
+ [%Q{"""",""}, ["\"",""]],
+ [%Q{,""}, [nil,""]],
+ [%Q{,"\r"}, [nil,"\r"]],
+ [%Q{"\r\n,"}, ["\r\n,"]],
+ [%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |edge_case|
+ assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
+ end
+ end
+
+ def test_james_edge_cases
+ # A read at eof? should return nil.
+ assert_equal(nil, CSV.parse_line(""))
+ #
+ # With Ruby 1.8 CSV it's impossible to tell an empty line from a line
+ # containing a single +nil+ field. The old CSV library returns
+ # <tt>[nil]</tt> in these cases, but <tt>Array.new</tt> makes more sense to
+ # me.
+ #
+ assert_equal(Array.new, CSV.parse_line("\n1,2,3\n"))
+ end
+
+ def test_malformed_csv
+ assert_raise(CSV::MalformedCSVError) do
+ CSV.parse_line("1,2\r,3", :row_sep => "\n")
+ end
+
+ bad_data = <<-END_DATA.gsub(/^ +/, "")
+ line,1,abc
+ line,2,"def\nghi"
+
+ line,4,some\rjunk
+ line,5,jkl
+ END_DATA
+ lines = bad_data.lines.to_a
+ assert_equal(6, lines.size)
+ assert_match(/\Aline,4/, lines.find { |l| l =~ /some\rjunk/ })
+
+ csv = CSV.new(bad_data)
+ begin
+ loop do
+ assert_not_nil(csv.shift)
+ assert_send([csv.lineno, :<, 4])
+ end
+ rescue CSV::MalformedCSVError
+ assert_equal( "Unquoted fields do not allow \\r or \\n (line 4).",
+ $!.message )
+ end
+
+ assert_raise(CSV::MalformedCSVError) { CSV.parse_line('1,2,"3...') }
+
+ bad_data = <<-END_DATA.gsub(/^ +/, "")
+ line,1,abc
+ line,2,"def\nghi"
+
+ line,4,8'10"
+ line,5,jkl
+ END_DATA
+ lines = bad_data.lines.to_a
+ assert_equal(6, lines.size)
+ assert_match(/\Aline,4/, lines.find { |l| l =~ /8'10"/ })
+
+ csv = CSV.new(bad_data)
+ begin
+ loop do
+ assert_not_nil(csv.shift)
+ assert_send([csv.lineno, :<, 4])
+ end
+ rescue CSV::MalformedCSVError
+ assert_equal("Unclosed quoted field on line 4.", $!.message)
+ end
+ end
+end
diff --git a/trunk/test/csv/tc_csv_writing.rb b/trunk/test/csv/tc_csv_writing.rb
new file mode 100644
index 0000000000..4677284306
--- /dev/null
+++ b/trunk/test/csv/tc_csv_writing.rb
@@ -0,0 +1,96 @@
+#!/usr/local/bin/ruby -w
+
+# tc_csv_writing.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestCSVWriting < Test::Unit::TestCase
+ def test_writing
+ [ ["\t", ["\t"]],
+ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
+ ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
+ ["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
+ ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
+ ["\"\"", [""]],
+ ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
+ ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
+ ["foo,\"\r\",baz", ["foo", "\r", "baz"]],
+ ["foo,\"\",baz", ["foo", "", "baz"]],
+ ["\",\"", [","]],
+ ["foo", ["foo"]],
+ [",,", [nil, nil, nil]],
+ [",", [nil, nil]],
+ ["foo,\"\n\",baz", ["foo", "\n", "baz"]],
+ ["foo,,baz", ["foo", nil, "baz"]],
+ ["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
+ ["\",\",\",\"", [",", ","]],
+ ["foo,bar,", ["foo", "bar", nil]],
+ [",foo,bar", [nil, "foo", "bar"]],
+ ["foo,bar", ["foo", "bar"]],
+ [";", [";"]],
+ ["\t,\t", ["\t", "\t"]],
+ ["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
+ ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
+ ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
+ [";,;", [";", ";"]],
+ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
+ ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
+ ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
+ ["\"\"", [""]],
+ ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
+ ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
+ ["foo,\"\r\",baz", ["foo", "\r", "baz"]],
+ ["foo,\"\",baz", ["foo", "", "baz"]],
+ ["foo", ["foo"]],
+ [",,", [nil, nil, nil]],
+ [",", [nil, nil]],
+ ["foo,\"\n\",baz", ["foo", "\n", "baz"]],
+ ["foo,,baz", ["foo", nil, "baz"]],
+ ["foo,bar", ["foo", "bar"]],
+ ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
+ ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
+ [%Q{a,b}, ["a", "b"]],
+ [%Q{a,"""b"""}, ["a", "\"b\""]],
+ [%Q{a,"""b"}, ["a", "\"b"]],
+ [%Q{a,"b"""}, ["a", "b\""]],
+ [%Q{a,"\nb"""}, ["a", "\nb\""]],
+ [%Q{a,"""\nb"}, ["a", "\"\nb"]],
+ [%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
+ [%Q{a,"""\nb\n""",}, ["a", "\"\nb\n\"", nil]],
+ [%Q{a,,,}, ["a", nil, nil, nil]],
+ [%Q{,}, [nil, nil]],
+ [%Q{"",""}, ["", ""]],
+ [%Q{""""}, ["\""]],
+ [%Q{"""",""}, ["\"",""]],
+ [%Q{,""}, [nil,""]],
+ [%Q{,"\r"}, [nil,"\r"]],
+ [%Q{"\r\n,"}, ["\r\n,"]],
+ [%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |test_case|
+ assert_equal(test_case.first + $/, CSV.generate_line(test_case.last))
+ end
+ end
+
+ def test_col_sep
+ assert_equal( "a;b;;c\n", CSV.generate_line( ["a", "b", nil, "c"],
+ :col_sep => ";" ) )
+ assert_equal( "a\tb\t\tc\n", CSV.generate_line( ["a", "b", nil, "c"],
+ :col_sep => "\t" ) )
+ end
+
+ def test_row_sep
+ assert_equal( "a,b,,c\r\n", CSV.generate_line( ["a", "b", nil, "c"],
+ :row_sep => "\r\n" ) )
+ end
+
+ def test_force_quotes
+ assert_equal( %Q{"1","b","","already ""quoted"""\n},
+ CSV.generate_line( [1, "b", nil, %Q{already "quoted"}],
+ :force_quotes => true ) )
+ end
+end
diff --git a/trunk/test/csv/tc_data_converters.rb b/trunk/test/csv/tc_data_converters.rb
new file mode 100644
index 0000000000..24c6b6b76f
--- /dev/null
+++ b/trunk/test/csv/tc_data_converters.rb
@@ -0,0 +1,260 @@
+#!/usr/local/bin/ruby -w
+
+# tc_data_converters.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestDataConverters < Test::Unit::TestCase
+ def setup
+ @data = "Numbers,:integer,1,:float,3.015"
+ @parser = CSV.new(@data)
+
+ @custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
+
+ @win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y")
+ end
+
+ def test_builtin_integer_converter
+ # does convert
+ [-5, 1, 10000000000].each do |n|
+ assert_equal(n, CSV::Converters[:integer][n.to_s])
+ end
+
+ # does not convert
+ (%w{junk 1.0} + [""]).each do |str|
+ assert_equal(str, CSV::Converters[:integer][str])
+ end
+ end
+
+ def test_builtin_float_converter
+ # does convert
+ [-5.1234, 0, 2.3e-11].each do |n|
+ assert_equal(n, CSV::Converters[:float][n.to_s])
+ end
+
+ # does not convert
+ (%w{junk 1..0 .015F} + [""]).each do |str|
+ assert_equal(str, CSV::Converters[:float][str])
+ end
+ end
+
+ def test_builtin_date_converter
+ # does convert
+ assert_instance_of(
+ Date,
+ CSV::Converters[:date][@win_safe_time_str.sub(/\d+:\d+:\d+ /, "")]
+ )
+
+ # does not convert
+ assert_instance_of(String, CSV::Converters[:date]["junk"])
+ end
+
+ def test_builtin_date_time_converter
+ # does convert
+ assert_instance_of( DateTime,
+ CSV::Converters[:date_time][@win_safe_time_str] )
+
+ # does not convert
+ assert_instance_of(String, CSV::Converters[:date_time]["junk"])
+ end
+
+ def test_convert_with_builtin
+ # setup parser...
+ assert(@parser.respond_to?(:convert))
+ assert_nothing_raised(Exception) { @parser.convert(:integer) }
+
+ # and use
+ assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], @parser.shift)
+
+ setup # reset
+
+ # setup parser...
+ assert_nothing_raised(Exception) { @parser.convert(:float) }
+
+ # and use
+ assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], @parser.shift)
+ end
+
+ def test_convert_order
+ # floats first, then integers...
+ assert_nothing_raised(Exception) do
+ @parser.convert(:float)
+ @parser.convert(:integer)
+ end
+
+ # gets us nothing but floats
+ assert_equal( [String, String, Float, String, Float],
+ @parser.shift.map { |field| field.class } )
+
+ setup # reset
+
+ # integers have precendance...
+ assert_nothing_raised(Exception) do
+ @parser.convert(:integer)
+ @parser.convert(:float)
+ end
+
+ # gives us proper number conversion
+ assert_equal( [String, String, Fixnum, String, Float],
+ @parser.shift.map { |field| field.class } )
+ end
+
+ def test_builtin_numeric_combo_converter
+ # setup parser...
+ assert_nothing_raised(Exception) { @parser.convert(:numeric) }
+
+ # and use
+ assert_equal( [String, String, Fixnum, String, Float],
+ @parser.shift.map { |field| field.class } )
+ end
+
+ def test_builtin_all_nested_combo_converter
+ # setup parser...
+ @data << ",#{@win_safe_time_str}" # add a DateTime field
+ @parser = CSV.new(@data) # reset parser
+ assert_nothing_raised(Exception) { @parser.convert(:all) }
+
+ # and use
+ assert_equal( [String, String, Fixnum, String, Float, DateTime],
+ @parser.shift.map { |field| field.class } )
+ end
+
+ def test_convert_with_custom_code
+ # define custom converter...
+ assert_nothing_raised(Exception) do
+ @parser.convert { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
+ end
+
+ # and use
+ assert_equal(["Numbers", :integer, "1", :float, "3.015"], @parser.shift)
+
+ setup # reset
+
+ # mix built-in and custom...
+ assert_nothing_raised(Exception) { @parser.convert(:numeric) }
+ assert_nothing_raised(Exception) { @parser.convert(&@custom) }
+
+ # and use
+ assert_equal(["Numbers", :integer, 1, :float, 3.015], @parser.shift)
+ end
+
+ def test_convert_with_custom_code_using_field_info
+ # define custom converter that uses field information...
+ assert_nothing_raised(Exception) do
+ @parser.convert do |field, info|
+ assert_equal(1, info.line)
+ info.index == 4 ? Float(field).floor : field
+ end
+ end
+
+ # and use
+ assert_equal(["Numbers", ":integer", "1", ":float", 3], @parser.shift)
+ end
+
+ def test_convert_with_custom_code_using_field_info_header
+ @parser = CSV.new(@data, :headers => %w{one two three four five})
+
+ # define custom converter that uses field header information...
+ assert_nothing_raised(Exception) do
+ @parser.convert do |field, info|
+ info.header == "three" ? Integer(field) * 100 : field
+ end
+ end
+
+ # and use
+ assert_equal( ["Numbers", ":integer", 100, ":float", "3.015"],
+ @parser.shift.fields )
+ end
+
+ def test_shortcut_interface
+ assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
+ CSV.parse_line(@data, :converters => :numeric) )
+
+ assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
+ CSV.parse_line(@data, :converters => [:integer, :float]) )
+
+ assert_equal( ["Numbers", :integer, 1, :float, 3.015],
+ CSV.parse_line(@data, :converters => [:numeric, @custom]) )
+ end
+
+ def test_unconverted_fields
+ [ [ @data,
+ ["Numbers", :integer, 1, :float, 3.015],
+ %w{Numbers :integer 1 :float 3.015} ],
+ ["\n", Array.new, Array.new] ].each do |test, fields, unconverted|
+ row = nil
+ assert_nothing_raised(Exception) do
+ row = CSV.parse_line( test,
+ :converters => [:numeric, @custom],
+ :unconverted_fields => true )
+ end
+ assert_not_nil(row)
+ assert_equal(fields, row)
+ assert_respond_to(row, :unconverted_fields)
+ assert_equal(unconverted, row.unconverted_fields)
+ end
+
+ data = <<-END_CSV.gsub(/^\s+/, "")
+ first,second,third
+ 1,2,3
+ END_CSV
+ row = nil
+ assert_nothing_raised(Exception) do
+ row = CSV.parse_line( data,
+ :converters => :numeric,
+ :unconverted_fields => true,
+ :headers => :first_row )
+ end
+ assert_not_nil(row)
+ assert_equal([["first", 1], ["second", 2], ["third", 3]], row.to_a)
+ assert_respond_to(row, :unconverted_fields)
+ assert_equal(%w{1 2 3}, row.unconverted_fields)
+
+ assert_nothing_raised(Exception) do
+ row = CSV.parse_line( data,
+ :converters => :numeric,
+ :unconverted_fields => true,
+ :headers => :first_row,
+ :return_headers => true )
+ end
+ assert_not_nil(row)
+ assert_equal( [%w{first first}, %w{second second}, %w{third third}],
+ row.to_a )
+ assert_respond_to(row, :unconverted_fields)
+ assert_equal(%w{first second third}, row.unconverted_fields)
+
+ assert_nothing_raised(Exception) do
+ row = CSV.parse_line( data,
+ :converters => :numeric,
+ :unconverted_fields => true,
+ :headers => :first_row,
+ :return_headers => true,
+ :header_converters => :symbol )
+ end
+ assert_not_nil(row)
+ assert_equal( [[:first, "first"], [:second, "second"], [:third, "third"]],
+ row.to_a )
+ assert_respond_to(row, :unconverted_fields)
+ assert_equal(%w{first second third}, row.unconverted_fields)
+
+ assert_nothing_raised(Exception) do
+ row = CSV.parse_line( data,
+ :converters => :numeric,
+ :unconverted_fields => true,
+ :headers => %w{my new headers},
+ :return_headers => true,
+ :header_converters => :symbol )
+ end
+ assert_not_nil(row)
+ assert_equal( [[:my, "my"], [:new, "new"], [:headers, "headers"]],
+ row.to_a )
+ assert_respond_to(row, :unconverted_fields)
+ assert_equal(Array.new, row.unconverted_fields)
+ end
+end
diff --git a/trunk/test/csv/tc_features.rb b/trunk/test/csv/tc_features.rb
new file mode 100644
index 0000000000..ae5a8a451b
--- /dev/null
+++ b/trunk/test/csv/tc_features.rb
@@ -0,0 +1,177 @@
+#!/usr/local/bin/ruby -w
+
+# tc_features.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+require "zlib"
+
+require "csv"
+
+class TestCSVFeatures < Test::Unit::TestCase
+ TEST_CASES = [ [%Q{a,b}, ["a", "b"]],
+ [%Q{a,"""b"""}, ["a", "\"b\""]],
+ [%Q{a,"""b"}, ["a", "\"b"]],
+ [%Q{a,"b"""}, ["a", "b\""]],
+ [%Q{a,"\nb"""}, ["a", "\nb\""]],
+ [%Q{a,"""\nb"}, ["a", "\"\nb"]],
+ [%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
+ [%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]],
+ [%Q{a,,,}, ["a", nil, nil, nil]],
+ [%Q{,}, [nil, nil]],
+ [%Q{"",""}, ["", ""]],
+ [%Q{""""}, ["\""]],
+ [%Q{"""",""}, ["\"",""]],
+ [%Q{,""}, [nil,""]],
+ [%Q{,"\r"}, [nil,"\r"]],
+ [%Q{"\r\n,"}, ["\r\n,"]],
+ [%Q{"\r\n,",}, ["\r\n,", nil]] ]
+
+ def setup
+ @sample_data = <<-END_DATA.gsub(/^ +/, "")
+ line,1,abc
+ line,2,"def\nghi"
+
+ line,4,jkl
+ END_DATA
+ @csv = CSV.new(@sample_data)
+ end
+
+ def test_col_sep
+ [";", "\t"].each do |sep|
+ TEST_CASES.each do |test_case|
+ assert_equal( test_case.last.map { |t| t.tr(",", sep) unless t.nil? },
+ CSV.parse_line( test_case.first.tr(",", sep),
+ :col_sep => sep ) )
+ end
+ end
+ assert_equal([",,,", nil], CSV.parse_line(",,,;", :col_sep => ";"))
+ end
+
+ def test_row_sep
+ assert_raise(CSV::MalformedCSVError) do
+ CSV.parse_line("1,2,3\n,4,5\r\n", :row_sep => "\r\n")
+ end
+ assert_equal( ["1", "2", "3\n", "4", "5"],
+ CSV.parse_line(%Q{1,2,"3\n",4,5\r\n}, :row_sep => "\r\n"))
+ end
+
+ def test_quote_char
+ TEST_CASES.each do |test_case|
+ assert_equal( test_case.last.map { |t| t.tr('"', "'") unless t.nil? },
+ CSV.parse_line( test_case.first.tr('"', "'"),
+ :quote_char => "'" ) )
+ end
+ end
+
+ def test_row_sep_auto_discovery
+ ["\r\n", "\n", "\r"].each do |line_end|
+ data = "1,2,3#{line_end}4,5#{line_end}"
+ discovered = CSV.new(data).instance_eval { @row_sep }
+ assert_equal(line_end, discovered)
+ end
+
+ assert_equal("\n", CSV.new("\n\r\n\r").instance_eval { @row_sep })
+
+ assert_equal($/, CSV.new("").instance_eval { @row_sep })
+
+ assert_equal($/, CSV.new(STDERR).instance_eval { @row_sep })
+ end
+
+ def test_lineno
+ assert_equal(5, @sample_data.lines.to_a.size)
+
+ 4.times do |line_count|
+ assert_equal(line_count, @csv.lineno)
+ assert_not_nil(@csv.shift)
+ assert_equal(line_count + 1, @csv.lineno)
+ end
+ assert_nil(@csv.shift)
+ end
+
+ def test_readline
+ test_lineno
+
+ @csv.rewind
+
+ test_lineno
+ end
+
+ def test_unknown_options
+ assert_raise(ArgumentError) { CSV.new(String.new, :unknown => :error) }
+ end
+
+ def test_skip_blanks
+ assert_equal(4, @csv.to_a.size)
+
+ @csv = CSV.new(@sample_data, :skip_blanks => true)
+
+ count = 0
+ @csv.each do |row|
+ count += 1
+ assert_equal("line", row.first)
+ end
+ assert_equal(3, count)
+ end
+
+ # reported by Kev Jackson
+ def test_failing_to_escape_col_sep_bug_fix
+ assert_nothing_raised(Exception) { CSV.new(String.new, :col_sep => "|") }
+ end
+
+ # reported by Chris Roos
+ def test_failing_to_reset_headers_in_rewind_bug_fix
+ csv = CSV.new("forename,surname", :headers => true, :return_headers => true)
+ csv.each { |row| assert row.header_row? }
+ csv.rewind
+ csv.each { |row| assert row.header_row? }
+ end
+
+ # reported by Dave Burt
+ def test_leading_empty_fields_with_multibyte_col_sep_bug_fix
+ data = <<-END_DATA.gsub(/^\s+/, "")
+ <=><=>A<=>B<=>C
+ 1<=>2<=>3
+ END_DATA
+ parsed = CSV.parse(data, :col_sep => "<=>")
+ assert_equal([[nil, nil, "A", "B", "C"], ["1", "2", "3"]], parsed)
+ end
+
+ def test_gzip_reader_bug_fix
+ zipped = nil
+ assert_nothing_raised(NoMethodError) do
+ zipped = CSV.new(
+ Zlib::GzipReader.open(
+ File.join(File.dirname(__FILE__), "line_endings.gz")
+ )
+ )
+ end
+ assert_equal("\r\n", zipped.instance_eval { @row_sep })
+ end
+
+ def test_gzip_writer_bug_fix
+ file = File.join(File.dirname(__FILE__), "temp.gz")
+ zipped = nil
+ assert_nothing_raised(NoMethodError) do
+ zipped = CSV.new(Zlib::GzipWriter.open(file))
+ end
+ zipped << %w[one two three]
+ zipped << [1, 2, 3]
+ zipped.close
+
+ assert( Zlib::GzipReader.open(file) { |f| f.read }.
+ include?($INPUT_RECORD_SEPARATOR),
+ "@row_sep did not default" )
+ File.unlink(file)
+ end
+
+ def test_version
+ assert_not_nil(CSV::VERSION)
+ assert_instance_of(String, CSV::VERSION)
+ assert(CSV::VERSION.frozen?)
+ assert_match(/\A\d\.\d\.\d\Z/, CSV::VERSION)
+ end
+end
diff --git a/trunk/test/csv/tc_headers.rb b/trunk/test/csv/tc_headers.rb
new file mode 100644
index 0000000000..74e2f54ad4
--- /dev/null
+++ b/trunk/test/csv/tc_headers.rb
@@ -0,0 +1,261 @@
+#!/usr/local/bin/ruby -w
+
+# tc_headers.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestCSVHeaders < Test::Unit::TestCase
+ def setup
+ @data = <<-END_CSV.gsub(/^\s+/, "")
+ first,second,third
+ A,B,C
+ 1,2,3
+ END_CSV
+ end
+
+ def test_first_row
+ [:first_row, true].each do |setting| # two names for the same setting
+ # activate headers
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => setting)
+ end
+
+ # first data row - skipping headers
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
+
+ # second data row
+ row = csv[1]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
+
+ # empty
+ assert_nil(csv[2])
+ end
+ end
+
+ def test_array_of_headers
+ # activate headers
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => [:my, :new, :headers])
+ end
+
+ # first data row - skipping headers
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal( [[:my, "first"], [:new, "second"], [:headers, "third"]],
+ row.to_a )
+
+ # second data row
+ row = csv[1]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([[:my, "A"], [:new, "B"], [:headers, "C"]], row.to_a)
+
+ # third data row
+ row = csv[2]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([[:my, "1"], [:new, "2"], [:headers, "3"]], row.to_a)
+
+ # empty
+ assert_nil(csv[3])
+
+ # with return and convert
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => [:my, :new, :headers],
+ :return_headers => true,
+ :header_converters => lambda { |h| h.to_s } )
+ end
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([["my", :my], ["new", :new], ["headers", :headers]], row.to_a)
+ assert(row.header_row?)
+ assert(!row.field_row?)
+ end
+
+ def test_csv_header_string
+ # activate headers
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => "my,new,headers")
+ end
+
+ # first data row - skipping headers
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
+
+ # second data row
+ row = csv[1]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{my A}, %w{new B}, %w{headers C}], row.to_a)
+
+ # third data row
+ row = csv[2]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{my 1}, %w{new 2}, %w{headers 3}], row.to_a)
+
+ # empty
+ assert_nil(csv[3])
+
+ # with return and convert
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => "my,new,headers",
+ :return_headers => true,
+ :header_converters => :symbol )
+ end
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([[:my, "my"], [:new, "new"], [:headers, "headers"]], row.to_a)
+ assert(row.header_row?)
+ assert(!row.field_row?)
+ end
+
+ def test_return_headers
+ # activate headers and request they are returned
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => true, :return_headers => true)
+ end
+
+ # header row
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal( [%w{first first}, %w{second second}, %w{third third}],
+ row.to_a )
+ assert(row.header_row?)
+ assert(!row.field_row?)
+
+ # first data row - skipping headers
+ row = csv[1]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
+ assert(!row.header_row?)
+ assert(row.field_row?)
+
+ # second data row
+ row = csv[2]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
+ assert(!row.header_row?)
+ assert(row.field_row?)
+
+ # empty
+ assert_nil(csv[3])
+ end
+
+ def test_converters
+ # create test data where headers and fields look alike
+ data = <<-END_MATCHING_CSV.gsub(/^\s+/, "")
+ 1,2,3
+ 1,2,3
+ END_MATCHING_CSV
+
+ # normal converters do not affect headers
+ csv = CSV.parse( data, :headers => true,
+ :return_headers => true,
+ :converters => :numeric )
+ assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv[0].to_a)
+ assert_equal([["1", 1], ["2", 2], ["3", 3]], csv[1].to_a)
+ assert_nil(csv[2])
+
+ # header converters do affect headers (only)
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse( data, :headers => true,
+ :return_headers => true,
+ :converters => :numeric,
+ :header_converters => :symbol )
+ end
+ assert_equal([[:"1", "1"], [:"2", "2"], [:"3", "3"]], csv[0].to_a)
+ assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv[1].to_a)
+ assert_nil(csv[2])
+ end
+
+ def test_builtin_downcase_converter
+ csv = CSV.parse( "One,TWO Three", :headers => true,
+ :return_headers => true,
+ :header_converters => :downcase )
+ assert_equal(%w{one two\ three}, csv.headers)
+ end
+
+ def test_builtin_symbol_converter
+ csv = CSV.parse( "One,TWO Three", :headers => true,
+ :return_headers => true,
+ :header_converters => :symbol )
+ assert_equal([:one, :two_three], csv.headers)
+ end
+
+ def test_custom_converter
+ converter = lambda { |header| header.tr(" ", "_") }
+ csv = CSV.parse( "One,TWO Three",
+ :headers => true,
+ :return_headers => true,
+ :header_converters => converter )
+ assert_equal(%w{One TWO_Three}, csv.headers)
+ end
+
+ def test_table_support
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse(@data, :headers => true)
+ end
+
+ assert_instance_of(CSV::Table, csv)
+ end
+
+ def test_skip_blanks
+ @data = <<-END_CSV.gsub(/^ +/, "")
+
+
+ A,B,C
+
+ 1,2,3
+
+
+
+ END_CSV
+
+ expected = [%w[1 2 3]]
+ CSV.parse(@data, :headers => true, :skip_blanks => true) do |row|
+ assert_equal(expected.shift, row.fields)
+ end
+
+ expected = [%w[A B C], %w[1 2 3]]
+ CSV.parse( @data,
+ :headers => true,
+ :return_headers => true,
+ :skip_blanks => true ) do |row|
+ assert_equal(expected.shift, row.fields)
+ end
+ end
+
+ def test_blank_row_bug_fix
+ @data += "\n#{@data}" # add a blank row
+
+ # ensure that everything returned is a Row object
+ CSV.parse(@data, :headers => true) do |row|
+ assert_instance_of(CSV::Row, row)
+ end
+ end
+end
diff --git a/trunk/test/csv/tc_interface.rb b/trunk/test/csv/tc_interface.rb
new file mode 100644
index 0000000000..e8cc920f9d
--- /dev/null
+++ b/trunk/test/csv/tc_interface.rb
@@ -0,0 +1,235 @@
+#!/usr/local/bin/ruby -w
+
+# tc_interface.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestCSVInterface < Test::Unit::TestCase
+ def setup
+ @path = File.join(File.dirname(__FILE__), "temp_test_data.csv")
+
+ File.open(@path, "w") do |file|
+ file << "1\t2\t3\r\n"
+ file << "4\t5\r\n"
+ end
+
+ @expected = [%w{1 2 3}, %w{4 5}]
+ end
+
+ def teardown
+ File.unlink(@path)
+ end
+
+ ### Test Read Interface ###
+
+ def test_foreach
+ CSV.foreach(@path, :col_sep => "\t", :row_sep => "\r\n") do |row|
+ assert_equal(@expected.shift, row)
+ end
+ end
+
+ def test_open_and_close
+ csv = CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n")
+ assert_not_nil(csv)
+ assert_instance_of(CSV, csv)
+ assert_equal(false, csv.closed?)
+ csv.close
+ assert(csv.closed?)
+
+ ret = CSV.open(@path) do |csv|
+ assert_instance_of(CSV, csv)
+ "Return value."
+ end
+ assert(csv.closed?)
+ assert_equal("Return value.", ret)
+ end
+
+ def test_parse
+ data = File.read(@path)
+ assert_equal( @expected,
+ CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") )
+
+ CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") do |row|
+ assert_equal(@expected.shift, row)
+ end
+ end
+
+ def test_parse_line
+ row = CSV.parse_line("1;2;3", :col_sep => ";")
+ assert_not_nil(row)
+ assert_instance_of(Array, row)
+ assert_equal(%w{1 2 3}, row)
+
+ # shortcut interface
+ row = "1;2;3".parse_csv(:col_sep => ";")
+ assert_not_nil(row)
+ assert_instance_of(Array, row)
+ assert_equal(%w{1 2 3}, row)
+ end
+
+ def test_read_and_readlines
+ assert_equal( @expected,
+ CSV.read(@path, :col_sep => "\t", :row_sep => "\r\n") )
+ assert_equal( @expected,
+ CSV.readlines(@path, :col_sep => "\t", :row_sep => "\r\n") )
+
+
+ data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ csv.read
+ end
+ assert_equal(@expected, data)
+ data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ csv.readlines
+ end
+ assert_equal(@expected, data)
+ end
+
+ def test_table
+ table = CSV.table(@path, :col_sep => "\t", :row_sep => "\r\n")
+ assert_instance_of(CSV::Table, table)
+ assert_equal([[:"1", :"2", :"3"], [4, 5, nil]], table.to_a)
+ end
+
+ def test_shift # aliased as gets() and readline()
+ CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ assert_equal(@expected.shift, csv.shift)
+ assert_equal(@expected.shift, csv.shift)
+ assert_equal(nil, csv.shift)
+ end
+ end
+
+ ### Test Write Interface ###
+
+ def test_generate
+ str = CSV.generate do |csv| # default empty String
+ assert_instance_of(CSV, csv)
+ assert_equal(csv, csv << [1, 2, 3])
+ assert_equal(csv, csv << [4, nil, 5])
+ end
+ assert_not_nil(str)
+ assert_instance_of(String, str)
+ assert_equal("1,2,3\n4,,5\n", str)
+
+ CSV.generate(str) do |csv| # appending to a String
+ assert_equal(csv, csv << ["last", %Q{"row"}])
+ end
+ assert_equal(%Q{1,2,3\n4,,5\nlast,"""row"""\n}, str)
+ end
+
+ def test_generate_line
+ line = CSV.generate_line(%w{1 2 3}, :col_sep => ";")
+ assert_not_nil(line)
+ assert_instance_of(String, line)
+ assert_equal("1;2;3\n", line)
+
+ # shortcut interface
+ line = %w{1 2 3}.to_csv(:col_sep => ";")
+ assert_not_nil(line)
+ assert_instance_of(String, line)
+ assert_equal("1;2;3\n", line)
+ end
+
+ def test_write_header_detection
+ File.unlink(@path)
+
+ headers = %w{a b c}
+ CSV.open(@path, "w", :headers => true) do |csv|
+ csv << headers
+ csv << %w{1 2 3}
+ assert_equal(headers, csv.instance_variable_get(:@headers))
+ end
+ end
+
+ def test_write_lineno
+ File.unlink(@path)
+
+ CSV.open(@path, "w") do |csv|
+ lines = 20
+ lines.times { csv << %w{a b c} }
+ assert_equal(lines, csv.lineno)
+ end
+ end
+
+ def test_write_hash
+ File.unlink(@path)
+
+ lines = [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
+ CSV.open( @path, "w", :headers => true,
+ :converters => :all,
+ :header_converters => :symbol ) do |csv|
+ csv << lines.first.keys
+ lines.each { |line| csv << line }
+ end
+ CSV.open( @path, "w", :headers => true,
+ :converters => :all,
+ :header_converters => :symbol ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_append # aliased add_row() and puts()
+ File.unlink(@path)
+
+ CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ @expected.each { |row| csv << row }
+ end
+
+ test_shift
+
+ # same thing using CSV::Row objects
+ File.unlink(@path)
+
+ CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ @expected.each { |row| csv << CSV::Row.new(Array.new, row) }
+ end
+
+ test_shift
+ end
+
+ ### Test Read and Write Interface ###
+
+ def test_filter
+ assert_respond_to(CSV, :filter)
+
+ expected = [[1, 2, 3], [4, 5]]
+ CSV.filter( "1;2;3\n4;5\n", (result = String.new),
+ :in_col_sep => ";", :out_col_sep => ",",
+ :converters => :all ) do |row|
+ assert_equal(row, expected.shift)
+ row.map! { |n| n * 2 }
+ row << "Added\r"
+ end
+ assert_equal("2,4,6,\"Added\r\"\n8,10,\"Added\r\"\n", result)
+ end
+
+ def test_instance
+ csv = String.new
+
+ first = nil
+ assert_nothing_raised(Exception) do
+ first = CSV.instance(csv, :col_sep => ";")
+ first << %w{a b c}
+ end
+
+ assert_equal("a;b;c\n", csv)
+
+ second = nil
+ assert_nothing_raised(Exception) do
+ second = CSV.instance(csv, :col_sep => ";")
+ second << [1, 2, 3]
+ end
+
+ assert_equal(first.object_id, second.object_id)
+ assert_equal("a;b;c\n1;2;3\n", csv)
+
+ # shortcuts
+ assert_equal(STDOUT, CSV.instance.instance_eval { @io })
+ assert_equal(STDOUT, CSV { |csv| csv.instance_eval { @io } })
+ end
+end
diff --git a/trunk/test/csv/tc_row.rb b/trunk/test/csv/tc_row.rb
new file mode 100644
index 0000000000..a9b7f042b2
--- /dev/null
+++ b/trunk/test/csv/tc_row.rb
@@ -0,0 +1,289 @@
+#!/usr/local/bin/ruby -w
+
+# tc_row.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestCSVRow < Test::Unit::TestCase
+ def setup
+ @row = CSV::Row.new(%w{A B C A A}, [1, 2, 3, 4])
+ end
+
+ def test_initialize
+ # basic
+ row = CSV::Row.new(%w{A B C}, [1, 2, 3])
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([["A", 1], ["B", 2], ["C", 3]], row.to_a)
+
+ # missing headers
+ row = CSV::Row.new(%w{A}, [1, 2, 3])
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([["A", 1], [nil, 2], [nil, 3]], row.to_a)
+
+ # missing fields
+ row = CSV::Row.new(%w{A B C}, [1, 2])
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([["A", 1], ["B", 2], ["C", nil]], row.to_a)
+ end
+
+ def test_row_type
+ # field rows
+ row = CSV::Row.new(%w{A B C}, [1, 2, 3]) # implicit
+ assert(!row.header_row?)
+ assert(row.field_row?)
+ row = CSV::Row.new(%w{A B C}, [1, 2, 3], false) # explicit
+ assert(!row.header_row?)
+ assert(row.field_row?)
+
+ # header row
+ row = CSV::Row.new(%w{A B C}, [1, 2, 3], true)
+ assert(row.header_row?)
+ assert(!row.field_row?)
+ end
+
+ def test_headers
+ assert_equal(%w{A B C A A}, @row.headers)
+ end
+
+ def test_field
+ # by name
+ assert_equal(2, @row.field("B"))
+ assert_equal(2, @row["B"]) # alias
+
+ # by index
+ assert_equal(3, @row.field(2))
+
+ # missing
+ assert_nil(@row.field("Missing"))
+ assert_nil(@row.field(10))
+
+ # minimum index
+ assert_equal(1, @row.field("A"))
+ assert_equal(1, @row.field("A", 0))
+ assert_equal(4, @row.field("A", 1))
+ assert_equal(4, @row.field("A", 2))
+ assert_equal(4, @row.field("A", 3))
+ assert_equal(nil, @row.field("A", 4))
+ assert_equal(nil, @row.field("A", 5))
+ end
+
+ def test_set_field
+ # set field by name
+ assert_equal(100, @row["A"] = 100)
+
+ # set field by index
+ assert_equal(300, @row[3] = 300)
+
+ # set field by name and minimum index
+ assert_equal([:a, :b, :c], @row["A", 4] = [:a, :b, :c])
+
+ # verify the changes
+ assert_equal( [ ["A", 100],
+ ["B", 2],
+ ["C", 3],
+ ["A", 300],
+ ["A", [:a, :b, :c]] ], @row.to_a )
+
+ # assigning an index past the end
+ assert_equal("End", @row[10] = "End")
+ assert_equal( [ ["A", 100],
+ ["B", 2],
+ ["C", 3],
+ ["A", 300],
+ ["A", [:a, :b, :c]],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, "End"] ], @row.to_a )
+
+ # assigning a new field by header
+ assert_equal("New", @row[:new] = "New")
+ assert_equal( [ ["A", 100],
+ ["B", 2],
+ ["C", 3],
+ ["A", 300],
+ ["A", [:a, :b, :c]],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, nil],
+ [nil, "End"],
+ [:new, "New"] ], @row.to_a )
+ end
+
+ def test_append
+ # add a value
+ assert_equal(@row, @row << "Value")
+ assert_equal( [ ["A", 1],
+ ["B", 2],
+ ["C", 3],
+ ["A", 4],
+ ["A", nil],
+ [nil, "Value"] ], @row.to_a )
+
+ # add a pair
+ assert_equal(@row, @row << %w{Header Field})
+ assert_equal( [ ["A", 1],
+ ["B", 2],
+ ["C", 3],
+ ["A", 4],
+ ["A", nil],
+ [nil, "Value"],
+ %w{Header Field} ], @row.to_a )
+
+ # a pair with Hash syntax
+ assert_equal(@row, @row << {:key => :value})
+ assert_equal( [ ["A", 1],
+ ["B", 2],
+ ["C", 3],
+ ["A", 4],
+ ["A", nil],
+ [nil, "Value"],
+ %w{Header Field},
+ [:key, :value] ], @row.to_a )
+
+ # multiple fields at once
+ assert_equal(@row, @row.push(100, 200, [:last, 300]))
+ assert_equal( [ ["A", 1],
+ ["B", 2],
+ ["C", 3],
+ ["A", 4],
+ ["A", nil],
+ [nil, "Value"],
+ %w{Header Field},
+ [:key, :value],
+ [nil, 100],
+ [nil, 200],
+ [:last, 300] ], @row.to_a )
+ end
+
+ def test_delete
+ # by index
+ assert_equal(["B", 2], @row.delete(1))
+
+ # by header
+ assert_equal(["C", 3], @row.delete("C"))
+
+ # using a block
+ assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? })
+ assert_equal([["A", nil]], @row.to_a)
+ end
+
+ def test_fields
+ # all fields
+ assert_equal([1, 2, 3, 4, nil], @row.fields)
+
+ # by header
+ assert_equal([1, 3], @row.fields("A", "C"))
+
+ # by index
+ assert_equal([2, 3, nil], @row.fields(1, 2, 10))
+
+ # by both
+ assert_equal([2, 3, 4], @row.fields("B", "C", 3))
+
+ # with minimum indices
+ assert_equal([2, 3, 4], @row.fields("B", "C", ["A", 3]))
+
+ # by header range
+ assert_equal([2, 3], @row.values_at("B".."C"))
+ end
+
+ def test_index
+ # basic usage
+ assert_equal(0, @row.index("A"))
+ assert_equal(1, @row.index("B"))
+ assert_equal(2, @row.index("C"))
+ assert_equal(nil, @row.index("Z"))
+
+ # with minimum index
+ assert_equal(0, @row.index("A"))
+ assert_equal(0, @row.index("A", 0))
+ assert_equal(3, @row.index("A", 1))
+ assert_equal(3, @row.index("A", 2))
+ assert_equal(3, @row.index("A", 3))
+ assert_equal(4, @row.index("A", 4))
+ assert_equal(nil, @row.index("A", 5))
+ end
+
+ def test_queries
+ # headers
+ assert(@row.header?("A"))
+ assert(@row.header?("C"))
+ assert(!@row.header?("Z"))
+ assert(@row.include?("A")) # alias
+
+ # fields
+ assert(@row.field?(4))
+ assert(@row.field?(nil))
+ assert(!@row.field?(10))
+ end
+
+ def test_each
+ # array style
+ ary = @row.to_a
+ @row.each do |pair|
+ assert_equal(ary.first.first, pair.first)
+ assert_equal(ary.shift.last, pair.last)
+ end
+
+ # hash style
+ ary = @row.to_a
+ @row.each do |header, field|
+ assert_equal(ary.first.first, header)
+ assert_equal(ary.shift.last, field)
+ end
+
+ # verify that we can chain the call
+ assert_equal(@row, @row.each { })
+ end
+
+ def test_enumerable
+ assert_equal( [["A", 1], ["A", 4], ["A", nil]],
+ @row.select { |pair| pair.first == "A" } )
+
+ assert_equal(10, @row.inject(0) { |sum, (header, n)| sum + (n || 0) })
+ end
+
+ def test_to_a
+ row = CSV::Row.new(%w{A B C}, [1, 2, 3]).to_a
+ assert_instance_of(Array, row)
+ row.each do |pair|
+ assert_instance_of(Array, pair)
+ assert_equal(2, pair.size)
+ end
+ assert_equal([["A", 1], ["B", 2], ["C", 3]], row)
+ end
+
+ def test_to_hash
+ assert_equal({"A" => nil, "B" => 2, "C" => 3}, @row.to_hash)
+ end
+
+ def test_to_csv
+ # normal conversion
+ assert_equal("1,2,3,4,\n", @row.to_csv)
+ assert_equal("1,2,3,4,\n", @row.to_s) # alias
+
+ # with options
+ assert_equal( "1|2|3|4|\r\n",
+ @row.to_csv(:col_sep => "|", :row_sep => "\r\n") )
+ end
+
+ def test_array_delegation
+ assert(!@row.empty?, "Row was empty.")
+
+ assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
+ end
+end
diff --git a/trunk/test/csv/tc_serialization.rb b/trunk/test/csv/tc_serialization.rb
new file mode 100644
index 0000000000..d9c37fde21
--- /dev/null
+++ b/trunk/test/csv/tc_serialization.rb
@@ -0,0 +1,155 @@
+#!/usr/local/bin/ruby -w
+
+# tc_serialization.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+# An example of how to provide custom CSV serialization.
+class Hash
+ def self.csv_load( meta, headers, fields )
+ self[*headers.zip(fields).to_a.flatten.map { |e| eval(e) }]
+ end
+
+ def csv_headers
+ keys.map { |key| key.inspect }
+ end
+
+ def csv_dump( headers )
+ headers.map { |header| fetch(eval(header)).inspect }
+ end
+end
+
+class TestSerialization < Test::Unit::TestCase
+
+ ### Classes Used to Test Serialization ###
+
+ class ReadOnlyName
+ def initialize( first, last )
+ @first, @last = first, last
+ end
+
+ attr_reader :first, :last
+
+ def ==( other )
+ %w{first last}.all? { |att| send(att) == other.send(att) }
+ end
+ end
+
+ Name = Struct.new(:first, :last)
+
+ class FullName < Name
+ def initialize( first, last, suffix = nil )
+ super(first, last)
+
+ @suffix = suffix
+ end
+
+ attr_accessor :suffix
+
+ def ==( other )
+ %w{first last suffix}.all? { |att| send(att) == other.send(att) }
+ end
+ end
+
+ ### Tests ###
+
+ def test_class_dump
+ @names = [ %w{James Gray},
+ %w{Dana Gray},
+ %w{Greg Brown} ].map do |first, last|
+ ReadOnlyName.new(first, last)
+ end
+
+ assert_nothing_raised(Exception) do
+ @data = CSV.dump(@names)
+ end
+ assert_equal(<<-END_CLASS_DUMP.gsub(/^\s*/, ""), @data)
+ class,TestSerialization::ReadOnlyName
+ @first,@last
+ James,Gray
+ Dana,Gray
+ Greg,Brown
+ END_CLASS_DUMP
+ end
+
+ def test_struct_dump
+ @names = [ %w{James Gray},
+ %w{Dana Gray},
+ %w{Greg Brown} ].map do |first, last|
+ Name.new(first, last)
+ end
+
+ assert_nothing_raised(Exception) do
+ @data = CSV.dump(@names)
+ end
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
+ class,TestSerialization::Name
+ first=,last=
+ James,Gray
+ Dana,Gray
+ Greg,Brown
+ END_STRUCT_DUMP
+ end
+
+ def test_inherited_struct_dump
+ @names = [ %w{James Gray II},
+ %w{Dana Gray},
+ %w{Greg Brown} ].map do |first, last, suffix|
+ FullName.new(first, last, suffix)
+ end
+
+ assert_nothing_raised(Exception) do
+ @data = CSV.dump(@names)
+ end
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
+ class,TestSerialization::FullName
+ @suffix,first=,last=
+ II,James,Gray
+ ,Dana,Gray
+ ,Greg,Brown
+ END_STRUCT_DUMP
+ end
+
+ def test_load
+ %w{ test_class_dump
+ test_struct_dump
+ test_inherited_struct_dump }.each do |test|
+ send(test)
+ CSV.load(@data).each do |loaded|
+ assert_instance_of(@names.first.class, loaded)
+ assert_equal(@names.shift, loaded)
+ end
+ end
+ end
+
+ def test_io
+ test_class_dump
+
+ data_file = File.join(File.dirname(__FILE__), "temp_test_data.csv")
+ CSV.dump(@names, File.open(data_file, "w"))
+
+ assert(File.exist?(data_file))
+ assert_equal(<<-END_IO_DUMP.gsub(/^\s*/, ""), File.read(data_file))
+ class,TestSerialization::ReadOnlyName
+ @first,@last
+ James,Gray
+ Dana,Gray
+ Greg,Brown
+ END_IO_DUMP
+
+ assert_equal(@names, CSV.load(File.open(data_file)))
+
+ File.unlink(data_file)
+ end
+
+ def test_custom_dump_and_load
+ obj = {1 => "simple", :test => Hash}
+ assert_equal(obj, CSV.load(CSV.dump([obj])).first)
+ end
+end
diff --git a/trunk/test/csv/tc_table.rb b/trunk/test/csv/tc_table.rb
new file mode 100644
index 0000000000..028274d97f
--- /dev/null
+++ b/trunk/test/csv/tc_table.rb
@@ -0,0 +1,392 @@
+#!/usr/local/bin/ruby -w
+
+# tc_table.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestCSVTable < Test::Unit::TestCase
+ def setup
+ @rows = [ CSV::Row.new(%w{A B C}, [1, 2, 3]),
+ CSV::Row.new(%w{A B C}, [4, 5, 6]),
+ CSV::Row.new(%w{A B C}, [7, 8, 9]) ]
+ @table = CSV::Table.new(@rows)
+
+ @header_table = CSV::Table.new(
+ [CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
+ )
+ end
+
+ def test_initialze
+ assert_not_nil(@table)
+ assert_instance_of(CSV::Table, @table)
+ end
+
+ def test_modes
+ assert_equal(:col_or_row, @table.mode)
+
+ # non-destructive changes, intended for one shot calls
+ cols = @table.by_col
+ assert_equal(:col_or_row, @table.mode)
+ assert_equal(:col, cols.mode)
+ assert_equal(@table, cols)
+
+ rows = @table.by_row
+ assert_equal(:col_or_row, @table.mode)
+ assert_equal(:row, rows.mode)
+ assert_equal(@table, rows)
+
+ # destructive mode changing calls
+ assert_equal(@table, @table.by_row!)
+ assert_equal(:row, @table.mode)
+ assert_equal(@table, @table.by_col_or_row!)
+ assert_equal(:col_or_row, @table.mode)
+ end
+
+ def test_headers
+ assert_equal(@rows.first.headers, @table.headers)
+ end
+
+ def test_index
+ ##################
+ ### Mixed Mode ###
+ ##################
+ # by row
+ @rows.each_index { |i| assert_equal(@rows[i], @table[i]) }
+ assert_equal(nil, @table[100]) # empty row
+
+ # by col
+ @rows.first.headers.each do |header|
+ assert_equal(@rows.map { |row| row[header] }, @table[header])
+ end
+ assert_equal([nil] * @rows.size, @table["Z"]) # empty col
+
+ # by cell, row then col
+ assert_equal(2, @table[0][1])
+ assert_equal(6, @table[1]["C"])
+
+ # by cell, col then row
+ assert_equal(5, @table["B"][1])
+ assert_equal(9, @table["C"][2])
+
+ # with headers (by col)
+ assert_equal(["B", 2, 5, 8], @header_table["B"])
+
+ ###################
+ ### Column Mode ###
+ ###################
+ @table.by_col!
+
+ assert_equal([2, 5, 8], @table[1])
+ assert_equal([2, 5, 8], @table["B"])
+
+ ################
+ ### Row Mode ###
+ ################
+ @table.by_row!
+
+ assert_equal(@rows[1], @table[1])
+ assert_raise(TypeError) { @table["B"] }
+
+ ############################
+ ### One Shot Mode Change ###
+ ############################
+ assert_equal(@rows[1], @table[1])
+ assert_equal([2, 5, 8], @table.by_col[1])
+ assert_equal(@rows[1], @table[1])
+ end
+
+ def test_set_row_or_column
+ ##################
+ ### Mixed Mode ###
+ ##################
+ # set row
+ @table[2] = [10, 11, 12]
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a)
+
+ @table[3] = CSV::Row.new(%w[A B C], [13, 14, 15])
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]],
+ @table.to_a )
+
+ # set col
+ @table["Type"] = "data"
+ assert_equal( [ %w[A B C Type],
+ [1, 2, 3, "data"],
+ [4, 5, 6, "data"],
+ [10, 11, 12, "data"],
+ [13, 14, 15, "data"] ],
+ @table.to_a )
+
+ @table["Index"] = [1, 2, 3]
+ assert_equal( [ %w[A B C Type Index],
+ [1, 2, 3, "data", 1],
+ [4, 5, 6, "data", 2],
+ [10, 11, 12, "data", 3],
+ [13, 14, 15, "data", nil] ],
+ @table.to_a )
+
+ @table["B"] = [100, 200]
+ assert_equal( [ %w[A B C Type Index],
+ [1, 100, 3, "data", 1],
+ [4, 200, 6, "data", 2],
+ [10, nil, 12, "data", 3],
+ [13, nil, 15, "data", nil] ],
+ @table.to_a )
+
+ # verify resulting table
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ A,B,C,Type,Index
+ 1,100,3,data,1
+ 4,200,6,data,2
+ 10,,12,data,3
+ 13,,15,data,
+ END_RESULT
+
+ # with headers
+ @header_table["Type"] = "data"
+ assert_equal(%w[Type data data data], @header_table["Type"])
+
+ ###################
+ ### Column Mode ###
+ ###################
+ @table.by_col!
+
+ @table[1] = [2, 5, 11, 14]
+ assert_equal( [ %w[A B C Type Index],
+ [1, 2, 3, "data", 1],
+ [4, 5, 6, "data", 2],
+ [10, 11, 12, "data", 3],
+ [13, 14, 15, "data", nil] ],
+ @table.to_a )
+
+ @table["Extra"] = "new stuff"
+ assert_equal( [ %w[A B C Type Index Extra],
+ [1, 2, 3, "data", 1, "new stuff"],
+ [4, 5, 6, "data", 2, "new stuff"],
+ [10, 11, 12, "data", 3, "new stuff"],
+ [13, 14, 15, "data", nil, "new stuff"] ],
+ @table.to_a )
+
+ ################
+ ### Row Mode ###
+ ################
+ @table.by_row!
+
+ @table[1] = (1..6).to_a
+ assert_equal( [ %w[A B C Type Index Extra],
+ [1, 2, 3, "data", 1, "new stuff"],
+ [1, 2, 3, 4, 5, 6],
+ [10, 11, 12, "data", 3, "new stuff"],
+ [13, 14, 15, "data", nil, "new stuff"] ],
+ @table.to_a )
+
+ assert_raise(TypeError) { @table["Extra"] = nil }
+ end
+
+ def test_each
+ ######################
+ ### Mixed/Row Mode ###
+ ######################
+ i = 0
+ @table.each do |row|
+ assert_equal(@rows[i], row)
+ i += 1
+ end
+
+ # verify that we can chain the call
+ assert_equal(@table, @table.each { })
+
+ ###################
+ ### Column Mode ###
+ ###################
+ @table.by_col!
+
+ headers = @table.headers
+ @table.each do |header, column|
+ assert_equal(headers.shift, header)
+ assert_equal(@table[header], column)
+ end
+
+ ############################
+ ### One Shot Mode Change ###
+ ############################
+ @table.by_col_or_row!
+
+ @table.each { |row| assert_instance_of(CSV::Row, row) }
+ @table.by_col.each { |tuple| assert_instance_of(Array, tuple) }
+ @table.each { |row| assert_instance_of(CSV::Row, row) }
+ end
+
+ def test_enumerable
+ assert_equal( @rows.values_at(0, 2),
+ @table.select { |row| (row["B"] % 2).zero? } )
+
+ assert_equal(@rows[1], @table.find { |row| row["C"] > 5 })
+ end
+
+ def test_to_a
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a)
+
+ # with headers
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]],
+ @header_table.to_a )
+ end
+
+ def test_to_csv
+ csv = <<-END_CSV.gsub(/^\s+/, "")
+ A,B,C
+ 1,2,3
+ 4,5,6
+ 7,8,9
+ END_CSV
+
+ # normal conversion
+ assert_equal(csv, @table.to_csv)
+ assert_equal(csv, @table.to_s) # alias
+
+ # with options
+ assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
+ @table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
+
+ # with headers
+ assert_equal(csv, @header_table.to_csv)
+ end
+
+ def test_append
+ # verify that we can chain the call
+ assert_equal(@table, @table << [10, 11, 12])
+
+ # Array append
+ assert_equal(CSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1])
+
+ # Row append
+ assert_equal(@table, @table << CSV::Row.new(%w[A B C], [13, 14, 15]))
+ assert_equal(CSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1])
+ end
+
+ def test_delete
+ ##################
+ ### Mixed Mode ###
+ ##################
+ # delete a row
+ assert_equal(@rows[1], @table.delete(1))
+
+ # delete a col
+ assert_equal(@rows.map { |row| row["A"] }, @table.delete("A"))
+
+ # verify resulting table
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ B,C
+ 2,3
+ 8,9
+ END_RESULT
+
+ ###################
+ ### Column Mode ###
+ ###################
+ setup
+ @table.by_col!
+
+ assert_equal(@rows.map { |row| row[0] }, @table.delete(0))
+ assert_equal(@rows.map { |row| row["C"] }, @table.delete("C"))
+
+ # verify resulting table
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ B
+ 2
+ 5
+ 8
+ END_RESULT
+
+ ################
+ ### Row Mode ###
+ ################
+ setup
+ @table.by_row!
+
+ assert_equal(@rows[1], @table.delete(1))
+ assert_raise(TypeError) { @table.delete("C") }
+
+ # verify resulting table
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ A,B,C
+ 1,2,3
+ 7,8,9
+ END_RESULT
+ end
+
+ def test_delete_if
+ ######################
+ ### Mixed/Row Mode ###
+ ######################
+ # verify that we can chain the call
+ assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? })
+
+ # verify resulting table
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ A,B,C
+ 4,5,6
+ END_RESULT
+
+ ###################
+ ### Column Mode ###
+ ###################
+ setup
+ @table.by_col!
+
+ assert_equal(@table, @table.delete_if { |h, v| h > "A" })
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
+ A
+ 1
+ 4
+ 7
+ END_RESULT
+ end
+
+ def test_values_at
+ ##################
+ ### Mixed Mode ###
+ ##################
+ # rows
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
+ assert_equal(@rows.values_at(1..2), @table.values_at(1..2))
+
+ # cols
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
+ assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C"))
+
+ ###################
+ ### Column Mode ###
+ ###################
+ @table.by_col!
+
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2))
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
+
+ ################
+ ### Row Mode ###
+ ################
+ @table.by_row!
+
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
+ assert_raise(TypeError) { @table.values_at("A", "C") }
+
+ ############################
+ ### One Shot Mode Change ###
+ ############################
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
+ end
+
+ def test_array_delegation
+ assert(!@table.empty?, "Table was empty.")
+
+ assert_equal(@rows.size, @table.size)
+ end
+end
diff --git a/trunk/test/csv/ts_all.rb b/trunk/test/csv/ts_all.rb
new file mode 100644
index 0000000000..c930523757
--- /dev/null
+++ b/trunk/test/csv/ts_all.rb
@@ -0,0 +1,19 @@
+#!/usr/local/bin/ruby -w
+
+# ts_all.rb
+#
+# Created by James Edward Gray II on 2005-10-31.
+# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "tc_csv_parsing"
+require "tc_features"
+require "tc_interface"
+require "tc_csv_writing"
+require "tc_data_converters"
+require "tc_row"
+require "tc_table"
+require "tc_headers"
+require "tc_serialization"
diff --git a/trunk/test/dbm/test_dbm.rb b/trunk/test/dbm/test_dbm.rb
new file mode 100644
index 0000000000..159ab43f35
--- /dev/null
+++ b/trunk/test/dbm/test_dbm.rb
@@ -0,0 +1,562 @@
+require 'test/unit'
+require 'tmpdir'
+
+begin
+ require 'dbm'
+rescue LoadError
+end
+
+if defined? DBM
+ require 'tmpdir'
+ require 'fileutils'
+
+ class TestDBM < Test::Unit::TestCase
+ def TestDBM.uname_s
+ require 'rbconfig'
+ case RbConfig::CONFIG['target_os']
+ when 'cygwin'
+ require 'Win32API'
+ uname = Win32API.new('cygwin1', 'uname', 'P', 'I')
+ utsname = ' ' * 100
+ raise 'cannot get system name' if uname.call(utsname) == -1
+
+ utsname.unpack('A20' * 5)[0]
+ else
+ RbConfig::CONFIG['target_os']
+ end
+ end
+ SYSTEM = uname_s
+
+ def setup
+ @tmpdir = Dir.mktmpdir("tmptest_dbm")
+ @prefix = "tmptest_dbm_#{$$}"
+ @path = "#{@tmpdir}/#{@prefix}_"
+ assert_instance_of(DBM, @dbm = DBM.new(@path))
+
+ # prepare to make readonly DBM file
+ DBM.open("#{@tmpdir}/#{@prefix}_rdonly") {|dbm|
+ dbm['foo'] = 'FOO'
+ }
+
+ File.chmod(0400, *Dir.glob("#{@tmpdir}/#{@prefix}_rdonly.*"))
+
+ assert_instance_of(DBM, @dbm_rdonly = DBM.new("#{@tmpdir}/#{@prefix}_rdonly", nil))
+ end
+ def teardown
+ assert_nil(@dbm.close)
+ assert_nil(@dbm_rdonly.close)
+ ObjectSpace.each_object(DBM) do |obj|
+ obj.close unless obj.closed?
+ end
+ FileUtils.remove_entry_secure @tmpdir
+ end
+
+ def check_size(expect, dbm=@dbm)
+ assert_equal(expect, dbm.size)
+ n = 0
+ dbm.each { n+=1 }
+ assert_equal(expect, n)
+ if expect == 0
+ assert_equal(true, dbm.empty?)
+ else
+ assert_equal(false, dbm.empty?)
+ end
+ end
+
+ def have_fork?
+ begin
+ fork{}
+ true
+ rescue NotImplementedError
+ false
+ end
+ end
+
+ def test_s_new_has_no_block
+ # DBM.new ignore the block
+ foo = true
+ assert_instance_of(DBM, dbm = DBM.new("#{@tmpdir}/#{@prefix}") { foo = false })
+ assert_equal(foo, true)
+ assert_nil(dbm.close)
+ end
+ def test_s_open_no_create
+ assert_nil(dbm = DBM.open("#{@tmpdir}/#{@prefix}", nil))
+ ensure
+ dbm.close if dbm
+ end
+ def test_s_open_with_block
+ assert_equal(DBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo)
+ end
+
+ def test_close
+ assert_instance_of(DBM, dbm = DBM.open("#{@tmpdir}/#{@prefix}"))
+ assert_nil(dbm.close)
+
+ # closed DBM file
+ assert_raise(DBMError) { dbm.close }
+ end
+
+ def test_aref
+ assert_equal('bar', @dbm['foo'] = 'bar')
+ assert_equal('bar', @dbm['foo'])
+
+ assert_nil(@dbm['bar'])
+ end
+
+ def test_fetch
+ assert_equal('bar', @dbm['foo']='bar')
+ assert_equal('bar', @dbm.fetch('foo'))
+
+ # key not found
+ assert_raise(IndexError) {
+ @dbm.fetch('bar')
+ }
+
+ # test for `ifnone' arg
+ assert_equal('baz', @dbm.fetch('bar', 'baz'))
+
+ # test for `ifnone' block
+ assert_equal('foobar', @dbm.fetch('bar') {|key| 'foo' + key })
+ end
+
+ def test_aset
+ num = 0
+ 2.times {|i|
+ assert_equal('foo', @dbm['foo'] = 'foo')
+ assert_equal('foo', @dbm['foo'])
+ assert_equal('bar', @dbm['foo'] = 'bar')
+ assert_equal('bar', @dbm['foo'])
+
+ num += 1 if i == 0
+ assert_equal(num, @dbm.size)
+
+ # assign nil
+ assert_equal('', @dbm['bar'] = '')
+ assert_equal('', @dbm['bar'])
+
+ num += 1 if i == 0
+ assert_equal(num, @dbm.size)
+
+ # empty string
+ assert_equal('', @dbm[''] = '')
+ assert_equal('', @dbm[''])
+
+ num += 1 if i == 0
+ assert_equal(num, @dbm.size)
+
+ # Fixnum
+ assert_equal('200', @dbm['100'] = '200')
+ assert_equal('200', @dbm['100'])
+
+ num += 1 if i == 0
+ assert_equal(num, @dbm.size)
+
+ # Big key and value
+ assert_equal('y' * 100, @dbm['x' * 100] = 'y' * 100)
+ assert_equal('y' * 100, @dbm['x' * 100])
+
+ num += 1 if i == 0
+ assert_equal(num, @dbm.size)
+ }
+ end
+
+ def test_index
+ assert_equal('bar', @dbm['foo'] = 'bar')
+ assert_equal('foo', @dbm.index('bar'))
+ assert_nil(@dbm['bar'])
+ end
+
+ def test_values_at
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+ assert_equal(values.reverse, @dbm.values_at(*keys.reverse))
+ end
+
+ def test_select_with_block
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+ ret = @dbm.select {|k,v|
+ assert_equal(k.upcase, v)
+ k != "bar"
+ }
+ assert_equal([['baz', 'BAZ'], ['foo', 'FOO']],
+ ret.sort)
+ end
+
+ def test_length
+ num = 10
+ assert_equal(0, @dbm.size)
+ num.times {|i|
+ i = i.to_s
+ @dbm[i] = i
+ }
+ assert_equal(num, @dbm.size)
+
+ @dbm.shift
+
+ assert_equal(num - 1, @dbm.size)
+ end
+
+ def test_empty?
+ assert_equal(true, @dbm.empty?)
+ @dbm['foo'] = 'FOO'
+ assert_equal(false, @dbm.empty?)
+ end
+
+ def test_each_pair
+ n = 0
+ @dbm.each_pair { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ n = 0
+ ret = @dbm.each_pair {|key, val|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@dbm, ret)
+ end
+
+ def test_each_value
+ n = 0
+ @dbm.each_value { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ n = 0
+ ret = @dbm.each_value {|val|
+ assert_not_nil(key = @dbm.index(val))
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@dbm, ret)
+ end
+
+ def test_each_key
+ n = 0
+ @dbm.each_key { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ n = 0
+ ret = @dbm.each_key {|key|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(@dbm[key], values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@dbm, ret)
+ end
+
+ def test_keys
+ assert_equal([], @dbm.keys)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ assert_equal(keys.sort, @dbm.keys.sort)
+ assert_equal(values.sort, @dbm.values.sort)
+ end
+
+ def test_values
+ test_keys
+ end
+
+ def test_shift
+ assert_nil(@dbm.shift)
+ assert_equal(0, @dbm.size)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ ret_keys = []
+ ret_values = []
+ while ret = @dbm.shift
+ ret_keys.push ret[0]
+ ret_values.push ret[1]
+
+ assert_equal(keys.size - ret_keys.size, @dbm.size)
+ end
+
+ assert_equal(keys.sort, ret_keys.sort)
+ assert_equal(values.sort, ret_values.sort)
+ end
+
+ def test_delete
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ key = keys[1]
+
+ assert_nil(@dbm.delete(key))
+ assert_equal(0, @dbm.size)
+
+ @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
+
+ assert_equal('BAR', @dbm.delete(key))
+ assert_nil(@dbm[key])
+ assert_equal(2, @dbm.size)
+
+ assert_nil(@dbm.delete(key))
+
+ if /^CYGWIN_9/ !~ SYSTEM
+ assert_raise(DBMError) {
+ @dbm_rdonly.delete("foo")
+ }
+
+ assert_nil(@dbm_rdonly.delete("bar"))
+ end
+ end
+ def test_delete_with_block
+ key = 'no called block'
+ @dbm[key] = 'foo'
+ assert_equal('foo', @dbm.delete(key) {|k| k.replace 'called block'})
+ assert_equal('no called block', key)
+ assert_equal(0, @dbm.size)
+
+ key = 'no called block'
+ assert_equal(:blockval,
+ @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
+ assert_equal('called block', key)
+ assert_equal(0, @dbm.size)
+ end
+
+ def test_delete_if
+ v = "0"
+ 100.times {@dbm[v] = v; v = v.next}
+
+ ret = @dbm.delete_if {|key, val| key.to_i < 50}
+ assert_equal(@dbm, ret)
+ check_size(50, @dbm)
+
+ ret = @dbm.delete_if {|key, val| key.to_i >= 50}
+ assert_equal(@dbm, ret)
+ check_size(0, @dbm)
+
+ # break
+ v = "0"
+ 100.times {@dbm[v] = v; v = v.next}
+ check_size(100, @dbm)
+ n = 0;
+ @dbm.delete_if {|key, val|
+ break if n > 50
+ n+=1
+ true
+ }
+ assert_equal(51, n)
+ check_size(49, @dbm)
+
+ @dbm.clear
+
+ # raise
+ v = "0"
+ 100.times {@dbm[v] = v; v = v.next}
+ check_size(100, @dbm)
+ n = 0;
+ begin
+ @dbm.delete_if {|key, val|
+ raise "runtime error" if n > 50
+ n+=1
+ true
+ }
+ rescue
+ end
+ assert_equal(51, n)
+ check_size(49, @dbm)
+ end
+
+ def test_reject
+ v = "0"
+ 100.times {@dbm[v] = v; v = v.next}
+
+ hash = @dbm.reject {|key, val| key.to_i < 50}
+ assert_instance_of(Hash, hash)
+ assert_equal(100, @dbm.size)
+
+ assert_equal(50, hash.size)
+ hash.each_pair {|key,val|
+ assert_equal(false, key.to_i < 50)
+ assert_equal(key, val)
+ }
+
+ hash = @dbm.reject {|key, val| key.to_i < 100}
+ assert_instance_of(Hash, hash)
+ assert_equal(true, hash.empty?)
+ end
+
+ def test_clear
+ v = "1"
+ 100.times {v = v.next; @dbm[v] = v}
+
+ assert_equal(@dbm, @dbm.clear)
+
+ # validate DBM#size
+ i = 0
+ @dbm.each { i += 1 }
+ assert_equal(@dbm.size, i)
+ assert_equal(0, i)
+ end
+
+ def test_invert
+ v = "0"
+ 100.times {@dbm[v] = v; v = v.next}
+
+ hash = @dbm.invert
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_update
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @dbm["101"] = "101"
+ @dbm.update hash
+ assert_equal(101, @dbm.size)
+ @dbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_replace
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @dbm["101"] = "101"
+ @dbm.replace hash
+ assert_equal(100, @dbm.size)
+ @dbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_haskey?
+ assert_equal('bar', @dbm['foo']='bar')
+ assert_equal(true, @dbm.has_key?('foo'))
+ assert_equal(false, @dbm.has_key?('bar'))
+ end
+
+ def test_has_value?
+ assert_equal('bar', @dbm['foo']='bar')
+ assert_equal(true, @dbm.has_value?('bar'))
+ assert_equal(false, @dbm.has_value?('foo'))
+ end
+
+ def test_to_a
+ v = "0"
+ 100.times {v = v.next; @dbm[v] = v}
+
+ ary = @dbm.to_a
+ assert_instance_of(Array, ary)
+ assert_equal(100, ary.size)
+ ary.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_to_hash
+ v = "0"
+ 100.times {v = v.next; @dbm[v] = v}
+
+ hash = @dbm.to_hash
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+ end
+
+ class TestDBM2 < Test::Unit::TestCase
+ def setup
+ @tmproot = Dir.mktmpdir('ruby-dbm')
+ end
+
+ def teardown
+ FileUtils.remove_entry_secure @tmproot if File.directory?(@tmproot)
+ end
+
+ def test_reader_open_notexist
+ assert_raise(Errno::ENOENT) {
+ DBM.open("#{@tmproot}/a", 0666, DBM::READER)
+ }
+ end
+
+ def test_writer_open_notexist
+ assert_raise(Errno::ENOENT) {
+ DBM.open("#{@tmproot}/a", 0666, DBM::WRITER)
+ }
+ end
+
+ def test_wrcreat_open_notexist
+ v = DBM.open("#{@tmproot}/a", 0666, DBM::WRCREAT)
+ assert_instance_of(DBM, v)
+ v.close
+ end
+
+ def test_newdb_open_notexist
+ v = DBM.open("#{@tmproot}/a", 0666, DBM::NEWDB)
+ assert_instance_of(DBM, v)
+ v.close
+ end
+
+ def test_reader_open
+ DBM.open("#{@tmproot}/a") {} # create a db.
+ v = DBM.open("#{@tmproot}/a", nil, DBM::READER) {|d|
+ # Errno::EPERM is raised on Solaris which use ndbm.
+ # DBMError is raised on Debian which use gdbm.
+ assert_raises(Errno::EPERM, DBMError) { d["k"] = "v" }
+ true
+ }
+ assert(v)
+ end
+
+ def test_newdb_open
+ DBM.open("#{@tmproot}/a") {|dbm|
+ dbm["k"] = "v"
+ }
+ v = DBM.open("#{@tmproot}/a", nil, DBM::NEWDB) {|d|
+ assert_equal(0, d.length)
+ assert_nil(d["k"])
+ true
+ }
+ assert(v)
+ end
+
+ def test_freeze
+ DBM.open("#{@tmproot}/a") {|d|
+ d.freeze
+ assert_raises(RuntimeError) { d["k"] = "v" }
+ }
+ end
+ end
+end
diff --git a/trunk/test/digest/test_digest.rb b/trunk/test/digest/test_digest.rb
new file mode 100644
index 0000000000..fa12086300
--- /dev/null
+++ b/trunk/test/digest/test_digest.rb
@@ -0,0 +1,120 @@
+#!/usr/bin/env ruby
+#
+# $RoughId: test.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
+# $Id$
+
+require 'test/unit'
+
+require 'digest'
+%w[digest/md5 digest/rmd160 digest/sha1 digest/sha2].each do |lib|
+ begin
+ require lib
+ rescue LoadError
+ end
+end
+
+module TestDigest
+ Data1 = "abc"
+ Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+
+ def test_s_hexdigest
+ self.class::DATA.each do |str, digest|
+ assert_equal(digest, self.class::ALGO.hexdigest(str))
+ end
+ end
+
+ def test_s_digest
+ self.class::DATA.each do |str, digest|
+ assert_equal([digest].pack("H*"), self.class::ALGO.digest(str))
+ end
+ end
+
+ def test_update
+ # This test is also for digest() and hexdigest()
+
+ str = "ABC"
+
+ md = self.class::ALGO.new
+ md.update str
+ assert_equal(self.class::ALGO.hexdigest(str), md.hexdigest)
+ assert_equal(self.class::ALGO.digest(str), md.digest)
+ end
+
+ def test_eq
+ # This test is also for clone()
+
+ md1 = self.class::ALGO.new
+ md1 << "ABC"
+
+ assert_equal(md1, md1.clone, self.class::ALGO)
+
+ md2 = self.class::ALGO.new
+ md2 << "A"
+
+ assert(md1 != md2, self.class::ALGO)
+
+ md2 << "BC"
+
+ assert_equal(md1, md2, self.class::ALGO)
+ end
+
+ def test_instance_eval
+ assert_nothing_raised {
+ self.class::ALGO.new.instance_eval { update "a" }
+ }
+ end
+
+ class TestMD5 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::MD5
+ DATA = {
+ Data1 => "900150983cd24fb0d6963f7d28e17f72",
+ Data2 => "8215ef0796a20bcaaae116d3876c664a",
+ }
+ end if defined?(Digest::MD5)
+
+ class TestSHA1 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::SHA1
+ DATA = {
+ Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d",
+ Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
+ }
+ end if defined?(Digest::SHA1)
+
+ class TestSHA256 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::SHA256
+ DATA = {
+ Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ }
+ end if defined?(Digest::SHA256)
+
+ class TestSHA384 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::SHA384
+ DATA = {
+ Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
+ Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b",
+ }
+ end if defined?(Digest::SHA384)
+
+ class TestSHA512 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::SHA512
+ DATA = {
+ Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
+ }
+ end if defined?(Digest::SHA512)
+
+ class TestRMD160 < Test::Unit::TestCase
+ include TestDigest
+ ALGO = Digest::RMD160
+ DATA = {
+ Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
+ Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
+ }
+ end if defined?(Digest::RMD160)
+end
diff --git a/trunk/test/digest/test_digest_hmac.rb b/trunk/test/digest/test_digest_hmac.rb
new file mode 100644
index 0000000000..a0d5d2f244
--- /dev/null
+++ b/trunk/test/digest/test_digest_hmac.rb
@@ -0,0 +1,3 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('../inlinetest.rb')
+InlineTest.loadtest__END__part('digest/hmac.rb')
diff --git a/trunk/test/drb/drbtest.rb b/trunk/test/drb/drbtest.rb
new file mode 100644
index 0000000000..143d856a1e
--- /dev/null
+++ b/trunk/test/drb/drbtest.rb
@@ -0,0 +1,352 @@
+require 'test/unit'
+require 'drb/drb'
+require 'drb/extservm'
+require 'timeout'
+begin
+ loadpath = $:.dup
+ $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
+ require 'envutil'
+ensure
+ $:.replace(loadpath)
+end
+
+class DRbService
+ @@manager = DRb::ExtServManager.new
+ @@ruby = EnvUtil.rubybin
+ @@ruby += " -d" if $DEBUG
+ def self.add_service_command(nm)
+ dir = File.dirname(File.expand_path(__FILE__))
+ DRb::ExtServManager.command[nm] = "\"#{@@ruby}\" \"#{dir}/#{nm}\""
+ end
+
+ %w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eval.rb).each do |nm|
+ add_service_command(nm)
+ end
+ @server = @@server = DRb::DRbServer.new('druby://localhost:0', @@manager, {})
+ @@manager.uri = @@server.uri
+ def self.manager
+ @@manager
+ end
+ def self.server
+ @server || @@server
+ end
+ def self.ext_service(name)
+ timeout(100, RuntimeError) do
+ manager.service(name)
+ end
+ end
+end
+
+class Onecky
+ include DRbUndumped
+ def initialize(n)
+ @num = n
+ end
+
+ def to_i
+ @num.to_i
+ end
+
+ def sleep(n)
+ Kernel.sleep(n)
+ to_i
+ end
+end
+
+class FailOnecky < Onecky
+ class OneckyError < RuntimeError; end
+ def to_i
+ raise(OneckyError, @num.to_s)
+ end
+end
+
+class XArray < Array
+ def initialize(ary)
+ ary.each do |x|
+ self.push(x)
+ end
+ end
+end
+
+module DRbCore
+ def setup
+ @ext = DRbService.ext_service('ut_drb.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ @ext.stop_service if @ext
+ end
+
+ def test_00_DRbObject
+ ro = DRbObject.new(nil, 'druby://localhost:12345')
+ assert_equal('druby://localhost:12345', ro.__drburi)
+ assert_equal(nil, ro.__drbref)
+
+ ro = DRbObject.new_with_uri('druby://localhost:12345')
+ assert_equal('druby://localhost:12345', ro.__drburi)
+ assert_equal(nil, ro.__drbref)
+
+ ro = DRbObject.new_with_uri('druby://localhost:12345?foobar')
+ assert_equal('druby://localhost:12345', ro.__drburi)
+ assert_equal(DRb::DRbURIOption.new('foobar'), ro.__drbref)
+ end
+
+ def test_01
+ assert_equal("hello", @there.hello)
+ onecky = Onecky.new('3')
+ assert_equal(6, @there.sample(onecky, 1, 2))
+ ary = @there.to_a
+ assert_kind_of(DRb::DRbObject, ary)
+
+ assert(@there.respond_to?(:to_a, true))
+ assert(@there.respond_to?(:eval, true))
+ assert(! @there.respond_to?(:eval, false))
+ assert(! @there.respond_to?(:eval))
+ end
+
+ def test_01_02_loop
+ onecky = Onecky.new('3')
+ 50.times do
+ assert_equal(6, @there.sample(onecky, 1, 2))
+ ary = @there.to_a
+ assert_kind_of(DRb::DRbObject, ary)
+ end
+ end
+
+ def test_02_unknown
+ obj = @there.unknown_class
+ assert_kind_of(DRb::DRbUnknown, obj)
+ assert_equal('Unknown2', obj.name)
+
+ obj = @there.unknown_module
+ assert_kind_of(DRb::DRbUnknown, obj)
+ if RUBY_VERSION >= '1.8'
+ assert_equal('DRbEx::', obj.name)
+ else
+ assert_equal('DRbEx', obj.name)
+ end
+
+ assert_raises(DRb::DRbUnknownError) do
+ @there.unknown_error
+ end
+
+ onecky = FailOnecky.new('3')
+
+ assert_raises(FailOnecky::OneckyError) do
+ @there.sample(onecky, 1, 2)
+ end
+ end
+
+ def test_03
+ assert_equal(8, @there.sum(1, 1, 1, 1, 1, 1, 1, 1))
+ assert_raises(ArgumentError) do
+ @there.sum(1, 1, 1, 1, 1, 1, 1, 1, 1)
+ end
+ assert_raises(DRb::DRbConnError) do
+ @there.sum('1' * 4096)
+ end
+ end
+
+ def test_04
+ assert_respond_to(@there, 'sum')
+ assert(!(@there.respond_to? "foobar"))
+ end
+
+ def test_05_eq
+ a = @there.to_a[0]
+ b = @there.to_a[0]
+ assert(a.object_id != b.object_id)
+ assert(a == b)
+ assert_equal(a, b)
+ assert(a == @there)
+ assert_equal(a.hash, b.hash)
+ assert_equal(a.hash, @there.hash)
+ assert(a.eql?(b))
+ assert(a.eql?(@there))
+ end
+
+ def test_06_timeout
+ ten = Onecky.new(10)
+ assert_raises(TimeoutError) do
+ @there.do_timeout(ten)
+ end
+ assert_raises(TimeoutError) do
+ @there.do_timeout(ten)
+ end
+ end
+
+ def test_07_public_private_protected_missing
+ assert_nothing_raised() {
+ begin
+ @there.method_missing(:eval, 'nil')
+ rescue NoMethodError
+ assert_match(/^private method \`eval\'/, $!.message)
+ end
+ }
+ assert_nothing_raised() {
+ begin
+ @there.call_private_method
+ rescue NoMethodError
+ assert_equal(NoMethodError, $!.class)
+ assert_match(/^private method \`call_private_method\'/, $!.message)
+ end
+ }
+ assert_nothing_raised() {
+ begin
+ @there.call_protected_method
+ rescue NoMethodError
+ assert_equal(NoMethodError, $!.class)
+ assert_match(/^protected method \`call_protected_method\'/, $!.message)
+ end
+ }
+ assert_nothing_raised() {
+ begin
+ @there.method_missing(:undefined_method_test)
+ rescue NoMethodError
+ assert_equal(NoMethodError, $!.class)
+ assert_match(/^undefined method \`undefined_method_test\'/, $!.message)
+ end
+ }
+ assert_raises(DRb::DRbConnError) do
+ @there.method_missing(:__send__, :to_s)
+ end
+ assert_equal(true, @there.missing)
+ end
+
+ def test_08_here
+ ro = DRbObject.new(nil, DRb.uri)
+ assert_kind_of(String, ro.to_s)
+
+ ro = DRbObject.new_with_uri(DRb.uri)
+ assert_kind_of(String, ro.to_s)
+ end
+
+ def uri_concat_option(uri, opt)
+ "#{uri}?#{opt}"
+ end
+
+ def test_09_option
+ uri = uri_concat_option(@there.__drburi, "foo")
+ ro = DRbObject.new_with_uri(uri)
+ assert_equal(ro.__drburi, @there.__drburi)
+ assert_equal(3, ro.size)
+
+ uri = uri_concat_option(@there.__drburi, "")
+ ro = DRbObject.new_with_uri(uri)
+ assert_equal(ro.__drburi, @there.__drburi)
+ assert_equal(DRb::DRbURIOption.new(''), ro.__drbref)
+
+ uri = uri_concat_option(@there.__drburi, "hello?world")
+ ro = DRbObject.new_with_uri(uri)
+ assert_equal(DRb::DRbURIOption.new('hello?world'), ro.__drbref)
+
+ uri = uri_concat_option(@there.__drburi, "?hello?world")
+ ro = DRbObject.new_with_uri(uri)
+ assert_equal(DRb::DRbURIOption.new('?hello?world'), ro.__drbref)
+ end
+
+ def test_10_yield
+ @there.simple_hash.each do |k, v|
+ assert_kind_of(String, k)
+ assert_kind_of(Symbol, v)
+ end
+ end
+
+ def test_10_yield_undumped
+ @there.xarray2_hash.each do |k, v|
+ assert_kind_of(String, k)
+ assert_kind_of(DRbObject, v)
+ end
+ end
+
+ def test_11_remote_no_method_error
+ assert_raises(DRb::DRbRemoteError) do
+ @there.remote_no_method_error
+ end
+ begin
+ @there.remote_no_method_error
+ rescue
+ error = $!
+ assert_match(/^undefined method .*\(NoMethodError\)/, error.message)
+ assert_equal('NoMethodError', error.reason)
+ end
+ end
+end
+
+module DRbAry
+ def setup
+ @ext = DRbService.ext_service('ut_array.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ @ext.stop_service if @ext
+ end
+
+ def test_01
+ assert_kind_of(DRb::DRbObject, @there)
+ end
+
+ def test_02_collect
+ ary = @there.collect do |x| x + x end
+ assert_kind_of(Array, ary)
+ assert_equal([2, 4, 'IIIIII', 8, 'fivefive', 12], ary)
+ end
+
+ def test_03_redo
+ ary = []
+ count = 0
+ @there.each do |x|
+ count += 1
+ ary.push x
+ redo if count == 3
+ end
+ assert_equal([1, 2, 'III', 'III', 4, 'five', 6], ary)
+ end
+
+ # retry in block is not supported on ruby 1.9
+ #def test_04_retry
+ # retried = false
+ # ary = []
+ # @there.each do |x|
+ # ary.push x
+ # if x == 4 && !retried
+ # retried = true
+ # retry
+ # end
+ # end
+ # assert_equal([1, 2, 'III', 4, 1, 2, 'III', 4, 'five', 6], ary)
+ #end
+
+ def test_05_break
+ ary = []
+ @there.each do |x|
+ ary.push x
+ break if x == 4
+ end
+ assert_equal([1, 2, 'III', 4], ary)
+ end
+
+ def test_06_next
+ ary = []
+ @there.each do |x|
+ next if String === x
+ ary.push x
+ end
+ assert_equal([1, 2, 4, 6], ary)
+ end
+
+ class_eval <<EOS
+ def test_07_break_18
+ ary = []
+ result = @there.each do |x|
+ ary.push x
+ break(:done) if x == 4
+ end
+ assert_equal([1, 2, 'III', 4], ary)
+ assert_equal(:done, result)
+ end
+EOS
+
+end
diff --git a/trunk/test/drb/ignore_test_drb.rb b/trunk/test/drb/ignore_test_drb.rb
new file mode 100644
index 0000000000..d0bb1f49b0
--- /dev/null
+++ b/trunk/test/drb/ignore_test_drb.rb
@@ -0,0 +1,24 @@
+require 'drbtest'
+
+class TestDRbReusePort < Test::Unit::TestCase
+ include DRbAry
+
+ def setup
+ @ext = DRbService.ext_service('ut_port.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ return unless @ext
+ @ext.stop_service
+ while true
+ sleep 0.1
+ begin
+ @ext.alive?
+ rescue DRb::DRbConnError
+ break
+ end
+ end
+ end
+end
+
diff --git a/trunk/test/drb/test_acl.rb b/trunk/test/drb/test_acl.rb
new file mode 100644
index 0000000000..d8955e0e75
--- /dev/null
+++ b/trunk/test/drb/test_acl.rb
@@ -0,0 +1,195 @@
+# acltest.rb - ACL unit test
+# Copyright (c) 2000 Masatoshi SEKI
+#
+# acltest.rb is copyrighted free software by Masatoshi SEKI.
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+require 'test/unit'
+require 'drb/acl'
+
+class SampleHosts
+ def initialize
+ list = %w(127.0.0.1 localhost
+ 192.168.1.1 x68k.linux.or.jp
+ 192.168.1.2 lc630.macos.or.jp
+ 192.168.1.3 lib30.win32.or.jp
+ 192.168.1.4 ns00.linux.or.jp
+ 192.168.1.5 yum.macos.or.jp
+ ::ffff:192.168.1.5 ipv6.macos.or.jp
+ ::192.168.1.5 too.yumipv6.macos.or.jp
+ 192.168.1.254 comstarz.foo.or.jp)
+
+ @hostlist = Array.new(list.size / 2)
+ @hostlist.each_index do |idx|
+ @hostlist[idx] = ["AF_INET", 10000, list[idx * 2 + 1], list[idx * 2]]
+ end
+
+ @hosts = Hash.new
+ @hostlist.each do |h|
+ @hosts[h[2].split('.')[0]] = h
+ end
+ end
+ attr_reader(:hostlist, :hosts)
+end
+
+
+class ACLEntryTest < Test::Unit::TestCase
+ HOSTS = SampleHosts.new
+
+ def setup
+ @hostlist = HOSTS.hostlist
+ @hosts = HOSTS.hosts
+ end
+
+ def test_all
+ a = ACL::ACLEntry.new("*")
+ b = ACL::ACLEntry.new("all")
+ @hostlist.each do |h|
+ assert(a.match(h))
+ assert(b.match(h))
+ end
+ end
+
+ def test_ip_v6
+ a = ACL::ACLEntry.new('::ffff:192.0.0.0/104')
+ assert(! a.match(@hosts['localhost']))
+ assert(a.match(@hosts['yum']))
+ assert(a.match(@hosts['ipv6']))
+ assert(! a.match(@hosts['too']))
+ end
+
+ def test_ip
+ a = ACL::ACLEntry.new('192.0.0.0/8')
+ assert(! a.match(@hosts['localhost']))
+ assert(a.match(@hosts['yum']))
+
+ a = ACL::ACLEntry.new('192.168.0.1/255.255.0.255')
+ assert(! a.match(@hosts['localhost']))
+ assert(! a.match(@hosts['yum']))
+ assert(a.match(@hosts['x68k']))
+
+ a = ACL::ACLEntry.new('192.168.1.0/24')
+ assert(! a.match(@hosts['localhost']))
+ assert(a.match(@hosts['yum']))
+ assert(a.match(@hosts['x68k']))
+
+ a = ACL::ACLEntry.new('92.0.0.0/8')
+ assert(! a.match(@hosts['localhost']))
+ assert(! a.match(@hosts['yum']))
+ assert(! a.match(@hosts['x68k']))
+
+ a = ACL::ACLEntry.new('127.0.0.1/255.0.0.255')
+ assert(a.match(@hosts['localhost']))
+ assert(! a.match(@hosts['yum']))
+ assert(! a.match(@hosts['x68k']))
+ end
+
+ def test_name
+ a = ACL::ACLEntry.new('*.jp')
+ assert(! a.match(@hosts['localhost']))
+ assert(a.match(@hosts['yum']))
+
+ a = ACL::ACLEntry.new('yum.*.jp')
+ assert(a.match(@hosts['yum']))
+ assert(! a.match(@hosts['lc630']))
+
+ a = ACL::ACLEntry.new('*.macos.or.jp')
+ assert(a.match(@hosts['yum']))
+ assert(a.match(@hosts['lc630']))
+ assert(! a.match(@hosts['lib30']))
+ end
+end
+
+class ACLListTest < Test::Unit::TestCase
+ HOSTS = SampleHosts.new
+
+ def setup
+ @hostlist = HOSTS.hostlist
+ @hosts = HOSTS.hosts
+ end
+
+ private
+ def build(list)
+ acl= ACL::ACLList.new
+ list.each do |s|
+ acl.add s
+ end
+ acl
+ end
+
+ public
+ def test_all_1
+ a = build(%w(all))
+ @hostlist.each do |h|
+ assert(a.match(h))
+ end
+ end
+
+ def test_all_2
+ a = build(%w(localhost 127.0.0.0/8 yum.* *))
+ @hostlist.each do |h|
+ assert(a.match(h))
+ end
+ end
+
+ def test_1
+ a = build(%w(192.0.0.1/255.0.0.255 yum.*.jp))
+ assert(a.match(@hosts['yum']))
+ assert(a.match(@hosts['x68k']))
+ assert(! a.match(@hosts['lc630']))
+ end
+
+ def test_2
+ a = build(%w(*.linux.or.jp))
+ assert(!a.match(@hosts['yum']))
+ assert(a.match(@hosts['x68k']))
+ assert(!a.match(@hosts['lc630']))
+ end
+end
+
+class ACLTest < Test::Unit::TestCase
+ HOSTS = SampleHosts.new
+
+ def setup
+ @hostlist = HOSTS.hostlist
+ @hosts = HOSTS.hosts
+ end
+
+ def test_0
+ a = ACL.new
+ @hostlist.each do |h|
+ assert(a.allow_addr?(h))
+ end
+ end
+
+ def test_not_0
+ a = ACL.new([], ACL::ALLOW_DENY)
+ @hostlist.each do |h|
+ assert(! a.allow_addr?(h))
+ end
+ end
+
+ def test_1
+ data = %w(deny all
+ allow localhost
+ allow x68k.*)
+
+ a = ACL.new(data)
+ assert(a.allow_addr?(@hosts['x68k']))
+ assert(a.allow_addr?(@hosts['localhost']))
+ assert(! a.allow_addr?(@hosts['lc630']))
+ end
+
+ def test_not_1
+ data = %w(deny 192.0.0.0/8
+ allow localhost
+ allow x68k.*)
+
+ a = ACL.new(data, ACL::ALLOW_DENY)
+ assert(!a.allow_addr?(@hosts['x68k']))
+ assert(a.allow_addr?(@hosts['localhost']))
+ assert(! a.allow_addr?(@hosts['lc630']))
+ end
+end
+
+
diff --git a/trunk/test/drb/test_drb.rb b/trunk/test/drb/test_drb.rb
new file mode 100644
index 0000000000..106e958d9a
--- /dev/null
+++ b/trunk/test/drb/test_drb.rb
@@ -0,0 +1,301 @@
+require 'drbtest'
+
+class TestDRbCore < Test::Unit::TestCase
+ include DRbCore
+end
+
+class TestDRbYield < Test::Unit::TestCase
+ def setup
+ @ext = DRbService.ext_service('ut_drb.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ @ext.stop_service if @ext
+ end
+
+ def test_01_one
+ @there.echo_yield_1([]) {|one|
+ assert_equal([], one)
+ }
+
+ @there.echo_yield_1(1) {|one|
+ assert_equal(1, one)
+ }
+
+ @there.echo_yield_1(nil) {|one|
+ assert_equal(nil, one)
+ }
+ end
+
+ def test_02_two
+ @there.echo_yield_2([], []) {|one, two|
+ assert_equal([], one)
+ assert_equal([], two)
+ }
+
+ @there.echo_yield_2(1, 2) {|one, two|
+ assert_equal(1, one)
+ assert_equal(2, two)
+ }
+
+ @there.echo_yield_2(3, nil) {|one, two|
+ assert_equal(3, one)
+ assert_equal(nil, two)
+ }
+
+ @there.echo_yield_1([:key, :value]) {|one, two|
+ assert_equal(:key, one)
+ assert_equal(:value, two)
+ }
+ end
+
+ def test_03_many
+ @there.echo_yield_0 {|*s|
+ assert_equal([], s)
+ }
+ @there.echo_yield(nil) {|*s|
+ assert_equal([nil], s)
+ }
+ @there.echo_yield(1) {|*s|
+ assert_equal([1], s)
+ }
+ @there.echo_yield(1, 2) {|*s|
+ assert_equal([1, 2], s)
+ }
+ @there.echo_yield(1, 2, 3) {|*s|
+ assert_equal([1, 2, 3], s)
+ }
+ @there.echo_yield([], []) {|*s|
+ assert_equal([[], []], s)
+ }
+ @there.echo_yield([]) {|*s|
+ assert_equal([[]], s) # !
+ }
+ end
+
+ def test_04_many_to_one
+ @there.echo_yield_0 {|*s|
+ assert_equal([], s)
+ }
+ @there.echo_yield(nil) {|*s|
+ assert_equal([nil], s)
+ }
+ @there.echo_yield(1) {|*s|
+ assert_equal([1], s)
+ }
+ @there.echo_yield(1, 2) {|*s|
+ assert_equal([1, 2], s)
+ }
+ @there.echo_yield(1, 2, 3) {|*s|
+ assert_equal([1, 2, 3], s)
+ }
+ @there.echo_yield([], []) {|*s|
+ assert_equal([[], []], s)
+ }
+ @there.echo_yield([]) {|*s|
+ assert_equal([[]], s)
+ }
+ end
+
+ def test_05_array_subclass
+ @there.xarray_each {|x| assert_kind_of(XArray, x)}
+ @there.xarray_each {|*x| assert_kind_of(XArray, x[0])}
+ end
+
+ def test_06_taint
+ x = proc {}
+ assert(! x.tainted?)
+ @there.echo_yield(x) {|o|
+ assert_equal(x, o)
+ assert(! x.tainted?)
+ }
+ end
+end
+
+class TestDRbRubyYield < TestDRbYield
+ def echo_yield(*arg)
+ yield(*arg)
+ end
+
+ def echo_yield_0
+ yield
+ end
+
+ def echo_yield_1(a)
+ yield(a)
+ end
+
+ def echo_yield_2(a, b)
+ yield(a, b)
+ end
+
+ def xarray_each
+ xary = [XArray.new([0])]
+ xary.each do |x|
+ yield(x)
+ end
+ end
+
+ def setup
+ @there = self
+ end
+
+ def teardown
+ end
+end
+
+class TestDRbRuby18Yield < TestDRbRubyYield
+ class YieldTest18
+ def echo_yield(*arg, &proc)
+ proc.call(*arg)
+ end
+
+ def echo_yield_0(&proc)
+ proc.call
+ end
+
+ def echo_yield_1(a, &proc)
+ proc.call(a)
+ end
+
+ def echo_yield_2(a, b, &proc)
+ proc.call(a, b)
+ end
+
+ def xarray_each(&proc)
+ xary = [XArray.new([0])]
+ xary.each(&proc)
+ end
+
+ end
+
+ def setup
+ @there = YieldTest18.new
+ end
+end
+
+class TestDRbAry < Test::Unit::TestCase
+ include DRbAry
+end
+
+class TestDRbMServer < Test::Unit::TestCase
+ def setup
+ @ext = DRbService.ext_service('ut_drb.rb')
+ @there = @ext.front
+ @server = (1..3).collect do |n|
+ DRb::DRbServer.new(nil, Onecky.new(n.to_s))
+ end
+ end
+
+ def teardown
+ @server.each do |s|
+ s.stop_service
+ end
+ @ext.stop_service if @ext
+ end
+
+ def test_01
+ assert_equal(6, @there.sample(@server[0].front, @server[1].front, @server[2].front))
+ end
+end
+
+class TestDRbSafe1 < TestDRbAry
+ def setup
+ @ext = DRbService.ext_service('ut_safe1.rb')
+ @there = @ext.front
+ end
+end
+
+class TestDRbEval # < Test::Unit::TestCase
+ def setup
+ super
+ @ext = DRbService.ext_service('ut_eval.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ @ext.stop_service if @ext
+ end
+
+ def test_01_safe1_safe4_eval
+ assert_raises(SecurityError) do
+ @there.method_missing(:instance_eval, 'ENV.inspect')
+ end
+
+ assert_raises(SecurityError) do
+ @there.method_missing(:send, :eval, 'ENV.inspect')
+ end
+
+ remote_class = @there.remote_class
+
+ assert_raises(SecurityError) do
+ remote_class.class_eval('ENV.inspect')
+ end
+
+ assert_raises(SecurityError) do
+ remote_class.module_eval('ENV.inspect')
+ end
+
+ four = @there.four
+ assert_equal(1, four.method_missing(:send, :eval, '1'))
+
+ remote_class = four.remote_class
+
+ assert_equal(1, remote_class.class_eval('1'))
+
+ assert_equal(1, remote_class.module_eval('1'))
+
+ assert_raises(SecurityError) do
+ remote_class.class_eval('ENV = {}')
+ end
+
+ assert_raises(SecurityError) do
+ remote_class.module_eval('ENV = {}')
+ end
+ end
+end
+
+class TestDRbLarge < Test::Unit::TestCase
+ def setup
+ @ext = DRbService.ext_service('ut_large.rb')
+ @there = @ext.front
+ end
+
+ def teardown
+ @ext.stop_service if @ext
+ end
+
+ def test_01_large_ary
+ ary = [2] * 10240
+ assert_equal(10240, @there.size(ary))
+ assert_equal(20480, @there.sum(ary))
+ end
+
+ def test_02_large_ary
+ ary = ["Hello, World"] * 10240
+ assert_equal(10240, @there.size(ary))
+ end
+
+ def test_03_large_ary
+ ary = [Thread.current] * 10240
+ assert_equal(10240, @there.size(ary))
+ end
+
+ def test_04_many_arg
+ assert_raises(ArgumentError) {
+ @there.arg_test(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
+ }
+ end
+
+ def test_05_too_large_ary
+ ary = ["Hello, World"] * 102400
+ exception = nil
+ begin
+ @there.size(ary)
+ rescue StandardError
+ exception = $!
+ end
+ assert_kind_of(StandardError, exception)
+ end
+end
diff --git a/trunk/test/drb/test_drbssl.rb b/trunk/test/drb/test_drbssl.rb
new file mode 100644
index 0000000000..cfb3bc36a4
--- /dev/null
+++ b/trunk/test/drb/test_drbssl.rb
@@ -0,0 +1,62 @@
+require 'drbtest'
+
+begin
+ require 'drb/ssl'
+rescue LoadError
+end
+
+if Object.const_defined?("OpenSSL")
+
+
+class DRbSSLService < DRbService
+ %w(ut_drb_drbssl.rb ut_array_drbssl.rb).each do |nm|
+ add_service_command(nm)
+ end
+ config = Hash.new
+
+ config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
+ config[:SSLVerifyCallback] = lambda{ |ok,x509_store|
+ true
+ }
+ begin
+ data = open("sample.key"){|io| io.read }
+ config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(data)
+ data = open("sample.crt"){|io| io.read }
+ config[:SSLCertificate] = OpenSSL::X509::Certificate.new(data)
+ rescue
+ # $stderr.puts "Switching to use self-signed certificate"
+ config[:SSLCertName] =
+ [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ]
+ end
+
+ uri = ARGV.shift if $0 == __FILE__
+ @server = DRb::DRbServer.new(uri || 'drbssl://:0', self.manager, config)
+end
+
+class TestDRbSSLCore < Test::Unit::TestCase
+ include DRbCore
+ def setup
+ @ext = DRbSSLService.ext_service('ut_drb_drbssl.rb')
+ @there = @ext.front
+ end
+
+ def test_02_unknown
+ end
+
+ def test_01_02_loop
+ end
+
+ def test_05_eq
+ end
+end
+
+class TestDRbSSLAry < Test::Unit::TestCase
+ include DRbAry
+ def setup
+ @ext = DRbSSLService.ext_service('ut_array_drbssl.rb')
+ @there = @ext.front
+ end
+end
+
+
+end
diff --git a/trunk/test/drb/test_drbunix.rb b/trunk/test/drb/test_drbunix.rb
new file mode 100644
index 0000000000..e1a17edd3d
--- /dev/null
+++ b/trunk/test/drb/test_drbunix.rb
@@ -0,0 +1,46 @@
+require 'drbtest'
+
+begin
+ require 'drb/unix'
+rescue LoadError
+end
+
+if Object.const_defined?("UNIXServer")
+
+
+class DRbUNIXService < DRbService
+ %w(ut_drb_drbunix.rb ut_array_drbunix.rb).each do |nm|
+ add_service_command(nm)
+ end
+
+ uri = ARGV.shift if $0 == __FILE__
+ @server = DRb::DRbServer.new(uri || 'drbunix:', self.manager, {})
+end
+
+class TestDRbUNIXCore < Test::Unit::TestCase
+ include DRbCore
+ def setup
+ @ext = DRbUNIXService.ext_service('ut_drb_drbunix.rb')
+ @there = @ext.front
+ end
+
+ def test_02_unknown
+ end
+
+ def test_01_02_loop
+ end
+
+ def test_05_eq
+ end
+end
+
+class TestDRbUNIXAry < Test::Unit::TestCase
+ include DRbAry
+ def setup
+ @ext = DRbUNIXService.ext_service('ut_array_drbunix.rb')
+ @there = @ext.front
+ end
+end
+
+
+end
diff --git a/trunk/test/drb/ut_array.rb b/trunk/test/drb/ut_array.rb
new file mode 100644
index 0000000000..6d9778ffbc
--- /dev/null
+++ b/trunk/test/drb/ut_array.rb
@@ -0,0 +1,15 @@
+require 'drb/drb'
+require 'drb/extserv'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ DRb.start_service(nil, [1, 2, 'III', 4, "five", 6])
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_array_drbssl.rb b/trunk/test/drb/ut_array_drbssl.rb
new file mode 100644
index 0000000000..5644af5600
--- /dev/null
+++ b/trunk/test/drb/ut_array_drbssl.rb
@@ -0,0 +1,24 @@
+require 'drb/drb'
+require 'drb/extserv'
+require 'drb/ssl'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ config = Hash.new
+ config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
+ config[:SSLVerifyCallback] = lambda{|ok,x509_store|
+ true
+ }
+ config[:SSLCertName] =
+ [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ]
+
+ DRb.start_service('drbssl://:0', [1, 2, 'III', 4, "five", 6], config)
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_array_drbunix.rb b/trunk/test/drb/ut_array_drbunix.rb
new file mode 100644
index 0000000000..76d2a610af
--- /dev/null
+++ b/trunk/test/drb/ut_array_drbunix.rb
@@ -0,0 +1,15 @@
+require 'drb/drb'
+require 'drb/extserv'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ DRb.start_service('drbunix:', [1, 2, 'III', 4, "five", 6])
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_drb.rb b/trunk/test/drb/ut_drb.rb
new file mode 100644
index 0000000000..f5720cfca2
--- /dev/null
+++ b/trunk/test/drb/ut_drb.rb
@@ -0,0 +1,160 @@
+require 'drb/drb'
+require 'drb/extserv'
+require 'timeout'
+
+class XArray < Array
+ def initialize(ary)
+ ary.each do |x|
+ self.push(x)
+ end
+ end
+end
+
+class XArray2 < XArray
+ include DRbUndumped
+end
+
+class Unknown2
+ def initialize
+ @foo = 'unknown2'
+ end
+end
+
+class DRbEx
+ include DRbUndumped
+
+ class FooBar
+ def initialize
+ @foo = 'bar'
+ end
+ end
+
+ class UError < RuntimeError; end
+
+ def initialize
+ @hello = 'hello'
+ end
+ attr_reader :hello
+
+ def sample(a, b, c)
+ a.to_i + b.to_i + c.to_i
+ end
+
+ def sum(*a)
+ s = 0
+ a.each do |e|
+ s += e.to_i
+ end
+ s
+ end
+
+ def do_timeout(n)
+ timeout(0.1) do
+ n.sleep(2)
+ end
+ end
+
+ def unknown_module
+ FooBar.new
+ end
+
+ def unknown_class
+ Unknown2.new
+ end
+
+ def unknown_error
+ raise UError
+ end
+
+ def remote_no_method_error
+ invoke_no_method(self)
+ end
+
+ def test_yield
+ yield
+ yield([])
+ yield(*[])
+ end
+
+ def echo_yield(*arg)
+ yield(*arg)
+ nil
+ end
+
+ def echo_yield_0
+ yield
+ nil
+ end
+
+ def echo_yield_1(one)
+ yield(one)
+ nil
+ end
+
+ def echo_yield_2(one, two)
+ yield(one, two)
+ nil
+ end
+
+ def xarray_each
+ xary = [XArray.new([0])]
+ xary.each do |x|
+ yield(x)
+ end
+ nil
+ end
+
+ def xarray2_hash
+ unless @xary2_hash
+ @xary2_hash = { "a" => XArray2.new([0]), "b" => XArray2.new([1]) }
+ end
+ DRbObject.new(@xary2_hash)
+ end
+
+ def simple_hash
+ unless @hash
+ @hash = { 'a'=>:a, 'b'=>:b }
+ end
+ DRbObject.new(@hash)
+ end
+
+ def [](key)
+ key.to_s
+ end
+
+ def to_a
+ [self]
+ end
+
+ def method_missing(msg, *a, &b)
+ if msg == :missing
+ return true
+ else
+ super(msg, *a, &b)
+ end
+ end
+
+ private
+ def call_private_method
+ true
+ end
+
+ protected
+ def call_protected_method
+ true
+ end
+end
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <manager-uri> <name>" unless it
+ it
+ end
+
+ DRb::DRbServer.default_argc_limit(8)
+ DRb::DRbServer.default_load_limit(4096)
+ DRb.start_service('druby://localhost:0', DRbEx.new)
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
diff --git a/trunk/test/drb/ut_drb_drbssl.rb b/trunk/test/drb/ut_drb_drbssl.rb
new file mode 100644
index 0000000000..0a2191e71a
--- /dev/null
+++ b/trunk/test/drb/ut_drb_drbssl.rb
@@ -0,0 +1,25 @@
+require "#{File.dirname(File.expand_path(__FILE__))}/ut_drb"
+require 'drb/ssl'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <manager-uri> <name>" unless it
+ it
+ end
+
+ config = Hash.new
+ config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
+ config[:SSLVerifyCallback] = lambda{|ok,x509_store|
+ true
+ }
+ config[:SSLCertName] =
+ [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ]
+
+ DRb::DRbServer.default_argc_limit(8)
+ DRb::DRbServer.default_load_limit(4096)
+ DRb.start_service('drbssl://localhost:0', DRbEx.new, config)
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_drb_drbunix.rb b/trunk/test/drb/ut_drb_drbunix.rb
new file mode 100644
index 0000000000..8b9484cf9c
--- /dev/null
+++ b/trunk/test/drb/ut_drb_drbunix.rb
@@ -0,0 +1,16 @@
+require "#{File.dirname(File.expand_path(__FILE__))}/ut_drb"
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <manager-uri> <name>" unless it
+ it
+ end
+
+ DRb::DRbServer.default_argc_limit(8)
+ DRb::DRbServer.default_load_limit(4096)
+ DRb.start_service('drbunix:', DRbEx.new)
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_eval.rb b/trunk/test/drb/ut_eval.rb
new file mode 100644
index 0000000000..4df963e7cd
--- /dev/null
+++ b/trunk/test/drb/ut_eval.rb
@@ -0,0 +1,31 @@
+require 'drb/drb'
+require 'drb/extserv'
+
+class EvalAttack
+ def initialize
+ @four = DRb::DRbServer.new('druby://localhost:0', self, {:safe_level => 4})
+ end
+
+ def four
+ DRbObject.new_with_uri(@four.uri)
+ end
+
+ def remote_class
+ DRbObject.new(self.class)
+ end
+end
+
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ $SAFE = 1
+
+ DRb.start_service('druby://localhost:0', EvalAttack.new, {:safe_level => 2})
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
diff --git a/trunk/test/drb/ut_large.rb b/trunk/test/drb/ut_large.rb
new file mode 100644
index 0000000000..d6717c5589
--- /dev/null
+++ b/trunk/test/drb/ut_large.rb
@@ -0,0 +1,38 @@
+require 'drb/drb'
+require 'drb/extserv'
+require 'timeout'
+
+class DRbLarge
+ include DRbUndumped
+
+ def size(ary)
+ ary.size
+ end
+
+ def sum(ary)
+ sum = 0
+ ary.each do |e|
+ sum += e.to_i
+ end
+ sum
+ end
+
+ def arg_test(*arg)
+ # nop
+ end
+end
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <manager-uri> <name>" unless it
+ it
+ end
+
+ DRb::DRbServer.default_argc_limit(3)
+ DRb::DRbServer.default_load_limit(100000)
+ DRb.start_service('druby://localhost:0', DRbLarge.new)
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
+
diff --git a/trunk/test/drb/ut_port.rb b/trunk/test/drb/ut_port.rb
new file mode 100644
index 0000000000..337e0eda86
--- /dev/null
+++ b/trunk/test/drb/ut_port.rb
@@ -0,0 +1,14 @@
+require 'drb/drb'
+require 'drb/extserv'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ DRb.start_service('druby://:8473', [1, 2, 'III', 4, "five", 6])
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
diff --git a/trunk/test/drb/ut_safe1.rb b/trunk/test/drb/ut_safe1.rb
new file mode 100644
index 0000000000..4df8e1e5a1
--- /dev/null
+++ b/trunk/test/drb/ut_safe1.rb
@@ -0,0 +1,15 @@
+require 'drb/drb'
+require 'drb/extserv'
+
+if __FILE__ == $0
+ def ARGV.shift
+ it = super()
+ raise "usage: #{$0} <uri> <name>" unless it
+ it
+ end
+
+ DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6],
+ {:safe_level => 1})
+ es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
+ DRb.thread.join
+end
diff --git a/trunk/test/drb/ut_timerholder.rb b/trunk/test/drb/ut_timerholder.rb
new file mode 100644
index 0000000000..141cb73302
--- /dev/null
+++ b/trunk/test/drb/ut_timerholder.rb
@@ -0,0 +1,49 @@
+require 'runit/testcase'
+require 'runit/cui/testrunner'
+require 'timerholder'
+
+class TimerHolderTest < RUNIT::TestCase
+ def do_test(timeout, keeper_sleep = nil)
+ holder = TimerHolder.new(timeout)
+ holder.keeper_sleep = keeper_sleep if keeper_sleep
+ key = holder.add(self)
+ sleep(timeout * 0.5)
+ assert_equal(holder.peek(key), self)
+ holder.delete(key)
+ assert(!holder.include?(key))
+ key = holder.add(self)
+ sleep(timeout+0.5)
+ assert_equal(holder.fetch(key), nil)
+ key = holder.add(self)
+ assert_equal(holder.fetch(key), self)
+ holder.store(key, true)
+ assert_equal(holder.fetch(key), true)
+ assert_equal(holder.include?(key), true)
+ sleep(timeout+0.5)
+ assert_exception(TimerHolder::InvalidIndexError) do
+ holder.store(key, 1)
+ end
+ assert_equal(holder.include?(key), false)
+ key = holder.add(self)
+ sleep(timeout * 0.5)
+ assert(holder.include?(key))
+ holder.extend(key, timeout)
+ sleep(timeout * 0.5)
+ assert(holder.include?(key))
+ sleep(timeout * 0.6)
+ assert(!holder.include?(key))
+ holder.delete(key)
+ end
+
+ def test_00
+ do_test(0.5)
+ end
+
+ def test_01
+ do_test(1, 0.5)
+ end
+end
+
+if __FILE__ == $0
+ RUNIT::CUI::TestRunner.run(TimerHolderTest.suite)
+end
diff --git a/trunk/test/erb/hello.erb b/trunk/test/erb/hello.erb
new file mode 100644
index 0000000000..d5ebcb73b9
--- /dev/null
+++ b/trunk/test/erb/hello.erb
@@ -0,0 +1,4 @@
+= hello
+<% 3.times do |n| %>
+* <%= n %>
+<% end %>
diff --git a/trunk/test/erb/test_erb.rb b/trunk/test/erb/test_erb.rb
new file mode 100644
index 0000000000..8a6221b517
--- /dev/null
+++ b/trunk/test/erb/test_erb.rb
@@ -0,0 +1,446 @@
+require 'test/unit'
+require 'erb'
+
+class TestERB < Test::Unit::TestCase
+ class MyError < RuntimeError ; end
+
+ def test_without_filename
+ erb = ERB.new("<% raise ::TestERB::MyError %>")
+ e = assert_raise(MyError) {
+ erb.result
+ }
+ assert_match(/\A\(erb\):1\b/, e.backtrace[0])
+ end
+
+ def test_with_filename
+ erb = ERB.new("<% raise ::TestERB::MyError %>")
+ erb.filename = "test filename"
+ e = assert_raise(MyError) {
+ erb.result
+ }
+ assert_match(/\Atest filename:1\b/, e.backtrace[0])
+ end
+
+ def test_without_filename_with_safe_level
+ erb = ERB.new("<% raise ::TestERB::MyError %>", 1)
+ e = assert_raise(MyError) {
+ erb.result
+ }
+ assert_match(/\A\(erb\):1\b/, e.backtrace[0])
+ end
+
+ def test_with_filename_and_safe_level
+ erb = ERB.new("<% raise ::TestERB::MyError %>", 1)
+ erb.filename = "test filename"
+ e = assert_raise(MyError) {
+ erb.result
+ }
+ assert_match(/\Atest filename:1\b/, e.backtrace[0])
+ end
+end
+
+class TestERBCore < Test::Unit::TestCase
+ def setup
+ @erb = ERB
+ end
+
+ def test_core
+ _test_core(nil)
+ _test_core(0)
+ _test_core(1)
+ _test_core(2)
+ _test_core(3)
+ end
+
+ def _test_core(safe)
+ erb = @erb.new("hello")
+ assert_equal("hello", erb.result)
+
+ erb = @erb.new("hello", safe, 0)
+ assert_equal("hello", erb.result)
+
+ erb = @erb.new("hello", safe, 1)
+ assert_equal("hello", erb.result)
+
+ erb = @erb.new("hello", safe, 2)
+ assert_equal("hello", erb.result)
+
+ src = <<EOS
+%% hi
+= hello
+<% 3.times do |n| %>
+% n=0
+* <%= n %>
+<% end %>
+EOS
+
+ ans = <<EOS
+%% hi
+= hello
+
+% n=0
+* 0
+
+% n=0
+* 1
+
+% n=0
+* 2
+
+EOS
+ erb = @erb.new(src)
+ assert_equal(ans, erb.result)
+ erb = @erb.new(src, safe, 0)
+ assert_equal(ans, erb.result)
+ erb = @erb.new(src, safe, '')
+ assert_equal(ans, erb.result)
+
+ ans = <<EOS
+%% hi
+= hello
+% n=0
+* 0% n=0
+* 1% n=0
+* 2
+EOS
+ erb = @erb.new(src, safe, 1)
+ assert_equal(ans.chomp, erb.result)
+ erb = @erb.new(src, safe, '>')
+ assert_equal(ans.chomp, erb.result)
+
+ ans = <<EOS
+%% hi
+= hello
+% n=0
+* 0
+% n=0
+* 1
+% n=0
+* 2
+EOS
+
+ erb = @erb.new(src, safe, 2)
+ assert_equal(ans, erb.result)
+ erb = @erb.new(src, safe, '<>')
+ assert_equal(ans, erb.result)
+
+ ans = <<EOS
+% hi
+= hello
+
+* 0
+
+* 0
+
+* 0
+
+EOS
+ erb = @erb.new(src, safe, '%')
+ assert_equal(ans, erb.result)
+
+ ans = <<EOS
+% hi
+= hello
+* 0* 0* 0
+EOS
+ erb = @erb.new(src, safe, '%>')
+ assert_equal(ans.chomp, erb.result)
+
+ ans = <<EOS
+% hi
+= hello
+* 0
+* 0
+* 0
+EOS
+ erb = @erb.new(src, safe, '%<>')
+ assert_equal(ans, erb.result)
+ end
+
+ def test_safe_04
+ erb = @erb.new('<%=$SAFE%>', 4)
+ assert_equal('4', erb.result(TOPLEVEL_BINDING.taint))
+ end
+
+ class Foo; end
+
+ def test_def_class
+ erb = @erb.new('hello')
+ cls = erb.def_class
+ assert_equal(Object, cls.superclass)
+ assert(cls.new.respond_to?('result'))
+ cls = erb.def_class(Foo)
+ assert_equal(Foo, cls.superclass)
+ assert(cls.new.respond_to?('result'))
+ cls = erb.def_class(Object, 'erb')
+ assert_equal(Object, cls.superclass)
+ assert(cls.new.respond_to?('erb'))
+ end
+
+ def test_percent
+ src = <<EOS
+%n = 1
+<%= n%>
+EOS
+ assert_equal("1\n", ERB.new(src, nil, '%').result)
+
+ src = <<EOS
+<%
+%>
+EOS
+ ans = "\n"
+ assert_equal(ans, ERB.new(src, nil, '%').result)
+
+ src = "<%\n%>"
+ # ans = "\n"
+ ans = ""
+ assert_equal(ans, ERB.new(src, nil, '%').result)
+
+ src = <<EOS
+<%
+n = 1
+%><%= n%>
+EOS
+ assert_equal("1\n", ERB.new(src, nil, '%').result)
+
+ src = <<EOS
+%n = 1
+%% <% n = 2
+n.times do |i|%>
+%% %%><%%<%= i%><%
+end%>
+EOS
+ ans = <<EOS
+%
+% %%><%0
+% %%><%1
+EOS
+ assert_equal(ans, ERB.new(src, nil, '%').result)
+ end
+
+ class Bar; end
+
+ def test_def_erb_method
+ assert(! Bar.new.respond_to?('hello'))
+ Bar.module_eval do
+ extend ERB::DefMethod
+ fname = File.join(File.dirname(File.expand_path(__FILE__)), 'hello.erb')
+ def_erb_method('hello', fname)
+ end
+ assert(Bar.new.respond_to?('hello'))
+
+ assert(! Bar.new.respond_to?('hello_world'))
+ erb = @erb.new('hello, world')
+ Bar.module_eval do
+ def_erb_method('hello_world', erb)
+ end
+ assert(Bar.new.respond_to?('hello_world'))
+ end
+
+ class DefMethodWithoutFname; end
+ class DefMethodWithFname; end
+
+ def test_def_method_without_filename
+ erb = ERB.new("<% raise ::TestERB::MyError %>")
+ erb.filename = "test filename"
+ assert(! DefMethodWithoutFname.new.respond_to?('my_error'))
+ erb.def_method(DefMethodWithoutFname, 'my_error')
+ e = assert_raise(::TestERB::MyError) {
+ DefMethodWithoutFname.new.my_error
+ }
+ assert_match(/\A\(ERB\):1\b/, e.backtrace[0])
+ end
+
+ def test_def_method_with_fname
+ erb = ERB.new("<% raise ::TestERB::MyError %>")
+ erb.filename = "test filename"
+ assert(! DefMethodWithFname.new.respond_to?('my_error'))
+ erb.def_method(DefMethodWithFname, 'my_error', 'test fname')
+ e = assert_raise(::TestERB::MyError) {
+ DefMethodWithFname.new.my_error
+ }
+ assert_match(/\Atest fname:1\b/, e.backtrace[0])
+ end
+
+ def test_escape
+ src = <<EOS
+1.<%% : <%="<%%"%>
+2.%%> : <%="%%>"%>
+3.
+% x = "foo"
+<%=x%>
+4.
+%% print "foo"
+5.
+%% <%="foo"%>
+6.<%="
+% print 'foo'
+"%>
+7.<%="
+%% print 'foo'
+"%>
+EOS
+ ans = <<EOS
+1.<% : <%%
+2.%%> : %>
+3.
+foo
+4.
+% print "foo"
+5.
+% foo
+6.
+% print 'foo'
+
+7.
+%% print 'foo'
+
+EOS
+ assert_equal(ans, ERB.new(src, nil, '%').result)
+ end
+
+ def test_keep_lineno
+ src = <<EOS
+Hello,
+% x = "World"
+<%= x%>
+% raise("lineno")
+EOS
+
+ erb = ERB.new(src, nil, '%')
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):4\b/, $@[0].to_s)
+ end
+
+ src = <<EOS
+%>
+Hello,
+<% x = "World%%>
+"%>
+<%= x%>
+EOS
+
+ ans = <<EOS
+%>Hello,
+World%>
+EOS
+ assert_equal(ans, ERB.new(src, nil, '>').result)
+
+ ans = <<EOS
+%>
+Hello,
+
+World%>
+EOS
+ assert_equal(ans, ERB.new(src, nil, '<>').result)
+
+ ans = <<EOS
+%>
+Hello,
+
+World%>
+
+EOS
+ assert_equal(ans, ERB.new(src).result)
+
+ src = <<EOS
+Hello,
+<% x = "World%%>
+"%>
+<%= x%>
+<% raise("lineno") %>
+EOS
+
+ erb = ERB.new(src)
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):5\b/, $@[0].to_s)
+ end
+
+ erb = ERB.new(src, nil, '>')
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):5\b/, $@[0].to_s)
+ end
+
+ erb = ERB.new(src, nil, '<>')
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):5\b/, $@[0].to_s)
+ end
+
+ src = <<EOS
+% y = 'Hello'
+<%- x = "World%%>
+"-%>
+<%= x %><%- x = nil -%>
+<% raise("lineno") %>
+EOS
+
+ erb = ERB.new(src, nil, '-')
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):5\b/, $@[0].to_s)
+ end
+
+ erb = ERB.new(src, nil, '%-')
+ begin
+ erb.result
+ assert(false)
+ rescue
+ assert_match(/\A\(erb\):5\b/, $@[0].to_s)
+ end
+ end
+
+ def test_explicit
+ src = <<EOS
+<% x = %w(hello world) -%>
+NotSkip <%- y = x -%> NotSkip
+<% x.each do |w| -%>
+ <%- up = w.upcase -%>
+ * <%= up %>
+<% end -%>
+ <%- z = nil -%> NotSkip <%- z = x %>
+ <%- z.each do |w| -%>
+ <%- down = w.downcase -%>
+ * <%= down %>
+ <%- up = w.upcase -%>
+ * <%= up %>
+ <%- end -%>
+KeepNewLine <%- z = nil -%>
+EOS
+
+ ans = <<EOS
+NotSkip NotSkip
+ * HELLO
+ * WORLD
+ NotSkip
+ * hello
+ * HELLO
+ * world
+ * WORLD
+KeepNewLine
+EOS
+ assert_equal(ans, ERB.new(src, nil, '-').result)
+ assert_equal(ans, ERB.new(src, nil, '-%').result)
+ end
+
+ def test_url_encode
+ assert_equal("Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide",
+ ERB::Util.url_encode("Programming Ruby: The Pragmatic Programmer's Guide"))
+
+ assert_equal("%A5%B5%A5%F3%A5%D7%A5%EB",
+ ERB::Util.url_encode("\xA5\xB5\xA5\xF3\xA5\xD7\xA5\xEB".force_encoding("EUC-JP")))
+ end
+end
diff --git a/trunk/test/etc/test_etc.rb b/trunk/test/etc/test_etc.rb
new file mode 100644
index 0000000000..6fc7c6092b
--- /dev/null
+++ b/trunk/test/etc/test_etc.rb
@@ -0,0 +1,139 @@
+require "test/unit"
+require "etc"
+
+class TestEtc < Test::Unit::TestCase
+ def test_getlogin
+ s = Etc.getlogin
+ assert(s.is_a?(String) || s == nil, "getlogin must return a String or nil")
+ end
+
+ def test_passwd
+ Etc.passwd do |s|
+ assert_instance_of(String, s.name)
+ assert_instance_of(String, s.passwd) if s.respond_to?(:passwd)
+ assert_kind_of(Integer, s.uid)
+ assert_kind_of(Integer, s.gid)
+ assert_instance_of(String, s.gecos) if s.respond_to?(:gecos)
+ assert_instance_of(String, s.dir)
+ assert_instance_of(String, s.shell)
+ assert_kind_of(Integer, s.change) if s.respond_to?(:change)
+ assert_kind_of(Integer, s.quota) if s.respond_to?(:quota)
+ assert(s.age.is_a?(Integer) || s.age.is_a?(String)) if s.respond_to?(:age)
+ assert_instance_of(String, s.uclass) if s.respond_to?(:uclass)
+ assert_instance_of(String, s.comment) if s.respond_to?(:comment)
+ assert_kind_of(Integer, s.expire) if s.respond_to?(:expire)
+ end
+
+ assert_raise(RuntimeError) { Etc.passwd { Etc.passwd { } } }
+ end
+
+ def test_getpwuid
+ passwd = {}
+ Etc.passwd {|s| passwd[s.uid] = s unless passwd[s.uid] }
+ passwd.values.each do |s|
+ assert_equal(s, Etc.getpwuid(s.uid))
+ assert_equal(s, Etc.getpwuid) if Etc.getlogin == s.name
+ end
+ end
+
+ def test_getpwnam
+ passwd = []
+ Etc.passwd {|s| passwd << s }
+ passwd.each do |s|
+ assert_equal(s, Etc.getpwnam(s.name))
+ end
+ end
+
+ def test_setpwent
+ a = []
+ Etc.passwd do |s|
+ a << s
+ Etc.setpwent if a.size == 3
+ end
+ assert_equal(a[0, 3], a[3, 3]) if a.size >= 6
+ end
+
+ def test_getpwent
+ a = []
+ Etc.passwd {|s| a << s }
+ b = []
+ Etc.passwd do |s|
+ b << s
+ s = Etc.getpwent
+ break unless s
+ b << s
+ end
+ assert_equal(a, b)
+ end
+
+ def test_endpwent
+ a = []
+ Etc.passwd do |s|
+ a << s
+ Etc.endpwent if a.size == 3
+ end
+ assert_equal(a[0, 3], a[3, 3]) if a.size >= 6
+ end
+
+ def test_group
+ Etc.group do |s|
+ assert_instance_of(String, s.name)
+ assert_instance_of(String, s.passwd) if s.respond_to?(:passwd)
+ assert_kind_of(Integer, s.gid)
+ end
+
+ assert_raise(RuntimeError) { Etc.group { Etc.group { } } }
+ end
+
+ def test_getgrgid
+ groups = []
+ Etc.group do |s|
+ groups << s
+ end
+ groups.each do |s|
+ assert_equal(s, Etc.getgrgid(s.gid))
+ assert_equal(s, Etc.getgrgid) if Etc.getlogin == s.name
+ end
+ end
+
+ def test_getgrnam
+ groups = []
+ Etc.group do |s|
+ groups << s
+ end
+ groups.each do |s|
+ assert_equal(s, Etc.getgrnam(s.name))
+ end
+ end
+
+ def test_setgrent
+ a = []
+ Etc.group do |s|
+ a << s
+ Etc.setgrent if a.size == 3
+ end
+ assert_equal(a[0, 3], a[3, 3]) if a.size >= 6
+ end
+
+ def test_getgrent
+ a = []
+ Etc.group {|s| a << s }
+ b = []
+ Etc.group do |s|
+ b << s
+ s = Etc.getgrent
+ break unless s
+ b << s
+ end
+ assert_equal(a, b)
+ end
+
+ def test_endgrent
+ a = []
+ Etc.group do |s|
+ a << s
+ Etc.endgrent if a.size == 3
+ end
+ assert_equal(a[0, 3], a[3, 3]) if a.size >= 6
+ end
+end
diff --git a/trunk/test/fileutils/fileasserts.rb b/trunk/test/fileutils/fileasserts.rb
new file mode 100644
index 0000000000..41469a6ac6
--- /dev/null
+++ b/trunk/test/fileutils/fileasserts.rb
@@ -0,0 +1,100 @@
+# $Id$
+
+module Test
+ module Unit
+ module Assertions # redefine
+
+ def assert_same_file(from, to)
+ _wrap_assertion {
+ assert_block("file #{from} != #{to}") {
+ File.read(from) == File.read(to)
+ }
+ }
+ end
+
+ def assert_same_entry(from, to)
+ a = File.stat(from)
+ b = File.stat(to)
+ assert_equal a.mode, b.mode, "mode #{a.mode} != #{b.mode}"
+ #assert_equal a.atime, b.atime
+ assert_equal_timestamp a.mtime, b.mtime, "mtime #{a.mtime} != #{b.mtime}"
+ assert_equal a.uid, b.uid, "uid #{a.uid} != #{b.uid}"
+ assert_equal a.gid, b.gid, "gid #{a.gid} != #{b.gid}"
+ end
+
+ def assert_file_exist(path)
+ _wrap_assertion {
+ assert_block("file not exist: #{path}") {
+ File.exist?(path)
+ }
+ }
+ end
+
+ def assert_file_not_exist(path)
+ _wrap_assertion {
+ assert_block("file not exist: #{path}") {
+ not File.exist?(path)
+ }
+ }
+ end
+
+ def assert_directory(path)
+ _wrap_assertion {
+ assert_block("is not directory: #{path}") {
+ File.directory?(path)
+ }
+ }
+ end
+
+ def assert_symlink(path)
+ _wrap_assertion {
+ assert_block("is not a symlink: #{path}") {
+ File.symlink?(path)
+ }
+ }
+ end
+
+ def assert_not_symlink(path)
+ _wrap_assertion {
+ assert_block("is a symlink: #{path}") {
+ not File.symlink?(path)
+ }
+ }
+ end
+
+ def assert_equal_time(expected, actual, message=nil)
+ _wrap_assertion {
+ expected_str = expected.to_s
+ actual_str = actual.to_s
+ if expected_str == actual_str
+ expected_str << " (nsec=#{expected.nsec})"
+ actual_str << " (nsec=#{actual.nsec})"
+ end
+ full_message = build_message(message, <<EOT)
+<#{expected_str}> expected but was
+<#{actual_str}>.
+EOT
+ assert_block(full_message) { expected == actual }
+ }
+ end
+
+ def assert_equal_timestamp(expected, actual, message=nil)
+ _wrap_assertion {
+ expected_str = expected.to_s
+ actual_str = actual.to_s
+ if expected_str == actual_str
+ expected_str << " (nsec=#{expected.nsec})"
+ actual_str << " (nsec=#{actual.nsec})"
+ end
+ full_message = build_message(message, <<EOT)
+<#{expected_str}> expected but was
+<#{actual_str}>.
+EOT
+ # subsecond timestamp is not portable.
+ assert_block(full_message) { expected.tv_sec == actual.tv_sec }
+ }
+ end
+
+ end
+ end
+end
diff --git a/trunk/test/fileutils/test_dryrun.rb b/trunk/test/fileutils/test_dryrun.rb
new file mode 100644
index 0000000000..2fdd65d2f6
--- /dev/null
+++ b/trunk/test/fileutils/test_dryrun.rb
@@ -0,0 +1,25 @@
+# $Id$
+
+require 'test/unit'
+require 'fileutils'
+
+class TestFileUtilsDryRun < Test::Unit::TestCase
+
+ include FileUtils::DryRun
+
+ def test_visibility
+ FileUtils::METHODS.each do |m|
+ assert_equal true, FileUtils::DryRun.respond_to?(m, true),
+ "FileUtils::DryRun.#{m} not defined"
+ assert_equal true, FileUtils::DryRun.respond_to?(m, false),
+ "FileUtils::DryRun.#{m} not public"
+ end
+ FileUtils::METHODS.each do |m|
+ assert_equal true, respond_to?(m, true)
+ "FileUtils::DryRun\##{m} is not defined"
+ assert_equal true, FileUtils::DryRun.private_method_defined?(m),
+ "FileUtils::DryRun\##{m} is not private"
+ end
+ end
+
+end
diff --git a/trunk/test/fileutils/test_fileutils.rb b/trunk/test/fileutils/test_fileutils.rb
new file mode 100644
index 0000000000..a52eb50071
--- /dev/null
+++ b/trunk/test/fileutils/test_fileutils.rb
@@ -0,0 +1,1081 @@
+# $Id$
+
+require 'fileutils'
+require 'fileasserts'
+require 'pathname'
+require 'tmpdir'
+require 'test/unit'
+
+class TestFileUtils < Test::Unit::TestCase
+ TMPROOT = "#{Dir.tmpdir}/fileutils.rb.#{$$}"
+end
+
+prevdir = Dir.pwd
+tmproot = TestFileUtils::TMPROOT
+Dir.mkdir tmproot unless File.directory?(tmproot)
+Dir.chdir tmproot
+
+def have_drive_letter?
+ /djgpp|mswin(?!ce)|mingw|bcc|emx/ =~ RUBY_PLATFORM
+end
+
+def have_file_perm?
+ /djgpp|mswin|mingw|bcc|wince|emx/ !~ RUBY_PLATFORM
+end
+
+$fileutils_rb_have_symlink = nil
+
+def have_symlink?
+ if $fileutils_rb_have_symlink == nil
+ $fileutils_rb_have_symlink = check_have_symlink?
+ end
+ $fileutils_rb_have_symlink
+end
+
+def check_have_symlink?
+ File.symlink nil, nil
+rescue NotImplementedError
+ return false
+rescue
+ return true
+end
+
+$fileutils_rb_have_hardlink = nil
+
+def have_hardlink?
+ if $fileutils_rb_have_hardlink == nil
+ $fileutils_rb_have_hardlink = check_have_hardlink?
+ end
+ $fileutils_rb_have_hardlink
+end
+
+def check_have_hardlink?
+ File.link nil, nil
+rescue NotImplementedError
+ return false
+rescue
+ return true
+end
+
+begin
+ Dir.mkdir("\n")
+ Dir.rmdir("\n")
+ def lf_in_path_allowed?
+ true
+ end
+rescue
+ def lf_in_path_allowed?
+ false
+ end
+end
+
+Dir.chdir prevdir
+Dir.rmdir tmproot
+
+class TestFileUtils
+
+ include FileUtils
+
+ def check_singleton(name)
+ assert_equal true, ::FileUtils.public_methods.include?(name.to_sym)
+ end
+
+ def my_rm_rf(path)
+ if File.exist?('/bin/rm')
+ system %Q[/bin/rm -rf "#{path}"]
+ else
+ FileUtils.rm_rf path
+ end
+ end
+
+ def mymkdir(path)
+ Dir.mkdir path
+ File.chown nil, Process.gid, path if have_file_perm?
+ end
+
+ def setup
+ @prevdir = Dir.pwd
+ tmproot = TMPROOT
+ mymkdir tmproot unless File.directory?(tmproot)
+ Dir.chdir tmproot
+ my_rm_rf 'data'; mymkdir 'data'
+ my_rm_rf 'tmp'; mymkdir 'tmp'
+ prepare_data_file
+ end
+
+ def teardown
+ tmproot = Dir.pwd
+ Dir.chdir @prevdir
+ my_rm_rf tmproot
+ end
+
+
+ TARGETS = %w( data/a data/all data/random data/zero )
+
+ def prepare_data_file
+ File.open('data/a', 'w') {|f|
+ 32.times do
+ f.puts 'a' * 50
+ end
+ }
+
+ all_chars = (0..255).map {|n| n.chr }.join('')
+ File.open('data/all', 'w') {|f|
+ 32.times do
+ f.puts all_chars
+ end
+ }
+
+ random_chars = (0...50).map { rand(256).chr }.join('')
+ File.open('data/random', 'w') {|f|
+ 32.times do
+ f.puts random_chars
+ end
+ }
+
+ File.open('data/zero', 'w') {|f|
+ ;
+ }
+ end
+
+ BIGFILE = 'data/big'
+
+ def prepare_big_file
+ File.open('data/big', 'w') {|f|
+ (4 * 1024 * 1024 / 256).times do # 4MB
+ f.print "aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa\n"
+ end
+ }
+ end
+
+ def prepare_time_data
+ File.open('data/old', 'w') {|f| f.puts 'dummy' }
+ File.open('data/newer', 'w') {|f| f.puts 'dummy' }
+ File.open('data/newest', 'w') {|f| f.puts 'dummy' }
+ t = Time.now
+ File.utime t-8, t-8, 'data/old'
+ File.utime t-4, t-4, 'data/newer'
+ end
+
+ def each_srcdest
+ TARGETS.each do |path|
+ yield path, "tmp/#{File.basename(path)}"
+ end
+ end
+
+ #
+ # Test Cases
+ #
+
+ def test_pwd
+ check_singleton :pwd
+
+ assert_equal Dir.pwd, pwd()
+
+ cwd = Dir.pwd
+if have_drive_letter?
+ cd('C:/') {
+ assert_equal 'C:/', pwd()
+ }
+ assert_equal cwd, pwd()
+else
+ cd('/') {
+ assert_equal '/', pwd()
+ }
+ assert_equal cwd, pwd()
+end
+ end
+
+ def test_cmp
+ check_singleton :cmp
+
+ TARGETS.each do |fname|
+ assert cmp(fname, fname), 'not same?'
+ end
+ assert_raises(ArgumentError) {
+ cmp TARGETS[0], TARGETS[0], :undefinedoption => true
+ }
+
+ # pathname
+ touch 'tmp/cmptmp'
+ assert_nothing_raised {
+ cmp Pathname.new('tmp/cmptmp'), 'tmp/cmptmp'
+ cmp 'tmp/cmptmp', Pathname.new('tmp/cmptmp')
+ cmp Pathname.new('tmp/cmptmp'), Pathname.new('tmp/cmptmp')
+ }
+ end
+
+ def test_cp
+ check_singleton :cp
+
+ each_srcdest do |srcpath, destpath|
+ cp srcpath, destpath
+ assert_same_file srcpath, destpath
+
+ cp srcpath, File.dirname(destpath)
+ assert_same_file srcpath, destpath
+
+ cp srcpath, File.dirname(destpath) + '/'
+ assert_same_file srcpath, destpath
+
+ cp srcpath, destpath, :preserve => true
+ assert_same_file srcpath, destpath
+ assert_same_entry srcpath, destpath
+ end
+
+ # src==dest (1) same path
+ touch 'tmp/cptmp'
+ assert_raises(ArgumentError) {
+ cp 'tmp/cptmp', 'tmp/cptmp'
+ }
+if have_symlink?
+ # src==dest (2) symlink and its target
+ File.symlink 'cptmp', 'tmp/cptmp_symlink'
+ assert_raises(ArgumentError) {
+ cp 'tmp/cptmp', 'tmp/cptmp_symlink'
+ }
+ assert_raises(ArgumentError) {
+ cp 'tmp/cptmp_symlink', 'tmp/cptmp'
+ }
+ # src==dest (3) looped symlink
+ File.symlink 'symlink', 'tmp/symlink'
+ assert_raises(Errno::ELOOP) {
+ cp 'tmp/symlink', 'tmp/symlink'
+ }
+end
+
+ # pathname
+ assert_nothing_raised {
+ cp 'tmp/cptmp', Pathname.new('tmp/tmpdest')
+ cp Pathname.new('tmp/cptmp'), 'tmp/tmpdest'
+ cp Pathname.new('tmp/cptmp'), Pathname.new('tmp/tmpdest')
+ mkdir 'tmp/tmpdir'
+ cp ['tmp/cptmp', 'tmp/tmpdest'], Pathname.new('tmp/tmpdir')
+ }
+ end
+
+ def test_cp_r
+ check_singleton :cp_r
+
+ cp_r 'data', 'tmp'
+ TARGETS.each do |fname|
+ assert_same_file fname, "tmp/#{fname}"
+ end
+
+ cp_r 'data', 'tmp2', :preserve => true
+ TARGETS.each do |fname|
+ assert_same_entry fname, "tmp2/#{File.basename(fname)}"
+ assert_same_file fname, "tmp2/#{File.basename(fname)}"
+ end
+
+ # a/* -> b/*
+ mkdir 'tmp/cpr_src'
+ mkdir 'tmp/cpr_dest'
+ File.open('tmp/cpr_src/a', 'w') {|f| f.puts 'a' }
+ File.open('tmp/cpr_src/b', 'w') {|f| f.puts 'b' }
+ File.open('tmp/cpr_src/c', 'w') {|f| f.puts 'c' }
+ mkdir 'tmp/cpr_src/d'
+ cp_r 'tmp/cpr_src/.', 'tmp/cpr_dest'
+ assert_same_file 'tmp/cpr_src/a', 'tmp/cpr_dest/a'
+ assert_same_file 'tmp/cpr_src/b', 'tmp/cpr_dest/b'
+ assert_same_file 'tmp/cpr_src/c', 'tmp/cpr_dest/c'
+ assert_directory 'tmp/cpr_dest/d'
+ my_rm_rf 'tmp/cpr_src'
+ my_rm_rf 'tmp/cpr_dest'
+
+if have_symlink?
+ # symlink in a directory
+ mkdir 'tmp/cpr_src'
+ ln_s 'SLdest', 'tmp/cpr_src/symlink'
+ cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
+ assert_symlink 'tmp/cpr_dest/symlink'
+ assert_equal 'SLdest', File.readlink('tmp/cpr_dest/symlink')
+
+ # root is a symlink
+ ln_s 'cpr_src', 'tmp/cpr_src2'
+ cp_r 'tmp/cpr_src2', 'tmp/cpr_dest2'
+ assert_directory 'tmp/cpr_dest2'
+ #assert_not_symlink 'tmp/cpr_dest2'
+ assert_symlink 'tmp/cpr_dest2' # 2005-05-26: feature change
+ assert_symlink 'tmp/cpr_dest2/symlink'
+ assert_equal 'SLdest', File.readlink('tmp/cpr_dest2/symlink')
+end
+
+ # pathname
+ touch 'tmp/cprtmp'
+ assert_nothing_raised {
+ cp_r Pathname.new('tmp/cprtmp'), 'tmp/tmpdest'
+ cp_r 'tmp/cprtmp', Pathname.new('tmp/tmpdest')
+ cp_r Pathname.new('tmp/cprtmp'), Pathname.new('tmp/tmpdest')
+ }
+ end
+
+ def test_mv
+ check_singleton :mv
+
+ mkdir 'tmp/dest'
+ TARGETS.each do |fname|
+ cp fname, 'tmp/mvsrc'
+ mv 'tmp/mvsrc', 'tmp/mvdest'
+ assert_same_file fname, 'tmp/mvdest'
+
+ mv 'tmp/mvdest', 'tmp/dest/'
+ assert_same_file fname, 'tmp/dest/mvdest'
+
+ mv 'tmp/dest/mvdest', 'tmp'
+ assert_same_file fname, 'tmp/mvdest'
+ end
+
+ mkdir 'tmp/tmpdir'
+ mkdir_p 'tmp/dest2/tmpdir'
+ assert_raises(Errno::EEXIST) {
+ mv 'tmp/tmpdir', 'tmp/dest2'
+ }
+ mkdir 'tmp/dest2/tmpdir/junk'
+ assert_raises(Errno::EEXIST, "[ruby-talk:124368]") {
+ mv 'tmp/tmpdir', 'tmp/dest2'
+ }
+
+ # src==dest (1) same path
+ touch 'tmp/cptmp'
+ assert_raises(ArgumentError) {
+ mv 'tmp/cptmp', 'tmp/cptmp'
+ }
+if have_symlink?
+ # src==dest (2) symlink and its target
+ File.symlink 'cptmp', 'tmp/cptmp_symlink'
+ assert_raises(ArgumentError) {
+ mv 'tmp/cptmp', 'tmp/cptmp_symlink'
+ }
+ assert_raises(ArgumentError) {
+ mv 'tmp/cptmp_symlink', 'tmp/cptmp'
+ }
+ # src==dest (3) looped symlink
+ File.symlink 'symlink', 'tmp/symlink'
+ assert_raises(Errno::ELOOP) {
+ mv 'tmp/symlink', 'tmp/symlink'
+ }
+end
+
+ # pathname
+ assert_nothing_raised {
+ touch 'tmp/mvtmpsrc'
+ mv Pathname.new('tmp/mvtmpsrc'), 'tmp/mvtmpdest'
+ touch 'tmp/mvtmpsrc'
+ mv 'tmp/mvtmpsrc', Pathname.new('tmp/mvtmpdest')
+ touch 'tmp/mvtmpsrc'
+ mv Pathname.new('tmp/mvtmpsrc'), Pathname.new('tmp/mvtmpdest')
+ }
+ end
+
+ def test_rm
+ check_singleton :rm
+
+ TARGETS.each do |fname|
+ cp fname, 'tmp/rmsrc'
+ rm 'tmp/rmsrc'
+ assert_file_not_exist 'tmp/rmsrc'
+ end
+
+ # pathname
+ touch 'tmp/rmtmp1'
+ touch 'tmp/rmtmp2'
+ touch 'tmp/rmtmp3'
+ assert_nothing_raised {
+ rm Pathname.new('tmp/rmtmp1')
+ rm [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
+ }
+ assert_file_not_exist 'tmp/rmtmp1'
+ assert_file_not_exist 'tmp/rmtmp2'
+ assert_file_not_exist 'tmp/rmtmp3'
+ end
+
+ def test_rm_f
+ check_singleton :rm_f
+
+ TARGETS.each do |fname|
+ cp fname, 'tmp/rmsrc'
+ rm_f 'tmp/rmsrc'
+ assert_file_not_exist 'tmp/rmsrc'
+ end
+
+if have_symlink?
+ File.open('tmp/lnf_symlink_src', 'w') {|f| f.puts 'dummy' }
+ File.symlink 'tmp/lnf_symlink_src', 'tmp/lnf_symlink_dest'
+ rm_f 'tmp/lnf_symlink_dest'
+ assert_file_not_exist 'tmp/lnf_symlink_dest'
+ assert_file_exist 'tmp/lnf_symlink_src'
+end
+
+ rm_f 'notexistdatafile'
+ rm_f 'tmp/notexistdatafile'
+ my_rm_rf 'tmpdatadir'
+ Dir.mkdir 'tmpdatadir'
+ # rm_f 'tmpdatadir'
+ Dir.rmdir 'tmpdatadir'
+
+ Dir.mkdir 'tmp/tmpdir'
+ File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
+ rm_f ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c']
+ assert_file_not_exist 'tmp/tmpdir/a'
+ assert_file_not_exist 'tmp/tmpdir/c'
+ Dir.rmdir 'tmp/tmpdir'
+
+ # pathname
+ touch 'tmp/rmtmp1'
+ touch 'tmp/rmtmp2'
+ touch 'tmp/rmtmp3'
+ touch 'tmp/rmtmp4'
+ assert_nothing_raised {
+ rm_f Pathname.new('tmp/rmtmp1')
+ rm_f [Pathname.new('tmp/rmtmp2'), Pathname.new('tmp/rmtmp3')]
+ }
+ assert_file_not_exist 'tmp/rmtmp1'
+ assert_file_not_exist 'tmp/rmtmp2'
+ assert_file_not_exist 'tmp/rmtmp3'
+ assert_file_exist 'tmp/rmtmp4'
+ end
+
+ def test_rm_r
+ check_singleton :rm_r
+
+ my_rm_rf 'tmpdatadir'
+
+ Dir.mkdir 'tmpdatadir'
+ rm_r 'tmpdatadir'
+ assert_file_not_exist 'tmpdatadir'
+
+ Dir.mkdir 'tmpdatadir'
+ rm_r 'tmpdatadir/'
+ assert_file_not_exist 'tmpdatadir'
+
+ Dir.mkdir 'tmp/tmpdir'
+ rm_r 'tmp/tmpdir/'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ rm_r 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
+ rm_r 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
+ rm_r ['tmp/tmpdir/a', 'tmp/tmpdir/b', 'tmp/tmpdir/c'], :force => true
+ assert_file_not_exist 'tmp/tmpdir/a'
+ assert_file_not_exist 'tmp/tmpdir/c'
+ Dir.rmdir 'tmp/tmpdir'
+
+if have_symlink?
+ # [ruby-talk:94635] a symlink to the directory
+ Dir.mkdir 'tmp/tmpdir'
+ File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
+ rm_r 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+end
+
+ # pathname
+ Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
+ Dir.mkdir 'tmp/tmpdir2'; touch 'tmp/tmpdir2/tmp'
+ Dir.mkdir 'tmp/tmpdir3'; touch 'tmp/tmpdir3/tmp'
+ assert_nothing_raised {
+ rm_r Pathname.new('tmp/tmpdir1')
+ rm_r [Pathname.new('tmp/tmpdir2'), Pathname.new('tmp/tmpdir3')]
+ }
+ assert_file_not_exist 'tmp/tmpdir1'
+ assert_file_not_exist 'tmp/tmpdir2'
+ assert_file_not_exist 'tmp/tmpdir3'
+ end
+
+ def test_remove_entry_secure
+ check_singleton :remove_entry_secure
+
+ my_rm_rf 'tmpdatadir'
+
+ Dir.mkdir 'tmpdatadir'
+ remove_entry_secure 'tmpdatadir'
+ assert_file_not_exist 'tmpdatadir'
+
+ Dir.mkdir 'tmpdatadir'
+ remove_entry_secure 'tmpdatadir/'
+ assert_file_not_exist 'tmpdatadir'
+
+ Dir.mkdir 'tmp/tmpdir'
+ remove_entry_secure 'tmp/tmpdir/'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ remove_entry_secure 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/b', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
+ remove_entry_secure 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+
+ Dir.mkdir 'tmp/tmpdir'
+ File.open('tmp/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ File.open('tmp/tmpdir/c', 'w') {|f| f.puts 'dummy' }
+ remove_entry_secure 'tmp/tmpdir/a', true
+ remove_entry_secure 'tmp/tmpdir/b', true
+ remove_entry_secure 'tmp/tmpdir/c', true
+ assert_file_not_exist 'tmp/tmpdir/a'
+ assert_file_not_exist 'tmp/tmpdir/c'
+ Dir.rmdir 'tmp/tmpdir'
+
+if have_symlink?
+ # [ruby-talk:94635] a symlink to the directory
+ Dir.mkdir 'tmp/tmpdir'
+ File.symlink '..', 'tmp/tmpdir/symlink_to_dir'
+ remove_entry_secure 'tmp/tmpdir'
+ assert_file_not_exist 'tmp/tmpdir'
+ assert_file_exist 'tmp'
+end
+
+ # pathname
+ Dir.mkdir 'tmp/tmpdir1'; touch 'tmp/tmpdir1/tmp'
+ assert_nothing_raised {
+ remove_entry_secure Pathname.new('tmp/tmpdir1')
+ }
+ assert_file_not_exist 'tmp/tmpdir1'
+ end
+
+ def test_with_big_file
+ prepare_big_file
+
+ cp BIGFILE, 'tmp/cpdest'
+ assert_same_file BIGFILE, 'tmp/cpdest'
+ assert cmp(BIGFILE, 'tmp/cpdest'), 'orig != copied'
+
+ mv 'tmp/cpdest', 'tmp/mvdest'
+ assert_same_file BIGFILE, 'tmp/mvdest'
+ assert_file_not_exist 'tmp/cpdest'
+
+ rm 'tmp/mvdest'
+ assert_file_not_exist 'tmp/mvdest'
+ end
+
+if have_hardlink?
+ def test_ln
+ TARGETS.each do |fname|
+ ln fname, 'tmp/lndest'
+ assert_same_file fname, 'tmp/lndest'
+ File.unlink 'tmp/lndest'
+ end
+
+ ln TARGETS, 'tmp'
+ TARGETS.each do |fname|
+ assert_same_file fname, 'tmp/' + File.basename(fname)
+ end
+ TARGETS.each do |fname|
+ File.unlink 'tmp/' + File.basename(fname)
+ end
+
+ # src==dest (1) same path
+ touch 'tmp/cptmp'
+ assert_raises(Errno::EEXIST) {
+ ln 'tmp/cptmp', 'tmp/cptmp'
+ }
+if have_symlink?
+ # src==dest (2) symlink and its target
+ File.symlink 'cptmp', 'tmp/symlink'
+ assert_raises(Errno::EEXIST) {
+ ln 'tmp/cptmp', 'tmp/symlink' # normal file -> symlink
+ }
+ assert_raises(Errno::EEXIST) {
+ ln 'tmp/symlink', 'tmp/cptmp' # symlink -> normal file
+ }
+ # src==dest (3) looped symlink
+ File.symlink 'cptmp_symlink', 'tmp/cptmp_symlink'
+ begin
+ ln 'tmp/cptmp_symlink', 'tmp/cptmp_symlink'
+ rescue => err
+ assert_kind_of SystemCallError, err
+ end
+end
+
+ # pathname
+ touch 'tmp/lntmp'
+ assert_nothing_raised {
+ ln Pathname.new('tmp/lntmp'), 'tmp/lndesttmp1'
+ ln 'tmp/lntmp', Pathname.new('tmp/lndesttmp2')
+ ln Pathname.new('tmp/lntmp'), Pathname.new('tmp/lndesttmp3')
+ }
+ end
+end
+
+if have_symlink?
+ def test_ln_s
+ check_singleton :ln_s
+
+ TARGETS.each do |fname|
+ ln_s fname, 'tmp/lnsdest'
+ assert FileTest.symlink?('tmp/lnsdest'), 'not symlink'
+ assert_equal fname, File.readlink('tmp/lnsdest')
+ rm_f 'tmp/lnsdest'
+ end
+ assert_nothing_raised {
+ ln_s 'symlink', 'tmp/symlink'
+ }
+ assert_symlink 'tmp/symlink'
+
+ # pathname
+ touch 'tmp/lnsdest'
+ assert_nothing_raised {
+ ln_s Pathname.new('lnsdest'), 'tmp/symlink_tmp1'
+ ln_s 'lnsdest', Pathname.new('tmp/symlink_tmp2')
+ ln_s Pathname.new('lnsdest'), Pathname.new('tmp/symlink_tmp3')
+ }
+ end
+end
+
+if have_symlink?
+ def test_ln_sf
+ check_singleton :ln_sf
+
+ TARGETS.each do |fname|
+ ln_sf fname, 'tmp/lnsdest'
+ assert FileTest.symlink?('tmp/lnsdest'), 'not symlink'
+ assert_equal fname, File.readlink('tmp/lnsdest')
+ ln_sf fname, 'tmp/lnsdest'
+ ln_sf fname, 'tmp/lnsdest'
+ end
+ assert_nothing_raised {
+ ln_sf 'symlink', 'tmp/symlink'
+ }
+
+ # pathname
+ touch 'tmp/lns_dest'
+ assert_nothing_raised {
+ ln_sf Pathname.new('lns_dest'), 'tmp/symlink_tmp1'
+ ln_sf 'lns_dest', Pathname.new('tmp/symlink_tmp2')
+ ln_sf Pathname.new('lns_dest'), Pathname.new('tmp/symlink_tmp3')
+ }
+ end
+end
+
+ def test_mkdir
+ check_singleton :mkdir
+
+ my_rm_rf 'tmpdatadir'
+ mkdir 'tmpdatadir'
+ assert_directory 'tmpdatadir'
+ Dir.rmdir 'tmpdatadir'
+
+ mkdir 'tmpdatadir/'
+ assert_directory 'tmpdatadir'
+ Dir.rmdir 'tmpdatadir'
+
+ mkdir 'tmp/mkdirdest'
+ assert_directory 'tmp/mkdirdest'
+ Dir.rmdir 'tmp/mkdirdest'
+
+ mkdir 'tmp/tmp', :mode => 0700
+ assert_directory 'tmp/tmp'
+ assert_equal 0700, (File.stat('tmp/tmp').mode & 0777) if have_file_perm?
+ Dir.rmdir 'tmp/tmp'
+
+if have_file_perm?
+ mkdir 'tmp/tmp', :mode => 07777
+ assert_directory 'tmp/tmp'
+ assert_equal 07777, (File.stat('tmp/tmp').mode & 07777)
+ Dir.rmdir 'tmp/tmp'
+end
+
+if lf_in_path_allowed?
+ mkdir "tmp-first-line\ntmp-second-line"
+ assert_directory "tmp-first-line\ntmp-second-line"
+ Dir.rmdir "tmp-first-line\ntmp-second-line"
+end
+
+ # pathname
+ assert_nothing_raised {
+ mkdir Pathname.new('tmp/tmpdirtmp')
+ mkdir [Pathname.new('tmp/tmpdirtmp2'), Pathname.new('tmp/tmpdirtmp3')]
+ }
+ end
+
+ def test_mkdir_p
+ check_singleton :mkdir_p
+
+ dirs = %w(
+ tmpdir/dir/
+ tmpdir/dir/./
+ tmpdir/dir/./.././dir/
+ tmpdir/a
+ tmpdir/a/
+ tmpdir/a/b
+ tmpdir/a/b/
+ tmpdir/a/b/c/
+ tmpdir/a/b/c
+ tmpdir/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a
+ tmpdir/a/a
+ )
+ my_rm_rf 'tmpdir'
+ dirs.each do |d|
+ mkdir_p d
+ assert_directory d
+ assert_file_not_exist "#{d}/a"
+ assert_file_not_exist "#{d}/b"
+ assert_file_not_exist "#{d}/c"
+ my_rm_rf 'tmpdir'
+ end
+ dirs.each do |d|
+ mkdir_p d
+ assert_directory d
+ end
+ rm_rf 'tmpdir'
+ dirs.each do |d|
+ mkdir_p "#{Dir.pwd}/#{d}"
+ assert_directory d
+ end
+ rm_rf 'tmpdir'
+
+ mkdir_p 'tmp/tmp/tmp', :mode => 0700
+ assert_directory 'tmp/tmp'
+ assert_directory 'tmp/tmp/tmp'
+ assert_equal 0700, (File.stat('tmp/tmp').mode & 0777) if have_file_perm?
+ assert_equal 0700, (File.stat('tmp/tmp/tmp').mode & 0777) if have_file_perm?
+ rm_rf 'tmp/tmp'
+
+ mkdir_p 'tmp/tmp', :mode => 0
+ assert_directory 'tmp/tmp'
+ assert_equal 0, (File.stat('tmp/tmp').mode & 0777) if have_file_perm?
+ # DO NOT USE rm_rf here.
+ # (rm(1) try to chdir to parent directory, it fails to remove directory.)
+ Dir.rmdir 'tmp/tmp'
+ Dir.rmdir 'tmp'
+
+if have_file_perm?
+ mkdir_p 'tmp/tmp/tmp', :mode => 07777
+ assert_directory 'tmp/tmp/tmp'
+ assert_equal 07777, (File.stat('tmp/tmp/tmp').mode & 07777)
+ Dir.rmdir 'tmp/tmp/tmp'
+ Dir.rmdir 'tmp/tmp'
+end
+
+ # pathname
+ assert_nothing_raised {
+ mkdir_p Pathname.new('tmp/tmp/tmp')
+ }
+ end
+
+ def test_install
+ check_singleton :install
+
+ File.open('tmp/aaa', 'w') {|f| f.puts 'aaa' }
+ File.open('tmp/bbb', 'w') {|f| f.puts 'bbb' }
+ install 'tmp/aaa', 'tmp/bbb', :mode => 0600
+ assert_equal "aaa\n", File.read('tmp/bbb')
+ assert_equal 0600, (File.stat('tmp/bbb').mode & 0777) if have_file_perm?
+
+ t = File.mtime('tmp/bbb')
+ install 'tmp/aaa', 'tmp/bbb'
+ assert_equal "aaa\n", File.read('tmp/bbb')
+ assert_equal 0600, (File.stat('tmp/bbb').mode & 0777) if have_file_perm?
+ assert_equal_time t, File.mtime('tmp/bbb')
+
+ File.unlink 'tmp/aaa'
+ File.unlink 'tmp/bbb'
+
+ # src==dest (1) same path
+ touch 'tmp/cptmp'
+ assert_raises(ArgumentError) {
+ install 'tmp/cptmp', 'tmp/cptmp'
+ }
+if have_symlink?
+ # src==dest (2) symlink and its target
+ File.symlink 'cptmp', 'tmp/cptmp_symlink'
+ assert_raises(ArgumentError) {
+ install 'tmp/cptmp', 'tmp/cptmp_symlink'
+ }
+ assert_raises(ArgumentError) {
+ install 'tmp/cptmp_symlink', 'tmp/cptmp'
+ }
+ # src==dest (3) looped symlink
+ File.symlink 'symlink', 'tmp/symlink'
+ assert_raises(Errno::ELOOP) {
+ # File#install invokes open(2), always ELOOP must be raised
+ install 'tmp/symlink', 'tmp/symlink'
+ }
+end
+
+ # pathname
+ assert_nothing_raised {
+ rm_f 'tmp/a'; touch 'tmp/a'
+ install 'tmp/a', Pathname.new('tmp/b')
+ rm_f 'tmp/a'; touch 'tmp/a'
+ install Pathname.new('tmp/a'), 'tmp/b'
+ rm_f 'tmp/a'; touch 'tmp/a'
+ install Pathname.new('tmp/a'), Pathname.new('tmp/b')
+ rm_f 'tmp/a'
+ touch 'tmp/a'
+ touch 'tmp/b'
+ mkdir 'tmp/dest'
+ install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], 'tmp/dest'
+ my_rm_rf 'tmp/dest'
+ mkdir 'tmp/dest'
+ install [Pathname.new('tmp/a'), Pathname.new('tmp/b')], Pathname.new('tmp/dest')
+ }
+ end
+
+if have_file_perm?
+ def test_chmod
+ check_singleton :chmod
+
+ touch 'tmp/a'
+ chmod 0700, 'tmp/a'
+ assert_equal 0700, File.stat('tmp/a').mode & 0777
+ chmod 0500, 'tmp/a'
+ assert_equal 0500, File.stat('tmp/a').mode & 0777
+ end
+
+ def test_chmod_R
+ check_singleton :chmod_R
+
+ mkdir_p 'tmp/dir/dir'
+ touch %w( tmp/dir/file tmp/dir/dir/file )
+ chmod_R 0700, 'tmp/dir'
+ assert_equal 0700, File.stat('tmp/dir').mode & 0777
+ assert_equal 0700, File.stat('tmp/dir/file').mode & 0777
+ assert_equal 0700, File.stat('tmp/dir/dir').mode & 0777
+ assert_equal 0700, File.stat('tmp/dir/dir/file').mode & 0777
+ chmod_R 0500, 'tmp/dir'
+ assert_equal 0500, File.stat('tmp/dir').mode & 0777
+ assert_equal 0500, File.stat('tmp/dir/file').mode & 0777
+ assert_equal 0500, File.stat('tmp/dir/dir').mode & 0777
+ assert_equal 0500, File.stat('tmp/dir/dir/file').mode & 0777
+ chmod_R 0700, 'tmp/dir' # to remove
+ end
+
+ # FIXME: How can I test this method?
+ def test_chown
+ check_singleton :chown
+ end
+
+ # FIXME: How can I test this method?
+ def test_chown_R
+ check_singleton :chown_R
+ end
+end
+
+ def test_copy_entry
+ check_singleton :copy_entry
+
+ each_srcdest do |srcpath, destpath|
+ copy_entry srcpath, destpath
+ assert_same_file srcpath, destpath
+ assert_equal File.stat(srcpath).ftype, File.stat(destpath).ftype
+ end
+if have_symlink?
+ # root is a symlink
+ File.symlink 'somewhere', 'tmp/symsrc'
+ copy_entry 'tmp/symsrc', 'tmp/symdest'
+ assert_symlink 'tmp/symdest'
+ assert_equal 'somewhere', File.readlink('tmp/symdest')
+
+ # content is a symlink
+ mkdir 'tmp/dir'
+ File.symlink 'somewhere', 'tmp/dir/sym'
+ copy_entry 'tmp/dir', 'tmp/dirdest'
+ assert_directory 'tmp/dirdest'
+ assert_not_symlink 'tmp/dirdest'
+ assert_symlink 'tmp/dirdest/sym'
+ assert_equal 'somewhere', File.readlink('tmp/dirdest/sym')
+end
+ end
+
+ def test_copy_file
+ check_singleton :copy_file
+
+ each_srcdest do |srcpath, destpath|
+ copy_file srcpath, destpath
+ assert_same_file srcpath, destpath
+ end
+ end
+
+ def test_copy_stream
+ check_singleton :copy_stream
+ # IO
+ each_srcdest do |srcpath, destpath|
+ File.open(srcpath) {|src|
+ File.open(destpath, 'w') {|dest|
+ copy_stream src, dest
+ }
+ }
+ assert_same_file srcpath, destpath
+ end
+
+ # duck typing test [ruby-dev:25369]
+ my_rm_rf 'tmp'
+ Dir.mkdir 'tmp'
+ each_srcdest do |srcpath, destpath|
+ File.open(srcpath) {|src|
+ File.open(destpath, 'w') {|dest|
+ copy_stream Stream.new(src), Stream.new(dest)
+ }
+ }
+ assert_same_file srcpath, destpath
+ end
+ end
+
+ def test_remove_file
+ check_singleton :remove_file
+ File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
+ remove_file 'data/tmp'
+ assert_file_not_exist 'data/tmp'
+if have_file_perm?
+ File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
+ File.chmod 0, 'data/tmp'
+ remove_file 'data/tmp'
+ assert_file_not_exist 'data/tmp'
+end
+ end
+
+ def test_remove_dir
+ check_singleton :remove_dir
+ Dir.mkdir 'data/tmpdir'
+ File.open('data/tmpdir/a', 'w') {|f| f.puts 'dummy' }
+ remove_dir 'data/tmpdir'
+ assert_file_not_exist 'data/tmpdir'
+if have_file_perm?
+ Dir.mkdir 'data/tmpdir'
+ File.chmod 0555, 'data/tmpdir'
+ remove_dir 'data/tmpdir'
+ assert_file_not_exist 'data/tmpdir'
+end
+ end
+
+ def test_compare_file
+ check_singleton :compare_file
+ # FIXME
+ end
+
+ def test_compare_stream
+ check_singleton :compare_stream
+ # FIXME
+ end
+
+ class Stream
+ def initialize(f)
+ @f = f
+ end
+
+ def read(n)
+ @f.read(n)
+ end
+
+ def write(str)
+ @f.write str
+ end
+ end
+
+ def test_uptodate?
+ check_singleton :uptodate?
+ prepare_time_data
+ Dir.chdir('data') {
+ assert( uptodate?('newest', %w(old newer notexist)) )
+ assert( ! uptodate?('newer', %w(old newest notexist)) )
+ assert( ! uptodate?('notexist', %w(old newest newer)) )
+ }
+
+ # pathname
+ touch 'tmp/a'
+ touch 'tmp/b'
+ touch 'tmp/c'
+ assert_nothing_raised {
+ uptodate? Pathname.new('tmp/a'), ['tmp/b', 'tmp/c']
+ uptodate? 'tmp/a', [Pathname.new('tmp/b'), 'tmp/c']
+ uptodate? 'tmp/a', ['tmp/b', Pathname.new('tmp/c')]
+ uptodate? Pathname.new('tmp/a'), [Pathname.new('tmp/b'), Pathname.new('tmp/c')]
+ }
+ end
+
+ def test_cd
+ check_singleton :cd
+ end
+
+ def test_chdir
+ check_singleton :chdir
+ end
+
+ def test_getwd
+ check_singleton :getwd
+ end
+
+ def test_identical?
+ check_singleton :identical?
+ end
+
+ def test_link
+ check_singleton :link
+ end
+
+ def test_makedirs
+ check_singleton :makedirs
+ end
+
+ def test_mkpath
+ check_singleton :mkpath
+ end
+
+ def test_move
+ check_singleton :move
+ end
+
+ def test_rm_rf
+ check_singleton :rm_rf
+ end
+
+ def test_rmdir
+ check_singleton :rmdir
+ end
+
+ def test_rmtree
+ check_singleton :rmtree
+ end
+
+ def test_safe_unlink
+ check_singleton :safe_unlink
+ end
+
+ def test_symlink
+ check_singleton :symlink
+ end
+
+ def test_touch
+ check_singleton :touch
+ end
+
+ def test_collect_methods
+ end
+
+ def test_commands
+ end
+
+ def test_have_option?
+ end
+
+ def test_options
+ end
+
+ def test_options_of
+ end
+
+end
diff --git a/trunk/test/fileutils/test_nowrite.rb b/trunk/test/fileutils/test_nowrite.rb
new file mode 100644
index 0000000000..369f8ca608
--- /dev/null
+++ b/trunk/test/fileutils/test_nowrite.rb
@@ -0,0 +1,99 @@
+# $Id$
+
+require 'fileutils'
+require 'fileasserts'
+require 'tmpdir'
+require 'test/unit'
+
+class TestFileUtilsNoWrite < Test::Unit::TestCase
+
+ include FileUtils::NoWrite
+
+ def test_visibility
+ FileUtils::METHODS.each do |m|
+ assert_equal true, FileUtils::NoWrite.respond_to?(m, true),
+ "FileUtils::NoWrite.#{m} is not defined"
+ assert_equal true, FileUtils::NoWrite.respond_to?(m, false),
+ "FileUtils::NoWrite.#{m} is not public"
+ end
+ FileUtils::METHODS.each do |m|
+ assert_equal true, respond_to?(m, true),
+ "FileUtils::NoWrite\##{m} is not defined"
+ assert_equal true, FileUtils::NoWrite.private_method_defined?(m),
+ "FileUtils::NoWrite\##{m} is not private"
+ end
+ end
+
+ def my_rm_rf(path)
+ if File.exist?('/bin/rm')
+ system %Q[/bin/rm -rf "#{path}"]
+ else
+ FileUtils.rm_rf path
+ end
+ end
+
+ SRC = 'data/src'
+ COPY = 'data/copy'
+
+ def setup
+ @prevdir = Dir.pwd
+ tmproot = "#{Dir.tmpdir}/fileutils.rb.#{$$}"
+ Dir.mkdir tmproot unless File.directory?(tmproot)
+ Dir.chdir tmproot
+ my_rm_rf 'data'; Dir.mkdir 'data'
+ my_rm_rf 'tmp'; Dir.mkdir 'tmp'
+ File.open(SRC, 'w') {|f| f.puts 'dummy' }
+ File.open(COPY, 'w') {|f| f.puts 'dummy' }
+ end
+
+ def teardown
+ tmproot = Dir.pwd
+ Dir.chdir @prevdir
+ my_rm_rf tmproot
+ end
+
+ def test_cp
+ cp SRC, 'tmp/cp'
+ check 'tmp/cp'
+ end
+
+ def test_mv
+ mv SRC, 'tmp/mv'
+ check 'tmp/mv'
+ end
+
+ def check(dest)
+ assert_file_not_exist dest
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_rm
+ rm SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_rm_f
+ rm_f SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_rm_rf
+ rm_rf SRC
+ assert_file_exist SRC
+ assert_same_file SRC, COPY
+ end
+
+ def test_mkdir
+ mkdir 'dir'
+ assert_file_not_exist 'dir'
+ end
+
+ def test_mkdir_p
+ mkdir 'dir/dir/dir'
+ assert_file_not_exist 'dir'
+ end
+
+end
diff --git a/trunk/test/fileutils/test_verbose.rb b/trunk/test/fileutils/test_verbose.rb
new file mode 100644
index 0000000000..e60e85ea4e
--- /dev/null
+++ b/trunk/test/fileutils/test_verbose.rb
@@ -0,0 +1,25 @@
+# $Id$
+
+require 'test/unit'
+require 'fileutils'
+
+class TestFileUtilsVerbose < Test::Unit::TestCase
+
+ include FileUtils::Verbose
+
+ def test_visibility
+ FileUtils::METHODS.each do |m|
+ assert_equal true, FileUtils::Verbose.respond_to?(m, true),
+ "FileUtils::Verbose.#{m} is not defined"
+ assert_equal true, FileUtils::Verbose.respond_to?(m, false),
+ "FileUtils::Verbose.#{m} is not public"
+ end
+ FileUtils::METHODS.each do |m|
+ assert_equal true, respond_to?(m, true),
+ "FileUtils::Verbose.#{m} is not defined"
+ assert_equal true, FileUtils::Verbose.private_method_defined?(m),
+ "FileUtils::Verbose.#{m} is not private"
+ end
+ end
+
+end
diff --git a/trunk/test/gdbm/test_gdbm.rb b/trunk/test/gdbm/test_gdbm.rb
new file mode 100644
index 0000000000..6033a7640b
--- /dev/null
+++ b/trunk/test/gdbm/test_gdbm.rb
@@ -0,0 +1,715 @@
+require 'test/unit'
+require 'tmpdir'
+
+begin
+ require 'gdbm'
+rescue LoadError
+end
+
+if defined? GDBM
+ require 'tmpdir'
+ require 'fileutils'
+
+ class TestGDBM < Test::Unit::TestCase
+ def TestGDBM.uname_s
+ require 'rbconfig'
+ case RbConfig::CONFIG['target_os']
+ when 'cygwin'
+ require 'Win32API'
+ uname = Win32API.new('cygwin1', 'uname', 'P', 'I')
+ utsname = ' ' * 100
+ raise 'cannot get system name' if uname.call(utsname) == -1
+
+ utsname.unpack('A20' * 5)[0]
+ else
+ RbConfig::CONFIG['target_os']
+ end
+ end
+ SYSTEM = uname_s
+
+ def setup
+ @tmpdir = Dir.mktmpdir("tmptest_gdbm")
+ @prefix = "tmptest_gdbm_#{$$}"
+ @path = "#{@tmpdir}/#{@prefix}_"
+ assert_instance_of(GDBM, @gdbm = GDBM.new(@path))
+
+ # prepare to make readonly GDBM file
+ GDBM.open("#{@tmpdir}/#{@prefix}_rdonly", 0400) {|gdbm|
+ gdbm['foo'] = 'FOO'
+ }
+ assert_instance_of(GDBM, @gdbm_rdonly = GDBM.new("#{@tmpdir}/#{@prefix}_rdonly", nil))
+ end
+ def teardown
+ assert_nil(@gdbm.close)
+ assert_nil(@gdbm_rdonly.close)
+ ObjectSpace.each_object(GDBM) do |obj|
+ obj.close unless obj.closed?
+ end
+ FileUtils.remove_entry_secure @tmpdir
+ end
+
+ def check_size(expect, gdbm=@gdbm)
+ assert_equal(expect, gdbm.size)
+ n = 0
+ gdbm.each { n+=1 }
+ assert_equal(expect, n)
+ if expect == 0
+ assert_equal(true, gdbm.empty?)
+ else
+ assert_equal(false, gdbm.empty?)
+ end
+ end
+
+ def have_fork?
+ begin
+ fork{}
+ true
+ rescue NotImplementedError
+ false
+ end
+ end
+
+ def test_s_new_has_no_block
+ # GDBM.new ignore the block
+ foo = true
+ assert_instance_of(GDBM, gdbm = GDBM.new("#{@tmpdir}/#{@prefix}") { foo = false })
+ assert_equal(foo, true)
+ assert_nil(gdbm.close)
+ end
+ def test_s_open_create_new
+ return if /^CYGWIN_9/ =~ SYSTEM
+
+ save_mask = File.umask(0)
+ begin
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}"))
+ gdbm.close
+ assert_equal(File.stat("#{@tmpdir}/#{@prefix}").mode & 0777, 0666)
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}2", 0644))
+ gdbm.close
+ assert_equal(File.stat("#{@tmpdir}/#{@prefix}2").mode & 0777, 0644)
+ ensure
+ File.umask save_mask
+ end
+ end
+ def test_s_open_no_create
+ assert_nil(gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", nil),
+ "this test is failed on libgdbm 1.8.0")
+ ensure
+ gdbm.close if gdbm
+ end
+ def test_s_open_3rd_arg
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ GDBM::FAST))
+ gdbm.close
+
+ # gdbm 1.8.0 specific
+ if defined? GDBM::SYNC
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ GDBM::SYNC))
+ gdbm.close
+ end
+ # gdbm 1.8.0 specific
+ if defined? GDBM::NOLOCK
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ GDBM::NOLOCK))
+ gdbm.close
+ end
+ end
+ def test_s_open_with_block
+ assert_equal(GDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo)
+ end
+ def test_s_open_lock
+ return unless have_fork? # snip this test
+ pid = fork() {
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ sleep 2
+ }
+ begin
+ sleep 1
+ assert_raise(Errno::EWOULDBLOCK) {
+ begin
+ assert_instance_of(GDBM, gdbm2 = GDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ rescue Errno::EAGAIN, Errno::EACCES
+ raise Errno::EWOULDBLOCK
+ end
+ }
+ ensure
+ Process.wait pid
+ end
+ end
+
+=begin
+ # Is it guaranteed on many OS?
+ def test_s_open_lock_one_process
+ # locking on one process
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ assert_raise(Errno::EWOULDBLOCK) {
+ begin
+ GDBM.open("#{@tmpdir}/#{@prefix}", 0644)
+ rescue Errno::EAGAIN
+ raise Errno::EWOULDBLOCK
+ end
+ }
+ end
+=end
+
+ def test_s_open_nolock
+ # gdbm 1.8.0 specific
+ if not defined? GDBM::NOLOCK
+ return
+ end
+ return unless have_fork? # snip this test
+
+ pid = fork() {
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ GDBM::NOLOCK))
+ sleep 2
+ }
+ sleep 1
+ begin
+ gdbm2 = nil
+ assert_nothing_raised(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
+ assert_instance_of(GDBM, gdbm2 = GDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ }
+ ensure
+ Process.wait pid
+ gdbm2.close if gdbm2
+ end
+
+ p Dir.glob("#{@tmpdir}/#{@prefix}*") if $DEBUG
+
+ pid = fork() {
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ sleep 2
+ }
+ begin
+ sleep 1
+ gdbm2 = nil
+ assert_nothing_raised(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
+ # this test is failed on Cygwin98 (???)
+ assert_instance_of(GDBM, gdbm2 = GDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ GDBM::NOLOCK))
+ }
+ ensure
+ Process.wait pid
+ gdbm2.close if gdbm2
+ end
+ end
+
+ def test_s_open_error
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0))
+ assert_raise(Errno::EACCES) {
+ GDBM.open("#{@tmpdir}/#{@prefix}", 0)
+ }
+ gdbm.close
+ end
+
+ def test_close
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}"))
+ assert_nil(gdbm.close)
+
+ # closed GDBM file
+ assert_raise(RuntimeError) { gdbm.close }
+ end
+
+ def test_aref
+ assert_equal('bar', @gdbm['foo'] = 'bar')
+ assert_equal('bar', @gdbm['foo'])
+
+ assert_nil(@gdbm['bar'])
+ end
+
+ def test_fetch
+ assert_equal('bar', @gdbm['foo']='bar')
+ assert_equal('bar', @gdbm.fetch('foo'))
+
+ # key not found
+ assert_raise(IndexError) {
+ @gdbm.fetch('bar')
+ }
+
+ # test for `ifnone' arg
+ assert_equal('baz', @gdbm.fetch('bar', 'baz'))
+
+ # test for `ifnone' block
+ assert_equal('foobar', @gdbm.fetch('bar') {|key| 'foo' + key })
+ end
+
+ def test_aset
+ num = 0
+ 2.times {|i|
+ assert_equal('foo', @gdbm['foo'] = 'foo')
+ assert_equal('foo', @gdbm['foo'])
+ assert_equal('bar', @gdbm['foo'] = 'bar')
+ assert_equal('bar', @gdbm['foo'])
+
+ num += 1 if i == 0
+ assert_equal(num, @gdbm.size)
+
+ # assign nil
+ assert_equal('', @gdbm['bar'] = '')
+ assert_equal('', @gdbm['bar'])
+
+ num += 1 if i == 0
+ assert_equal(num, @gdbm.size)
+
+ # empty string
+ assert_equal('', @gdbm[''] = '')
+ assert_equal('', @gdbm[''])
+
+ num += 1 if i == 0
+ assert_equal(num, @gdbm.size)
+
+ # Fixnum
+ assert_equal('200', @gdbm['100'] = '200')
+ assert_equal('200', @gdbm['100'])
+
+ num += 1 if i == 0
+ assert_equal(num, @gdbm.size)
+
+ # Big key and value
+ assert_equal('y' * 100, @gdbm['x' * 100] = 'y' * 100)
+ assert_equal('y' * 100, @gdbm['x' * 100])
+
+ num += 1 if i == 0
+ assert_equal(num, @gdbm.size)
+ }
+ end
+
+ def test_index
+ assert_equal('bar', @gdbm['foo'] = 'bar')
+ assert_equal('foo', @gdbm.index('bar'))
+ assert_nil(@gdbm['bar'])
+ end
+
+ def test_values_at
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+ assert_equal(values.reverse, @gdbm.values_at(*keys.reverse))
+ end
+
+ def test_select_with_block
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+ ret = @gdbm.select {|k,v|
+ assert_equal(k.upcase, v)
+ k != "bar"
+ }
+ assert_equal([['baz', 'BAZ'], ['foo', 'FOO']],
+ ret.sort)
+ end
+
+ def test_length
+ num = 10
+ assert_equal(0, @gdbm.size)
+ num.times {|i|
+ i = i.to_s
+ @gdbm[i] = i
+ }
+ assert_equal(num, @gdbm.size)
+
+ @gdbm.shift
+
+ assert_equal(num - 1, @gdbm.size)
+ end
+
+ def test_empty?
+ assert_equal(true, @gdbm.empty?)
+ @gdbm['foo'] = 'FOO'
+ assert_equal(false, @gdbm.empty?)
+ end
+
+ def test_each_pair
+ n = 0
+ @gdbm.each_pair { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ n = 0
+ ret = @gdbm.each_pair {|key, val|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@gdbm, ret)
+ end
+
+ def test_each_value
+ n = 0
+ @gdbm.each_value { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ n = 0
+ ret = @gdbm.each_value {|val|
+ assert_not_nil(key = @gdbm.index(val))
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@gdbm, ret)
+ end
+
+ def test_each_key
+ n = 0
+ @gdbm.each_key { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ n = 0
+ ret = @gdbm.each_key {|key|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(@gdbm[key], values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@gdbm, ret)
+ end
+
+ def test_keys
+ assert_equal([], @gdbm.keys)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ assert_equal(keys.sort, @gdbm.keys.sort)
+ assert_equal(values.sort, @gdbm.values.sort)
+ end
+
+ def test_values
+ test_keys
+ end
+
+ def test_shift
+ assert_nil(@gdbm.shift)
+ assert_equal(0, @gdbm.size)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ ret_keys = []
+ ret_values = []
+ while ret = @gdbm.shift
+ ret_keys.push ret[0]
+ ret_values.push ret[1]
+
+ assert_equal(keys.size - ret_keys.size, @gdbm.size)
+ end
+
+ assert_equal(keys.sort, ret_keys.sort)
+ assert_equal(values.sort, ret_values.sort)
+ end
+
+ def test_delete
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ key = keys[1]
+
+ assert_nil(@gdbm.delete(key))
+ assert_equal(0, @gdbm.size)
+
+ @gdbm[keys[0]], @gdbm[keys[1]], @gdbm[keys[2]] = values
+
+ assert_equal('BAR', @gdbm.delete(key))
+ assert_nil(@gdbm[key])
+ assert_equal(2, @gdbm.size)
+
+ assert_nil(@gdbm.delete(key))
+
+ if /^CYGWIN_9/ !~ SYSTEM
+ assert_raise(GDBMError) {
+ @gdbm_rdonly.delete("foo")
+ }
+
+ assert_nil(@gdbm_rdonly.delete("bar"))
+ end
+ end
+ def test_delete_with_block
+ key = 'no called block'
+ @gdbm[key] = 'foo'
+ assert_equal('foo', @gdbm.delete(key) {|k| k.replace 'called block'})
+ assert_equal('no called block', key)
+ assert_equal(0, @gdbm.size)
+
+ key = 'no called block'
+ assert_equal(:blockval,
+ @gdbm.delete(key) {|k| k.replace 'called block'; :blockval})
+ assert_equal('called block', key)
+ assert_equal(0, @gdbm.size)
+ end
+
+ def test_delete_if
+ v = "0"
+ 100.times {@gdbm[v] = v; v = v.next}
+
+ ret = @gdbm.delete_if {|key, val| key.to_i < 50}
+ assert_equal(@gdbm, ret)
+ check_size(50, @gdbm)
+
+ ret = @gdbm.delete_if {|key, val| key.to_i >= 50}
+ assert_equal(@gdbm, ret)
+ check_size(0, @gdbm)
+
+ # break
+ v = "0"
+ 100.times {@gdbm[v] = v; v = v.next}
+ check_size(100, @gdbm)
+ n = 0;
+ @gdbm.delete_if {|key, val|
+ break if n > 50
+ n+=1
+ true
+ }
+ assert_equal(51, n)
+ check_size(49, @gdbm)
+
+ @gdbm.clear
+
+ # raise
+ v = "0"
+ 100.times {@gdbm[v] = v; v = v.next}
+ check_size(100, @gdbm)
+ n = 0;
+ begin
+ @gdbm.delete_if {|key, val|
+ raise "runtime error" if n > 50
+ n+=1
+ true
+ }
+ rescue
+ end
+ assert_equal(51, n)
+ check_size(49, @gdbm)
+ end
+
+ def test_reject
+ v = "0"
+ 100.times {@gdbm[v] = v; v = v.next}
+
+ hash = @gdbm.reject {|key, val| key.to_i < 50}
+ assert_instance_of(Hash, hash)
+ assert_equal(100, @gdbm.size)
+
+ assert_equal(50, hash.size)
+ hash.each_pair {|key,val|
+ assert_equal(false, key.to_i < 50)
+ assert_equal(key, val)
+ }
+
+ hash = @gdbm.reject {|key, val| key.to_i < 100}
+ assert_instance_of(Hash, hash)
+ assert_equal(true, hash.empty?)
+ end
+
+ def test_clear
+ v = "1"
+ 100.times {v = v.next; @gdbm[v] = v}
+
+ assert_equal(@gdbm, @gdbm.clear)
+
+ # validate GDBM#size
+ i = 0
+ @gdbm.each { i += 1 }
+ assert_equal(@gdbm.size, i)
+ assert_equal(0, i)
+ end
+
+ def test_invert
+ v = "0"
+ 100.times {@gdbm[v] = v; v = v.next}
+
+ hash = @gdbm.invert
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_update
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @gdbm["101"] = "101"
+ @gdbm.update hash
+ assert_equal(101, @gdbm.size)
+ @gdbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_replace
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @gdbm["101"] = "101"
+ @gdbm.replace hash
+ assert_equal(100, @gdbm.size)
+ @gdbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_reorganize
+ size1 = File.size(@path)
+ i = "1"
+ 1000.times {i = i.next; @gdbm[i] = i}
+ @gdbm.clear
+ @gdbm.sync
+
+ size2 = File.size(@path)
+ @gdbm.reorganize
+ size3 = File.size(@path)
+
+ # p [size1, size2, size3]
+ assert_equal(true, size1 < size2)
+ # this test is failed on Cygwin98. `GDBM version 1.8.0, as of May 19, 1999'
+ assert_equal(true, size3 < size2)
+ assert_equal(size1, size3)
+ end
+
+ def test_sync
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0666, GDBM::FAST))
+ assert_equal(gdbm.sync, gdbm)
+ gdbm.close
+ assert_instance_of(GDBM, gdbm = GDBM.open("#{@tmpdir}/#{@prefix}", 0666))
+ assert_equal(gdbm.sync, gdbm)
+ gdbm.close
+ end
+
+ def test_cachesize=
+ assert_equal(@gdbm.cachesize = 1024, 1024)
+ end
+
+ def test_fastmode=
+ assert_equal(@gdbm.fastmode = true, true)
+ end
+
+ def test_syncmode=
+ assert_equal(@gdbm.syncmode = true, true)
+ end
+
+ def test_haskey?
+ assert_equal('bar', @gdbm['foo']='bar')
+ assert_equal(true, @gdbm.has_key?('foo'))
+ assert_equal(false, @gdbm.has_key?('bar'))
+ end
+
+ def test_has_value?
+ assert_equal('bar', @gdbm['foo']='bar')
+ assert_equal(true, @gdbm.has_value?('bar'))
+ assert_equal(false, @gdbm.has_value?('foo'))
+ end
+
+ def test_to_a
+ v = "0"
+ 100.times {v = v.next; @gdbm[v] = v}
+
+ ary = @gdbm.to_a
+ assert_instance_of(Array, ary)
+ assert_equal(100, ary.size)
+ ary.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_to_hash
+ v = "0"
+ 100.times {v = v.next; @gdbm[v] = v}
+
+ hash = @gdbm.to_hash
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+ end
+
+ class TestGDBM2 < Test::Unit::TestCase
+ def setup
+ @tmproot = Dir.mktmpdir('ruby-gdbm')
+ end
+
+ def teardown
+ FileUtils.remove_entry_secure @tmproot if File.directory?(@tmproot)
+ end
+
+ def test_reader_open_notexist
+ assert_raise(Errno::ENOENT) {
+ GDBM.open("#{@tmproot}/a", 0666, GDBM::READER)
+ }
+ end
+
+ def test_writer_open_notexist
+ assert_raise(Errno::ENOENT) {
+ GDBM.open("#{@tmproot}/a", 0666, GDBM::WRITER)
+ }
+ end
+
+ def test_wrcreat_open_notexist
+ v = GDBM.open("#{@tmproot}/a", 0666, GDBM::WRCREAT)
+ assert_instance_of(GDBM, v)
+ v.close
+ end
+
+ def test_newdb_open_notexist
+ v = GDBM.open("#{@tmproot}/a", 0666, GDBM::NEWDB)
+ assert_instance_of(GDBM, v)
+ v.close
+ end
+
+ def test_reader_open
+ GDBM.open("#{@tmproot}/a.dbm") {} # create a db.
+ v = GDBM.open("#{@tmproot}/a.dbm", nil, GDBM::READER) {|d|
+ assert_raises(GDBMError) { d["k"] = "v" }
+ true
+ }
+ assert(v)
+ end
+
+ def test_newdb_open
+ GDBM.open("#{@tmproot}/a.dbm") {|dbm|
+ dbm["k"] = "v"
+ }
+ v = GDBM.open("#{@tmproot}/a.dbm", nil, GDBM::NEWDB) {|d|
+ assert_equal(0, d.length)
+ assert_nil(d["k"])
+ true
+ }
+ assert(v)
+ end
+
+ def test_freeze
+ GDBM.open("#{@tmproot}/a.dbm") {|d|
+ d.freeze
+ assert_raises(RuntimeError) { d["k"] = "v" }
+ }
+ end
+ end
+end
diff --git a/trunk/test/iconv/test_basic.rb b/trunk/test/iconv/test_basic.rb
new file mode 100644
index 0000000000..ea564e91f1
--- /dev/null
+++ b/trunk/test/iconv/test_basic.rb
@@ -0,0 +1,49 @@
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestIconv::Basic < TestIconv
+ def test_euc2sjis
+ iconv = Iconv.open('SHIFT_JIS', 'EUC-JP')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str)
+ iconv.close
+ end
+
+ def test_close
+ iconv = Iconv.new('Shift_JIS', 'EUC-JP')
+ output = ""
+ begin
+ output += iconv.iconv(EUCJ_STR)
+ output += iconv.iconv(nil)
+ ensure
+ assert_respond_to(iconv, :close)
+ assert_equal("", iconv.close)
+ assert_equal(SJIS_STR, output)
+ end
+ end
+
+ def test_open_without_block
+ assert_respond_to(Iconv, :open)
+ iconv = Iconv.open('SHIFT_JIS', 'EUC-JP')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str )
+ iconv.close
+ end
+
+ def test_open_with_block
+ input = "#{EUCJ_STR}\n"*2
+ output = ""
+ Iconv.open("Shift_JIS", "EUC-JP") do |cd|
+ input.each_line do |s|
+ output << cd.iconv(s)
+ end
+ output << cd.iconv(nil)
+ end
+ assert_equal("#{SJIS_STR}\n"*2, output)
+ end
+
+ def test_unknown_encoding
+ assert_raise(Iconv::InvalidEncoding) { Iconv.iconv("utf-8", "X-UKNOWN", "heh") }
+ end
+end if defined?(TestIconv)
diff --git a/trunk/test/iconv/test_option.rb b/trunk/test/iconv/test_option.rb
new file mode 100644
index 0000000000..b899ba2db1
--- /dev/null
+++ b/trunk/test/iconv/test_option.rb
@@ -0,0 +1,43 @@
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestIconv::Option < TestIconv
+ def test_ignore_option
+ begin
+ iconv = Iconv.new('SHIFT_JIS', 'EUC-JP')
+ iconv.transliterate?
+ rescue NotImplementedError
+ return
+ end
+ iconv = Iconv.new('SHIFT_JIS', 'EUC-JP//ignore')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str)
+ iconv.close
+
+ iconv = Iconv.new('SHIFT_JIS//IGNORE', 'EUC-JP//ignore')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str)
+ iconv.close
+ end
+
+ def test_translit_option
+ begin
+ iconv = Iconv.new('SHIFT_JIS', 'EUC-JP')
+ iconv.transliterate?
+ rescue NotImplementedError
+ return
+ end
+ iconv = Iconv.new('SHIFT_JIS', 'EUC-JP//ignore')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str)
+ iconv.close
+
+ iconv = Iconv.new('SHIFT_JIS//TRANSLIT', 'EUC-JP//translit//ignore')
+ str = iconv.iconv(EUCJ_STR)
+ str << iconv.iconv(nil)
+ assert_equal(SJIS_STR, str)
+ iconv.close
+ end
+end if defined?(TestIconv)
diff --git a/trunk/test/iconv/test_partial.rb b/trunk/test/iconv/test_partial.rb
new file mode 100644
index 0000000000..aa4d0ba250
--- /dev/null
+++ b/trunk/test/iconv/test_partial.rb
@@ -0,0 +1,41 @@
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestIconv::Partial < TestIconv
+ def test_partial_ascii
+ c = Iconv.open(ASCII, ASCII)
+ ref = '[ruby-core:17092]'
+ rescue
+ return
+ else
+ assert_equal("abc", c.iconv("abc"))
+ assert_equal("c", c.iconv("abc", 2), "#{ref}: with start")
+ assert_equal("c", c.iconv("abc", 2, 1), "#{ref}: with start, length")
+ assert_equal("c", c.iconv("abc", 2, 5), "#{ref}: with start, longer length")
+ assert_equal("bc", c.iconv("abc", -2), "#{ref}: with nagative start")
+ assert_equal("b", c.iconv("abc", -2, 1), "#{ref}: with nagative start, length")
+ assert_equal("bc", c.iconv("abc", -2, 5), "#{ref}: with nagative start, longer length")
+ assert_equal("", c.iconv("abc", 5), "#{ref}: with OOB")
+ assert_equal("", c.iconv("abc", 5, 2), "#{ref}: with OOB, length")
+ ensure
+ c.close if c
+ end
+
+ def test_partial_euc2sjis
+ c = Iconv.open('SHIFT_JIS', 'EUC-JP')
+ rescue
+ return
+ else
+ assert_equal(SJIS_STR[0, 2], c.iconv(EUCJ_STR, 0, 2))
+ assert_equal(SJIS_STR, c.iconv(EUCJ_STR, 0, 20))
+ assert_equal(SJIS_STR[2..-1], c.iconv(EUCJ_STR, 2))
+ assert_equal(SJIS_STR[2, 2], c.iconv(EUCJ_STR, 2, 2))
+ assert_equal(SJIS_STR[2..-1], c.iconv(EUCJ_STR, 2, 20))
+ assert_equal(SJIS_STR[-4..-1], c.iconv(EUCJ_STR, -4))
+ assert_equal(SJIS_STR[-4, 2], c.iconv(EUCJ_STR, -4, 2))
+ assert_equal(SJIS_STR[-4..-1], c.iconv(EUCJ_STR, -4, 20))
+ assert_equal("", c.iconv(EUCJ_STR, 20))
+ assert_equal("", c.iconv(EUCJ_STR, 20, 2))
+ ensure
+ c.close
+ end
+end if defined?(TestIconv)
diff --git a/trunk/test/iconv/utils.rb b/trunk/test/iconv/utils.rb
new file mode 100644
index 0000000000..bc75deb173
--- /dev/null
+++ b/trunk/test/iconv/utils.rb
@@ -0,0 +1,26 @@
+begin
+ require 'iconv'
+rescue LoadError
+else
+ require 'test/unit'
+end
+
+class TestIconv < ::Test::Unit::TestCase
+ if defined?(::Encoding) and String.method_defined?(:force_encoding)
+ def self.encode(str, enc)
+ str.force_encoding(enc)
+ end
+ else
+ def self.encode(str, enc)
+ str
+ end
+ end
+
+ def default_test
+ self.class == TestIconv or super
+ end
+
+ ASCII = "ascii"
+ EUCJ_STR = encode("\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa", "EUC-JP").freeze
+ SJIS_STR = encode("\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8", "Shift_JIS").freeze
+end if defined?(::Iconv)
diff --git a/trunk/test/inlinetest.rb b/trunk/test/inlinetest.rb
new file mode 100644
index 0000000000..46287364a9
--- /dev/null
+++ b/trunk/test/inlinetest.rb
@@ -0,0 +1,55 @@
+module InlineTest
+ def eval_part(libname, sep, part)
+ path = libpath(libname)
+ program = File.open(path) { |f| f.read }
+ mainpart, endpart = program.split(sep)
+ if endpart.nil?
+ raise RuntimeError.new("No #{part} part in the library '#{path}'")
+ end
+ eval(endpart, TOPLEVEL_BINDING, path, mainpart.count("\n")+1)
+ end
+ module_function :eval_part
+
+ def loadtest(libname)
+ require(libname)
+ in_critical do
+ in_progname(libpath(libname)) do
+ eval_part(libname, /^(?=if\s+(?:\$0\s*==\s*__FILE__|__FILE__\s*==\s*\$0)(?:[\#\s]|$))/, '$0 == __FILE__')
+ end
+ end
+ end
+ module_function :loadtest
+
+ def loadtest__END__part(libname)
+ require(libname)
+ eval_part(libname, /^__END__\r?$/, '__END__')
+ end
+ module_function :loadtest__END__part
+
+ @mutex = Mutex.new
+
+ def self.in_critical(&block)
+ @mutex.synchronize(&block)
+ end
+
+ def self.in_progname(progname)
+ $program_name = progname
+ alias $0 $program_name
+ begin
+ yield
+ ensure
+ alias $0 $PROGRAM_NAME
+ end
+ end
+
+ def self.libpath(libname)
+ libpath = nil
+ $:.find do |path|
+ File.file?(testname = File.join(path, libname)) && libpath = testname
+ end
+ if libpath.nil?
+ raise RuntimeError.new("'#{libname}' not found")
+ end
+ libpath
+ end
+end
diff --git a/trunk/test/io/nonblock/test_flush.rb b/trunk/test/io/nonblock/test_flush.rb
new file mode 100644
index 0000000000..2217dbcec9
--- /dev/null
+++ b/trunk/test/io/nonblock/test_flush.rb
@@ -0,0 +1,36 @@
+require 'test/unit'
+require 'timeout'
+begin
+ require 'io/nonblock'
+rescue LoadError
+end
+
+class TestIONonblock < Test::Unit::TestCase
+ def test_flush
+ r,w = IO.pipe
+ w.nonblock = true
+ w.sync = false
+ w << "b"
+ w.flush
+ w << "a" * 4096
+ result = ""
+ timeout(10) {
+ Thread.new {
+ Thread.pass
+ w.close
+ }
+ t = Thread.new {
+ while (Thread.pass; s = r.read(4096))
+ result << s
+ end
+ }
+ begin
+ w.flush # assert_raise(IOError, "[ruby-dev:24985]") {w.flush}
+ rescue Errno::EBADF, IOError
+ # ignore [ruby-dev:35638]
+ end
+ assert_nothing_raised {t.join}
+ }
+ assert_equal(4097, result.size)
+ end
+end if IO.method_defined?(:nonblock)
diff --git a/trunk/test/json/fixtures/fail1.json b/trunk/test/json/fixtures/fail1.json
new file mode 100644
index 0000000000..6216b865f1
--- /dev/null
+++ b/trunk/test/json/fixtures/fail1.json
@@ -0,0 +1 @@
+"A JSON payload should be an object or array, not a string." \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail10.json b/trunk/test/json/fixtures/fail10.json
new file mode 100644
index 0000000000..5d8c0047bd
--- /dev/null
+++ b/trunk/test/json/fixtures/fail10.json
@@ -0,0 +1 @@
+{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail11.json b/trunk/test/json/fixtures/fail11.json
new file mode 100644
index 0000000000..76eb95b458
--- /dev/null
+++ b/trunk/test/json/fixtures/fail11.json
@@ -0,0 +1 @@
+{"Illegal expression": 1 + 2} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail12.json b/trunk/test/json/fixtures/fail12.json
new file mode 100644
index 0000000000..77580a4522
--- /dev/null
+++ b/trunk/test/json/fixtures/fail12.json
@@ -0,0 +1 @@
+{"Illegal invocation": alert()} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail13.json b/trunk/test/json/fixtures/fail13.json
new file mode 100644
index 0000000000..379406b59b
--- /dev/null
+++ b/trunk/test/json/fixtures/fail13.json
@@ -0,0 +1 @@
+{"Numbers cannot have leading zeroes": 013} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail14.json b/trunk/test/json/fixtures/fail14.json
new file mode 100644
index 0000000000..0ed366b38a
--- /dev/null
+++ b/trunk/test/json/fixtures/fail14.json
@@ -0,0 +1 @@
+{"Numbers cannot be hex": 0x14} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail18.json b/trunk/test/json/fixtures/fail18.json
new file mode 100644
index 0000000000..d61a345465
--- /dev/null
+++ b/trunk/test/json/fixtures/fail18.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] // No, we don't limit our depth: Moved to pass...
diff --git a/trunk/test/json/fixtures/fail19.json b/trunk/test/json/fixtures/fail19.json
new file mode 100644
index 0000000000..3b9c46fa9a
--- /dev/null
+++ b/trunk/test/json/fixtures/fail19.json
@@ -0,0 +1 @@
+{"Missing colon" null} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail2.json b/trunk/test/json/fixtures/fail2.json
new file mode 100644
index 0000000000..6b7c11e5a5
--- /dev/null
+++ b/trunk/test/json/fixtures/fail2.json
@@ -0,0 +1 @@
+["Unclosed array" \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail20.json b/trunk/test/json/fixtures/fail20.json
new file mode 100644
index 0000000000..27c1af3e72
--- /dev/null
+++ b/trunk/test/json/fixtures/fail20.json
@@ -0,0 +1 @@
+{"Double colon":: null} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail21.json b/trunk/test/json/fixtures/fail21.json
new file mode 100644
index 0000000000..62474573b2
--- /dev/null
+++ b/trunk/test/json/fixtures/fail21.json
@@ -0,0 +1 @@
+{"Comma instead of colon", null} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail22.json b/trunk/test/json/fixtures/fail22.json
new file mode 100644
index 0000000000..a7752581bc
--- /dev/null
+++ b/trunk/test/json/fixtures/fail22.json
@@ -0,0 +1 @@
+["Colon instead of comma": false] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail23.json b/trunk/test/json/fixtures/fail23.json
new file mode 100644
index 0000000000..494add1ca1
--- /dev/null
+++ b/trunk/test/json/fixtures/fail23.json
@@ -0,0 +1 @@
+["Bad value", truth] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail24.json b/trunk/test/json/fixtures/fail24.json
new file mode 100644
index 0000000000..caff239bfc
--- /dev/null
+++ b/trunk/test/json/fixtures/fail24.json
@@ -0,0 +1 @@
+['single quote'] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail25.json b/trunk/test/json/fixtures/fail25.json
new file mode 100644
index 0000000000..2dfbd259ee
--- /dev/null
+++ b/trunk/test/json/fixtures/fail25.json
@@ -0,0 +1 @@
+["tab character in string "]
diff --git a/trunk/test/json/fixtures/fail27.json b/trunk/test/json/fixtures/fail27.json
new file mode 100644
index 0000000000..6b01a2ca4a
--- /dev/null
+++ b/trunk/test/json/fixtures/fail27.json
@@ -0,0 +1,2 @@
+["line
+break"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail28.json b/trunk/test/json/fixtures/fail28.json
new file mode 100644
index 0000000000..621a0101c6
--- /dev/null
+++ b/trunk/test/json/fixtures/fail28.json
@@ -0,0 +1,2 @@
+["line\
+break"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail3.json b/trunk/test/json/fixtures/fail3.json
new file mode 100644
index 0000000000..168c81eb78
--- /dev/null
+++ b/trunk/test/json/fixtures/fail3.json
@@ -0,0 +1 @@
+{unquoted_key: "keys must be quoted"} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail4.json b/trunk/test/json/fixtures/fail4.json
new file mode 100644
index 0000000000..9de168bf34
--- /dev/null
+++ b/trunk/test/json/fixtures/fail4.json
@@ -0,0 +1 @@
+["extra comma",] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail5.json b/trunk/test/json/fixtures/fail5.json
new file mode 100644
index 0000000000..ddf3ce3d24
--- /dev/null
+++ b/trunk/test/json/fixtures/fail5.json
@@ -0,0 +1 @@
+["double extra comma",,] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail6.json b/trunk/test/json/fixtures/fail6.json
new file mode 100644
index 0000000000..ed91580e1b
--- /dev/null
+++ b/trunk/test/json/fixtures/fail6.json
@@ -0,0 +1 @@
+[ , "<-- missing value"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail7.json b/trunk/test/json/fixtures/fail7.json
new file mode 100644
index 0000000000..8a96af3e4e
--- /dev/null
+++ b/trunk/test/json/fixtures/fail7.json
@@ -0,0 +1 @@
+["Comma after the close"], \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail8.json b/trunk/test/json/fixtures/fail8.json
new file mode 100644
index 0000000000..b28479c6ec
--- /dev/null
+++ b/trunk/test/json/fixtures/fail8.json
@@ -0,0 +1 @@
+["Extra close"]] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/fail9.json b/trunk/test/json/fixtures/fail9.json
new file mode 100644
index 0000000000..5815574f36
--- /dev/null
+++ b/trunk/test/json/fixtures/fail9.json
@@ -0,0 +1 @@
+{"Extra comma": true,} \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass1.json b/trunk/test/json/fixtures/pass1.json
new file mode 100644
index 0000000000..7828fcc137
--- /dev/null
+++ b/trunk/test/json/fixtures/pass1.json
@@ -0,0 +1,56 @@
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E666,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],
+ "compact": [1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066
+
+
+,"rosebud"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass15.json b/trunk/test/json/fixtures/pass15.json
new file mode 100644
index 0000000000..fc8376b605
--- /dev/null
+++ b/trunk/test/json/fixtures/pass15.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \x15"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass16.json b/trunk/test/json/fixtures/pass16.json
new file mode 100644
index 0000000000..c43ae3c286
--- /dev/null
+++ b/trunk/test/json/fixtures/pass16.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \'"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass17.json b/trunk/test/json/fixtures/pass17.json
new file mode 100644
index 0000000000..62b9214aed
--- /dev/null
+++ b/trunk/test/json/fixtures/pass17.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \017"] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass2.json b/trunk/test/json/fixtures/pass2.json
new file mode 100644
index 0000000000..d3c63c7ad8
--- /dev/null
+++ b/trunk/test/json/fixtures/pass2.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass26.json b/trunk/test/json/fixtures/pass26.json
new file mode 100644
index 0000000000..845d26a6a5
--- /dev/null
+++ b/trunk/test/json/fixtures/pass26.json
@@ -0,0 +1 @@
+["tab\ character\ in\ string\ "] \ No newline at end of file
diff --git a/trunk/test/json/fixtures/pass3.json b/trunk/test/json/fixtures/pass3.json
new file mode 100644
index 0000000000..4528d51f1a
--- /dev/null
+++ b/trunk/test/json/fixtures/pass3.json
@@ -0,0 +1,6 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
diff --git a/trunk/test/json/runner.rb b/trunk/test/json/runner.rb
new file mode 100755
index 0000000000..91bc12a594
--- /dev/null
+++ b/trunk/test/json/runner.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+
+require 'test/unit/ui/console/testrunner'
+require 'test/unit/testsuite'
+$:.unshift File.expand_path(File.dirname($0))
+$:.unshift 'tests'
+require 'test_json'
+require 'test_json_generate'
+require 'test_json_unicode'
+require 'test_json_addition'
+require 'test_json_rails'
+require 'test_json_fixtures'
+
+class TS_AllTests
+ def self.suite
+ suite = Test::Unit::TestSuite.new name
+ suite << TC_JSONGenerate.suite
+ suite << TC_JSON.suite
+ suite << TC_JSONUnicode.suite
+ suite << TC_JSONAddition.suite
+ suite << TC_JSONRails.suite
+ suite << TC_JSONFixtures.suite
+ end
+end
+Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
+ # vim: set et sw=2 ts=2:
diff --git a/trunk/test/json/test_json.rb b/trunk/test/json/test_json.rb
new file mode 100755
index 0000000000..257b8e0f63
--- /dev/null
+++ b/trunk/test/json/test_json.rb
@@ -0,0 +1,255 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+require 'test/unit'
+require 'json'
+
+class TC_JSON < Test::Unit::TestCase
+ include JSON
+
+ def setup
+ @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true].map do
+ |x| [x]
+ end
+ @ary_to_parse = ["1", '"foo"', "3.14", "4711.0", "2.718", "null",
+ "[1,-2,3]", "false", "true"].map do
+ |x| "[#{x}]"
+ end
+ @hash = {
+ 'a' => 2,
+ 'b' => 3.141,
+ 'c' => 'c',
+ 'd' => [ 1, "b", 3.14 ],
+ 'e' => { 'foo' => 'bar' },
+ 'g' => "\"\0\037",
+ 'h' => 1000.0,
+ 'i' => 0.001
+ }
+ @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
+ '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
+ end
+ suite << TC_JSON.suite
+
+ def test_construction
+ parser = JSON::Parser.new('test')
+ assert_equal 'test', parser.source
+ end
+
+ def assert_equal_float(expected, is)
+ assert_in_delta(expected.first, is.first, 1e-2)
+ end
+
+ def test_parse_simple_arrays
+ assert_equal([], parse('[]'))
+ assert_equal([], parse(' [ ] '))
+ assert_equal([nil], parse('[null]'))
+ assert_equal([false], parse('[false]'))
+ assert_equal([true], parse('[true]'))
+ assert_equal([-23], parse('[-23]'))
+ assert_equal([23], parse('[23]'))
+ assert_equal([0.23], parse('[0.23]'))
+ assert_equal([0.0], parse('[0e0]'))
+ assert_raises(JSON::ParserError) { parse('[+23.2]') }
+ assert_raises(JSON::ParserError) { parse('[+23]') }
+ assert_raises(JSON::ParserError) { parse('[.23]') }
+ assert_raises(JSON::ParserError) { parse('[023]') }
+ assert_equal_float [3.141], parse('[3.141]')
+ assert_equal_float [-3.141], parse('[-3.141]')
+ assert_equal_float [3.141], parse('[3141e-3]')
+ assert_equal_float [3.141], parse('[3141.1e-3]')
+ assert_equal_float [3.141], parse('[3141E-3]')
+ assert_equal_float [3.141], parse('[3141.0E-3]')
+ assert_equal_float [-3.141], parse('[-3141.0e-3]')
+ assert_equal_float [-3.141], parse('[-3141e-3]')
+ assert_equal([""], parse('[""]'))
+ assert_equal(["foobar"], parse('["foobar"]'))
+ assert_equal([{}], parse('[{}]'))
+ end
+
+ def test_parse_simple_objects
+ assert_equal({}, parse('{}'))
+ assert_equal({}, parse(' { } '))
+ assert_equal({ "a" => nil }, parse('{ "a" : null}'))
+ assert_equal({ "a" => nil }, parse('{"a":null}'))
+ assert_equal({ "a" => false }, parse('{ "a" : false } '))
+ assert_equal({ "a" => false }, parse('{"a":false}'))
+ assert_raises(JSON::ParserError) { parse('{false}') }
+ assert_equal({ "a" => true }, parse('{"a":true}'))
+ assert_equal({ "a" => true }, parse(' { "a" : true } '))
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
+ assert_equal({ "a" => 23 }, parse('{"a":23 } '))
+ assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
+ end
+
+ begin
+ require 'permutation'
+ def test_parse_more_complex_arrays
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
+ perms = Permutation.for a
+ perms.each do |perm|
+ orig_ary = perm.project
+ json = pretty_generate(orig_ary)
+ assert_equal orig_ary, parse(json)
+ end
+ end
+
+ def test_parse_complex_objects
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
+ perms = Permutation.for a
+ perms.each do |perm|
+ s = "a"
+ orig_obj = perm.project.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
+ json = pretty_generate(orig_obj)
+ assert_equal orig_obj, parse(json)
+ end
+ end
+ rescue LoadError
+ warn "Skipping permutation tests."
+ end
+
+ def test_parse_arrays
+ assert_equal([1,2,3], parse('[1,2,3]'))
+ assert_equal([1.2,2,3], parse('[1.2,2,3]'))
+ assert_equal([[],[[],[]]], parse('[[],[[],[]]]'))
+ end
+
+ def test_parse_values
+ assert_equal([""], parse('[""]'))
+ assert_equal(["\\"], parse('["\\\\"]'))
+ assert_equal(['"'], parse('["\""]'))
+ assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
+ assert_equal(["\"\b\n\r\t\0\037"],
+ parse('["\"\b\n\r\t\u0000\u001f"]'))
+ for i in 0 ... @ary.size
+ assert_equal(@ary[i], parse(@ary_to_parse[i]))
+ end
+ end
+
+ def test_parse_array
+ assert_equal([], parse('[]'))
+ assert_equal([], parse(' [ ] '))
+ assert_equal([1], parse('[1]'))
+ assert_equal([1], parse(' [ 1 ] '))
+ assert_equal(@ary,
+ parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]]'\
+ ',[false],[true]]'))
+ assert_equal(@ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]
+ , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
+ end
+
+ def test_parse_object
+ assert_equal({}, parse('{}'))
+ assert_equal({}, parse(' { } '))
+ assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}'))
+ assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } '))
+ end
+
+ def test_parser_reset
+ parser = Parser.new(@json)
+ assert_equal(@hash, parser.parse)
+ assert_equal(@hash, parser.parse)
+ end
+
+ def test_comments
+ json = <<EOT
+{
+ "key1":"value1", // eol comment
+ "key2":"value2" /* multi line
+ * comment */,
+ "key3":"value3" /* multi line
+ // nested eol comment
+ * comment */
+}
+EOT
+ assert_equal(
+ { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
+ parse(json))
+ json = <<EOT
+{
+ "key1":"value1" /* multi line
+ // nested eol comment
+ /* illegal nested multi line comment */
+ * comment */
+}
+EOT
+ assert_raises(ParserError) { parse(json) }
+ json = <<EOT
+{
+ "key1":"value1" /* multi line
+ // nested eol comment
+ closed multi comment */
+ and again, throw an Error */
+}
+EOT
+ assert_raises(ParserError) { parse(json) }
+ json = <<EOT
+{
+ "key1":"value1" /*/*/
+}
+EOT
+ assert_equal({ "key1" => "value1" }, parse(json))
+ end
+
+ def test_backslash
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
+ assert_equal json, JSON.unparse(data)
+ assert_equal data, JSON.parse(json)
+ #
+ data = [ '\\"' ]
+ json = '["\\\\\""]'
+ assert_equal json, JSON.unparse(data)
+ assert_equal data, JSON.parse(json)
+ #
+ json = '["\/"]'
+ data = JSON.parse(json)
+ assert_equal ['/'], data
+ assert_equal json, JSON.unparse(data)
+ #
+ json = '["\""]'
+ data = JSON.parse(json)
+ assert_equal ['"'], data
+ assert_equal json, JSON.unparse(data)
+ json = '["\\\'"]'
+ data = JSON.parse(json)
+ assert_equal ["'"], data
+ assert_equal '["\'"]', JSON.unparse(data)
+ end
+
+ def test_wrong_inputs
+ assert_raises(ParserError) { JSON.parse('"foo"') }
+ assert_raises(ParserError) { JSON.parse('123') }
+ assert_raises(ParserError) { JSON.parse('[] bla') }
+ assert_raises(ParserError) { JSON.parse('[] 1') }
+ assert_raises(ParserError) { JSON.parse('[] []') }
+ assert_raises(ParserError) { JSON.parse('[] {}') }
+ assert_raises(ParserError) { JSON.parse('{} []') }
+ assert_raises(ParserError) { JSON.parse('{} {}') }
+ assert_raises(ParserError) { JSON.parse('[NULL]') }
+ assert_raises(ParserError) { JSON.parse('[FALSE]') }
+ assert_raises(ParserError) { JSON.parse('[TRUE]') }
+ assert_raises(ParserError) { JSON.parse('[07] ') }
+ assert_raises(ParserError) { JSON.parse('[0a]') }
+ assert_raises(ParserError) { JSON.parse('[1.]') }
+ assert_raises(ParserError) { JSON.parse(' ') }
+ end
+
+ def test_nesting
+ to_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
+ assert_raises(JSON::NestingError) { JSON.parse to_deep }
+ assert_raises(JSON::NestingError) { JSON.parser.new(to_deep).parse }
+ assert_raises(JSON::NestingError) { JSON.parse to_deep, :max_nesting => 19 }
+ ok = JSON.parse to_deep, :max_nesting => 20
+ assert_kind_of Array, ok
+ ok = JSON.parse to_deep, :max_nesting => nil
+ assert_kind_of Array, ok
+ ok = JSON.parse to_deep, :max_nesting => false
+ assert_kind_of Array, ok
+ ok = JSON.parse to_deep, :max_nesting => 0
+ assert_kind_of Array, ok
+ end
+end
+ # vim: set et sw=2 ts=2:
diff --git a/trunk/test/json/test_json_addition.rb b/trunk/test/json/test_json_addition.rb
new file mode 100755
index 0000000000..04c690ce31
--- /dev/null
+++ b/trunk/test/json/test_json_addition.rb
@@ -0,0 +1,143 @@
+#!/usr/bin/env ruby
+
+require 'test/unit'
+require 'json/add/core'
+require 'date'
+
+class TC_JSONAddition < Test::Unit::TestCase
+ include JSON
+
+ class A
+ def initialize(a)
+ @a = a
+ end
+
+ attr_reader :a
+
+ def ==(other)
+ a == other.a
+ end
+
+ def self.json_create(object)
+ new(*object['args'])
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name,
+ 'args' => [ @a ],
+ }.to_json(*args)
+ end
+ end
+
+ class B
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name,
+ }.to_json(*args)
+ end
+ end
+
+ class C
+ def self.json_creatable?
+ false
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => 'TC_JSONAddition::Nix',
+ }.to_json(*args)
+ end
+ end
+
+ def setup
+ end
+
+ def test_extended_json
+ a = A.new(666)
+ assert A.json_creatable?
+ json = generate(a)
+ a_again = JSON.parse(json)
+ assert_kind_of a.class, a_again
+ assert_equal a, a_again
+ end
+
+ def test_extended_json_disabled
+ a = A.new(666)
+ assert A.json_creatable?
+ json = generate(a)
+ a_again = JSON.parse(json, :create_additions => true)
+ assert_kind_of a.class, a_again
+ assert_equal a, a_again
+ a_hash = JSON.parse(json, :create_additions => false)
+ assert_kind_of Hash, a_hash
+ assert_equal(
+ {"args"=>[666], "json_class"=>"TC_JSONAddition::A"}.sort_by { |k,| k },
+ a_hash.sort_by { |k,| k }
+ )
+ end
+
+ def test_extended_json_fail
+ b = B.new
+ assert !B.json_creatable?
+ json = generate(b)
+ assert_equal({ 'json_class' => B.name }, JSON.parse(json))
+ end
+
+ def test_extended_json_fail
+ c = C.new
+ assert !C.json_creatable?
+ json = generate(c)
+ assert_raises(ArgumentError) { JSON.parse(json) }
+ end
+
+ def test_raw_strings
+ raw = ''
+ raw_array = []
+ for i in 0..255
+ raw << i
+ raw_array << i
+ end
+ json = raw.to_json_raw
+ json_raw_object = raw.to_json_raw_object
+ hash = { 'json_class' => 'String', 'raw'=> raw_array }
+ assert_equal hash, json_raw_object
+ json_raw = <<EOT.chomp
+{\"json_class\":\"String\",\"raw\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]}
+EOT
+# "
+ assert_equal json_raw, json
+ raw_again = JSON.parse(json)
+ assert_equal raw, raw_again
+ end
+
+ def test_core
+ t = Time.at(1198254128, 895990)
+ assert_equal t, JSON(JSON(t))
+ d = Date.today
+ assert_equal d, JSON(JSON(d))
+ d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
+ assert_equal d, JSON(JSON(d))
+ assert_equal 1..10, JSON(JSON(1..10))
+ assert_equal 1...10, JSON(JSON(1...10))
+ assert_equal "a".."c", JSON(JSON("a".."c"))
+ assert_equal "a"..."c", JSON(JSON("a"..."c"))
+ struct = Struct.new 'MyJsonStruct', :foo, :bar
+ s = struct.new 4711, 'foot'
+ assert_equal s, JSON(JSON(s))
+ struct = Struct.new :foo, :bar
+ s = struct.new 4711, 'foot'
+ assert_raises(JSONError) { JSON(s) }
+ begin
+ raise TypeError, "test me"
+ rescue TypeError => e
+ e_json = JSON.generate e
+ e_again = JSON e_json
+ assert_kind_of TypeError, e_again
+ assert_equal e.message, e_again.message
+ assert_equal e.backtrace, e_again.backtrace
+ end
+ assert_equal /foo/, JSON(JSON(/foo/))
+ assert_equal /foo/i, JSON(JSON(/foo/i))
+ end
+end
diff --git a/trunk/test/json/test_json_fixtures.rb b/trunk/test/json/test_json_fixtures.rb
new file mode 100755
index 0000000000..33573cd300
--- /dev/null
+++ b/trunk/test/json/test_json_fixtures.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+
+require 'test/unit'
+require 'json'
+
+class TC_JSONFixtures < Test::Unit::TestCase
+ def setup
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/*.json')
+ passed, failed = Dir[fixtures].partition { |f| f['pass'] }
+ @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
+ @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
+ end
+
+ def test_passing
+ for name, source in @passed
+ assert JSON.parse(source),
+ "Did not pass for fixture '#{name}'"
+ end
+ end
+
+ def test_failing
+ for name, source in @failed
+ assert_raises(JSON::ParserError, JSON::NestingError,
+ "Did not fail for fixture '#{name}'") do
+ JSON.parse(source)
+ end
+ end
+ end
+end
diff --git a/trunk/test/json/test_json_generate.rb b/trunk/test/json/test_json_generate.rb
new file mode 100644
index 0000000000..e720b2d862
--- /dev/null
+++ b/trunk/test/json/test_json_generate.rb
@@ -0,0 +1,80 @@
+require 'test/unit'
+require 'json'
+
+class TC_JSONGenerate < Test::Unit::TestCase
+ include JSON
+
+ def setup
+ @hash = {
+ 'a' => 2,
+ 'b' => 3.141,
+ 'c' => 'c',
+ 'd' => [ 1, "b", 3.14 ],
+ 'e' => { 'foo' => 'bar' },
+ 'g' => "\"\0\037",
+ 'h' => 1000.0,
+ 'i' => 0.001
+ }
+ @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
+ @json3 = <<'EOT'.chomp
+{
+ "a": 2,
+ "b": 3.141,
+ "c": "c",
+ "d": [
+ 1,
+ "b",
+ 3.14
+ ],
+ "e": {
+ "foo": "bar"
+ },
+ "g": "\"\u0000\u001f",
+ "h": 1000.0,
+ "i": 0.001
+}
+EOT
+ end
+
+ def test_unparse
+ json = unparse(@hash)
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
+ parsed_json = parse(json)
+ assert_equal(@hash, parsed_json)
+ json = generate({1=>2})
+ assert_equal('{"1":2}', json)
+ parsed_json = parse(json)
+ assert_equal({"1"=>2}, parsed_json)
+ end
+
+ def test_unparse_pretty
+ json = pretty_unparse(@hash)
+ assert_equal(JSON.parse(@json3), JSON.parse(json))
+ parsed_json = parse(json)
+ assert_equal(@hash, parsed_json)
+ json = pretty_generate({1=>2})
+ assert_equal(<<'EOT'.chomp, json)
+{
+ "1": 2
+}
+EOT
+ parsed_json = parse(json)
+ assert_equal({"1"=>2}, parsed_json)
+ end
+
+ def test_states
+ json = generate({1=>2}, nil)
+ assert_equal('{"1":2}', json)
+ s = JSON.state.new(:check_circular => true)
+ #assert s.check_circular
+ h = { 1=>2 }
+ h[3] = h
+ assert_raises(JSON::CircularDatastructure) { generate(h, s) }
+ s = JSON.state.new(:check_circular => true)
+ #assert s.check_circular
+ a = [ 1, 2 ]
+ a << a
+ assert_raises(JSON::CircularDatastructure) { generate(a, s) }
+ end
+end
diff --git a/trunk/test/json/test_json_rails.rb b/trunk/test/json/test_json_rails.rb
new file mode 100644
index 0000000000..e44ea606e3
--- /dev/null
+++ b/trunk/test/json/test_json_rails.rb
@@ -0,0 +1,113 @@
+#!/usr/bin/env ruby
+
+require 'test/unit'
+require 'json/add/rails'
+require 'date'
+
+class TC_JSONRails < Test::Unit::TestCase
+ include JSON
+
+ class A
+ def initialize(a)
+ @a = a
+ end
+
+ attr_reader :a
+
+ def ==(other)
+ a == other.a
+ end
+
+ def self.json_create(object)
+ new(*object['args'])
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name,
+ 'args' => [ @a ],
+ }.to_json(*args)
+ end
+ end
+
+ class B
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name,
+ }.to_json(*args)
+ end
+ end
+
+ class C
+ def to_json(*args)
+ {
+ 'json_class' => 'TC_JSONRails::Nix',
+ }.to_json(*args)
+ end
+ end
+
+ def setup
+ end
+
+ def test_extended_json
+ a = A.new(666)
+ assert A.json_creatable?
+ json = generate(a)
+ a_again = JSON.parse(json)
+ assert_kind_of a.class, a_again
+ assert_equal a, a_again
+ end
+
+ def test_extended_json_disabled
+ a = A.new(666)
+ assert A.json_creatable?
+ json = generate(a)
+ a_again = JSON.parse(json, :create_additions => true)
+ assert_kind_of a.class, a_again
+ assert_equal a, a_again
+ a_hash = JSON.parse(json, :create_additions => false)
+ assert_kind_of Hash, a_hash
+ assert_equal(
+ {"args"=>[666], "json_class"=>"TC_JSONRails::A"}.sort_by { |k,| k },
+ a_hash.sort_by { |k,| k }
+ )
+ end
+
+ def test_extended_json_fail
+ b = B.new
+ assert !B.json_creatable?
+ json = generate(b)
+ assert_equal({ 'json_class' => B.name }, JSON.parse(json))
+ end
+
+ def test_extended_json_fail
+ c = C.new # with rails addition all objects are theoretically creatable
+ assert C.json_creatable?
+ json = generate(c)
+ assert_raises(ArgumentError) { JSON.parse(json) }
+ end
+
+ def test_raw_strings
+ raw = ''
+ raw_array = []
+ for i in 0..255
+ raw << i
+ raw_array << i
+ end
+ json = raw.to_json_raw
+ json_raw_object = raw.to_json_raw_object
+ hash = { 'json_class' => 'String', 'raw'=> raw_array }
+ assert_equal hash, json_raw_object
+ json_raw = <<EOT.chomp
+{\"json_class\":\"String\",\"raw\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]}
+EOT
+# "
+ assert_equal json_raw, json
+ raw_again = JSON.parse(json)
+ assert_equal raw, raw_again
+ end
+
+ def test_symbol
+ assert_equal '"foo"', JSON(:foo) # we don't want an object here
+ end
+end
diff --git a/trunk/test/json/test_json_unicode.rb b/trunk/test/json/test_json_unicode.rb
new file mode 100755
index 0000000000..cad93846b5
--- /dev/null
+++ b/trunk/test/json/test_json_unicode.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+require 'test/unit'
+require 'json'
+
+class TC_JSONUnicode < Test::Unit::TestCase
+ include JSON
+
+ def setup
+ end
+
+ def test_unicode
+ assert_equal '""', ''.to_json
+ assert_equal '"\\b"', "\b".to_json
+ assert_equal '"\u0001"', 0x1.chr.to_json
+ assert_equal '"\u001f"', 0x1f.chr.to_json
+ assert_equal '" "', ' '.to_json
+ assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
+ utf8 = [ "© ≠ €! \01" ]
+ json = '["\u00a9 \u2260 \u20ac! \u0001"]'
+ assert_equal json, utf8.to_json
+ assert_equal utf8, parse(json)
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
+ json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
+ assert_equal json, utf8.to_json
+ assert_equal utf8, parse(json)
+ utf8 = ['სáƒáƒ¥áƒáƒ áƒ—ველáƒ']
+ json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
+ assert_equal json, utf8.to_json
+ assert_equal utf8, parse(json)
+ assert_equal '["\\u00c3"]', JSON.generate(["Ã"])
+ assert_equal ["€"], JSON.parse('["\u20ac"]')
+ utf8 = ["\xf0\xa0\x80\x81"]
+ json = '["\ud840\udc01"]'
+ assert_equal json, JSON.generate(utf8)
+ assert_equal utf8, JSON.parse(json)
+ end
+
+ def test_chars
+ (0..0x7f).each do |i|
+ json = '["\u%04x"]' % i
+ if RUBY_VERSION >= "1.9."
+ i = i.chr
+ end
+ assert_equal i, JSON.parse(json).first[0]
+ if i == ?\b
+ generated = JSON.generate(["" << i])
+ assert '["\b"]' == generated || '["\10"]' == generated
+ elsif [?\n, ?\r, ?\t, ?\f].include?(i)
+ assert_equal '[' << ('' << i).dump << ']', JSON.generate(["" << i])
+ elsif i.chr < 0x20.chr
+ assert_equal json, JSON.generate(["" << i])
+ end
+ end
+ assert_raises(JSON::GeneratorError) do
+ JSON.generate(["" << 0x80])
+ end
+ assert_equal "\302\200", JSON.parse('["\u0080"]').first
+ end
+end
diff --git a/trunk/test/logger/test_logger.rb b/trunk/test/logger/test_logger.rb
new file mode 100644
index 0000000000..12728c608b
--- /dev/null
+++ b/trunk/test/logger/test_logger.rb
@@ -0,0 +1,376 @@
+require 'test/unit'
+require 'logger'
+require 'tempfile'
+
+
+class TestLoggerSeverity < Test::Unit::TestCase
+ def test_enum
+ logger_levels = Logger.constants
+ levels = [:WARN, :UNKNOWN, :INFO, :FATAL, :DEBUG, :ERROR]
+ Logger::Severity.constants.each do |level|
+ assert(levels.include?(level))
+ assert(logger_levels.include?(level))
+ end
+ assert_equal(levels.size, Logger::Severity.constants.size)
+ end
+end
+
+
+class TestLogger < Test::Unit::TestCase
+ include Logger::Severity
+
+ def setup
+ @logger = Logger.new(nil)
+ end
+
+ class Log
+ attr_reader :label, :datetime, :pid, :severity, :progname, :msg
+ def initialize(line)
+ /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/n =~ line
+ @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
+ end
+ end
+
+ def log_add(logger, severity, msg, progname = nil, &block)
+ log(logger, :add, severity, msg, progname, &block)
+ end
+
+ def log(logger, msg_id, *arg, &block)
+ Log.new(log_raw(logger, msg_id, *arg, &block))
+ end
+
+ def log_raw(logger, msg_id, *arg, &block)
+ logdev = Tempfile.new(File.basename(__FILE__) + '.log')
+ logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
+ logger.__send__(msg_id, *arg, &block)
+ logdev.open
+ msg = logdev.read
+ logdev.close
+ msg
+ end
+
+ def test_level
+ @logger.level = UNKNOWN
+ assert_equal(UNKNOWN, @logger.level)
+ @logger.level = INFO
+ assert_equal(INFO, @logger.level)
+ @logger.sev_threshold = ERROR
+ assert_equal(ERROR, @logger.sev_threshold)
+ @logger.sev_threshold = WARN
+ assert_equal(WARN, @logger.sev_threshold)
+ assert_equal(WARN, @logger.level)
+
+ @logger.level = DEBUG
+ assert(@logger.debug?)
+ assert(@logger.info?)
+ @logger.level = INFO
+ assert(!@logger.debug?)
+ assert(@logger.info?)
+ assert(@logger.warn?)
+ @logger.level = WARN
+ assert(!@logger.info?)
+ assert(@logger.warn?)
+ assert(@logger.error?)
+ @logger.level = ERROR
+ assert(!@logger.warn?)
+ assert(@logger.error?)
+ assert(@logger.fatal?)
+ @logger.level = FATAL
+ assert(!@logger.error?)
+ assert(@logger.fatal?)
+ @logger.level = UNKNOWN
+ assert(!@logger.error?)
+ assert(!@logger.fatal?)
+ end
+
+ def test_progname
+ assert_nil(@logger.progname)
+ @logger.progname = "name"
+ assert_equal("name", @logger.progname)
+ end
+
+ def test_datetime_format
+ dummy = STDERR
+ logger = Logger.new(dummy)
+ log = log_add(logger, INFO, "foo")
+ assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime)
+ logger.datetime_format = "%d%b%Y@%H:%M:%S"
+ log = log_add(logger, INFO, "foo")
+ assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
+ logger.datetime_format = ""
+ log = log_add(logger, INFO, "foo")
+ assert_match(/^$/, log.datetime)
+ end
+
+ def test_formatter
+ dummy = STDERR
+ logger = Logger.new(dummy)
+ # default
+ log = log(logger, :info, "foo")
+ assert_equal("foo\n", log.msg)
+ # config
+ logger.formatter = proc { |severity, timestamp, progname, msg|
+ "#{severity}:#{msg}\n\n"
+ }
+ line = log_raw(logger, :info, "foo")
+ assert_equal("INFO:foo\n\n", line)
+ # recover
+ logger.formatter = nil
+ log = log(logger, :info, "foo")
+ assert_equal("foo\n", log.msg)
+ # again
+ o = Object.new
+ def o.call(severity, timestamp, progname, msg)
+ "<<#{severity}-#{msg}>>\n"
+ end
+ logger.formatter = o
+ line = log_raw(logger, :info, "foo")
+ assert_equal("<<INFO-foo>>\n", line)
+ end
+
+ def test_initialize
+ logger = Logger.new(STDERR)
+ assert_nil(logger.progname)
+ assert_equal(DEBUG, logger.level)
+ assert_nil(logger.datetime_format)
+ end
+
+ def test_add
+ logger = Logger.new(nil)
+ logger.progname = "my_progname"
+ assert(logger.add(INFO))
+ log = log_add(logger, nil, "msg")
+ assert_equal("ANY", log.severity)
+ assert_equal("my_progname", log.progname)
+ logger.level = WARN
+ assert(logger.log(INFO))
+ assert_nil(log_add(logger, INFO, "msg").msg)
+ log = log_add(logger, WARN, nil) { "msg" }
+ assert_equal("msg\n", log.msg)
+ log = log_add(logger, WARN, "") { "msg" }
+ assert_equal("\n", log.msg)
+ assert_equal("my_progname", log.progname)
+ log = log_add(logger, WARN, nil, "progname?")
+ assert_equal("progname?\n", log.msg)
+ assert_equal("my_progname", log.progname)
+ end
+
+ def test_level_log
+ logger = Logger.new(nil)
+ logger.progname = "my_progname"
+ log = log(logger, :debug, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("DEBUG", log.severity)
+ assert_equal("D", log.label)
+ #
+ log = log(logger, :debug) { "msg_block" }
+ assert_equal("msg_block\n", log.msg)
+ assert_equal("my_progname", log.progname)
+ log = log(logger, :debug, "msg_inline")
+ assert_equal("msg_inline\n", log.msg)
+ assert_equal("my_progname", log.progname)
+ #
+ log = log(logger, :info, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("INFO", log.severity)
+ assert_equal("I", log.label)
+ #
+ log = log(logger, :warn, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("WARN", log.severity)
+ assert_equal("W", log.label)
+ #
+ log = log(logger, :error, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("ERROR", log.severity)
+ assert_equal("E", log.label)
+ #
+ log = log(logger, :fatal, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("FATAL", log.severity)
+ assert_equal("F", log.label)
+ #
+ log = log(logger, :unknown, "custom_progname") { "msg" }
+ assert_equal("msg\n", log.msg)
+ assert_equal("custom_progname", log.progname)
+ assert_equal("ANY", log.severity)
+ assert_equal("A", log.label)
+ end
+
+ def test_close
+ r, w = IO.pipe
+ assert(!w.closed?)
+ logger = Logger.new(w)
+ logger.close
+ assert(w.closed?)
+ r.close
+ end
+
+ class MyError < StandardError
+ end
+
+ class MyMsg
+ def inspect
+ "my_msg"
+ end
+ end
+
+ def test_format
+ logger = Logger.new(nil)
+ log = log_add(logger, INFO, "msg\n")
+ assert_equal("msg\n\n", log.msg)
+ begin
+ raise MyError.new("excn")
+ rescue MyError => e
+ log = log_add(logger, INFO, e)
+ assert_match(/^excn \(TestLogger::MyError\)/, log.msg)
+ # expects backtrace is dumped across multi lines. 10 might be changed.
+ assert(log.msg.split(/\n/).size >= 10)
+ end
+ log = log_add(logger, INFO, MyMsg.new)
+ assert_equal("my_msg\n", log.msg)
+ end
+
+ def test_lshift
+ r, w = IO.pipe
+ logger = Logger.new(w)
+ logger << "msg"
+ read_ready, = IO.select([r], nil, nil, 0.1)
+ w.close
+ msg = r.read
+ r.close
+ assert_equal("msg", msg)
+ #
+ r, w = IO.pipe
+ logger = Logger.new(w)
+ logger << "msg2\n\n"
+ read_ready, = IO.select([r], nil, nil, 0.1)
+ w.close
+ msg = r.read
+ r.close
+ assert_equal("msg2\n\n", msg)
+ end
+end
+
+class TestLogDevice < Test::Unit::TestCase
+ def d(log)
+ Logger::LogDevice.new(log)
+ end
+
+ def test_initialize
+ logdev = d(STDERR)
+ assert_equal(STDERR, logdev.dev)
+ assert_nil(logdev.filename)
+ assert_raises(TypeError) do
+ d(nil)
+ end
+ #
+ filename = __FILE__ + ".#{$$}"
+ begin
+ logdev = d(filename)
+ assert(File.exist?(filename))
+ assert(logdev.dev.sync)
+ assert_equal(filename, logdev.filename)
+ ensure
+ logdev.close
+ File.unlink(filename)
+ end
+ end
+
+ def test_write
+ r, w = IO.pipe
+ logdev = d(w)
+ logdev.write("msg2\n\n")
+ read_ready, = IO.select([r], nil, nil, 0.1)
+ w.close
+ msg = r.read
+ r.close
+ assert_equal("msg2\n\n", msg)
+ end
+
+ def test_close
+ r, w = IO.pipe
+ logdev = d(w)
+ logdev.write("msg2\n\n")
+ read_ready, = IO.select([r], nil, nil, 0.1)
+ assert(!w.closed?)
+ logdev.close
+ assert(w.closed?)
+ r.close
+ end
+
+ def test_shifting_size
+ logfile = File.basename(__FILE__) + '_1.log'
+ logfile0 = logfile + '.0'
+ logfile1 = logfile + '.1'
+ logfile2 = logfile + '.2'
+ logfile3 = logfile + '.3'
+ File.unlink(logfile) if File.exist?(logfile)
+ File.unlink(logfile0) if File.exist?(logfile0)
+ File.unlink(logfile1) if File.exist?(logfile1)
+ File.unlink(logfile2) if File.exist?(logfile2)
+ logger = Logger.new(logfile, 4, 100)
+ logger.error("0" * 15)
+ assert(File.exist?(logfile))
+ assert(!File.exist?(logfile0))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile0))
+ assert(!File.exist?(logfile1))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile1))
+ assert(!File.exist?(logfile2))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile2))
+ assert(!File.exist?(logfile3))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile3))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile3))
+ logger.close
+ File.unlink(logfile)
+ File.unlink(logfile0)
+ File.unlink(logfile1)
+ File.unlink(logfile2)
+
+ logfile = File.basename(__FILE__) + '_2.log'
+ logfile0 = logfile + '.0'
+ logfile1 = logfile + '.1'
+ logfile2 = logfile + '.2'
+ logfile3 = logfile + '.3'
+ logger = Logger.new(logfile, 4, 150)
+ logger.error("0" * 15)
+ assert(File.exist?(logfile))
+ assert(!File.exist?(logfile0))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile0))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile0))
+ assert(!File.exist?(logfile1))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile1))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile1))
+ assert(!File.exist?(logfile2))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile2))
+ logger.error("0" * 15)
+ assert(File.exist?(logfile2))
+ assert(!File.exist?(logfile3))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile3))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile3))
+ logger.error("0" * 15)
+ assert(!File.exist?(logfile3))
+ logger.close
+ File.unlink(logfile)
+ File.unlink(logfile0)
+ File.unlink(logfile1)
+ File.unlink(logfile2)
+ end
+end
diff --git a/trunk/test/monitor/test_monitor.rb b/trunk/test/monitor/test_monitor.rb
new file mode 100644
index 0000000000..064471eecb
--- /dev/null
+++ b/trunk/test/monitor/test_monitor.rb
@@ -0,0 +1,163 @@
+require "monitor"
+require "thread"
+
+require "test/unit"
+
+class TestMonitor < Test::Unit::TestCase
+ def setup
+ @monitor = Monitor.new
+ end
+
+ def test_enter
+ ary = []
+ queue = Queue.new
+ th = Thread.start {
+ queue.pop
+ @monitor.enter
+ for i in 6 .. 10
+ ary.push(i)
+ Thread.pass
+ end
+ @monitor.exit
+ }
+ @monitor.enter
+ queue.enq(nil)
+ for i in 1 .. 5
+ ary.push(i)
+ Thread.pass
+ end
+ @monitor.exit
+ th.join
+ assert_equal((1..10).to_a, ary)
+ end
+
+ def test_synchronize
+ ary = []
+ queue = Queue.new
+ th = Thread.start {
+ queue.pop
+ @monitor.synchronize do
+ for i in 6 .. 10
+ ary.push(i)
+ Thread.pass
+ end
+ end
+ }
+ @monitor.synchronize do
+ queue.enq(nil)
+ for i in 1 .. 5
+ ary.push(i)
+ Thread.pass
+ end
+ end
+ th.join
+ assert_equal((1..10).to_a, ary)
+ end
+
+ def test_try_enter
+ queue1 = Queue.new
+ queue2 = Queue.new
+ th = Thread.start {
+ queue1.deq
+ @monitor.enter
+ queue2.enq(nil)
+ queue1.deq
+ @monitor.exit
+ queue2.enq(nil)
+ }
+ assert_equal(true, @monitor.try_enter)
+ @monitor.exit
+ queue1.enq(nil)
+ queue2.deq
+ assert_equal(false, @monitor.try_enter)
+ queue1.enq(nil)
+ queue2.deq
+ assert_equal(true, @monitor.try_enter)
+ end
+
+ def test_cond
+ cond = @monitor.new_cond
+
+ a = "foo"
+ queue1 = Queue.new
+ Thread.start do
+ queue1.deq
+ @monitor.synchronize do
+ a = "bar"
+ cond.signal
+ end
+ end
+ @monitor.synchronize do
+ queue1.enq(nil)
+ assert_equal("foo", a)
+ result1 = cond.wait
+ assert_equal(true, result1)
+ assert_equal("bar", a)
+ end
+ end
+
+ def _test_timedwait
+ b = "foo"
+ queue2 = Queue.new
+ Thread.start do
+ queue2.deq
+ @monitor.synchronize do
+ b = "bar"
+ cond.signal
+ end
+ end
+ @monitor.synchronize do
+ queue2.enq(nil)
+ assert_equal("foo", b)
+ result2 = cond.wait(0.1)
+ assert_equal(true, result2)
+ assert_equal("bar", b)
+ end
+
+ c = "foo"
+ queue3 = Queue.new
+ Thread.start do
+ queue3.deq
+ @monitor.synchronize do
+ c = "bar"
+ cond.signal
+ end
+ end
+ @monitor.synchronize do
+ assert_equal("foo", c)
+ result3 = cond.wait(0.1)
+ assert_equal(false, result3)
+ assert_equal("foo", c)
+ queue3.enq(nil)
+ result4 = cond.wait
+ assert_equal(true, result4)
+ assert_equal("bar", c)
+ end
+
+# d = "foo"
+# cumber_thread = Thread.start {
+# loop do
+# @monitor.synchronize do
+# d = "foo"
+# end
+# end
+# }
+# queue3 = Queue.new
+# Thread.start do
+# queue3.pop
+# @monitor.synchronize do
+# d = "bar"
+# cond.signal
+# end
+# end
+# @monitor.synchronize do
+# queue3.enq(nil)
+# assert_equal("foo", d)
+# result5 = cond.wait
+# assert_equal(true, result5)
+# # this thread has priority over cumber_thread
+# assert_equal("bar", d)
+# end
+# cumber_thread.kill
+ end
+end
diff --git a/trunk/test/net/http/test_http.rb b/trunk/test/net/http/test_http.rb
new file mode 100644
index 0000000000..50d1fe2eae
--- /dev/null
+++ b/trunk/test/net/http/test_http.rb
@@ -0,0 +1,320 @@
+# $Id$
+
+require 'test/unit'
+require 'net/http'
+require 'stringio'
+require File.expand_path("utils", File.dirname(__FILE__))
+
+module TestNetHTTP_version_1_1_methods
+
+ def test_s_get
+ assert_equal $test_net_http_data,
+ Net::HTTP.get(config('host'), '/', config('port'))
+ end
+
+ def test_head
+ start {|http|
+ res = http.head('/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_equal $test_net_http_data.size, res['Content-Length'].to_i
+ }
+ end
+
+ def test_get
+ start {|http|
+ _test_get__get http
+ _test_get__iter http
+ _test_get__chunked http
+ }
+ end
+
+ def _test_get__get(http)
+ res, body = http.get('/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_kind_of String, body
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_equal $test_net_http_data.size, body.size
+ assert_equal $test_net_http_data, body
+ assert_equal $test_net_http_data.size, res.body.size
+ assert_equal $test_net_http_data, res.body
+ end
+
+ def _test_get__iter(http)
+ buf = ''
+ res, body = http.get('/') {|s| buf << s }
+ assert_kind_of Net::HTTPResponse, res
+ # assert_kind_of String, res.body
+ # assert_kind_of String, body
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_equal $test_net_http_data.size, buf.size
+ assert_equal $test_net_http_data, buf
+ # assert_equal $test_net_http_data.size, res.body.size
+ # assert_equal $test_net_http_data, res.body
+ end
+
+ def _test_get__chunked(http)
+ buf = ''
+ res, body = http.get('/') {|s| buf << s }
+ assert_kind_of Net::HTTPResponse, res
+ # assert_kind_of String, res.body
+ # assert_kind_of String, body
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_equal $test_net_http_data.size, buf.size
+ assert_equal $test_net_http_data, buf
+ # assert_equal $test_net_http_data.size, res.body.size
+ # assert_equal $test_net_http_data, res.body
+ end
+
+ def test_get__break
+ i = 0
+ start {|http|
+ http.get('/') do |str|
+ i += 1
+ break
+ end
+ }
+ assert_equal 1, i
+ end
+
+ def test_get__implicit_start
+ res, body = new().get('/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, body
+ assert_kind_of String, res.body
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_equal $test_net_http_data.size, res.body.size
+ assert_equal $test_net_http_data, res.body
+ end
+
+ def test_get2
+ start {|http|
+ http.get2('/') {|res|
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of Net::HTTPResponse, res.header
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data_type, res['Content-Type']
+ assert_kind_of String, res.body
+ assert_kind_of String, res.entity
+ assert_equal $test_net_http_data.size, res.body.size
+ assert_equal $test_net_http_data, res.body
+ assert_equal $test_net_http_data, res.entity
+ }
+ }
+ end
+
+ def test_post
+ start {|http|
+ _test_post__base http
+ _test_post__file http
+ }
+ end
+
+ def _test_post__base(http)
+ uheader = {}
+ uheader['Accept'] = 'application/octet-stream'
+ data = 'post data'
+ res, body = http.post('/', data)
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, body
+ assert_kind_of String, res.body
+ assert_equal data, body
+ assert_equal data, res.body
+ assert_equal data, res.entity
+ end
+
+ def _test_post__file(http)
+ data = 'post data'
+ f = StringIO.new
+ http.post('/', data, nil, f)
+ assert_equal data, f.string
+ end
+
+ def test_s_post_form
+ res = Net::HTTP.post_form(
+ URI.parse("http://#{config('host')}:#{config('port')}/"),
+ "a" => "x")
+ assert_equal ["a=x"], res.body.split(/[;&]/).sort
+
+ res = Net::HTTP.post_form(
+ URI.parse("http://#{config('host')}:#{config('port')}/"),
+ "a" => "x",
+ "b" => "y")
+ assert_equal ["a=x", "b=y"], res.body.split(/[;&]/).sort
+
+ res = Net::HTTP.post_form(
+ URI.parse("http://#{config('host')}:#{config('port')}/"),
+ "a" => ["x1", "x2"],
+ "b" => "y")
+ assert_equal ["a=x1", "a=x2", "b=y"], res.body.split(/[;&]/).sort
+ end
+
+end
+
+
+module TestNetHTTP_version_1_2_methods
+
+ def test_request
+ start {|http|
+ _test_request__GET http
+ _test_request__file http
+ # _test_request__range http # WEBrick does not support Range: header.
+ _test_request__HEAD http
+ _test_request__POST http
+ _test_request__stream_body http
+ }
+ end
+
+ def _test_request__GET(http)
+ req = Net::HTTP::Get.new('/')
+ http.request(req) {|res|
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_equal $test_net_http_data.size, res.body.size
+ assert_equal $test_net_http_data, res.body
+ }
+ end
+
+ def _test_request__file(http)
+ req = Net::HTTP::Get.new('/')
+ http.request(req) {|res|
+ assert_kind_of Net::HTTPResponse, res
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ f = StringIO.new("".force_encoding("ASCII-8BIT"))
+ res.read_body f
+ assert_equal $test_net_http_data.bytesize, f.string.bytesize
+ assert_equal $test_net_http_data.encoding, f.string.encoding
+ assert_equal $test_net_http_data, f.string
+ }
+ end
+
+ def _test_request__range(http)
+ req = Net::HTTP::Get.new('/')
+ req['range'] = 'bytes=0-5'
+ assert_equal $test_net_http_data[0,6], http.request(req).body
+ end
+
+ def _test_request__HEAD(http)
+ req = Net::HTTP::Head.new('/')
+ http.request(req) {|res|
+ assert_kind_of Net::HTTPResponse, res
+ assert_not_nil res['content-length']
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_nil res.body
+ }
+ end
+
+ def _test_request__POST(http)
+ data = 'post data'
+ req = Net::HTTP::Post.new('/')
+ req['Accept'] = $test_net_http_data_type
+ http.request(req, data) {|res|
+ assert_kind_of Net::HTTPResponse, res
+ assert_equal data.size, res['content-length'].to_i
+ assert_kind_of String, res.body
+ assert_equal data, res.body
+ }
+ end
+
+ def _test_request__stream_body(http)
+ req = Net::HTTP::Post.new('/')
+ data = $test_net_http_data
+ req.content_length = data.size
+ req.body_stream = StringIO.new(data)
+ res = http.request(req)
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_equal data.size, res.body.size
+ assert_equal data, res.body
+ end
+
+ def test_send_request
+ start {|http|
+ _test_send_request__GET http
+ _test_send_request__POST http
+ }
+ end
+
+ def _test_send_request__GET(http)
+ res = http.send_request('GET', '/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_equal $test_net_http_data.size, res['content-length'].to_i
+ assert_kind_of String, res.body
+ assert_equal $test_net_http_data, res.body
+ end
+
+ def _test_send_request__POST(http)
+ data = 'aaabbb cc ddddddddddd lkjoiu4j3qlkuoa'
+ res = http.send_request('POST', '/', data)
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_equal data.size, res.body.size
+ assert_equal data, res.body
+ end
+end
+
+class TestNetHTTP_version_1_1 < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'port' => 10081,
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+ include TestNetHTTP_version_1_1_methods
+
+ def new
+ Net::HTTP.version_1_1
+ super
+ end
+end
+
+class TestNetHTTP_v1_2 < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'port' => 10081,
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+ include TestNetHTTP_version_1_1_methods
+ include TestNetHTTP_version_1_2_methods
+
+ def new
+ Net::HTTP.version_1_2
+ super
+ end
+end
+
+=begin
+class TestNetHTTP_proxy < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'port' => 10081,
+ 'proxy_host' => '127.0.0.1',
+ 'proxy_port' => 10082,
+ }
+
+ include TestNetHTTPUtils
+ include TestNetHTTP_version_1_1_methods
+ include TestNetHTTP_version_1_2_methods
+
+ def new
+ Net::HTTP.version_1_2
+ super
+ end
+end
+=end
diff --git a/trunk/test/net/http/test_httpheader.rb b/trunk/test/net/http/test_httpheader.rb
new file mode 100644
index 0000000000..3ba1b217c0
--- /dev/null
+++ b/trunk/test/net/http/test_httpheader.rb
@@ -0,0 +1,317 @@
+require 'net/http'
+require 'test/unit'
+
+class HTTPHeaderTest < Test::Unit::TestCase
+
+ class C
+ include Net::HTTPHeader
+ def initialize
+ initialize_http_header({})
+ end
+ attr_accessor :body
+ end
+
+ def setup
+ @c = C.new
+ end
+
+ def test_size
+ assert_equal 0, @c.size
+ @c['a'] = 'a'
+ assert_equal 1, @c.size
+ @c['b'] = 'b'
+ assert_equal 2, @c.size
+ @c['b'] = 'b'
+ assert_equal 2, @c.size
+ @c['c'] = 'c'
+ assert_equal 3, @c.size
+ end
+
+ def test_ASET
+ @c['My-Header'] = 'test string'
+ @c['my-Header'] = 'test string'
+ @c['My-header'] = 'test string'
+ @c['my-header'] = 'test string'
+ @c['MY-HEADER'] = 'test string'
+ assert_equal 1, @c.size
+
+ @c['AaA'] = 'aaa'
+ @c['aaA'] = 'aaa'
+ @c['AAa'] = 'aaa'
+ assert_equal 2, @c.length
+ end
+
+ def test_AREF
+ @c['My-Header'] = 'test string'
+ assert_equal 'test string', @c['my-header']
+ assert_equal 'test string', @c['MY-header']
+ assert_equal 'test string', @c['my-HEADER']
+
+ @c['Next-Header'] = 'next string'
+ assert_equal 'next string', @c['next-header']
+ end
+
+ def test_add_field
+ @c.add_field 'My-Header', 'a'
+ assert_equal 'a', @c['My-Header']
+ assert_equal ['a'], @c.get_fields('My-Header')
+ @c.add_field 'My-Header', 'b'
+ assert_equal 'a, b', @c['My-Header']
+ assert_equal ['a', 'b'], @c.get_fields('My-Header')
+ @c.add_field 'My-Header', 'c'
+ assert_equal 'a, b, c', @c['My-Header']
+ assert_equal ['a', 'b', 'c'], @c.get_fields('My-Header')
+ @c.add_field 'My-Header', 'd, d'
+ assert_equal 'a, b, c, d, d', @c['My-Header']
+ assert_equal ['a', 'b', 'c', 'd, d'], @c.get_fields('My-Header')
+ end
+
+ def test_get_fields
+ @c['My-Header'] = 'test string'
+ assert_equal ['test string'], @c.get_fields('my-header')
+ assert_equal ['test string'], @c.get_fields('My-header')
+ assert_equal ['test string'], @c.get_fields('my-Header')
+
+ assert_nil @c.get_fields('not-found')
+ assert_nil @c.get_fields('Not-Found')
+
+ @c.get_fields('my-header').push 'junk'
+ assert_equal ['test string'], @c.get_fields('my-header')
+ @c.get_fields('my-header').clear
+ assert_equal ['test string'], @c.get_fields('my-header')
+ end
+
+ def test_delete
+ @c['My-Header'] = 'test'
+ assert_equal 'test', @c['My-Header']
+ assert_nil @c['not-found']
+ @c.delete 'My-Header'
+ assert_nil @c['My-Header']
+ assert_nil @c['not-found']
+ @c.delete 'My-Header'
+ @c.delete 'My-Header'
+ assert_nil @c['My-Header']
+ assert_nil @c['not-found']
+ end
+
+ def test_each
+ @c['My-Header'] = 'test'
+ @c.each do |k, v|
+ assert_equal 'my-header', k
+ assert_equal 'test', v
+ end
+ @c.each do |k, v|
+ assert_equal 'my-header', k
+ assert_equal 'test', v
+ end
+ end
+
+ def test_each_key
+ @c['My-Header'] = 'test'
+ @c.each_key do |k|
+ assert_equal 'my-header', k
+ end
+ @c.each_key do |k|
+ assert_equal 'my-header', k
+ end
+ end
+
+ def test_each_value
+ @c['My-Header'] = 'test'
+ @c.each_value do |v|
+ assert_equal 'test', v
+ end
+ @c.each_value do |v|
+ assert_equal 'test', v
+ end
+ end
+
+ def test_canonical_each
+ @c['my-header'] = ['a', 'b']
+ @c.canonical_each do |k,v|
+ assert_equal 'My-Header', k
+ assert_equal 'a, b', v
+ end
+ end
+
+ def test_each_capitalized
+ @c['my-header'] = ['a', 'b']
+ @c.each_capitalized do |k,v|
+ assert_equal 'My-Header', k
+ assert_equal 'a, b', v
+ end
+ end
+
+ def test_key?
+ @c['My-Header'] = 'test'
+ assert_equal true, @c.key?('My-Header')
+ assert_equal true, @c.key?('my-header')
+ assert_equal false, @c.key?('Not-Found')
+ assert_equal false, @c.key?('not-found')
+ assert_equal false, @c.key?('')
+ assert_equal false, @c.key?('x' * 1024)
+ end
+
+ def test_to_hash
+ end
+
+ def test_range
+ try_range(1..5, '1-5')
+ try_range(234..567, '234-567')
+ try_range(-5..-1, '-5')
+ try_range(1..-1, '1-')
+ end
+
+ def try_range(r, s)
+ @c['range'] = "bytes=#{s}"
+ assert_equal r, Array(@c.range)[0]
+ end
+
+ def test_range=
+ @c.range = 0..499
+ assert_equal 'bytes=0-499', @c['range']
+ @c.range = 0...500
+ assert_equal 'bytes=0-499', @c['range']
+ @c.range = 300
+ assert_equal 'bytes=0-299', @c['range']
+ @c.range = -400
+ assert_equal 'bytes=-400', @c['range']
+ @c.set_range 0, 500
+ assert_equal 'bytes=0-499', @c['range']
+ end
+
+ def test_content_range
+ end
+
+ def test_range_length
+ @c['Content-Range'] = "bytes 0-499/1000"
+ assert_equal 500, @c.range_length
+ @c['Content-Range'] = "bytes 1-500/1000"
+ assert_equal 500, @c.range_length
+ @c['Content-Range'] = "bytes 1-1/1000"
+ assert_equal 1, @c.range_length
+ end
+
+ def test_chunked?
+ try_chunked true, 'chunked'
+ try_chunked true, ' chunked '
+ try_chunked true, '(OK)chunked'
+
+ try_chunked false, 'not-chunked'
+ try_chunked false, 'chunked-but-not-chunked'
+ end
+
+ def try_chunked(bool, str)
+ @c['transfer-encoding'] = str
+ assert_equal bool, @c.chunked?
+ end
+
+ def test_content_length
+ @c.delete('content-length')
+ assert_nil @c['content-length']
+
+ try_content_length 500, '500'
+ try_content_length 10000_0000_0000, '1000000000000'
+ try_content_length 123, ' 123'
+ try_content_length 1, '1 23'
+ try_content_length 500, '(OK)500'
+ assert_raises(Net::HTTPHeaderSyntaxError, 'here is no digit, but') {
+ @c['content-length'] = 'no digit'
+ @c.content_length
+ }
+ end
+
+ def try_content_length(len, str)
+ @c['content-length'] = str
+ assert_equal len, @c.content_length
+ end
+
+ def test_content_length=
+ @c.content_length = 0
+ assert_equal 0, @c.content_length
+ @c.content_length = 1
+ assert_equal 1, @c.content_length
+ @c.content_length = 999
+ assert_equal 999, @c.content_length
+ @c.content_length = 10000000000000
+ assert_equal 10000000000000, @c.content_length
+ end
+
+ def test_content_type
+ assert_nil @c.content_type
+ @c.content_type = 'text/html'
+ assert_equal 'text/html', @c.content_type
+ @c.content_type = 'application/pdf'
+ assert_equal 'application/pdf', @c.content_type
+ @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'}
+ assert_equal 'text/html', @c.content_type
+ @c.content_type = 'text'
+ assert_equal 'text', @c.content_type
+ end
+
+ def test_main_type
+ assert_nil @c.main_type
+ @c.content_type = 'text/html'
+ assert_equal 'text', @c.main_type
+ @c.content_type = 'application/pdf'
+ assert_equal 'application', @c.main_type
+ @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'}
+ assert_equal 'text', @c.main_type
+ @c.content_type = 'text'
+ assert_equal 'text', @c.main_type
+ end
+
+ def test_sub_type
+ assert_nil @c.sub_type
+ @c.content_type = 'text/html'
+ assert_equal 'html', @c.sub_type
+ @c.content_type = 'application/pdf'
+ assert_equal 'pdf', @c.sub_type
+ @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'}
+ assert_equal 'html', @c.sub_type
+ @c.content_type = 'text'
+ assert_nil @c.sub_type
+ end
+
+ def test_type_params
+ assert_equal({}, @c.type_params)
+ @c.content_type = 'text/html'
+ assert_equal({}, @c.type_params)
+ @c.content_type = 'application/pdf'
+ assert_equal({}, @c.type_params)
+ @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'}
+ assert_equal({'charset' => 'iso-2022-jp'}, @c.type_params)
+ @c.content_type = 'text'
+ assert_equal({}, @c.type_params)
+ end
+
+ def test_set_content_type
+ end
+
+ def test_form_data=
+ @c.form_data = {"cmd"=>"search", "q"=>"ruby", "max"=>"50"}
+ assert_equal 'application/x-www-form-urlencoded', @c.content_type
+ assert_equal %w( cmd=search max=50 q=ruby ), @c.body.split('&').sort
+ end
+
+ def test_set_form_data
+ @c.set_form_data "cmd"=>"search", "q"=>"ruby", "max"=>"50"
+ assert_equal 'application/x-www-form-urlencoded', @c.content_type
+ assert_equal %w( cmd=search max=50 q=ruby ), @c.body.split('&').sort
+
+ @c.set_form_data "cmd"=>"search", "q"=>"ruby", "max"=>50
+ assert_equal 'application/x-www-form-urlencoded', @c.content_type
+ assert_equal %w( cmd=search max=50 q=ruby ), @c.body.split('&').sort
+
+ @c.set_form_data({"cmd"=>"search", "q"=>"ruby", "max"=>"50"}, ';')
+ assert_equal 'application/x-www-form-urlencoded', @c.content_type
+ assert_equal %w( cmd=search max=50 q=ruby ), @c.body.split(';').sort
+ end
+
+ def test_basic_auth
+ end
+
+ def test_proxy_basic_auth
+ end
+
+end
diff --git a/trunk/test/net/http/test_https.rb b/trunk/test/net/http/test_https.rb
new file mode 100644
index 0000000000..adb50c58fb
--- /dev/null
+++ b/trunk/test/net/http/test_https.rb
@@ -0,0 +1,97 @@
+require "test/unit"
+begin
+ require 'net/https'
+ require 'stringio'
+ require File.expand_path("../../openssl/utils", File.dirname(__FILE__))
+ require File.expand_path("utils", File.dirname(__FILE__))
+rescue LoadError
+ # should skip this test
+end
+
+class TestNetHTTPS < Test::Unit::TestCase
+ include TestNetHTTPUtils
+
+ subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+ exts = [
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
+ ]
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ cert = OpenSSL::TestUtils.issue_cert(
+ subject, key, 1, Time.now, Time.now + 3600, exts,
+ nil, nil, OpenSSL::Digest::SHA1.new
+ )
+
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'port' => 10081,
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ 'ssl_enable' => true,
+ 'ssl_certificate' => cert,
+ 'ssl_private_key' => key,
+ }
+
+ def test_get
+ http = Net::HTTP.new("localhost", config("port"))
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == config('ssl_certificate').to_der
+ end
+ http.request_get("/") {|res|
+ assert_equal($test_net_http_data, res.body)
+ }
+ end
+
+ def test_post
+ http = Net::HTTP.new("localhost", config("port"))
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == config('ssl_certificate').to_der
+ end
+ data = config('ssl_private_key').to_der
+ http.request_post("/", data) {|res|
+ assert_equal(data, res.body)
+ }
+ end
+
+ if ENV["RUBY_OPENSSL_TEST_ALL"]
+ def test_verify
+ http = Net::HTTP.new("ssl.netlab.jp", 443)
+ http.use_ssl = true
+ assert(
+ (http.request_head("/"){|res| } rescue false),
+ "The system may not have default CA certificate store."
+ )
+ end
+ end
+
+ def test_verify_none
+ http = Net::HTTP.new("localhost", config("port"))
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ http.request_get("/") {|res|
+ assert_equal($test_net_http_data, res.body)
+ }
+ end
+
+ def test_certificate_verify_failure
+ http = Net::HTTP.new("localhost", config("port"))
+ http.use_ssl = true
+ ex = assert_raise(OpenSSL::SSL::SSLError){
+ http.request_get("/") {|res| }
+ }
+ assert_match(/certificate verify failed/, ex.message)
+ end
+
+ def test_identity_verify_failure
+ http = Net::HTTP.new("127.0.0.1", config("port"))
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == config('ssl_certificate').to_der
+ end
+ ex = assert_raise(OpenSSL::SSL::SSLError){
+ http.request_get("/") {|res| }
+ }
+ assert_match(/hostname was not match/, ex.message)
+ end
+end if defined?(OpenSSL)
diff --git a/trunk/test/net/http/test_https_proxy.rb b/trunk/test/net/http/test_https_proxy.rb
new file mode 100644
index 0000000000..4f26342339
--- /dev/null
+++ b/trunk/test/net/http/test_https_proxy.rb
@@ -0,0 +1,37 @@
+begin
+ require 'net/https'
+rescue LoadError
+end
+require 'test/unit'
+
+class HTTPSProxyTest < Test::Unit::TestCase
+ def test_https_proxy_authentication
+ t = nil
+ TCPServer.open("127.0.0.1", 0) {|serv|
+ _, port, _, _ = serv.addr
+ t = Thread.new {
+ proxy = Net::HTTP.Proxy("127.0.0.1", port, 'user', 'password')
+ http = proxy.new("foo.example.org", 8000)
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ begin
+ http.start
+ rescue EOFError
+ end
+ }
+ sock = serv.accept
+ proxy_request = sock.gets("\r\n\r\n")
+ assert_equal(
+ "CONNECT foo.example.org:8000 HTTP/1.1\r\n" +
+ "Host: foo.example.org:8000\r\n" +
+ "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n" +
+ "\r\n",
+ proxy_request,
+ "[ruby-dev:25673]")
+ sock.close
+ }
+ ensure
+ t.join if t
+ end
+end if defined?(OpenSSL)
+
diff --git a/trunk/test/net/http/utils.rb b/trunk/test/net/http/utils.rb
new file mode 100644
index 0000000000..e685a8ff61
--- /dev/null
+++ b/trunk/test/net/http/utils.rb
@@ -0,0 +1,96 @@
+require 'webrick'
+begin
+ require "webrick/https"
+rescue LoadError
+ # SSL features cannot be tested
+end
+require 'webrick/httpservlet/abstract'
+
+module TestNetHTTPUtils
+ def start(&block)
+ new().start(&block)
+ end
+
+ def new
+ klass = Net::HTTP::Proxy(config('proxy_host'), config('proxy_port'))
+ http = klass.new(config('host'), config('port'))
+ http.set_debug_output logfile()
+ http
+ end
+
+ def config(key)
+ self.class::CONFIG[key]
+ end
+
+ def logfile
+ $DEBUG ? $stderr : NullWriter.new
+ end
+
+ def setup
+ spawn_server
+ end
+
+ def teardown
+ @server.shutdown
+ until @server.status == :Stop
+ sleep 0.1
+ end
+ # resume global state
+ Net::HTTP.version_1_2
+ end
+
+ def spawn_server
+ server_config = {
+ :BindAddress => config('host'),
+ :Port => config('port'),
+ :Logger => WEBrick::Log.new(NullWriter.new),
+ :AccessLog => [],
+ :ShutdownSocketWithoutClose => true,
+ :ServerType => Thread,
+ }
+ if defined?(OpenSSL) and config('ssl_enable')
+ server_config.update({
+ :SSLEnable => true,
+ :SSLCertificate => config('ssl_certificate'),
+ :SSLPrivateKey => config('ssl_private_key'),
+ })
+ end
+ @server = WEBrick::HTTPServer.new(server_config)
+ @server.mount('/', Servlet)
+ @server.start
+ n_try_max = 5
+ begin
+ TCPSocket.open(config('host'), config('port')).close
+ rescue Errno::ECONNREFUSED
+ sleep 0.2
+ n_try_max -= 1
+ raise 'cannot spawn server; give up' if n_try_max < 0
+ retry
+ end
+ end
+
+ $test_net_http = nil
+ $test_net_http_data = (0...256).to_a.map {|i| i.chr }.join('') * 64
+ $test_net_http_data.force_encoding("ASCII-8BIT")
+ $test_net_http_data_type = 'application/octet-stream'
+
+ class Servlet < WEBrick::HTTPServlet::AbstractServlet
+ def do_GET(req, res)
+ res['Content-Type'] = $test_net_http_data_type
+ res.body = $test_net_http_data
+ end
+
+ # echo server
+ def do_POST(req, res)
+ res['Content-Type'] = req['Content-Type']
+ res.body = req.body
+ end
+ end
+
+ class NullWriter
+ def <<(s) end
+ def puts(*args) end
+ def print(*args) end
+ def printf(*args) end
+ end
+end
diff --git a/trunk/test/net/imap/cacert.pem b/trunk/test/net/imap/cacert.pem
new file mode 100644
index 0000000000..8a48e07a90
--- /dev/null
+++ b/trunk/test/net/imap/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ d2:9c:5c:81:a3:b0:3b:ec
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=JP, ST=Shimane, O=Ruby Core Team, CN=Ruby Test CA
+ Validity
+ Not Before: Dec 22 08:35:19 2007 GMT
+ Not After : Dec 21 08:35:19 2010 GMT
+ Subject: C=JP, ST=Shimane, O=Ruby Core Team, CN=Ruby Test CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ee:b1:1a:06:25:1f:29:80:a1:59:ef:0f:0d:8b:
+ 5a:88:40:73:56:95:d9:db:b4:71:3c:36:7f:b4:fc:
+ 68:51:54:8b:8d:9e:41:27:fb:31:d1:7a:6c:5c:21:
+ 30:3d:22:f6:7a:92:c3:fa:b3:85:36:44:76:22:6c:
+ 08:82:78:89:7d:c3:19:d4:ec:7d:05:5b:75:cd:38:
+ 1c:89:03:ef:02:aa:7e:6d:5b:36:ea:ad:e2:0b:ec:
+ 4b:e2:36:bf:c0:49:44:93:a6:cc:da:40:be:5f:c0:
+ 75:3b:be:c0:28:db:42:57:90:3b:83:af:2d:60:9a:
+ c6:b1:bc:5c:68:12:2d:70:25
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AE:F5:39:FE:D2:35:A2:2C:1E:CB:0E:08:4C:0E:5A:DC:44:99:E2:9C
+ X509v3 Authority Key Identifier:
+ keyid:AE:F5:39:FE:D2:35:A2:2C:1E:CB:0E:08:4C:0E:5A:DC:44:99:E2:9C
+ DirName:/C=JP/ST=Shimane/O=Ruby Core Team/CN=Ruby Test CA
+ serial:D2:9C:5C:81:A3:B0:3B:EC
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 9e:28:89:81:83:55:1b:38:cb:85:86:ec:ee:cc:f4:cf:f0:47:
+ 61:72:07:f2:2e:ca:67:f7:c8:29:b5:3c:34:d2:cf:c2:f7:9c:
+ 4d:ce:8d:37:24:57:85:c1:0e:27:86:81:15:99:ec:af:05:ae:
+ 09:96:f6:f7:5a:c0:d2:a4:82:ed:d6:d3:26:e9:3d:50:50:0c:
+ 71:c2:6e:9a:50:30:73:8a:94:0d:c1:9c:1a:da:76:80:b8:8b:
+ 46:ec:10:93:6c:8d:cb:ab:eb:12:5d:e0:6f:1a:5a:ac:5c:34:
+ 12:df:7b:a7:dc:b6:0f:d6:3e:ac:2f:69:db:11:aa:1d:c4:90:
+ f6:fa
+-----BEGIN CERTIFICATE-----
+MIICzjCCAjegAwIBAgIJANKcXIGjsDvsMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV
+BAYTAkpQMRAwDgYDVQQIEwdTaGltYW5lMRcwFQYDVQQKEw5SdWJ5IENvcmUgVGVh
+bTEVMBMGA1UEAxMMUnVieSBUZXN0IENBMB4XDTA3MTIyMjA4MzUxOVoXDTEwMTIy
+MTA4MzUxOVowTzELMAkGA1UEBhMCSlAxEDAOBgNVBAgTB1NoaW1hbmUxFzAVBgNV
+BAoTDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDEwxSdWJ5IFRlc3QgQ0EwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAO6xGgYlHymAoVnvDw2LWohAc1aV2du0cTw2
+f7T8aFFUi42eQSf7MdF6bFwhMD0i9nqSw/qzhTZEdiJsCIJ4iX3DGdTsfQVbdc04
+HIkD7wKqfm1bNuqt4gvsS+I2v8BJRJOmzNpAvl/AdTu+wCjbQleQO4OvLWCaxrG8
+XGgSLXAlAgMBAAGjgbEwga4wHQYDVR0OBBYEFK71Of7SNaIsHssOCEwOWtxEmeKc
+MH8GA1UdIwR4MHaAFK71Of7SNaIsHssOCEwOWtxEmeKcoVOkUTBPMQswCQYDVQQG
+EwJKUDEQMA4GA1UECBMHU2hpbWFuZTEXMBUGA1UEChMOUnVieSBDb3JlIFRlYW0x
+FTATBgNVBAMTDFJ1YnkgVGVzdCBDQYIJANKcXIGjsDvsMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADgYEAniiJgYNVGzjLhYbs7sz0z/BHYXIH8i7KZ/fIKbU8
+NNLPwvecTc6NNyRXhcEOJ4aBFZnsrwWuCZb291rA0qSC7dbTJuk9UFAMccJumlAw
+c4qUDcGcGtp2gLiLRuwQk2yNy6vrEl3gbxparFw0Et97p9y2D9Y+rC9p2xGqHcSQ
+9vo=
+-----END CERTIFICATE-----
diff --git a/trunk/test/net/imap/server.crt b/trunk/test/net/imap/server.crt
new file mode 100644
index 0000000000..77803ee385
--- /dev/null
+++ b/trunk/test/net/imap/server.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB0jCCATsCAQIwDQYJKoZIhvcNAQEFBQAwTzELMAkGA1UEBhMCSlAxEDAOBgNV
+BAgTB1NoaW1hbmUxFzAVBgNVBAoTDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDEwxS
+dWJ5IFRlc3QgQ0EwHhcNMDcxMjIyMDg0MDA1WhcNMTcxMjE5MDg0MDA1WjAUMRIw
+EAYDVQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANt1
+0EXesd+/caAOsKXmvPQcneUlZ2TFe8vxr8a+mqrqfg/MBa/vQGkGsskTnX7rogbi
+6n0Hx8eZx/vVuOtjd2IrGBLDU1jQ9cdADAHRJoI0Fgnj3GX03LtdpUFg56l0utdM
+tqOcxYyJr8vonwX+6v5kJL/n7eP20PzW6/wGghD7AgMBAAEwDQYJKoZIhvcNAQEF
+BQADgYEA2zl2U40/ogkC3k1ccoO4n/szaGW/wfxFREjn9BCvSB8iGRYNCGO/MdZ6
+maaSuAPdIw6RdFncL6dC3xf5IrriCyOmdZM/O8hgC/sNOnWtRAA/+XJqs0UnZ/A2
+f06bSqE1BTSiUU5wY4UraN2aDgnbFonCrY5RipZgLYaWyEbRtF8=
+-----END CERTIFICATE-----
diff --git a/trunk/test/net/imap/server.key b/trunk/test/net/imap/server.key
new file mode 100644
index 0000000000..7c57546ece
--- /dev/null
+++ b/trunk/test/net/imap/server.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDbddBF3rHfv3GgDrCl5rz0HJ3lJWdkxXvL8a/Gvpqq6n4PzAWv
+70BpBrLJE51+66IG4up9B8fHmcf71bjrY3diKxgSw1NY0PXHQAwB0SaCNBYJ49xl
+9Ny7XaVBYOepdLrXTLajnMWMia/L6J8F/ur+ZCS/5+3j9tD81uv8BoIQ+wIDAQAB
+AoGAGtYHR+P5gFDaxiXFuCPFC1zMeg7e29XCU6gURIteQnQ2QhxCvcbV64HkLu51
+HeYWhB0Pa4aeCWxmpgb2e+JH4MEoIjeJSGyZQeqwkQLgWJDdvkgWx5am58QzA60I
+ipkZ9QHcPffSs5RiGx4yfr58KqAmwFphGCY8W7v4LqaENdECQQD9H5VTW9g4gj1c
+j3uNYvSI/D7a9P7gfI+ziczuwMm5xsBx3D/t5TAr3SJKNne3sl1E6ZERCUbzxf+C
+k58EiHx1AkEA3fRLGqDOq7EcQhbjTcA/v/t5MwlGEUsS9+XrqOWn50YuoIwRZJ3v
+qHRQzfQfFNklGtfBvwQ4md3irXjMeGVprwJBAMEAuwiDiHuV+xm/ofKtmE13IKot
+ksYy1BOOp/8IawhHXueyi+BmF/PqOkIiA+jCjNGF0oIN89beizPSQbbgJx0CQG/K
+qL1bu1ys0y/SeWBi8XkP/0aeaCUzq/UiYCTsrzoEll2UzvnftqMhGsXxLGqCyHaR
+r2s3hA6zvIVlL4+AfM8CQQClq+WDrC5VKciLYakZNWJjV1m+H2Ut/0fXdUjKHajE
+FWLcsrOhADf6bkTb71GwPxnKRkkRmud5upP0ZYYTqM4X
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/test/net/imap/test_imap.rb b/trunk/test/net/imap/test_imap.rb
new file mode 100644
index 0000000000..cff09d3cbc
--- /dev/null
+++ b/trunk/test/net/imap/test_imap.rb
@@ -0,0 +1,195 @@
+require "net/imap"
+require "test/unit"
+
+class IMAPTest < Test::Unit::TestCase
+ CA_FILE = File.expand_path("cacert.pem", File.dirname(__FILE__))
+ SERVER_KEY = File.expand_path("server.key", File.dirname(__FILE__))
+ SERVER_CERT = File.expand_path("server.crt", File.dirname(__FILE__))
+
+ def test_encode_utf7
+ utf8 = "\357\274\241\357\274\242\357\274\243".force_encoding("UTF-8")
+ s = Net::IMAP.encode_utf7(utf8)
+ assert_equal("&,yH,Iv8j-".force_encoding("UTF-8"), s)
+ end
+
+ def test_decode_utf7
+ s = Net::IMAP.decode_utf7("&,yH,Iv8j-")
+ utf8 = "\357\274\241\357\274\242\357\274\243".force_encoding("UTF-8")
+ assert_equal(utf8, s)
+ end
+
+ def test_imaps_unknown_ca
+ if defined?(OpenSSL)
+ assert_raise(OpenSSL::SSL::SSLError) do
+ imaps_test do |port|
+ Net::IMAP.new("localhost",
+ :port => port,
+ :ssl => true)
+ end
+ end
+ end
+ end
+
+ def test_imaps_with_ca_file
+ if defined?(OpenSSL)
+ assert_nothing_raised do
+ imaps_test do |port|
+ Net::IMAP.new("localhost",
+ :port => port,
+ :ssl => { :ca_file => CA_FILE })
+ end
+ end
+ end
+ end
+
+ def test_imaps_verify_none
+ if defined?(OpenSSL)
+ assert_nothing_raised do
+ imaps_test do |port|
+ Net::IMAP.new("localhost",
+ :port => port,
+ :ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE })
+ end
+ end
+ end
+ end
+
+ def test_imaps_post_connection_check
+ if defined?(OpenSSL)
+ assert_raise(OpenSSL::SSL::SSLError) do
+ imaps_test do |port|
+ Net::IMAP.new("127.0.0.1",
+ :port => port,
+ :ssl => { :ca_file => CA_FILE })
+ end
+ end
+ end
+ end
+
+ def test_starttls
+ imap = nil
+ if defined?(OpenSSL)
+ starttls_test do |port|
+ imap = Net::IMAP.new("localhost", :port => port)
+ imap.starttls(:ca_file => CA_FILE)
+ imap
+ end
+ end
+ ensure
+ if imap && !imap.disconnected?
+ imap.disconnect
+ end
+ end
+
+ def test_unexpected_eof
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ Thread.start do
+ begin
+ sock = server.accept
+ begin
+ sock.print("* OK test server\r\n")
+ sock.gets
+# sock.print("* BYE terminating connection\r\n")
+# sock.print("RUBY0001 OK LOGOUT completed\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = Net::IMAP.new("localhost", :port => port)
+ assert_raise(EOFError) do
+ imap.logout
+ end
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ server.close
+ end
+ end
+
+ private
+
+ def imaps_test
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ca_file = CA_FILE
+ ctx.key = File.open(SERVER_KEY) { |f|
+ OpenSSL::PKey::RSA.new(f)
+ }
+ ctx.cert = File.open(SERVER_CERT) { |f|
+ OpenSSL::X509::Certificate.new(f)
+ }
+ ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx)
+ Thread.start do
+ begin
+ sock = ssl_server.accept
+ begin
+ sock.print("* OK test server\r\n")
+ sock.gets
+ sock.print("* BYE terminating connection\r\n")
+ sock.print("RUBY0001 OK LOGOUT completed\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = yield(port)
+ imap.logout
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ ssl_server.close
+ end
+ end
+
+ def starttls_test
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ Thread.start do
+ begin
+ sock = server.accept
+ sock.print("* OK test server\r\n")
+ sock.gets
+ sock.print("RUBY0001 OK completed\r\n")
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ca_file = CA_FILE
+ ctx.key = File.open(SERVER_KEY) { |f|
+ OpenSSL::PKey::RSA.new(f)
+ }
+ ctx.cert = File.open(SERVER_CERT) { |f|
+ OpenSSL::X509::Certificate.new(f)
+ }
+ sock = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ begin
+ sock.accept
+ sock.gets
+ sock.print("* BYE terminating connection\r\n")
+ sock.print("RUBY0002 OK LOGOUT completed\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = yield(port)
+ imap.logout
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ server.close
+ end
+ end
+end
diff --git a/trunk/test/nkf/test_kconv.rb b/trunk/test/nkf/test_kconv.rb
new file mode 100644
index 0000000000..d396b4be47
--- /dev/null
+++ b/trunk/test/nkf/test_kconv.rb
@@ -0,0 +1,74 @@
+require 'test/unit'
+require 'kconv'
+
+class TestKconv < Test::Unit::TestCase
+ def setup
+ @euc_str = "\
+\xa5\xaa\xa5\xd6\xa5\xb8\xa5\xa7\xa5\xaf\xa5\xc8\xbb\xd8\xb8\xfe\
+\xa5\xd7\xa5\xed\xa5\xb0\xa5\xe9\xa5\xdf\xa5\xf3\xa5\xb0\xb8\xc0\xb8\xec
+\x52\x75\x62\x79".force_encoding('EUC-JP')
+ @utf8_str = "\
+\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\
+\xe3\x82\xaf\xe3\x83\x88\xe6\x8c\x87\xe5\x90\x91\
+\xe3\x83\x97\xe3\x83\xad\xe3\x82\xb0\xe3\x83\xa9\xe3\x83\x9f\
+\xe3\x83\xb3\xe3\x82\xb0\xe8\xa8\x80\xe8\xaa\x9e
+\x52\x75\x62\x79".force_encoding('UTF-8')
+ @sjis_str = "\
+\x83\x49\x83\x75\x83\x57\x83\x46\x83\x4e\x83\x67\x8e\x77\x8c\xfc\
+\x83\x76\x83\x8d\x83\x4f\x83\x89\x83\x7e\x83\x93\x83\x4f\x8c\xbe\x8c\xea
+\x52\x75\x62\x79".force_encoding('Shift_JIS')
+ @jis_str = "\
+\x1b\x24\x42\x25\x2a\x25\x56\x25\x38\x25\x27\x25\x2f\x25\x48\x3b\x58\x38\x7e\
+\x25\x57\x25\x6d\x25\x30\x25\x69\x25\x5f\x25\x73\x25\x30\x38\x40\x38\x6c\x1b\x28\x42
+\x52\x75\x62\x79".force_encoding('ISO-2022-JP')
+ end
+
+
+ def test_eucjp
+ assert(@euc_str.iseuc)
+ assert_equal(::Kconv::EUC, Kconv.guess(@euc_str))
+ assert_equal(@euc_str, @euc_str.toeuc)
+ assert_equal(@euc_str, @sjis_str.toeuc)
+ assert_equal(@euc_str, @utf8_str.toeuc)
+ assert_equal(@euc_str, @jis_str.toeuc)
+ assert_equal(@euc_str, @euc_str.kconv(::NKF::EUC))
+ assert_equal(@euc_str, @sjis_str.kconv(::NKF::EUC))
+ assert_equal(@euc_str, @utf8_str.kconv(::NKF::EUC))
+ assert_equal(@euc_str, @jis_str.kconv(::NKF::EUC))
+ end
+ def test_shiftjis
+ assert(@sjis_str.issjis)
+ assert_equal(::Kconv::SJIS, Kconv.guess(@sjis_str))
+ assert_equal(@sjis_str, @euc_str.tosjis)
+ assert_equal(@sjis_str, @sjis_str.tosjis)
+ assert_equal(@sjis_str, @utf8_str.tosjis)
+ assert_equal(@sjis_str, @jis_str.tosjis)
+ assert_equal(@sjis_str, @euc_str.kconv(::NKF::SJIS))
+ assert_equal(@sjis_str, @sjis_str.kconv(::NKF::SJIS))
+ assert_equal(@sjis_str, @utf8_str.kconv(::NKF::SJIS))
+ assert_equal(@sjis_str, @jis_str.kconv(::NKF::SJIS))
+ end
+ def test_utf8
+ assert(@utf8_str.isutf8)
+ assert_equal(::Kconv::UTF8, Kconv.guess(@utf8_str))
+ assert_equal(@utf8_str, @euc_str.toutf8)
+ assert_equal(@utf8_str, @sjis_str.toutf8)
+ assert_equal(@utf8_str, @utf8_str.toutf8)
+ assert_equal(@utf8_str, @jis_str.toutf8)
+ assert_equal(@utf8_str, @euc_str.kconv(::NKF::UTF8))
+ assert_equal(@utf8_str, @sjis_str.kconv(::NKF::UTF8))
+ assert_equal(@utf8_str, @utf8_str.kconv(::NKF::UTF8))
+ assert_equal(@utf8_str, @jis_str.kconv(::NKF::UTF8))
+ end
+ def test_jis
+ assert_equal(::Kconv::JIS, Kconv.guess(@jis_str))
+ assert_equal(@jis_str, @euc_str.tojis)
+ assert_equal(@jis_str, @sjis_str.tojis)
+ assert_equal(@jis_str, @utf8_str.tojis)
+ assert_equal(@jis_str, @jis_str.tojis)
+ assert_equal(@jis_str, @euc_str.kconv(::NKF::JIS))
+ assert_equal(@jis_str, @sjis_str.kconv(::NKF::JIS))
+ assert_equal(@jis_str, @utf8_str.kconv(::NKF::JIS))
+ assert_equal(@jis_str, @jis_str.kconv(::NKF::JIS))
+ end
+end
diff --git a/trunk/test/nkf/test_nkf.rb b/trunk/test/nkf/test_nkf.rb
new file mode 100644
index 0000000000..279ad59e1a
--- /dev/null
+++ b/trunk/test/nkf/test_nkf.rb
@@ -0,0 +1,16 @@
+require 'test/unit'
+require 'nkf'
+
+class TestNKF < Test::Unit::TestCase
+ EUC_STR = "\xa5\xaa\xa5\xd6\xa5\xb8\xa5\xa7\xa5\xaf\xa5\xc8\xbb\xd8\xb8\xfe\
+\xa5\xb9\xa5\xaf\xa5\xea\xa5\xd7\xa5\xc8\xb8\xc0\xb8\xec\
+Ruby"
+
+ def test_guess
+ str_euc = EUC_STR
+ str_jis = NKF.nkf('-j', str_euc)
+ assert_equal(::NKF::JIS, NKF.guess(str_jis))
+ assert_equal(::NKF::EUC, NKF.guess(str_euc))
+ end
+
+end
diff --git a/trunk/test/openssl/ssl_server.rb b/trunk/test/openssl/ssl_server.rb
new file mode 100644
index 0000000000..6e620629c5
--- /dev/null
+++ b/trunk/test/openssl/ssl_server.rb
@@ -0,0 +1,81 @@
+require "socket"
+require "thread"
+require "openssl"
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+def get_pem(io=$stdin)
+ buf = ""
+ while line = io.gets
+ if /^-----BEGIN / =~ line
+ buf << line
+ break
+ end
+ end
+ while line = io.gets
+ buf << line
+ if /^-----END / =~ line
+ break
+ end
+ end
+ return buf
+end
+
+def make_key(pem)
+ begin
+ return OpenSSL::PKey::RSA.new(pem)
+ rescue
+ return OpenSSL::PKey::DSA.new(pem)
+ end
+end
+
+ca_cert = OpenSSL::X509::Certificate.new(get_pem)
+ssl_cert = OpenSSL::X509::Certificate.new(get_pem)
+ssl_key = make_key(get_pem)
+port = Integer(ARGV.shift)
+verify_mode = Integer(ARGV.shift)
+start_immediately = (/yes/ =~ ARGV.shift)
+
+store = OpenSSL::X509::Store.new
+store.add_cert(ca_cert)
+store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ctx = OpenSSL::SSL::SSLContext.new
+ctx.cert_store = store
+#ctx.extra_chain_cert = [ ca_cert ]
+ctx.cert = ssl_cert
+ctx.key = ssl_key
+ctx.verify_mode = verify_mode
+
+Socket.do_not_reverse_lookup = true
+tcps = nil
+100.times{|i|
+ begin
+ tcps = TCPServer.new("0.0.0.0", port+i)
+ port = port + i
+ break
+ rescue Errno::EADDRINUSE
+ next
+ end
+}
+ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+ssls.start_immediately = start_immediately
+
+$stdout.sync = true
+$stdout.puts Process.pid
+$stdout.puts port
+
+loop do
+ ssl = ssls.accept rescue next
+ Thread.start{
+ q = Queue.new
+ th = Thread.start{ ssl.write(q.shift) while true }
+ while line = ssl.gets
+ if line =~ /^STARTTLS$/
+ ssl.accept
+ next
+ end
+ q.push(line)
+ end
+ th.kill if q.empty?
+ ssl.close
+ }
+end
diff --git a/trunk/test/openssl/test_asn1.rb b/trunk/test/openssl/test_asn1.rb
new file mode 100644
index 0000000000..86811a464c
--- /dev/null
+++ b/trunk/test/openssl/test_asn1.rb
@@ -0,0 +1,197 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require 'test/unit'
+
+class OpenSSL::TestASN1 < Test::Unit::TestCase
+ def test_decode
+ subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA")
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ now = Time.at(Time.now.to_i) # suppress usec
+ s = 0xdeadbeafdeadbeafdeadbeafdeadbeaf
+ exts = [
+ ["basicConstraints","CA:TRUE,pathlen:1",true],
+ ["keyUsage","keyCertSign, cRLSign",true],
+ ["subjectKeyIdentifier","hash",false],
+ ]
+ dgst = OpenSSL::Digest::SHA1.new
+ cert = OpenSSL::TestUtils.issue_cert(
+ subj, key, s, now, now+3600, exts, nil, nil, dgst)
+
+
+ asn1 = OpenSSL::ASN1.decode(cert)
+ assert_equal(OpenSSL::ASN1::Sequence, asn1.class)
+ assert_equal(3, asn1.value.size)
+ tbs_cert, sig_alg, sig_val = *asn1.value
+
+ assert_equal(OpenSSL::ASN1::Sequence, tbs_cert.class)
+ assert_equal(8, tbs_cert.value.size)
+
+ version = tbs_cert.value[0]
+ assert_equal(:CONTEXT_SPECIFIC, version.tag_class)
+ assert_equal(0, version.tag)
+ assert_equal(1, version.value.size)
+ assert_equal(OpenSSL::ASN1::Integer, version.value[0].class)
+ assert_equal(2, version.value[0].value)
+
+ serial = tbs_cert.value[1]
+ assert_equal(OpenSSL::ASN1::Integer, serial.class)
+ assert_equal(0xdeadbeafdeadbeafdeadbeafdeadbeaf, serial.value)
+
+ sig = tbs_cert.value[2]
+ assert_equal(OpenSSL::ASN1::Sequence, sig.class)
+ assert_equal(2, sig.value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, sig.value[0].class)
+ assert_equal("1.2.840.113549.1.1.5", sig.value[0].oid)
+ assert_equal(OpenSSL::ASN1::Null, sig.value[1].class)
+
+ dn = tbs_cert.value[3] # issuer
+ assert_equal(subj.hash, OpenSSL::X509::Name.new(dn).hash)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.class)
+ assert_equal(3, dn.value.size)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[0].class)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[1].class)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[2].class)
+ assert_equal(1, dn.value[0].value.size)
+ assert_equal(1, dn.value[1].value.size)
+ assert_equal(1, dn.value[2].value.size)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[0].value[0].class)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[1].value[0].class)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[2].value[0].class)
+ assert_equal(2, dn.value[0].value[0].value.size)
+ assert_equal(2, dn.value[1].value[0].value.size)
+ assert_equal(2, dn.value[2].value[0].value.size)
+ oid, value = *dn.value[0].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("0.9.2342.19200300.100.1.25", oid.oid)
+ assert_equal(OpenSSL::ASN1::IA5String, value.class)
+ assert_equal("org", value.value)
+ oid, value = *dn.value[1].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("0.9.2342.19200300.100.1.25", oid.oid)
+ assert_equal(OpenSSL::ASN1::IA5String, value.class)
+ assert_equal("ruby-lang", value.value)
+ oid, value = *dn.value[2].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("2.5.4.3", oid.oid)
+ assert_equal(OpenSSL::ASN1::UTF8String, value.class)
+ assert_equal("TestCA", value.value)
+
+ validity = tbs_cert.value[4]
+ assert_equal(OpenSSL::ASN1::Sequence, validity.class)
+ assert_equal(2, validity.value.size)
+ assert_equal(OpenSSL::ASN1::UTCTime, validity.value[0].class)
+ assert_equal(now, validity.value[0].value)
+ assert_equal(OpenSSL::ASN1::UTCTime, validity.value[1].class)
+ assert_equal(now+3600, validity.value[1].value)
+
+ dn = tbs_cert.value[5] # subject
+ assert_equal(subj.hash, OpenSSL::X509::Name.new(dn).hash)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.class)
+ assert_equal(3, dn.value.size)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[0].class)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[1].class)
+ assert_equal(OpenSSL::ASN1::Set, dn.value[2].class)
+ assert_equal(1, dn.value[0].value.size)
+ assert_equal(1, dn.value[1].value.size)
+ assert_equal(1, dn.value[2].value.size)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[0].value[0].class)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[1].value[0].class)
+ assert_equal(OpenSSL::ASN1::Sequence, dn.value[2].value[0].class)
+ assert_equal(2, dn.value[0].value[0].value.size)
+ assert_equal(2, dn.value[1].value[0].value.size)
+ assert_equal(2, dn.value[2].value[0].value.size)
+ oid, value = *dn.value[0].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("0.9.2342.19200300.100.1.25", oid.oid)
+ assert_equal(OpenSSL::ASN1::IA5String, value.class)
+ assert_equal("org", value.value)
+ oid, value = *dn.value[1].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("0.9.2342.19200300.100.1.25", oid.oid)
+ assert_equal(OpenSSL::ASN1::IA5String, value.class)
+ assert_equal("ruby-lang", value.value)
+ oid, value = *dn.value[2].value[0].value
+ assert_equal(OpenSSL::ASN1::ObjectId, oid.class)
+ assert_equal("2.5.4.3", oid.oid)
+ assert_equal(OpenSSL::ASN1::UTF8String, value.class)
+ assert_equal("TestCA", value.value)
+
+ pkey = tbs_cert.value[6]
+ assert_equal(OpenSSL::ASN1::Sequence, pkey.class)
+ assert_equal(2, pkey.value.size)
+ assert_equal(OpenSSL::ASN1::Sequence, pkey.value[0].class)
+ assert_equal(2, pkey.value[0].value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, pkey.value[0].value[0].class)
+ assert_equal("1.2.840.113549.1.1.1", pkey.value[0].value[0].oid)
+ assert_equal(OpenSSL::ASN1::BitString, pkey.value[1].class)
+ assert_equal(0, pkey.value[1].unused_bits)
+ spkey = OpenSSL::ASN1.decode(pkey.value[1].value)
+ assert_equal(OpenSSL::ASN1::Sequence, spkey.class)
+ assert_equal(2, spkey.value.size)
+ assert_equal(OpenSSL::ASN1::Integer, spkey.value[0].class)
+ assert_equal(143085709396403084580358323862163416700436550432664688288860593156058579474547937626086626045206357324274536445865308750491138538454154232826011964045825759324933943290377903384882276841880081931690695505836279972214003660451338124170055999155993192881685495391496854691199517389593073052473319331505702779271, spkey.value[0].value)
+ assert_equal(OpenSSL::ASN1::Integer, spkey.value[1].class)
+ assert_equal(65537, spkey.value[1].value)
+
+ extensions = tbs_cert.value[7]
+ assert_equal(:CONTEXT_SPECIFIC, extensions.tag_class)
+ assert_equal(3, extensions.tag)
+ assert_equal(1, extensions.value.size)
+ assert_equal(OpenSSL::ASN1::Sequence, extensions.value[0].class)
+ assert_equal(3, extensions.value[0].value.size)
+
+ ext = extensions.value[0].value[0] # basicConstraints
+ assert_equal(OpenSSL::ASN1::Sequence, ext.class)
+ assert_equal(3, ext.value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class)
+ assert_equal("2.5.29.19", ext.value[0].oid)
+ assert_equal(OpenSSL::ASN1::Boolean, ext.value[1].class)
+ assert_equal(true, ext.value[1].value)
+ assert_equal(OpenSSL::ASN1::OctetString, ext.value[2].class)
+ extv = OpenSSL::ASN1.decode(ext.value[2].value)
+ assert_equal(OpenSSL::ASN1::Sequence, extv.class)
+ assert_equal(2, extv.value.size)
+ assert_equal(OpenSSL::ASN1::Boolean, extv.value[0].class)
+ assert_equal(true, extv.value[0].value)
+ assert_equal(OpenSSL::ASN1::Integer, extv.value[1].class)
+ assert_equal(1, extv.value[1].value)
+
+ ext = extensions.value[0].value[1] # keyUsage
+ assert_equal(OpenSSL::ASN1::Sequence, ext.class)
+ assert_equal(3, ext.value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class)
+ assert_equal("2.5.29.15", ext.value[0].oid)
+ assert_equal(OpenSSL::ASN1::Boolean, ext.value[1].class)
+ assert_equal(true, ext.value[1].value)
+ assert_equal(OpenSSL::ASN1::OctetString, ext.value[2].class)
+ extv = OpenSSL::ASN1.decode(ext.value[2].value)
+ assert_equal(OpenSSL::ASN1::BitString, extv.class)
+ str = "\000"; str[0] = 0b00000110.chr
+ assert_equal(str, extv.value)
+
+ ext = extensions.value[0].value[2] # subjetKeyIdentifier
+ assert_equal(OpenSSL::ASN1::Sequence, ext.class)
+ assert_equal(2, ext.value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class)
+ assert_equal("2.5.29.14", ext.value[0].oid)
+ assert_equal(OpenSSL::ASN1::OctetString, ext.value[1].class)
+ extv = OpenSSL::ASN1.decode(ext.value[1].value)
+ assert_equal(OpenSSL::ASN1::OctetString, extv.class)
+ sha1 = OpenSSL::Digest::SHA1.new
+ sha1.update(pkey.value[1].value)
+ assert_equal(sha1.digest, extv.value)
+
+ assert_equal(OpenSSL::ASN1::Sequence, sig_alg.class)
+ assert_equal(2, sig_alg.value.size)
+ assert_equal(OpenSSL::ASN1::ObjectId, pkey.value[0].value[0].class)
+ assert_equal("1.2.840.113549.1.1.1", pkey.value[0].value[0].oid)
+ assert_equal(OpenSSL::ASN1::Null, pkey.value[0].value[1].class)
+
+ assert_equal(OpenSSL::ASN1::BitString, sig_val.class)
+ cululated_sig = key.sign(OpenSSL::Digest::SHA1.new, tbs_cert.to_der)
+ assert_equal(cululated_sig, sig_val.value)
+ end
+end if defined?(OpenSSL)
diff --git a/trunk/test/openssl/test_cipher.rb b/trunk/test/openssl/test_cipher.rb
new file mode 100644
index 0000000000..d671908165
--- /dev/null
+++ b/trunk/test/openssl/test_cipher.rb
@@ -0,0 +1,95 @@
+begin
+ require "openssl"
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestCipher < Test::Unit::TestCase
+ def setup
+ @c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC")
+ @c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC")
+ @key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ @iv = "\0\0\0\0\0\0\0\0"
+ @hexkey = "0000000000000000000000000000000000000000000000"
+ @hexiv = "0000000000000000"
+ @data = "DATA"
+ end
+
+ def teardown
+ @c1 = @c2 = nil
+ end
+
+ def test_crypt
+ @c1.encrypt.pkcs5_keyivgen(@key, @iv)
+ @c2.encrypt.pkcs5_keyivgen(@key, @iv)
+ s1 = @c1.update(@data) + @c1.final
+ s2 = @c2.update(@data) + @c2.final
+ assert_equal(s1, s2, "encrypt")
+
+ @c1.decrypt.pkcs5_keyivgen(@key, @iv)
+ @c2.decrypt.pkcs5_keyivgen(@key, @iv)
+ assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt")
+ assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt")
+ end
+
+ def test_info
+ assert_equal("DES-EDE3-CBC", @c1.name, "name")
+ assert_equal("DES-EDE3-CBC", @c2.name, "name")
+ assert_kind_of(Fixnum, @c1.key_len, "key_len")
+ assert_kind_of(Fixnum, @c1.iv_len, "iv_len")
+ end
+
+ def test_dup
+ assert_equal(@c1.name, @c1.dup.name, "dup")
+ assert_equal(@c1.name, @c1.clone.name, "clone")
+ @c1.encrypt
+ @c1.key = @key
+ @c1.iv = @iv
+ tmpc = @c1.dup
+ s1 = @c1.update(@data) + @c1.final
+ s2 = tmpc.update(@data) + tmpc.final
+ assert_equal(s1, s2, "encrypt dup")
+ end
+
+ def test_reset
+ @c1.encrypt
+ @c1.key = @key
+ @c1.iv = @iv
+ s1 = @c1.update(@data) + @c1.final
+ @c1.reset
+ s2 = @c1.update(@data) + @c1.final
+ assert_equal(s1, s2, "encrypt reset")
+ end
+
+ def test_empty_data
+ @c1.encrypt
+ assert_raises(ArgumentError){ @c1.update("") }
+ end
+
+ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000
+ def test_ciphers
+ OpenSSL::Cipher.ciphers.each{|name|
+ assert(OpenSSL::Cipher::Cipher.new(name).is_a?(OpenSSL::Cipher::Cipher))
+ }
+ end
+
+ def test_AES
+ pt = File.read(__FILE__)
+ %w(ECB CBC CFB OFB).each{|mode|
+ c1 = OpenSSL::Cipher::AES256.new(mode)
+ c1.encrypt
+ c1.pkcs5_keyivgen("passwd")
+ ct = c1.update(pt) + c1.final
+
+ c2 = OpenSSL::Cipher::AES256.new(mode)
+ c2.decrypt
+ c2.pkcs5_keyivgen("passwd")
+ assert_equal(pt, c2.update(ct) + c2.final)
+ }
+ end
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_digest.rb b/trunk/test/openssl/test_digest.rb
new file mode 100644
index 0000000000..8941588b97
--- /dev/null
+++ b/trunk/test/openssl/test_digest.rb
@@ -0,0 +1,88 @@
+begin
+ require "openssl"
+rescue LoadError
+end
+require "digest/md5"
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestDigest < Test::Unit::TestCase
+ def setup
+ @d1 = OpenSSL::Digest::Digest::new("MD5")
+ @d2 = OpenSSL::Digest::MD5.new
+ @md = Digest::MD5.new
+ @data = "DATA"
+ end
+
+ def teardown
+ @d1 = @d2 = @md = nil
+ end
+
+ def test_digest
+ assert_equal(@md.digest, @d1.digest)
+ assert_equal(@md.hexdigest, @d1.hexdigest)
+ @d1 << @data
+ @d2 << @data
+ @md << @data
+ assert_equal(@md.digest, @d1.digest)
+ assert_equal(@md.hexdigest, @d1.hexdigest)
+ assert_equal(@d1.digest, @d2.digest)
+ assert_equal(@d1.hexdigest, @d2.hexdigest)
+ assert_equal(@md.digest, OpenSSL::Digest::MD5.digest(@data))
+ assert_equal(@md.hexdigest, OpenSSL::Digest::MD5.hexdigest(@data))
+ end
+
+ def test_eql
+ assert(@d1 == @d2, "==")
+ d = @d1.clone
+ assert(d == @d1, "clone")
+ end
+
+ def test_info
+ assert_equal("MD5", @d1.name, "name")
+ assert_equal("MD5", @d2.name, "name")
+ assert_equal(16, @d1.size, "size")
+ end
+
+ def test_dup
+ @d1.update(@data)
+ assert_equal(@d1.name, @d1.dup.name, "dup")
+ assert_equal(@d1.name, @d1.clone.name, "clone")
+ assert_equal(@d1.digest, @d1.clone.digest, "clone .digest")
+ end
+
+ def test_reset
+ @d1.update(@data)
+ dig1 = @d1.digest
+ @d1.reset
+ @d1.update(@data)
+ dig2 = @d1.digest
+ assert_equal(dig1, dig2, "reset")
+ end
+
+ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
+ def encode16(str)
+ str.unpack("H*").first
+ end
+
+ def test_098_features
+ sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"
+ sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
+ sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
+ sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
+
+ assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a"))
+ assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a"))
+ assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a"))
+ assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a"))
+
+ assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a")))
+ assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a")))
+ assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a")))
+ assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a")))
+ end
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_ec.rb b/trunk/test/openssl/test_ec.rb
new file mode 100644
index 0000000000..671901ca36
--- /dev/null
+++ b/trunk/test/openssl/test_ec.rb
@@ -0,0 +1,113 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL::PKey::EC)
+
+class OpenSSL::TestEC < Test::Unit::TestCase
+ def setup
+ @data1 = 'foo'
+ @data2 = 'bar' * 1000 # data too long for DSA sig
+
+ @group1 = OpenSSL::PKey::EC::Group.new('secp112r1')
+ @group2 = OpenSSL::PKey::EC::Group.new('sect163k1')
+
+ @key1 = OpenSSL::PKey::EC.new
+ @key1.group = @group1
+ @key1.generate_key
+
+ @key2 = OpenSSL::PKey::EC.new(@group2.curve_name)
+ @key2.generate_key
+
+ @groups = [@group1, @group2]
+ @keys = [@key1, @key2]
+ end
+
+ def compare_keys(k1, k2)
+ assert_equal(k1.to_pem, k2.to_pem)
+ end
+
+ def test_curve_names
+ @groups.each_with_index do |group, idx|
+ key = @keys[idx]
+ assert_equal(group.curve_name, key.group.curve_name)
+ end
+ end
+
+ def test_check_key
+ for key in @keys
+ assert_equal(key.check_key, true)
+ assert_equal(key.private_key?, true)
+ assert_equal(key.public_key?, true)
+ end
+ end
+
+ def test_encoding
+ for group in @groups
+ for meth in [:to_der, :to_pem]
+ txt = group.send(meth)
+ gr = OpenSSL::PKey::EC::Group.new(txt)
+ assert_equal(txt, gr.send(meth))
+
+ assert_equal(group.generator.to_bn, gr.generator.to_bn)
+ assert_equal(group.cofactor, gr.cofactor)
+ assert_equal(group.order, gr.order)
+ assert_equal(group.seed, gr.seed)
+ assert_equal(group.degree, gr.degree)
+ end
+ end
+
+ for key in @keys
+ group = key.group
+
+ for meth in [:to_der, :to_pem]
+ txt = key.send(meth)
+ assert_equal(txt, OpenSSL::PKey::EC.new(txt).send(meth))
+ end
+
+ bn = key.public_key.to_bn
+ assert_equal(bn, OpenSSL::PKey::EC::Point.new(group, bn).to_bn)
+ end
+ end
+
+ def test_set_keys
+ for key in @keys
+ k = OpenSSL::PKey::EC.new
+ k.group = key.group
+ k.private_key = key.private_key
+ k.public_key = key.public_key
+
+ compare_keys(key, k)
+ end
+ end
+
+ def test_dsa_sign_verify
+ for key in @keys
+ sig = key.dsa_sign_asn1(@data1)
+ assert_equal(key.dsa_verify_asn1(@data1, sig), true)
+
+ assert_raises(OpenSSL::PKey::ECError) { key.dsa_sign_asn1(@data2) }
+ end
+ end
+
+ def test_dh_compute_key
+ for key in @keys
+ k = OpenSSL::PKey::EC.new(key.group)
+ k.generate_key
+
+ puba = key.public_key
+ pubb = k.public_key
+ a = key.dh_compute_key(pubb)
+ b = k.dh_compute_key(puba)
+ assert_equal(a, b)
+ end
+ end
+
+# test Group: asn1_flag, point_conversion
+
+end
+
+end
diff --git a/trunk/test/openssl/test_hmac.rb b/trunk/test/openssl/test_hmac.rb
new file mode 100644
index 0000000000..2f8d6bba20
--- /dev/null
+++ b/trunk/test/openssl/test_hmac.rb
@@ -0,0 +1,34 @@
+begin
+ require "openssl"
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestHMAC < Test::Unit::TestCase
+ def setup
+ @digest = OpenSSL::Digest::MD5.new
+ @key = "KEY"
+ @data = "DATA"
+ @h1 = OpenSSL::HMAC.new(@key, @digest)
+ @h2 = OpenSSL::HMAC.new(@key, @digest)
+ end
+
+ def teardown
+ end
+
+ def test_hmac
+ @h1.update(@data)
+ assert_equal(OpenSSL::HMAC.digest(@digest, @key, @data), @h1.digest, "digest")
+ assert_equal(OpenSSL::HMAC.hexdigest(@digest, @key, @data), @h1.hexdigest, "hexdigest")
+ end
+
+ def test_dup
+ @h1.update(@data)
+ h = @h1.dup
+ assert_equal(@h1.digest, h.digest, "dup digest")
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_ns_spki.rb b/trunk/test/openssl/test_ns_spki.rb
new file mode 100644
index 0000000000..3937132aa0
--- /dev/null
+++ b/trunk/test/openssl/test_ns_spki.rb
@@ -0,0 +1,59 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+
+class OpenSSL::TestNSSPI < Test::Unit::TestCase
+ def setup
+ # This request data is adopt from the specification of
+ # "Netscape Extensions for User Key Generation".
+ # -- http://wp.netscape.com/eng/security/comm4-keygen.html
+ @b64 = "MIHFMHEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAnX0TILJrOMUue+PtwBRE6XfV"
+ @b64 << "WtKQbsshxk5ZhcUwcwyvcnIq9b82QhJdoACdD34rqfCAIND46fXKQUnb0mvKzQID"
+ @b64 << "AQABFhFNb3ppbGxhSXNNeUZyaWVuZDANBgkqhkiG9w0BAQQFAANBAAKv2Eex2n/S"
+ @b64 << "r/7iJNroWlSzSMtTiQTEB+ADWHGj9u1xrUrOilq/o2cuQxIfZcNZkYAkWP4DubqW"
+ @b64 << "i0//rgBvmco="
+ end
+
+ def teardown
+ end
+
+ def test_build_data
+ key1 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ key2 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ spki = OpenSSL::Netscape::SPKI.new
+ spki.challenge = "RandomString"
+ spki.public_key = key1.public_key
+ spki.sign(key1, OpenSSL::Digest::SHA1.new)
+ assert(spki.verify(spki.public_key))
+ assert(spki.verify(key1.public_key))
+ assert(!spki.verify(key2.public_key))
+
+ der = spki.to_der
+ spki = OpenSSL::Netscape::SPKI.new(der)
+ assert_equal("RandomString", spki.challenge)
+ assert_equal(key1.public_key.to_der, spki.public_key.to_der)
+ assert(spki.verify(spki.public_key))
+ end
+
+ def test_decode_data
+ spki = OpenSSL::Netscape::SPKI.new(@b64)
+ assert_equal(@b64, spki.to_pem)
+ assert_equal(@b64.unpack("m").first, spki.to_der)
+ assert_equal("MozillaIsMyFriend", spki.challenge)
+ assert_equal(OpenSSL::PKey::RSA, spki.public_key.class)
+
+ spki = OpenSSL::Netscape::SPKI.new(@b64.unpack("m").first)
+ assert_equal(@b64, spki.to_pem)
+ assert_equal(@b64.unpack("m").first, spki.to_der)
+ assert_equal("MozillaIsMyFriend", spki.challenge)
+ assert_equal(OpenSSL::PKey::RSA, spki.public_key.class)
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_pair.rb b/trunk/test/openssl/test_pair.rb
new file mode 100644
index 0000000000..17713c9988
--- /dev/null
+++ b/trunk/test/openssl/test_pair.rb
@@ -0,0 +1,149 @@
+begin
+ require "openssl"
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(OpenSSL)
+
+require 'socket'
+dir = File.expand_path(__FILE__)
+2.times {dir = File.dirname(dir)}
+$:.replace([File.join(dir, "ruby")] | $:)
+require 'ut_eof'
+
+module SSLPair
+ def server
+ host = "127.0.0.1"
+ port = 0
+ ctx = OpenSSL::SSL::SSLContext.new()
+ ctx.ciphers = "ADH"
+ tcps = TCPServer.new(host, port)
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+ return ssls
+ end
+
+ def client(port)
+ host = "127.0.0.1"
+ ctx = OpenSSL::SSL::SSLContext.new()
+ ctx.ciphers = "ADH"
+ s = TCPSocket.new(host, port)
+ ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
+ ssl.connect
+ ssl.sync_close = true
+ ssl
+ end
+
+ def ssl_pair
+ ssls = server
+ th = Thread.new {
+ ns = ssls.accept
+ ssls.close
+ ns
+ }
+ port = ssls.to_io.addr[1]
+ c = client(port)
+ s = th.value
+ if block_given?
+ begin
+ yield c, s
+ ensure
+ c.close unless c.closed?
+ s.close unless s.closed?
+ end
+ else
+ return c, s
+ end
+ ensure
+ if th && th.alive?
+ th.kill
+ th.join
+ end
+ end
+end
+
+class OpenSSL::TestEOF1 < Test::Unit::TestCase
+ include TestEOF
+ include SSLPair
+
+ def open_file(content)
+ s1, s2 = ssl_pair
+ Thread.new { s2 << content; s2.close }
+ yield s1
+ end
+end
+
+class OpenSSL::TestEOF2 < Test::Unit::TestCase
+ include TestEOF
+ include SSLPair
+
+ def open_file(content)
+ s1, s2 = ssl_pair
+ Thread.new { s1 << content; s1.close }
+ yield s2
+ end
+end
+
+class OpenSSL::TestPair < Test::Unit::TestCase
+ include SSLPair
+
+ def test_getc
+ ssl_pair {|s1, s2|
+ s1 << "a"
+ assert_equal(?a, s2.getc)
+ }
+ end
+
+ def test_readpartial
+ ssl_pair {|s1, s2|
+ s2.write "a\nbcd"
+ assert_equal("a\n", s1.gets)
+ assert_equal("bcd", s1.readpartial(10))
+ s2.write "efg"
+ assert_equal("efg", s1.readpartial(10))
+ s2.close
+ assert_raise(EOFError) { s1.readpartial(10) }
+ assert_raise(EOFError) { s1.readpartial(10) }
+ assert_equal("", s1.readpartial(0))
+ }
+ end
+
+ def test_readall
+ ssl_pair {|s1, s2|
+ s2.close
+ assert_equal("", s1.read)
+ }
+ end
+
+ def test_readline
+ ssl_pair {|s1, s2|
+ s2.close
+ assert_raise(EOFError) { s1.readline }
+ }
+ end
+
+ def test_puts_meta
+ ssl_pair {|s1, s2|
+ begin
+ old = $/
+ $/ = '*'
+ s1.puts 'a'
+ ensure
+ $/ = old
+ end
+ s1.close
+ assert_equal("a\n", s2.read)
+ }
+ end
+
+ def test_puts_empty
+ ssl_pair {|s1, s2|
+ s1.puts
+ s1.close
+ assert_equal("\n", s2.read)
+ }
+ end
+
+end
+
+end
diff --git a/trunk/test/openssl/test_pkcs7.rb b/trunk/test/openssl/test_pkcs7.rb
new file mode 100644
index 0000000000..2cdd9343ff
--- /dev/null
+++ b/trunk/test/openssl/test_pkcs7.rb
@@ -0,0 +1,154 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestPKCS7 < Test::Unit::TestCase
+ def setup
+ @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+ ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
+ ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
+
+ now = Time.now
+ ca_exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["keyUsage","keyCertSign, cRLSign",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ]
+ @ca_cert = issue_cert(ca, @rsa2048, 1, Time.now, Time.now+3600, ca_exts,
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ ee_exts = [
+ ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
+ ]
+ @ee1_cert = issue_cert(ee1, @rsa1024, 2, Time.now, Time.now+1800, ee_exts,
+ @ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ @ee2_cert = issue_cert(ee2, @rsa1024, 3, Time.now, Time.now+1800, ee_exts,
+ @ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ end
+
+ def issue_cert(*args)
+ OpenSSL::TestUtils.issue_cert(*args)
+ end
+
+ def test_signed
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ ca_certs = [@ca_cert]
+
+ data = "aaaaa\r\nbbbbb\r\nccccc\r\n"
+ tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs)
+ p7 = OpenSSL::PKCS7.new(tmp.to_der)
+ certs = p7.certificates
+ signers = p7.signers
+ assert(p7.verify([], store))
+ assert_equal(data, p7.data)
+ assert_equal(2, certs.size)
+ assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s)
+ assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s)
+ assert_equal(1, signers.size)
+ assert_equal(@ee1_cert.serial, signers[0].serial)
+ assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s)
+
+ # Normaly OpenSSL tries to translate the supplied content into canonical
+ # MIME format (e.g. a newline character is converted into CR+LF).
+ # If the content is a binary, PKCS7::BINARY flag should be used.
+
+ data = "aaaaa\nbbbbb\nccccc\n"
+ flag = OpenSSL::PKCS7::BINARY
+ tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag)
+ p7 = OpenSSL::PKCS7.new(tmp.to_der)
+ certs = p7.certificates
+ signers = p7.signers
+ assert(p7.verify([], store))
+ assert_equal(data, p7.data)
+ assert_equal(2, certs.size)
+ assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s)
+ assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s)
+ assert_equal(1, signers.size)
+ assert_equal(@ee1_cert.serial, signers[0].serial)
+ assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s)
+
+ # A signed-data which have multiple signatures can be created
+ # through the following steps.
+ # 1. create two signed-data
+ # 2. copy signerInfo and certificate from one to another
+
+ tmp1 = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, [], flag)
+ tmp2 = OpenSSL::PKCS7.sign(@ee2_cert, @rsa1024, data, [], flag)
+ tmp1.add_signer(tmp2.signers[0])
+ tmp1.add_certificate(@ee2_cert)
+
+ p7 = OpenSSL::PKCS7.new(tmp1.to_der)
+ certs = p7.certificates
+ signers = p7.signers
+ assert(p7.verify([], store))
+ assert_equal(data, p7.data)
+ assert_equal(2, certs.size)
+ assert_equal(2, signers.size)
+ assert_equal(@ee1_cert.serial, signers[0].serial)
+ assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s)
+ assert_equal(@ee2_cert.serial, signers[1].serial)
+ assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s)
+ end
+
+ def test_detached_sign
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ ca_certs = [@ca_cert]
+
+ data = "aaaaa\nbbbbb\nccccc\n"
+ flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED
+ tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag)
+ p7 = OpenSSL::PKCS7.new(tmp.to_der)
+ a1 = OpenSSL::ASN1.decode(p7)
+
+ certs = p7.certificates
+ signers = p7.signers
+ assert(!p7.verify([], store))
+ assert(p7.verify([], store, data))
+ assert_equal(data, p7.data)
+ assert_equal(2, certs.size)
+ assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s)
+ assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s)
+ assert_equal(1, signers.size)
+ assert_equal(@ee1_cert.serial, signers[0].serial)
+ assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s)
+ end
+
+ def test_enveloped
+ if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x0090704f
+ # PKCS7_encrypt() of OpenSSL-0.9.7d goes to SEGV.
+ # http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html
+ return
+ end
+
+ certs = [@ee1_cert, @ee2_cert]
+ cipher = OpenSSL::Cipher::AES.new("128-CBC")
+ data = "aaaaa\nbbbbb\nccccc\n"
+
+ tmp = OpenSSL::PKCS7.encrypt(certs, data, cipher, OpenSSL::PKCS7::BINARY)
+ p7 = OpenSSL::PKCS7.new(tmp.to_der)
+ recip = p7.recipients
+ assert_equal(:enveloped, p7.type)
+ assert_equal(2, recip.size)
+
+ assert_equal(@ca_cert.subject.to_s, recip[0].issuer.to_s)
+ assert_equal(2, recip[0].serial)
+ assert_equal(data, p7.decrypt(@rsa1024, @ee1_cert))
+
+ assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s)
+ assert_equal(3, recip[1].serial)
+ assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert))
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_pkey_rsa.rb b/trunk/test/openssl/test_pkey_rsa.rb
new file mode 100644
index 0000000000..401cb6c3e0
--- /dev/null
+++ b/trunk/test/openssl/test_pkey_rsa.rb
@@ -0,0 +1,49 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestPKeyRSA < Test::Unit::TestCase
+ def test_padding
+ key = OpenSSL::PKey::RSA.new(512, 3)
+
+ # Need right size for raw mode
+ plain0 = "x" * (512/8)
+ cipher = key.private_encrypt(plain0, OpenSSL::PKey::RSA::NO_PADDING)
+ plain1 = key.public_decrypt(cipher, OpenSSL::PKey::RSA::NO_PADDING)
+ assert_equal(plain0, plain1)
+
+ # Need smaller size for pkcs1 mode
+ plain0 = "x" * (512/8 - 11)
+ cipher1 = key.private_encrypt(plain0, OpenSSL::PKey::RSA::PKCS1_PADDING)
+ plain1 = key.public_decrypt(cipher1, OpenSSL::PKey::RSA::PKCS1_PADDING)
+ assert_equal(plain0, plain1)
+
+ cipherdef = key.private_encrypt(plain0) # PKCS1_PADDING is default
+ plain1 = key.public_decrypt(cipherdef)
+ assert_equal(plain0, plain1)
+ assert_equal(cipher1, cipherdef)
+
+ # Failure cases
+ assert_raise(ArgumentError){ key.private_encrypt() }
+ assert_raise(ArgumentError){ key.private_encrypt("hi", 1, nil) }
+ assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt(plain0, 666) }
+ end
+
+ def test_private
+ key = OpenSSL::PKey::RSA.new(512, 3)
+ assert(key.private?)
+ key2 = OpenSSL::PKey::RSA.new(key.to_der)
+ assert(key2.private?)
+ key3 = key.public_key
+ assert(!key3.private?)
+ key4 = OpenSSL::PKey::RSA.new(key3.to_der)
+ assert(!key4.private?)
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_ssl.rb b/trunk/test/openssl/test_ssl.rb
new file mode 100644
index 0000000000..ea959892f3
--- /dev/null
+++ b/trunk/test/openssl/test_ssl.rb
@@ -0,0 +1,557 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "rbconfig"
+require "socket"
+require "test/unit"
+begin
+ loadpath = $:.dup
+ $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
+ require 'envutil'
+ensure
+ $:.replace(loadpath)
+end
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestSSL < Test::Unit::TestCase
+ RUBY = EnvUtil.rubybin
+ SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb")
+ PORT = 20443
+ ITERATIONS = ($0 == __FILE__) ? 100 : 10
+
+ def setup
+ @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256
+ @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+ @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+ @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+
+ now = Time.at(Time.now.to_i)
+ ca_exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["keyUsage","cRLSign,keyCertSign",true],
+ ]
+ ee_exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ]
+ @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts,
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ @server = nil
+ end
+
+ def teardown
+ end
+
+ def issue_cert(*arg)
+ OpenSSL::TestUtils.issue_cert(*arg)
+ end
+
+ def issue_crl(*arg)
+ OpenSSL::TestUtils.issue_crl(*arg)
+ end
+
+ def readwrite_loop(ctx, ssl)
+ while line = ssl.gets
+ if line =~ /^STARTTLS$/
+ ssl.accept
+ next
+ end
+ ssl.write(line)
+ end
+ rescue OpenSSL::SSL::SSLError
+ rescue IOError
+ ensure
+ ssl.close rescue nil
+ end
+
+ def server_loop(ctx, ssls, server_proc)
+ loop do
+ ssl = nil
+ begin
+ ssl = ssls.accept
+ rescue OpenSSL::SSL::SSLError
+ retry
+ end
+
+ Thread.start do
+ Thread.current.abort_on_exception = true
+ server_proc.call(ctx, ssl)
+ end
+ end
+ rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED
+ end
+
+ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
+ ctx_proc = args[:ctx_proc]
+ server_proc = args[:server_proc]
+ server_proc ||= method(:readwrite_loop)
+
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.cert_store = store
+ #ctx.extra_chain_cert = [ ca_cert ]
+ ctx.cert = @svr_cert
+ ctx.key = @svr_key
+ ctx.verify_mode = verify_mode
+ ctx_proc.call(ctx) if ctx_proc
+
+ Socket.do_not_reverse_lookup = true
+ tcps = nil
+ port = port0
+ begin
+ tcps = TCPServer.new("127.0.0.1", port)
+ rescue Errno::EADDRINUSE
+ port += 1
+ retry
+ end
+
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+ ssls.start_immediately = start_immediately
+
+ begin
+ server = Thread.new do
+ Thread.current.abort_on_exception = true
+ server_loop(ctx, ssls, server_proc)
+ end
+
+ $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG
+
+ block.call(server, port.to_i)
+ ensure
+ begin
+ begin
+ tcps.shutdown
+ rescue Errno::ENOTCONN
+ # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
+ # call #close instead of #shutdown.
+ tcps.close
+ tcps = nil
+ end if (tcps)
+ if (server)
+ server.join(5)
+ if server.alive?
+ server.kill
+ server.join
+ flunk("TCPServer was closed and SSLServer is still alive") unless $!
+ end
+ end
+ ensure
+ tcps.close if (tcps)
+ end
+ end
+ end
+
+ def starttls(ssl)
+ ssl.puts("STARTTLS")
+
+ sleep 1 # When this line is eliminated, process on Cygwin blocks
+ # forever at ssl.connect. But I don't know why it does.
+
+ ssl.connect
+ end
+
+ def test_ctx_setup
+ ctx = OpenSSL::SSL::SSLContext.new
+ assert_equal(ctx.setup, true)
+ assert_equal(ctx.setup, nil)
+ end
+
+ def test_connect_and_close
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ assert(ssl.connect)
+ ssl.close
+ assert(!sock.closed?)
+ sock.close
+
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true # !!
+ assert(ssl.connect)
+ ssl.close
+ assert(sock.closed?)
+ }
+ end
+
+ def test_read_and_write
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ ssl.connect
+
+ # syswrite and sysread
+ ITERATIONS.times{|i|
+ str = "x" * 100 + "\n"
+ ssl.syswrite(str)
+ assert_equal(str, ssl.sysread(str.size))
+
+ str = "x" * i * 100 + "\n"
+ buf = ""
+ ssl.syswrite(str)
+ assert_equal(buf.object_id, ssl.sysread(str.size, buf).object_id)
+ assert_equal(str, buf)
+ }
+
+ # puts and gets
+ ITERATIONS.times{
+ str = "x" * 100 + "\n"
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+
+ str = "x" * 100
+ ssl.puts(str)
+ assert_equal(str, ssl.gets("\n", 100))
+ assert_equal("\n", ssl.gets)
+ }
+
+ # read and write
+ ITERATIONS.times{|i|
+ str = "x" * 100 + "\n"
+ ssl.write(str)
+ assert_equal(str, ssl.read(str.size))
+
+ str = "x" * i * 100 + "\n"
+ buf = ""
+ ssl.write(str)
+ assert_equal(buf.object_id, ssl.read(str.size, buf).object_id)
+ assert_equal(str, buf)
+ }
+
+ ssl.close
+ }
+ end
+
+ def test_client_auth
+ vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
+ start_server(PORT, vflag, true){|server, port|
+ assert_raises(OpenSSL::SSL::SSLError){
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ }
+
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.key = @cli_key
+ ctx.cert = @cli_cert
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.sync_close = true
+ ssl.connect
+ ssl.puts("foo")
+ assert_equal("foo\n", ssl.gets)
+ ssl.close
+
+ called = nil
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.client_cert_cb = Proc.new{ |sslconn|
+ called = true
+ [@cli_cert, @cli_key]
+ }
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.sync_close = true
+ ssl.connect
+ assert(called)
+ ssl.puts("foo")
+ assert_equal("foo\n", ssl.gets)
+ ssl.close
+ }
+ end
+
+ def test_starttls
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, false){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ str = "x" * 1000 + "\n"
+
+ ITERATIONS.times{
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+ }
+
+ starttls(ssl)
+
+ ITERATIONS.times{
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+ }
+
+ ssl.close
+ }
+ end
+
+ def test_parallel
+ GC.start
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ ssls = []
+ 10.times{
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ ssl.sync_close = true
+ ssls << ssl
+ }
+ str = "x" * 1000 + "\n"
+ ITERATIONS.times{
+ ssls.each{|ssl|
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+ }
+ }
+ ssls.each{|ssl| ssl.close }
+ }
+ end
+
+ def test_verify_result
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ssl.verify_result)
+
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(
+ :verify_callback => Proc.new do |preverify_ok, store_ctx|
+ store_ctx.error = OpenSSL::X509::V_OK
+ true
+ end
+ )
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.connect
+ assert_equal(OpenSSL::X509::V_OK, ssl.verify_result)
+
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(
+ :verify_callback => Proc.new do |preverify_ok, store_ctx|
+ store_ctx.error = OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION
+ false
+ end
+ )
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION, ssl.verify_result)
+ }
+ end
+
+ def test_sslctx_set_params
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, ctx.verify_mode)
+ assert_equal(OpenSSL::SSL::OP_ALL, ctx.options)
+ ciphers = ctx.ciphers
+ ciphers_versions = ciphers.collect{|_, v, _, _| v }
+ ciphers_names = ciphers.collect{|v, _, _, _| v }
+ assert(ciphers_names.all?{|v| /ADH/ !~ v })
+ assert(ciphers_versions.all?{|v| /SSLv2/ !~ v })
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ssl.verify_result)
+ }
+ end
+
+ def test_post_connection_check
+ sslerr = OpenSSL::SSL::SSLError
+
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert_raises(sslerr){ssl.post_connection_check("localhost.localdomain")}
+ assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert(ssl.post_connection_check("localhost"))
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+
+ cert = ssl.peer_cert
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
+ }
+
+ now = Time.now
+ exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ["subjectAltName","DNS:localhost.localdomain",false],
+ ["subjectAltName","IP:127.0.0.1",false],
+ ]
+ @svr_cert = issue_cert(@svr, @svr_key, 4, now, now+1800, exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert(ssl.post_connection_check("localhost.localdomain"))
+ assert(ssl.post_connection_check("127.0.0.1"))
+ assert_raises(sslerr){ssl.post_connection_check("localhost")}
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+
+ cert = ssl.peer_cert
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
+ }
+
+ now = Time.now
+ exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ["subjectAltName","DNS:*.localdomain",false],
+ ]
+ @svr_cert = issue_cert(@svr, @svr_key, 5, now, now+1800, exts,
+ @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.connect
+ assert(ssl.post_connection_check("localhost.localdomain"))
+ assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert_raises(sslerr){ssl.post_connection_check("localhost")}
+ assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ cert = ssl.peer_cert
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
+ }
+ end
+
+ def test_client_session
+ last_session = nil
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
+ 2.times do
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ ssl.session = last_session if last_session
+ ssl.connect
+
+ session = ssl.session
+ if last_session
+ assert(ssl.session_reused?)
+
+ if session.respond_to?(:id)
+ assert_equal(session.id, last_session.id)
+ end
+ assert_equal(session.to_pem, last_session.to_pem)
+ assert_equal(session.to_der, last_session.to_der)
+ # Older version of OpenSSL may not be consistent. Look up which versions later.
+ assert_equal(session.to_text, last_session.to_text)
+ else
+ assert(!ssl.session_reused?)
+ end
+ last_session = session
+
+ str = "x" * 100 + "\n"
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+
+ ssl.close
+ end
+ end
+ end
+
+ def test_server_session
+ connections = 0
+ saved_session = nil
+
+ ctx_proc = Proc.new do |ctx, ssl|
+# add test for session callbacks here
+ end
+
+ server_proc = Proc.new do |ctx, ssl|
+ session = ssl.session
+ stats = ctx.session_cache_stats
+
+ case connections
+ when 0
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 0)
+ assert_equal(stats[:cache_misses], 0)
+ assert(!ssl.session_reused?)
+ when 1
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 1)
+ assert_equal(stats[:cache_misses], 0)
+ assert(ssl.session_reused?)
+ ctx.session_remove(session)
+ saved_session = session
+ when 2
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 1)
+ assert_equal(stats[:cache_misses], 1)
+ assert(!ssl.session_reused?)
+ ctx.session_add(saved_session)
+ when 3
+ assert_equal(stats[:cache_num], 2)
+ assert_equal(stats[:cache_hits], 2)
+ assert_equal(stats[:cache_misses], 1)
+ assert(ssl.session_reused?)
+ ctx.flush_sessions(Time.now + 5000)
+ when 4
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 2)
+ assert_equal(stats[:cache_misses], 2)
+ assert(!ssl.session_reused?)
+ ctx.session_add(saved_session)
+ end
+ connections += 1
+
+ readwrite_loop(ctx, ssl)
+ end
+
+ first_session = nil
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
+ 10.times do |i|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ if defined?(OpenSSL::SSL::OP_NO_TICKET)
+ # disable RFC4507 support
+ ctx.options = OpenSSL::SSL::OP_NO_TICKET
+ end
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.sync_close = true
+ ssl.session = first_session if first_session
+ ssl.connect
+
+ session = ssl.session
+ if first_session
+ case i
+ when 1; assert(ssl.session_reused?)
+ when 2; assert(!ssl.session_reused?)
+ when 3; assert(ssl.session_reused?)
+ when 4; assert(!ssl.session_reused?)
+ when 5..10; assert(ssl.session_reused?)
+ end
+ end
+ first_session ||= session
+
+ str = "x" * 100 + "\n"
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+
+ ssl.close
+ end
+ end
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509cert.rb b/trunk/test/openssl/test_x509cert.rb
new file mode 100644
index 0000000000..a5a75ff1b6
--- /dev/null
+++ b/trunk/test/openssl/test_x509cert.rb
@@ -0,0 +1,175 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509Certificate < Test::Unit::TestCase
+ def setup
+ @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
+ @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
+ @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+ @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
+ @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
+ end
+
+ def teardown
+ end
+
+ def issue_cert(*args)
+ OpenSSL::TestUtils.issue_cert(*args)
+ end
+
+ def test_serial
+ [1, 2**32, 2**100].each{|s|
+ cert = issue_cert(@ca, @rsa2048, s, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(s, cert.serial)
+ cert = OpenSSL::X509::Certificate.new(cert.to_der)
+ assert_equal(s, cert.serial)
+ }
+ end
+
+ def test_public_key
+ exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ]
+
+ sha1 = OpenSSL::Digest::SHA1.new
+ dss1 = OpenSSL::Digest::DSS1.new
+ [
+ [@rsa1024, sha1], [@rsa2048, sha1], [@dsa256, dss1], [@dsa512, dss1],
+ ].each{|pk, digest|
+ cert = issue_cert(@ca, pk, 1, Time.now, Time.now+3600, exts,
+ nil, nil, digest)
+ assert_equal(cert.extensions[1].value,
+ OpenSSL::TestUtils.get_subject_key_id(cert))
+ cert = OpenSSL::X509::Certificate.new(cert.to_der)
+ assert_equal(cert.extensions[1].value,
+ OpenSSL::TestUtils.get_subject_key_id(cert))
+ }
+ end
+
+ def test_validity
+ now = Time.now until now && now.usec != 0
+ cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_not_equal(now, cert.not_before)
+ assert_not_equal(now+3600, cert.not_after)
+
+ now = Time.at(now.to_i)
+ cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(now.getutc, cert.not_before)
+ assert_equal((now+3600).getutc, cert.not_after)
+
+ now = Time.at(0)
+ cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(now.getutc, cert.not_before)
+ assert_equal(now.getutc, cert.not_after)
+
+ now = Time.at(0x7fffffff)
+ cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(now.getutc, cert.not_before)
+ assert_equal(now.getutc, cert.not_after)
+ end
+
+ def test_extension
+ ca_exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["keyUsage","keyCertSign, cRLSign",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ]
+ ca_cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, ca_exts,
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ ca_cert.extensions.each_with_index{|ext, i|
+ assert_equal(ca_exts[i].first, ext.oid)
+ assert_equal(ca_exts[i].last, ext.critical?)
+ }
+
+ ee1_exts = [
+ ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
+ ["subjectAltName","email:ee1@ruby-lang.org",false],
+ ]
+ ee1_cert = issue_cert(@ee1, @rsa1024, 2, Time.now, Time.now+1800, ee1_exts,
+ ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der)
+ ee1_cert.extensions.each_with_index{|ext, i|
+ assert_equal(ee1_exts[i].first, ext.oid)
+ assert_equal(ee1_exts[i].last, ext.critical?)
+ }
+
+ ee2_exts = [
+ ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","issuer:always",false],
+ ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
+ ["subjectAltName","email:ee2@ruby-lang.org",false],
+ ]
+ ee2_cert = issue_cert(@ee2, @rsa1024, 3, Time.now, Time.now+1800, ee2_exts,
+ ca_cert, @rsa2048, OpenSSL::Digest::MD5.new)
+ assert_equal(ca_cert.subject.to_der, ee2_cert.issuer.to_der)
+ ee2_cert.extensions.each_with_index{|ext, i|
+ assert_equal(ee2_exts[i].first, ext.oid)
+ assert_equal(ee2_exts[i].last, ext.critical?)
+ }
+
+ end
+
+ def test_sign_and_verify
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(false, cert.verify(@rsa1024))
+ assert_equal(true, cert.verify(@rsa2048))
+ assert_equal(false, cert.verify(@dsa256))
+ assert_equal(false, cert.verify(@dsa512))
+ cert.serial = 2
+ assert_equal(false, cert.verify(@rsa2048))
+
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::MD5.new)
+ assert_equal(false, cert.verify(@rsa1024))
+ assert_equal(true, cert.verify(@rsa2048))
+ assert_equal(false, cert.verify(@dsa256))
+ assert_equal(false, cert.verify(@dsa512))
+ cert.subject = @ee1
+ assert_equal(false, cert.verify(@rsa2048))
+
+ cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::DSS1.new)
+ assert_equal(false, cert.verify(@rsa1024))
+ assert_equal(false, cert.verify(@rsa2048))
+ assert_equal(false, cert.verify(@dsa256))
+ assert_equal(true, cert.verify(@dsa512))
+ cert.not_after = Time.now
+ assert_equal(false, cert.verify(@dsa512))
+
+ assert_raises(OpenSSL::X509::CertificateError){
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::DSS1.new)
+ }
+ assert_raises(OpenSSL::X509::CertificateError){
+ cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::MD5.new)
+ }
+ assert_raises(OpenSSL::X509::CertificateError){
+ cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ }
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509crl.rb b/trunk/test/openssl/test_x509crl.rb
new file mode 100644
index 0000000000..444a00a586
--- /dev/null
+++ b/trunk/test/openssl/test_x509crl.rb
@@ -0,0 +1,218 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509CRL < Test::Unit::TestCase
+ def setup
+ @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
+ @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
+ @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+ @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
+ @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
+ end
+
+ def teardown
+ end
+
+ def issue_crl(*args)
+ OpenSSL::TestUtils.issue_crl(*args)
+ end
+
+ def issue_cert(*args)
+ OpenSSL::TestUtils.issue_cert(*args)
+ end
+
+ def test_basic
+ now = Time.at(Time.now.to_i)
+
+ cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ crl = issue_crl([], 1, now, now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_equal(1, crl.version)
+ assert_equal(cert.issuer.to_der, crl.issuer.to_der)
+ assert_equal(now, crl.last_update)
+ assert_equal(now+1600, crl.next_update)
+
+ crl = OpenSSL::X509::CRL.new(crl.to_der)
+ assert_equal(1, crl.version)
+ assert_equal(cert.issuer.to_der, crl.issuer.to_der)
+ assert_equal(now, crl.last_update)
+ assert_equal(now+1600, crl.next_update)
+ end
+
+ def test_revoked
+
+ # CRLReason ::= ENUMERATED {
+ # unspecified (0),
+ # keyCompromise (1),
+ # cACompromise (2),
+ # affiliationChanged (3),
+ # superseded (4),
+ # cessationOfOperation (5),
+ # certificateHold (6),
+ # removeFromCRL (8),
+ # privilegeWithdrawn (9),
+ # aACompromise (10) }
+
+ now = Time.at(Time.now.to_i)
+ revoke_info = [
+ [1, Time.at(0), 1],
+ [2, Time.at(0x7fffffff), 2],
+ [3, now, 3],
+ [4, now, 4],
+ [5, now, 5],
+ ]
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ revoked = crl.revoked
+ assert_equal(5, revoked.size)
+ assert_equal(1, revoked[0].serial)
+ assert_equal(2, revoked[1].serial)
+ assert_equal(3, revoked[2].serial)
+ assert_equal(4, revoked[3].serial)
+ assert_equal(5, revoked[4].serial)
+
+ assert_equal(Time.at(0), revoked[0].time)
+ assert_equal(Time.at(0x7fffffff), revoked[1].time)
+ assert_equal(now, revoked[2].time)
+ assert_equal(now, revoked[3].time)
+ assert_equal(now, revoked[4].time)
+
+ assert_equal("CRLReason", revoked[0].extensions[0].oid)
+ assert_equal("CRLReason", revoked[1].extensions[0].oid)
+ assert_equal("CRLReason", revoked[2].extensions[0].oid)
+ assert_equal("CRLReason", revoked[3].extensions[0].oid)
+ assert_equal("CRLReason", revoked[4].extensions[0].oid)
+
+ assert_equal("Key Compromise", revoked[0].extensions[0].value)
+ assert_equal("CA Compromise", revoked[1].extensions[0].value)
+ assert_equal("Affiliation Changed", revoked[2].extensions[0].value)
+ assert_equal("Superseded", revoked[3].extensions[0].value)
+ assert_equal("Cessation Of Operation", revoked[4].extensions[0].value)
+
+ assert_equal(false, revoked[0].extensions[0].critical?)
+ assert_equal(false, revoked[1].extensions[0].critical?)
+ assert_equal(false, revoked[2].extensions[0].critical?)
+ assert_equal(false, revoked[3].extensions[0].critical?)
+ assert_equal(false, revoked[4].extensions[0].critical?)
+
+ crl = OpenSSL::X509::CRL.new(crl.to_der)
+ assert_equal("Key Compromise", revoked[0].extensions[0].value)
+ assert_equal("CA Compromise", revoked[1].extensions[0].value)
+ assert_equal("Affiliation Changed", revoked[2].extensions[0].value)
+ assert_equal("Superseded", revoked[3].extensions[0].value)
+ assert_equal("Cessation Of Operation", revoked[4].extensions[0].value)
+
+ revoke_info = (1..1000).collect{|i| [i, now, 0] }
+ crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ revoked = crl.revoked
+ assert_equal(1000, revoked.size)
+ assert_equal(1, revoked[0].serial)
+ assert_equal(1000, revoked[999].serial)
+ end
+
+ def test_extension
+ cert_exts = [
+ ["basicConstraints", "CA:TRUE", true],
+ ["subjectKeyIdentifier", "hash", false],
+ ["authorityKeyIdentifier", "keyid:always", false],
+ ["subjectAltName", "email:xyzzy@ruby-lang.org", false],
+ ["keyUsage", "cRLSign, keyCertSign", true],
+ ]
+ crl_exts = [
+ ["authorityKeyIdentifier", "keyid:always", false],
+ ["issuerAltName", "issuer:copy", false],
+ ]
+
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, cert_exts,
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts,
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ exts = crl.extensions
+ assert_equal(3, exts.size)
+ assert_equal("1", exts[0].value)
+ assert_equal("crlNumber", exts[0].oid)
+ assert_equal(false, exts[0].critical?)
+
+ assert_equal("authorityKeyIdentifier", exts[1].oid)
+ keyid = OpenSSL::TestUtils.get_subject_key_id(cert)
+ assert_match(/^keyid:#{keyid}/, exts[1].value)
+ assert_equal(false, exts[1].critical?)
+
+ assert_equal("issuerAltName", exts[2].oid)
+ assert_equal("email:xyzzy@ruby-lang.org", exts[2].value)
+ assert_equal(false, exts[2].critical?)
+
+ crl = OpenSSL::X509::CRL.new(crl.to_der)
+ exts = crl.extensions
+ assert_equal(3, exts.size)
+ assert_equal("1", exts[0].value)
+ assert_equal("crlNumber", exts[0].oid)
+ assert_equal(false, exts[0].critical?)
+
+ assert_equal("authorityKeyIdentifier", exts[1].oid)
+ keyid = OpenSSL::TestUtils.get_subject_key_id(cert)
+ assert_match(/^keyid:#{keyid}/, exts[1].value)
+ assert_equal(false, exts[1].critical?)
+
+ assert_equal("issuerAltName", exts[2].oid)
+ assert_equal("email:xyzzy@ruby-lang.org", exts[2].value)
+ assert_equal(false, exts[2].critical?)
+ end
+
+ def test_crlnumber
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ crl = issue_crl([], 1, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_match(1.to_s, crl.extensions[0].value)
+ assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text)
+
+ crl = issue_crl([], 2**32, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_match((2**32).to_s, crl.extensions[0].value)
+ assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text)
+
+ crl = issue_crl([], 2**100, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text)
+ assert_match((2**100).to_s, crl.extensions[0].value)
+ end
+
+ def test_sign_and_verify
+ cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ crl = issue_crl([], 1, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ assert_equal(false, crl.verify(@rsa1024))
+ assert_equal(true, crl.verify(@rsa2048))
+ assert_equal(false, crl.verify(@dsa256))
+ assert_equal(false, crl.verify(@dsa512))
+ crl.version = 0
+ assert_equal(false, crl.verify(@rsa2048))
+
+ cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::DSS1.new)
+ crl = issue_crl([], 1, Time.now, Time.now+1600, [],
+ cert, @dsa512, OpenSSL::Digest::DSS1.new)
+ assert_equal(false, crl.verify(@rsa1024))
+ assert_equal(false, crl.verify(@rsa2048))
+ assert_equal(false, crl.verify(@dsa256))
+ assert_equal(true, crl.verify(@dsa512))
+ crl.version = 0
+ assert_equal(false, crl.verify(@dsa512))
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509ext.rb b/trunk/test/openssl/test_x509ext.rb
new file mode 100644
index 0000000000..d43bbd6bd3
--- /dev/null
+++ b/trunk/test/openssl/test_x509ext.rb
@@ -0,0 +1,74 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509Extension < Test::Unit::TestCase
+ def setup
+ @basic_constraints_value = OpenSSL::ASN1::Sequence([
+ OpenSSL::ASN1::Boolean(true), # CA
+ OpenSSL::ASN1::Integer(2) # pathlen
+ ])
+ @basic_constraints = OpenSSL::ASN1::Sequence([
+ OpenSSL::ASN1::ObjectId("basicConstraints"),
+ OpenSSL::ASN1::Boolean(true),
+ OpenSSL::ASN1::OctetString(@basic_constraints_value.to_der),
+ ])
+ end
+
+ def teardown
+ end
+
+ def test_new
+ ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
+ assert_equal("basicConstraints", ext.oid)
+ assert_equal(true, ext.critical?)
+ assert_equal("CA:TRUE, pathlen:2", ext.value)
+
+ ext = OpenSSL::X509::Extension.new("2.5.29.19",
+ @basic_constraints_value.to_der, true)
+ assert_equal(@basic_constraints.to_der, ext.to_der)
+ end
+
+ def test_create_by_factory
+ ef = OpenSSL::X509::ExtensionFactory.new
+
+ bc = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
+ assert_equal(@basic_constraints.to_der, bc.to_der)
+
+ bc = ef.create_extension("basicConstraints", "CA:TRUE, pathlen:2", true)
+ assert_equal(@basic_constraints.to_der, bc.to_der)
+
+ begin
+ ef.config = OpenSSL::Config.parse(<<-_end_of_cnf_)
+ [crlDistPts]
+ URI.1 = http://www.example.com/crl
+ URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary
+ _end_of_cnf_
+ rescue NotImplementedError
+ return
+ end
+
+ cdp = ef.create_extension("crlDistributionPoints", "@crlDistPts")
+ assert_equal(false, cdp.critical?)
+ assert_equal("crlDistributionPoints", cdp.oid)
+ assert_match(%{URI:http://www\.example\.com/crl}, cdp.value)
+ assert_match(
+ %r{URI:ldap://ldap\.example\.com/cn=ca\?certificateRevocationList;binary},
+ cdp.value)
+
+ cdp = ef.create_extension("crlDistributionPoints", "critical, @crlDistPts")
+ assert_equal(true, cdp.critical?)
+ assert_equal("crlDistributionPoints", cdp.oid)
+ assert_match(%{URI:http://www.example.com/crl}, cdp.value)
+ assert_match(
+ %r{URI:ldap://ldap.example.com/cn=ca\?certificateRevocationList;binary},
+ cdp.value)
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509name.rb b/trunk/test/openssl/test_x509name.rb
new file mode 100644
index 0000000000..fb5a1ae4ff
--- /dev/null
+++ b/trunk/test/openssl/test_x509name.rb
@@ -0,0 +1,266 @@
+begin
+ require "openssl"
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509Name < Test::Unit::TestCase
+ OpenSSL::ASN1::ObjectId.register(
+ "1.2.840.113549.1.9.1", "emailAddress", "emailAddress")
+ OpenSSL::ASN1::ObjectId.register(
+ "2.5.4.5", "serialNumber", "serialNumber")
+
+ def setup
+ @obj_type_tmpl = Hash.new(OpenSSL::ASN1::PRINTABLESTRING)
+ @obj_type_tmpl.update(OpenSSL::X509::Name::OBJECT_TYPE_TEMPLATE)
+ end
+
+ def teardown
+ end
+
+ def test_s_new
+ dn = [ ["C", "JP"], ["O", "example"], ["CN", "www.example.jp"] ]
+ name = OpenSSL::X509::Name.new(dn)
+ ary = name.to_a
+ assert_equal("/C=JP/O=example/CN=www.example.jp", name.to_s)
+ assert_equal("C", ary[0][0])
+ assert_equal("O", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("JP", ary[0][1])
+ assert_equal("example", ary[1][1])
+ assert_equal("www.example.jp", ary[2][1])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+
+ dn = [
+ ["countryName", "JP"],
+ ["organizationName", "example"],
+ ["commonName", "www.example.jp"]
+ ]
+ name = OpenSSL::X509::Name.new(dn)
+ ary = name.to_a
+ assert_equal("/C=JP/O=example/CN=www.example.jp", name.to_s)
+ assert_equal("C", ary[0][0])
+ assert_equal("O", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("JP", ary[0][1])
+ assert_equal("example", ary[1][1])
+ assert_equal("www.example.jp", ary[2][1])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+
+ name = OpenSSL::X509::Name.new(dn, @obj_type_tmpl)
+ ary = name.to_a
+ assert_equal("/C=JP/O=example/CN=www.example.jp", name.to_s)
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[2][2])
+
+ dn = [
+ ["countryName", "JP", OpenSSL::ASN1::PRINTABLESTRING],
+ ["organizationName", "example", OpenSSL::ASN1::PRINTABLESTRING],
+ ["commonName", "www.example.jp", OpenSSL::ASN1::PRINTABLESTRING]
+ ]
+ name = OpenSSL::X509::Name.new(dn)
+ ary = name.to_a
+ assert_equal("/C=JP/O=example/CN=www.example.jp", name.to_s)
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[2][2])
+
+ dn = [
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["CN", "GOTOU Yuuzou"],
+ ["emailAddress", "gotoyuzo@ruby-lang.org"],
+ ["serialNumber", "123"],
+ ]
+ name = OpenSSL::X509::Name.new(dn)
+ ary = name.to_a
+ assert_equal("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou/emailAddress=gotoyuzo@ruby-lang.org/serialNumber=123", name.to_s)
+ assert_equal("DC", ary[0][0])
+ assert_equal("DC", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("emailAddress", ary[3][0])
+ assert_equal("serialNumber", ary[4][0])
+ assert_equal("org", ary[0][1])
+ assert_equal("ruby-lang", ary[1][1])
+ assert_equal("GOTOU Yuuzou", ary[2][1])
+ assert_equal("gotoyuzo@ruby-lang.org", ary[3][1])
+ assert_equal("123", ary[4][1])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[3][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[4][2])
+
+ name_from_der = OpenSSL::X509::Name.new(name.to_der)
+ assert_equal(name_from_der.to_s, name.to_s)
+ assert_equal(name_from_der.to_a, name.to_a)
+ assert_equal(name_from_der.to_der, name.to_der)
+ end
+
+ def test_s_parse
+ dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org"
+ name = OpenSSL::X509::Name.parse(dn)
+ assert_equal(dn, name.to_s)
+ ary = name.to_a
+ assert_equal("DC", ary[0][0])
+ assert_equal("DC", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("org", ary[0][1])
+ assert_equal("ruby-lang", ary[1][1])
+ assert_equal("www.ruby-lang.org", ary[2][1])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+
+ dn2 = "DC=org, DC=ruby-lang, CN=www.ruby-lang.org"
+ name = OpenSSL::X509::Name.parse(dn)
+ ary = name.to_a
+ assert_equal(dn, name.to_s)
+ assert_equal("org", ary[0][1])
+ assert_equal("ruby-lang", ary[1][1])
+ assert_equal("www.ruby-lang.org", ary[2][1])
+
+ name = OpenSSL::X509::Name.parse(dn, @obj_type_tmpl)
+ ary = name.to_a
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[2][2])
+ end
+
+ def test_s_parse_rfc2253
+ scanner = OpenSSL::X509::Name::RFC2253DN.method(:scan)
+
+ assert_equal([["C", "JP"]], scanner.call("C=JP"))
+ assert_equal([
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["CN", "GOTOU Yuuzou"],
+ ["emailAddress", "gotoyuzo@ruby-lang.org"],
+ ],
+ scanner.call(
+ "emailAddress=gotoyuzo@ruby-lang.org,CN=GOTOU Yuuzou,"+
+ "DC=ruby-lang,DC=org")
+ )
+
+ u8 = OpenSSL::ASN1::UTF8STRING
+ assert_equal([
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["O", ",=+<>#;"],
+ ["O", ",=+<>#;"],
+ ["OU", ""],
+ ["OU", ""],
+ ["L", "aaa=\"bbb, ccc\""],
+ ["L", "aaa=\"bbb, ccc\""],
+ ["CN", "\345\276\214\350\227\244\350\243\225\350\224\265"],
+ ["CN", "\345\276\214\350\227\244\350\243\225\350\224\265"],
+ ["CN", "\345\276\214\350\227\244\350\243\225\350\224\265"],
+ ["CN", "\345\276\214\350\227\244\350\243\225\350\224\265", u8],
+ ["2.5.4.3", "GOTOU, Yuuzou"],
+ ["2.5.4.3", "GOTOU, Yuuzou"],
+ ["2.5.4.3", "GOTOU, Yuuzou"],
+ ["2.5.4.3", "GOTOU, Yuuzou"],
+ ["CN", "GOTOU \"gotoyuzo\" Yuuzou"],
+ ["CN", "GOTOU \"gotoyuzo\" Yuuzou"],
+ ["1.2.840.113549.1.9.1", "gotoyuzo@ruby-lang.org"],
+ ["emailAddress", "gotoyuzo@ruby-lang.org"],
+ ],
+ scanner.call(
+ "emailAddress=gotoyuzo@ruby-lang.org," +
+ "1.2.840.113549.1.9.1=gotoyuzo@ruby-lang.org," +
+ 'CN=GOTOU \"gotoyuzo\" Yuuzou,' +
+ 'CN="GOTOU \"gotoyuzo\" Yuuzou",' +
+ '2.5.4.3=GOTOU\,\20Yuuzou,' +
+ '2.5.4.3=GOTOU\, Yuuzou,' +
+ '2.5.4.3="GOTOU, Yuuzou",' +
+ '2.5.4.3="GOTOU\, Yuuzou",' +
+ "CN=#0C0CE5BE8CE897A4E8A395E894B5," +
+ 'CN=\E5\BE\8C\E8\97\A4\E8\A3\95\E8\94\B5,' +
+ "CN=\"\xE5\xBE\x8C\xE8\x97\xA4\xE8\xA3\x95\xE8\x94\xB5\"," +
+ "CN=\xE5\xBE\x8C\xE8\x97\xA4\xE8\xA3\x95\xE8\x94\xB5," +
+ 'L=aaa\=\"bbb\, ccc\",' +
+ 'L="aaa=\"bbb, ccc\"",' +
+ 'OU=,' +
+ 'OU="",' +
+ 'O=\,\=\+\<\>\#\;,' +
+ 'O=",=+<>#;",' +
+ "DC=ruby-lang," +
+ "DC=org")
+ )
+
+ [
+ "DC=org+DC=jp",
+ "DC=org,DC=ruby-lang+DC=rubyist,DC=www"
+ ].each{|dn|
+ ex = scanner.call(dn) rescue $!
+ dn_r = Regexp.escape(dn)
+ assert_match(/^multi-valued RDN is not supported: #{dn_r}/, ex.message)
+ }
+
+ [
+ ["DC=org,DC=exapmle,CN", "CN"],
+ ["DC=org,DC=example,", ""],
+ ["DC=org,DC=exapmle,CN=www.example.org;", "CN=www.example.org;"],
+ ["DC=org,DC=exapmle,CN=#www.example.org", "CN=#www.example.org"],
+ ["DC=org,DC=exapmle,CN=#777777.example.org", "CN=#777777.example.org"],
+ ["DC=org,DC=exapmle,CN=\"www.example\".org", "CN=\"www.example\".org"],
+ ["DC=org,DC=exapmle,CN=www.\"example.org\"", "CN=www.\"example.org\""],
+ ["DC=org,DC=exapmle,CN=www.\"example\".org", "CN=www.\"example\".org"],
+ ].each{|dn, msg|
+ ex = scanner.call(dn) rescue $!
+ assert_match(/^malformed RDN: .*=>#{Regexp.escape(msg)}/, ex.message)
+ }
+
+ dn = "CN=www.ruby-lang.org,DC=ruby-lang,DC=org"
+ name = OpenSSL::X509::Name.parse_rfc2253(dn)
+ assert_equal(dn, name.to_s(OpenSSL::X509::Name::RFC2253))
+ ary = name.to_a
+ assert_equal("DC", ary[0][0])
+ assert_equal("DC", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("org", ary[0][1])
+ assert_equal("ruby-lang", ary[1][1])
+ assert_equal("www.ruby-lang.org", ary[2][1])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+ end
+
+ def test_add_entry
+ dn = [
+ ["DC", "org"],
+ ["DC", "ruby-lang"],
+ ["CN", "GOTOU Yuuzou"],
+ ["emailAddress", "gotoyuzo@ruby-lang.org"],
+ ["serialNumber", "123"],
+ ]
+ name = OpenSSL::X509::Name.new
+ dn.each{|attr| name.add_entry(*attr) }
+ ary = name.to_a
+ assert_equal("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou/emailAddress=gotoyuzo@ruby-lang.org/serialNumber=123", name.to_s)
+ assert_equal("DC", ary[0][0])
+ assert_equal("DC", ary[1][0])
+ assert_equal("CN", ary[2][0])
+ assert_equal("emailAddress", ary[3][0])
+ assert_equal("serialNumber", ary[4][0])
+ assert_equal("org", ary[0][1])
+ assert_equal("ruby-lang", ary[1][1])
+ assert_equal("GOTOU Yuuzou", ary[2][1])
+ assert_equal("gotoyuzo@ruby-lang.org", ary[3][1])
+ assert_equal("123", ary[4][1])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[0][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[1][2])
+ assert_equal(OpenSSL::ASN1::UTF8STRING, ary[2][2])
+ assert_equal(OpenSSL::ASN1::IA5STRING, ary[3][2])
+ assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[4][2])
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509req.rb b/trunk/test/openssl/test_x509req.rb
new file mode 100644
index 0000000000..a37ed5c5ef
--- /dev/null
+++ b/trunk/test/openssl/test_x509req.rb
@@ -0,0 +1,140 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509Request < Test::Unit::TestCase
+ def setup
+ @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
+ @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
+ @dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou")
+ end
+
+ def issue_csr(ver, dn, key, digest)
+ req = OpenSSL::X509::Request.new
+ req.version = ver
+ req.subject = dn
+ req.public_key = key.public_key
+ req.sign(key, digest)
+ req
+ end
+
+ def test_public_key
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
+ req = OpenSSL::X509::Request.new(req.to_der)
+ assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
+
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::DSS1.new)
+ assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
+ req = OpenSSL::X509::Request.new(req.to_der)
+ assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
+ end
+
+ def test_version
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ assert_equal(0, req.version)
+ req = OpenSSL::X509::Request.new(req.to_der)
+ assert_equal(0, req.version)
+
+ req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ assert_equal(1, req.version)
+ req = OpenSSL::X509::Request.new(req.to_der)
+ assert_equal(1, req.version)
+ end
+
+ def test_subject
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ assert_equal(@dn.to_der, req.subject.to_der)
+ req = OpenSSL::X509::Request.new(req.to_der)
+ assert_equal(@dn.to_der, req.subject.to_der)
+ end
+
+ def create_ext_req(exts)
+ ef = OpenSSL::X509::ExtensionFactory.new
+ exts = exts.collect{|e| ef.create_extension(*e) }
+ return OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(exts)])
+ end
+
+ def get_ext_req(ext_req_value)
+ set = OpenSSL::ASN1.decode(ext_req_value)
+ seq = set.value[0]
+ seq.value.collect{|asn1ext|
+ OpenSSL::X509::Extension.new(asn1ext).to_a
+ }
+ end
+
+ def test_attr
+ exts = [
+ ["keyUsage", "Digital Signature, Key Encipherment", true],
+ ["subjectAltName", "email:gotoyuzo@ruby-lang.org", false],
+ ]
+ attrval = create_ext_req(exts)
+ attrs = [
+ OpenSSL::X509::Attribute.new("extReq", attrval),
+ OpenSSL::X509::Attribute.new("msExtReq", attrval),
+ ]
+
+ req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ attrs.each{|attr| req0.add_attribute(attr) }
+ req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req1.attributes = attrs
+ assert_equal(req0.to_der, req1.to_der)
+
+ attrs = req0.attributes
+ assert_equal(2, attrs.size)
+ assert_equal("extReq", attrs[0].oid)
+ assert_equal("msExtReq", attrs[1].oid)
+ assert_equal(exts, get_ext_req(attrs[0].value))
+ assert_equal(exts, get_ext_req(attrs[1].value))
+
+ req = OpenSSL::X509::Request.new(req0.to_der)
+ attrs = req.attributes
+ assert_equal(2, attrs.size)
+ assert_equal("extReq", attrs[0].oid)
+ assert_equal("msExtReq", attrs[1].oid)
+ assert_equal(exts, get_ext_req(attrs[0].value))
+ assert_equal(exts, get_ext_req(attrs[1].value))
+ end
+
+ def test_sign_and_verify
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ assert_equal(true, req.verify(@rsa1024))
+ assert_equal(false, req.verify(@rsa2048))
+ assert_equal(false, req.verify(@dsa256))
+ assert_equal(false, req.verify(@dsa512))
+ req.version = 1
+ assert_equal(false, req.verify(@rsa1024))
+
+ req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest::MD5.new)
+ assert_equal(false, req.verify(@rsa1024))
+ assert_equal(true, req.verify(@rsa2048))
+ assert_equal(false, req.verify(@dsa256))
+ assert_equal(false, req.verify(@dsa512))
+ req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBar")
+ assert_equal(false, req.verify(@rsa2048))
+
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::DSS1.new)
+ assert_equal(false, req.verify(@rsa1024))
+ assert_equal(false, req.verify(@rsa2048))
+ assert_equal(false, req.verify(@dsa256))
+ assert_equal(true, req.verify(@dsa512))
+ req.public_key = @rsa1024.public_key
+ assert_equal(false, req.verify(@dsa512))
+
+ assert_raise(OpenSSL::X509::RequestError){
+ issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::DSS1.new) }
+ assert_raise(OpenSSL::X509::RequestError){
+ issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new) }
+ assert_raise(OpenSSL::X509::RequestError){
+ issue_csr(0, @dn, @dsa512, OpenSSL::Digest::MD5.new) }
+ end
+end
+
+end
diff --git a/trunk/test/openssl/test_x509store.rb b/trunk/test/openssl/test_x509store.rb
new file mode 100644
index 0000000000..b0fe597262
--- /dev/null
+++ b/trunk/test/openssl/test_x509store.rb
@@ -0,0 +1,218 @@
+begin
+ require "openssl"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(OpenSSL)
+
+class OpenSSL::TestX509Store < Test::Unit::TestCase
+ def setup
+ @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+ @dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
+ @dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
+ @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1")
+ @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2")
+ @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
+ @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
+ end
+
+ def teardown
+ end
+
+ def issue_cert(*args)
+ OpenSSL::TestUtils.issue_cert(*args)
+ end
+
+ def issue_crl(*args)
+ OpenSSL::TestUtils.issue_crl(*args)
+ end
+
+ def test_verify
+ now = Time.at(Time.now.to_i)
+ ca_exts = [
+ ["basicConstraints","CA:TRUE",true],
+ ["keyUsage","cRLSign,keyCertSign",true],
+ ]
+ ee_exts = [
+ ["keyUsage","keyEncipherment,digitalSignature",true],
+ ]
+ ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, ca_exts,
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ ca2_cert = issue_cert(@ca2, @rsa1024, 2, now, now+1800, ca_exts,
+ ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ ee1_cert = issue_cert(@ee1, @dsa256, 10, now, now+1800, ee_exts,
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ ee2_cert = issue_cert(@ee2, @dsa512, 20, now, now+1800, ee_exts,
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ ee3_cert = issue_cert(@ee2, @dsa512, 30, now-100, now-1, ee_exts,
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ ee4_cert = issue_cert(@ee2, @dsa512, 40, now+1000, now+2000, ee_exts,
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+
+ revoke_info = []
+ crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
+ ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ revoke_info = [ [2, now, 1], ]
+ crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [],
+ ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ revoke_info = [ [20, now, 1], ]
+ crl2 = issue_crl(revoke_info, 1, now, now+1800, [],
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ revoke_info = []
+ crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [],
+ ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+
+ assert(true, ca1_cert.verify(ca1_cert.public_key)) # self signed
+ assert(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1
+ assert(true, ee1_cert.verify(ca2_cert.public_key)) # issued by ca2
+ assert(true, ee2_cert.verify(ca2_cert.public_key)) # issued by ca2
+ assert(true, ee3_cert.verify(ca2_cert.public_key)) # issued by ca2
+ assert(true, crl1.verify(ca1_cert.public_key)) # issued by ca1
+ assert(true, crl1_2.verify(ca1_cert.public_key)) # issued by ca1
+ assert(true, crl2.verify(ca2_cert.public_key)) # issued by ca2
+ assert(true, crl2_2.verify(ca2_cert.public_key)) # issued by ca2
+
+ store = OpenSSL::X509::Store.new
+ assert_equal(false, store.verify(ca1_cert))
+ assert_not_equal(OpenSSL::X509::V_OK, store.error)
+
+ assert_equal(false, store.verify(ca2_cert))
+ assert_not_equal(OpenSSL::X509::V_OK, store.error)
+
+ store.add_cert(ca1_cert)
+ assert_equal(true, store.verify(ca2_cert))
+ assert_equal(OpenSSL::X509::V_OK, store.error)
+ assert_equal("ok", store.error_string)
+ chain = store.chain
+ assert_equal(2, chain.size)
+ assert_equal(@ca2.to_der, chain[0].subject.to_der)
+ assert_equal(@ca1.to_der, chain[1].subject.to_der)
+
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ assert_equal(false, store.verify(ca2_cert))
+ assert_not_equal(OpenSSL::X509::V_OK, store.error)
+
+ store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN
+ assert_equal(true, store.verify(ca2_cert))
+ assert_equal(OpenSSL::X509::V_OK, store.error)
+
+ store.add_cert(ca2_cert)
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ assert_equal(true, store.verify(ee1_cert))
+ assert_equal(true, store.verify(ee2_cert))
+ assert_equal(OpenSSL::X509::V_OK, store.error)
+ assert_equal("ok", store.error_string)
+ chain = store.chain
+ assert_equal(3, chain.size)
+ assert_equal(@ee2.to_der, chain[0].subject.to_der)
+ assert_equal(@ca2.to_der, chain[1].subject.to_der)
+ assert_equal(@ca1.to_der, chain[2].subject.to_der)
+ assert_equal(false, store.verify(ee3_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
+ assert_match(/expire/i, store.error_string)
+ assert_equal(false, store.verify(ee4_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
+ assert_match(/not yet valid/i, store.error_string)
+
+ store = OpenSSL::X509::Store.new
+ store.add_cert(ca1_cert)
+ store.add_cert(ca2_cert)
+ store.time = now + 1500
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(true, store.verify(ca2_cert))
+ assert_equal(true, store.verify(ee4_cert))
+ store.time = now + 1900
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(false, store.verify(ca2_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
+ assert_equal(false, store.verify(ee4_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
+ store.time = now + 4000
+ assert_equal(false, store.verify(ee1_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
+ assert_equal(false, store.verify(ee4_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
+
+ # the underlying X509 struct caches the result of the last
+ # verification for signature and not-before. so the following code
+ # rebuilds new objects to avoid site effect.
+ store.time = Time.now - 4000
+ assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ca2_cert)))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
+ assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert)))
+ assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
+
+ return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK)
+
+ store = OpenSSL::X509::Store.new
+ store.purpose = OpenSSL::X509::PURPOSE_ANY
+ store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK
+ store.add_cert(ca1_cert)
+ store.add_crl(crl1) # revoke no cert
+ store.add_crl(crl2) # revoke ee2_cert
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(true, store.verify(ca2_cert))
+ assert_equal(true, store.verify(ee1_cert, [ca2_cert]))
+ assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
+
+ store = OpenSSL::X509::Store.new
+ store.purpose = OpenSSL::X509::PURPOSE_ANY
+ store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK
+ store.add_cert(ca1_cert)
+ store.add_crl(crl1_2) # revoke ca2_cert
+ store.add_crl(crl2) # revoke ee2_cert
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(false, store.verify(ca2_cert))
+ assert_equal(true, store.verify(ee1_cert, [ca2_cert]),
+ "This test is expected to be success with OpenSSL 0.9.7c or later.")
+ assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
+
+ store.flags =
+ OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(false, store.verify(ca2_cert))
+ assert_equal(false, store.verify(ee1_cert, [ca2_cert]))
+ assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
+
+ store = OpenSSL::X509::Store.new
+ store.purpose = OpenSSL::X509::PURPOSE_ANY
+ store.flags =
+ OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+ store.add_cert(ca1_cert)
+ store.add_cert(ca2_cert)
+ store.add_crl(crl1)
+ store.add_crl(crl2_2) # issued by ca2 but expired.
+ assert_equal(true, store.verify(ca1_cert))
+ assert_equal(true, store.verify(ca2_cert))
+ assert_equal(false, store.verify(ee1_cert))
+ assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error)
+ assert_equal(false, store.verify(ee2_cert))
+ end
+
+ def test_set_errors
+ now = Time.now
+ ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ store = OpenSSL::X509::Store.new
+ store.add_cert(ca1_cert)
+ assert_raises(OpenSSL::X509::StoreError){
+ store.add_cert(ca1_cert) # add same certificate twice
+ }
+
+ revoke_info = []
+ crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
+ ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ revoke_info = [ [2, now, 1], ]
+ crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [],
+ ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ store.add_crl(crl1)
+ assert_raises(OpenSSL::X509::StoreError){
+ store.add_crl(crl2) # add CRL issued by same CA twice.
+ }
+ end
+end
+
+end
diff --git a/trunk/test/openssl/utils.rb b/trunk/test/openssl/utils.rb
new file mode 100644
index 0000000000..07a1835f9d
--- /dev/null
+++ b/trunk/test/openssl/utils.rb
@@ -0,0 +1,135 @@
+require "openssl"
+require "test/unit"
+
+module OpenSSL::TestUtils
+ TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx
+aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/
+Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB
+AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0
+maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T
+gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572
+74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE
+JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX
+sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII
+8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA
+wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi
+qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD
+dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA==
+-----END RSA PRIVATE KEY-----
+ _end_of_pem_
+
+ TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
+s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
+4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
+kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
+NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
+DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
+I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
+PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
+seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
+Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
+VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
+wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
+0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
+XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
+aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
+h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
+Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
+IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
+v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
+U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
+vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
+Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
+9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
+gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
+4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
+-----END RSA PRIVATE KEY-----
+ _end_of_pem_
+
+ TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
+-----BEGIN DSA PRIVATE KEY-----
+MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE
+9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed
+AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM
+3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT
+b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn
+ISNX5cMzFHRW3Q==
+-----END DSA PRIVATE KEY-----
+ _end_of_pem_
+
+ TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
+-----BEGIN DSA PRIVATE KEY-----
+MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok
+RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D
+AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR
+S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++
+Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S
+55jreJD3Se3slps=
+-----END DSA PRIVATE KEY-----
+ _end_of_pem_
+
+ module_function
+
+ def issue_cert(dn, key, serial, not_before, not_after, extensions,
+ issuer, issuer_key, digest)
+ cert = OpenSSL::X509::Certificate.new
+ issuer = cert unless issuer
+ issuer_key = key unless issuer_key
+ cert.version = 2
+ cert.serial = serial
+ cert.subject = dn
+ cert.issuer = issuer.subject
+ cert.public_key = key.public_key
+ cert.not_before = not_before
+ cert.not_after = not_after
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.subject_certificate = cert
+ ef.issuer_certificate = issuer
+ extensions.each{|oid, value, critical|
+ cert.add_extension(ef.create_extension(oid, value, critical))
+ }
+ cert.sign(issuer_key, digest)
+ cert
+ end
+
+ def issue_crl(revoke_info, serial, lastup, nextup, extensions,
+ issuer, issuer_key, digest)
+ crl = OpenSSL::X509::CRL.new
+ crl.issuer = issuer.subject
+ crl.version = 1
+ crl.last_update = lastup
+ crl.next_update = nextup
+ revoke_info.each{|rserial, time, reason_code|
+ revoked = OpenSSL::X509::Revoked.new
+ revoked.serial = rserial
+ revoked.time = time
+ enum = OpenSSL::ASN1::Enumerated(reason_code)
+ ext = OpenSSL::X509::Extension.new("CRLReason", enum)
+ revoked.add_extension(ext)
+ crl.add_revoked(revoked)
+ }
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.issuer_certificate = issuer
+ ef.crl = crl
+ crlnum = OpenSSL::ASN1::Integer(serial)
+ crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", crlnum))
+ extensions.each{|oid, value, critical|
+ crl.add_extension(ef.create_extension(oid, value, critical))
+ }
+ crl.sign(issuer_key, digest)
+ crl
+ end
+
+ def get_subject_key_id(cert)
+ asn1_cert = OpenSSL::ASN1.decode(cert)
+ tbscert = asn1_cert.value[0]
+ pkinfo = tbscert.value[6]
+ publickey = pkinfo.value[1]
+ pkvalue = publickey.value
+ OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase
+ end
+end
diff --git a/trunk/test/optparse/test_getopts.rb b/trunk/test/optparse/test_getopts.rb
new file mode 100644
index 0000000000..fdefe5f3e5
--- /dev/null
+++ b/trunk/test/optparse/test_getopts.rb
@@ -0,0 +1,31 @@
+require 'test/unit'
+
+class TestOptionParserGetopts < Test::Unit::TestCase
+ def setup
+ @opt = OptionParser.new
+ end
+
+ def test_short_noarg
+ o = @opt.getopts(%w[-a], "ab")
+ assert_equal(true, o['a'])
+ assert_equal(false, o['b'])
+ end
+
+ def test_short_arg
+ o = @opt.getopts(%w[-a1], "a:b:")
+ assert_equal("1", o['a'])
+ assert_equal(nil, o['b'])
+ end
+
+ def test_long_noarg
+ o = @opt.getopts(%w[--foo], "", "foo", "bar")
+ assert_equal(true, o['foo'])
+ assert_equal(false, o['bar'])
+ end
+
+ def test_long_arg
+ o = @opt.getopts(%w[--bar ZOT], "", "foo:FOO", "bar:BAR")
+ assert_equal("FOO", o['foo'])
+ assert_equal("ZOT", o['bar'])
+ end
+end
diff --git a/trunk/test/optparse/test_noarg.rb b/trunk/test/optparse/test_noarg.rb
new file mode 100644
index 0000000000..28c469093d
--- /dev/null
+++ b/trunk/test/optparse/test_noarg.rb
@@ -0,0 +1,57 @@
+require 'test_optparse'
+
+module TestOptionParser::NoArg
+ class Def1 < TestOptionParser
+ include NoArg
+ def setup
+ super
+ @opt.def_option("-x") {|x| @flag = x}
+ @opt.def_option("--option") {|x| @flag = x}
+ end
+ end
+ class Def2 < TestOptionParser
+ include NoArg
+ def setup
+ super
+ @opt.def_option("-x", "--option") {|x| @flag = x}
+ end
+ end
+
+ def test_short
+ assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-xq")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x")})
+ assert_equal(true, @flag)
+ @flag = nil
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"-x foo")})
+ assert_equal(true, @flag)
+ end
+
+ def test_abbrev
+ assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-oq")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o")})
+ assert_equal(true, @flag)
+ @flag = nil
+ assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-O")}
+ assert_nil(@flag)
+ @flag = nil
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"-o foo")})
+ assert_equal(true, @flag)
+ end
+
+ def test_long
+ assert_raises(OptionParser::NeedlessArgument) {@opt.parse!(%w"--option=x")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt")})
+ assert_equal(true, @flag)
+ @flag = nil
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt foo")})
+ assert_equal(true, @flag)
+ end
+
+ def test_ambiguous
+ @opt.def_option("--open") {|x|}
+ assert_raises(OptionParser::AmbiguousOption) {@opt.parse!(%w"--op")}
+ assert_raises(OptionParser::AmbiguousOption) {@opt.parse!(%w"-o")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt")})
+ assert_equal(true, @flag)
+ end
+end
diff --git a/trunk/test/optparse/test_optarg.rb b/trunk/test/optparse/test_optarg.rb
new file mode 100644
index 0000000000..49cb1b93ec
--- /dev/null
+++ b/trunk/test/optparse/test_optarg.rb
@@ -0,0 +1,44 @@
+require 'test_optparse'
+
+class TestOptionParser::OptArg < TestOptionParser
+ def setup
+ super
+ @opt.def_option("-x[VAL]") {|x| @flag = x}
+ @opt.def_option("--option[=VAL]") {|x| @flag = x}
+ end
+
+ def test_short
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x")})
+ assert_equal(nil, @flag)
+ @flag = false
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"-x foo")})
+ assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-xfoo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_abbrev
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o")})
+ assert_equal(nil, @flag)
+ @flag = false
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"-o foo")})
+ assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-ofoo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_long
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt")})
+ assert_equal(nil, @flag)
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")})
+ assert_equal("", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt foo")})
+ assert_equal(nil, @flag)
+ end
+end
diff --git a/trunk/test/optparse/test_optparse.rb b/trunk/test/optparse/test_optparse.rb
new file mode 100644
index 0000000000..9c73399f5b
--- /dev/null
+++ b/trunk/test/optparse/test_optparse.rb
@@ -0,0 +1,46 @@
+require 'test/unit'
+require 'optparse'
+
+class TestOptionParser < Test::Unit::TestCase
+ def setup
+ @opt = OptionParser.new
+ @flag = self.class # cannot set by option
+ end
+ def no_error(*args)
+ assert_nothing_raised(*args) {return yield}
+ end
+
+ def test_permute
+ assert_equal(%w"", no_error {@opt.permute!(%w"")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo bar", no_error {@opt.permute!(%w"foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"- foo bar", no_error {@opt.permute!(%w"- foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo bar", no_error {@opt.permute!(%w"-- foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo - bar", no_error {@opt.permute!(%w"foo - bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo bar", no_error {@opt.permute!(%w"foo -- bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo --help bar", no_error {@opt.permute!(%w"foo -- --help bar")})
+ assert_equal(self.class, @flag)
+ end
+
+ def test_order
+ assert_equal(%w"", no_error {@opt.order!(%w"")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo bar", no_error {@opt.order!(%w"foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"- foo bar", no_error {@opt.order!(%w"- foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo bar", no_error {@opt.permute!(%w"-- foo bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo - bar", no_error {@opt.order!(%w"foo - bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo -- bar", no_error {@opt.order!(%w"foo -- bar")})
+ assert_equal(self.class, @flag)
+ assert_equal(%w"foo -- --help bar", no_error {@opt.order!(%w"foo -- --help bar")})
+ assert_equal(self.class, @flag)
+ end
+end
diff --git a/trunk/test/optparse/test_placearg.rb b/trunk/test/optparse/test_placearg.rb
new file mode 100644
index 0000000000..f4fd249b7f
--- /dev/null
+++ b/trunk/test/optparse/test_placearg.rb
@@ -0,0 +1,45 @@
+require 'test_optparse'
+
+class TestOptionParser::PlaceArg < TestOptionParser
+ def setup
+ super
+ @opt.def_option("-x [VAL]") {|x| @flag = x}
+ @opt.def_option("--option [VAL]") {|x| @flag = x}
+ @opt.def_option("-n") {}
+ end
+
+ def test_short
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x -n")})
+ assert_equal(nil, @flag)
+ @flag = false
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-xbar")})
+ assert_equal("bar", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_abbrev
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o -n")})
+ assert_equal(nil, @flag)
+ @flag = false
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-obar")})
+ assert_equal("bar", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_long
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt -n")})
+ assert_equal(nil, @flag)
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")})
+ assert_equal("", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt bar")})
+ assert_equal("bar", @flag)
+ end
+end
diff --git a/trunk/test/optparse/test_reqarg.rb b/trunk/test/optparse/test_reqarg.rb
new file mode 100644
index 0000000000..0999e5e603
--- /dev/null
+++ b/trunk/test/optparse/test_reqarg.rb
@@ -0,0 +1,63 @@
+require 'test_optparse'
+
+module TestOptionParser::ReqArg
+ class Def1 < TestOptionParser
+ include ReqArg
+ def setup
+ super
+ @opt.def_option("-xVAL") {|x| @flag = x}
+ @opt.def_option("--option=VAL") {|x| @flag = x}
+ end
+ end
+ class Def2 < TestOptionParser
+ include ReqArg
+ def setup
+ super
+ @opt.def_option("-x", "--option=VAL") {|x| @flag = x}
+ end
+ end
+ class Def3 < TestOptionParser
+ include ReqArg
+ def setup
+ super
+ @opt.def_option("--option=VAL", "-x") {|x| @flag = x}
+ end
+ end
+ class Def4 < TestOptionParser
+ include ReqArg
+ def setup
+ super
+ @opt.def_option("-xVAL", "--option=VAL") {|x| @flag = x}
+ end
+ end
+
+ def test_short
+ assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"-x")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-xbar")})
+ assert_equal("bar", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_abbrev
+ assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"-o")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-obar")})
+ assert_equal("bar", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o=")})
+ assert_equal("=", @flag)
+ end
+
+ def test_long
+ assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"--opt")}
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt foo")})
+ assert_equal("foo", @flag)
+ assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")})
+ assert_equal("", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")})
+ assert_equal("foo", @flag)
+ end
+end
diff --git a/trunk/test/ostruct/test_ostruct.rb b/trunk/test/ostruct/test_ostruct.rb
new file mode 100644
index 0000000000..24ed17f800
--- /dev/null
+++ b/trunk/test/ostruct/test_ostruct.rb
@@ -0,0 +1,23 @@
+require 'test/unit'
+require 'ostruct'
+
+class TC_OpenStruct < Test::Unit::TestCase
+ def test_equality
+ o1 = OpenStruct.new
+ o2 = OpenStruct.new
+ assert_equal(o1, o2)
+
+ o1.a = 'a'
+ assert_not_equal(o1, o2)
+
+ o2.a = 'a'
+ assert_equal(o1, o2)
+
+ o1.a = 'b'
+ assert_not_equal(o1, o2)
+
+ o2 = Object.new
+ o2.instance_eval{@table = {:a => 'b'}}
+ assert_not_equal(o1, o2)
+ end
+end
diff --git a/trunk/test/pathname/test_pathname.rb b/trunk/test/pathname/test_pathname.rb
new file mode 100644
index 0000000000..11c1bb7b2b
--- /dev/null
+++ b/trunk/test/pathname/test_pathname.rb
@@ -0,0 +1,517 @@
+#!/usr/bin/env ruby
+
+require 'test/unit'
+require 'pathname'
+
+require 'fileutils'
+require 'tmpdir'
+require 'enumerator'
+
+class TestPathname < Test::Unit::TestCase
+ def self.define_assertion(name, &block)
+ @defassert_num ||= {}
+ @defassert_num[name] ||= 0
+ @defassert_num[name] += 1
+ define_method("test_#{name}_#{@defassert_num[name]}", &block)
+ end
+
+ def self.defassert(name, result, *args)
+ define_assertion(name) {
+ assert_equal(result, self.send(name, *args), "#{name}(#{args.map {|a| a.inspect }.join(', ')})")
+ }
+ end
+
+ DOSISH = File::ALT_SEPARATOR != nil
+ DOSISH_DRIVE_LETTER = File.dirname("A:") == "A:."
+ DOSISH_UNC = File.dirname("//") == "//"
+
+ def cleanpath_aggressive(path)
+ Pathname.new(path).cleanpath.to_s
+ end
+
+ defassert(:cleanpath_aggressive, '/', '/')
+ defassert(:cleanpath_aggressive, '.', '')
+ defassert(:cleanpath_aggressive, '.', '.')
+ defassert(:cleanpath_aggressive, '..', '..')
+ defassert(:cleanpath_aggressive, 'a', 'a')
+ defassert(:cleanpath_aggressive, '/', '/.')
+ defassert(:cleanpath_aggressive, '/', '/..')
+ defassert(:cleanpath_aggressive, '/a', '/a')
+ defassert(:cleanpath_aggressive, '.', './')
+ defassert(:cleanpath_aggressive, '..', '../')
+ defassert(:cleanpath_aggressive, 'a', 'a/')
+ defassert(:cleanpath_aggressive, 'a/b', 'a//b')
+ defassert(:cleanpath_aggressive, 'a', 'a/.')
+ defassert(:cleanpath_aggressive, 'a', 'a/./')
+ defassert(:cleanpath_aggressive, '.', 'a/..')
+ defassert(:cleanpath_aggressive, '.', 'a/../')
+ defassert(:cleanpath_aggressive, '/a', '/a/.')
+ defassert(:cleanpath_aggressive, '..', './..')
+ defassert(:cleanpath_aggressive, '..', '../.')
+ defassert(:cleanpath_aggressive, '..', './../')
+ defassert(:cleanpath_aggressive, '..', '.././')
+ defassert(:cleanpath_aggressive, '/', '/./..')
+ defassert(:cleanpath_aggressive, '/', '/../.')
+ defassert(:cleanpath_aggressive, '/', '/./../')
+ defassert(:cleanpath_aggressive, '/', '/.././')
+ defassert(:cleanpath_aggressive, 'a/b/c', 'a/b/c')
+ defassert(:cleanpath_aggressive, 'b/c', './b/c')
+ defassert(:cleanpath_aggressive, 'a/c', 'a/./c')
+ defassert(:cleanpath_aggressive, 'a/b', 'a/b/.')
+ defassert(:cleanpath_aggressive, '.', 'a/../.')
+ defassert(:cleanpath_aggressive, '/a', '/../.././../a')
+ defassert(:cleanpath_aggressive, '../../d', 'a/b/../../../../c/../d')
+
+ if DOSISH_UNC
+ defassert(:cleanpath_aggressive, '//a/b/c', '//a/b/c/')
+ else
+ defassert(:cleanpath_aggressive, '/', '///')
+ defassert(:cleanpath_aggressive, '/a', '///a')
+ defassert(:cleanpath_aggressive, '/', '///..')
+ defassert(:cleanpath_aggressive, '/', '///.')
+ defassert(:cleanpath_aggressive, '/', '///a/../..')
+ end
+
+ def cleanpath_conservative(path)
+ Pathname.new(path).cleanpath(true).to_s
+ end
+
+ defassert(:cleanpath_conservative, '/', '/')
+ defassert(:cleanpath_conservative, '.', '')
+ defassert(:cleanpath_conservative, '.', '.')
+ defassert(:cleanpath_conservative, '..', '..')
+ defassert(:cleanpath_conservative, 'a', 'a')
+ defassert(:cleanpath_conservative, '/', '/.')
+ defassert(:cleanpath_conservative, '/', '/..')
+ defassert(:cleanpath_conservative, '/a', '/a')
+ defassert(:cleanpath_conservative, '.', './')
+ defassert(:cleanpath_conservative, '..', '../')
+ defassert(:cleanpath_conservative, 'a/', 'a/')
+ defassert(:cleanpath_conservative, 'a/b', 'a//b')
+ defassert(:cleanpath_conservative, 'a/.', 'a/.')
+ defassert(:cleanpath_conservative, 'a/.', 'a/./')
+ defassert(:cleanpath_conservative, 'a/..', 'a/../')
+ defassert(:cleanpath_conservative, '/a/.', '/a/.')
+ defassert(:cleanpath_conservative, '..', './..')
+ defassert(:cleanpath_conservative, '..', '../.')
+ defassert(:cleanpath_conservative, '..', './../')
+ defassert(:cleanpath_conservative, '..', '.././')
+ defassert(:cleanpath_conservative, '/', '/./..')
+ defassert(:cleanpath_conservative, '/', '/../.')
+ defassert(:cleanpath_conservative, '/', '/./../')
+ defassert(:cleanpath_conservative, '/', '/.././')
+ defassert(:cleanpath_conservative, 'a/b/c', 'a/b/c')
+ defassert(:cleanpath_conservative, 'b/c', './b/c')
+ defassert(:cleanpath_conservative, 'a/c', 'a/./c')
+ defassert(:cleanpath_conservative, 'a/b/.', 'a/b/.')
+ defassert(:cleanpath_conservative, 'a/..', 'a/../.')
+ defassert(:cleanpath_conservative, '/a', '/../.././../a')
+ defassert(:cleanpath_conservative, 'a/b/../../../../c/../d', 'a/b/../../../../c/../d')
+
+ if DOSISH_UNC
+ defassert(:cleanpath_conservative, '//', '//')
+ else
+ defassert(:cleanpath_conservative, '/', '//')
+ end
+
+ # has_trailing_separator?(path) -> bool
+ def has_trailing_separator?(path)
+ Pathname.allocate.__send__(:has_trailing_separator?, path)
+ end
+
+ defassert(:has_trailing_separator?, false, "/")
+ defassert(:has_trailing_separator?, false, "///")
+ defassert(:has_trailing_separator?, false, "a")
+ defassert(:has_trailing_separator?, true, "a/")
+
+ def add_trailing_separator(path)
+ Pathname.allocate.__send__(:add_trailing_separator, path)
+ end
+
+ def del_trailing_separator(path)
+ Pathname.allocate.__send__(:del_trailing_separator, path)
+ end
+
+ defassert(:del_trailing_separator, "/", "/")
+ defassert(:del_trailing_separator, "/a", "/a")
+ defassert(:del_trailing_separator, "/a", "/a/")
+ defassert(:del_trailing_separator, "/a", "/a//")
+ defassert(:del_trailing_separator, ".", ".")
+ defassert(:del_trailing_separator, ".", "./")
+ defassert(:del_trailing_separator, ".", ".//")
+
+ if DOSISH_DRIVE_LETTER
+ defassert(:del_trailing_separator, "A:", "A:")
+ defassert(:del_trailing_separator, "A:/", "A:/")
+ defassert(:del_trailing_separator, "A:/", "A://")
+ defassert(:del_trailing_separator, "A:.", "A:.")
+ defassert(:del_trailing_separator, "A:.", "A:./")
+ defassert(:del_trailing_separator, "A:.", "A:.//")
+ end
+
+ if DOSISH_UNC
+ defassert(:del_trailing_separator, "//", "//")
+ defassert(:del_trailing_separator, "//a", "//a")
+ defassert(:del_trailing_separator, "//a", "//a/")
+ defassert(:del_trailing_separator, "//a", "//a//")
+ defassert(:del_trailing_separator, "//a/b", "//a/b")
+ defassert(:del_trailing_separator, "//a/b", "//a/b/")
+ defassert(:del_trailing_separator, "//a/b", "//a/b//")
+ defassert(:del_trailing_separator, "//a/b/c", "//a/b/c")
+ defassert(:del_trailing_separator, "//a/b/c", "//a/b/c/")
+ defassert(:del_trailing_separator, "//a/b/c", "//a/b/c//")
+ else
+ defassert(:del_trailing_separator, "/", "///")
+ defassert(:del_trailing_separator, "///a", "///a/")
+ end
+
+ if DOSISH
+ defassert(:del_trailing_separator, "a", "a\\")
+ require 'Win32API'
+ if Win32API.new('kernel32', 'GetACP', nil, 'L').call == 932
+ defassert(:del_trailing_separator, "\225\\", "\225\\\\") # SJIS
+ end
+ end
+
+ def plus(path1, path2) # -> path
+ (Pathname.new(path1) + Pathname.new(path2)).to_s
+ end
+
+ defassert(:plus, '/', '/', '/')
+ defassert(:plus, 'a/b', 'a', 'b')
+ defassert(:plus, 'a', 'a', '.')
+ defassert(:plus, 'b', '.', 'b')
+ defassert(:plus, '.', '.', '.')
+ defassert(:plus, '/b', 'a', '/b')
+
+ defassert(:plus, '/', '/', '..')
+ defassert(:plus, '.', 'a', '..')
+ defassert(:plus, 'a', 'a/b', '..')
+ defassert(:plus, '../..', '..', '..')
+ defassert(:plus, '/c', '/', '../c')
+ defassert(:plus, 'c', 'a', '../c')
+ defassert(:plus, 'a/c', 'a/b', '../c')
+ defassert(:plus, '../../c', '..', '../c')
+
+ defassert(:plus, 'a//b/d//e', 'a//b/c', '../d//e')
+
+ def relative?(path)
+ Pathname.new(path).relative?
+ end
+
+ defassert(:relative?, false, '/')
+ defassert(:relative?, false, '/a')
+ defassert(:relative?, false, '/..')
+ defassert(:relative?, true, 'a')
+ defassert(:relative?, true, 'a/b')
+
+ if DOSISH_DRIVE_LETTER
+ defassert(:relative?, false, 'A:')
+ defassert(:relative?, false, 'A:/')
+ defassert(:relative?, false, 'A:/a')
+ end
+
+ if File.dirname('//') == '//'
+ defassert(:relative?, false, '//')
+ defassert(:relative?, false, '//a')
+ defassert(:relative?, false, '//a/')
+ defassert(:relative?, false, '//a/b')
+ defassert(:relative?, false, '//a/b/')
+ defassert(:relative?, false, '//a/b/c')
+ end
+
+ def relative_path_from(dest_directory, base_directory)
+ Pathname.new(dest_directory).relative_path_from(Pathname.new(base_directory)).to_s
+ end
+
+ defassert(:relative_path_from, "../a", "a", "b")
+ defassert(:relative_path_from, "../a", "a", "b/")
+ defassert(:relative_path_from, "../a", "a/", "b")
+ defassert(:relative_path_from, "../a", "a/", "b/")
+ defassert(:relative_path_from, "../a", "/a", "/b")
+ defassert(:relative_path_from, "../a", "/a", "/b/")
+ defassert(:relative_path_from, "../a", "/a/", "/b")
+ defassert(:relative_path_from, "../a", "/a/", "/b/")
+
+ defassert(:relative_path_from, "../b", "a/b", "a/c")
+ defassert(:relative_path_from, "../a", "../a", "../b")
+
+ defassert(:relative_path_from, "a", "a", ".")
+ defassert(:relative_path_from, "..", ".", "a")
+
+ defassert(:relative_path_from, ".", ".", ".")
+ defassert(:relative_path_from, ".", "..", "..")
+ defassert(:relative_path_from, "..", "..", ".")
+
+ defassert(:relative_path_from, "c/d", "/a/b/c/d", "/a/b")
+ defassert(:relative_path_from, "../..", "/a/b", "/a/b/c/d")
+ defassert(:relative_path_from, "../../../../e", "/e", "/a/b/c/d")
+ defassert(:relative_path_from, "../b/c", "a/b/c", "a/d")
+
+ defassert(:relative_path_from, "../a", "/../a", "/b")
+ defassert(:relative_path_from, "../../a", "../a", "b")
+ defassert(:relative_path_from, ".", "/a/../../b", "/b")
+ defassert(:relative_path_from, "..", "a/..", "a")
+ defassert(:relative_path_from, ".", "a/../b", "b")
+
+ defassert(:relative_path_from, "a", "a", "b/..")
+ defassert(:relative_path_from, "b/c", "b/c", "b/..")
+
+ def self.defassert_raise(name, exc, *args)
+ define_assertion(name) {
+ message = "#{name}(#{args.map {|a| a.inspect }.join(', ')})"
+ assert_raise(exc, message) { self.send(name, *args) }
+ }
+ end
+
+ defassert_raise(:relative_path_from, ArgumentError, "/", ".")
+ defassert_raise(:relative_path_from, ArgumentError, ".", "/")
+ defassert_raise(:relative_path_from, ArgumentError, "a", "..")
+ defassert_raise(:relative_path_from, ArgumentError, ".", "..")
+
+ def realpath(path)
+ Pathname.new(path).realpath.to_s
+ end
+
+ def test_realpath
+ begin
+ File.symlink(nil, nil)
+ rescue NotImplementedError
+ return
+ rescue TypeError
+ end
+ Dir.mktmpdir('rubytest-pathname') {|dir|
+ File.symlink("not-exist-target", "#{dir}/not-exist")
+ assert_raise(Errno::ENOENT) { realpath("#{dir}/not-exist") }
+ File.symlink("loop", "#{dir}/loop")
+ assert_raise(Errno::ELOOP) { realpath("#{dir}/loop") }
+ }
+ end
+
+ def descend(path)
+ Pathname.new(path).enum_for(:descend).map {|v| v.to_s }
+ end
+
+ defassert(:descend, %w[/ /a /a/b /a/b/c], "/a/b/c")
+ defassert(:descend, %w[a a/b a/b/c], "a/b/c")
+ defassert(:descend, %w[. ./a ./a/b ./a/b/c], "./a/b/c")
+ defassert(:descend, %w[a/], "a/")
+
+ def ascend(path)
+ Pathname.new(path).enum_for(:ascend).map {|v| v.to_s }
+ end
+
+ defassert(:ascend, %w[/a/b/c /a/b /a /], "/a/b/c")
+ defassert(:ascend, %w[a/b/c a/b a], "a/b/c")
+ defassert(:ascend, %w[./a/b/c ./a/b ./a .], "./a/b/c")
+ defassert(:ascend, %w[a/], "a/")
+
+ def test_initialize
+ p1 = Pathname.new('a')
+ assert_equal('a', p1.to_s)
+ p2 = Pathname.new(p1)
+ assert_equal(p1, p2)
+ end
+
+ def test_initialize_nul
+ assert_raise(ArgumentError) { Pathname.new("a\0") }
+ end
+
+ class AnotherStringLike # :nodoc:
+ def initialize(s) @s = s end
+ def to_str() @s end
+ def ==(other) @s == other end
+ end
+
+ def test_equality
+ obj = Pathname.new("a")
+ str = "a"
+ sym = :a
+ ano = AnotherStringLike.new("a")
+ assert_equal(false, obj == str)
+ assert_equal(false, str == obj)
+ assert_equal(false, obj == ano)
+ assert_equal(false, ano == obj)
+ assert_equal(false, obj == sym)
+ assert_equal(false, sym == obj)
+
+ obj2 = Pathname.new("a")
+ assert_equal(true, obj == obj2)
+ assert_equal(true, obj === obj2)
+ assert_equal(true, obj.eql?(obj2))
+ end
+
+ def test_hashkey
+ h = {}
+ h[Pathname.new("a")] = 1
+ h[Pathname.new("a")] = 2
+ assert_equal(1, h.size)
+ end
+
+ def assert_pathname_cmp(e, s1, s2)
+ p1 = Pathname.new(s1)
+ p2 = Pathname.new(s2)
+ r = p1 <=> p2
+ assert(e == r,
+ "#{p1.inspect} <=> #{p2.inspect}: <#{e}> expected but was <#{r}>")
+ end
+ def test_comparison
+ assert_pathname_cmp( 0, "a", "a")
+ assert_pathname_cmp( 1, "b", "a")
+ assert_pathname_cmp(-1, "a", "b")
+ ss = %w(
+ a
+ a/
+ a/b
+ a.
+ a0
+ )
+ s1 = ss.shift
+ ss.each {|s2|
+ assert_pathname_cmp(-1, s1, s2)
+ s1 = s2
+ }
+ end
+
+ def test_comparison_string
+ assert_equal(nil, Pathname.new("a") <=> "a")
+ assert_equal(nil, "a" <=> Pathname.new("a"))
+ end
+
+ def pathsub(path, pat, repl) Pathname.new(path).sub(pat, repl).to_s end
+ defassert(:pathsub, "a.o", "a.c", /\.c\z/, ".o")
+
+ def pathsubext(path, repl) Pathname.new(path).sub_ext(repl).to_s end
+ defassert(:pathsubext, 'a.o', 'a.c', '.o')
+ defassert(:pathsubext, 'a.o', 'a.c++', '.o')
+ defassert(:pathsubext, 'a.png', 'a.gif', '.png')
+ defassert(:pathsubext, 'ruby.tar.bz2', 'ruby.tar.gz', '.bz2')
+ defassert(:pathsubext, 'd/a.o', 'd/a.c', '.o')
+ defassert(:pathsubext, 'foo', 'foo.exe', '')
+ defassert(:pathsubext, 'lex.yy.o', 'lex.yy.c', '.o')
+ defassert(:pathsubext, 'fooaa.o', 'fooaa', '.o')
+ defassert(:pathsubext, 'd.e/aa.o', 'd.e/aa', '.o')
+
+ def root?(path)
+ Pathname.new(path).root?
+ end
+
+ defassert(:root?, true, "/")
+ defassert(:root?, true, "//")
+ defassert(:root?, true, "///")
+ defassert(:root?, false, "")
+ defassert(:root?, false, "a")
+
+ def test_destructive_update
+ path = Pathname.new("a")
+ path.to_s.replace "b"
+ assert_equal(Pathname.new("a"), path)
+ end
+
+ def test_null_character
+ assert_raise(ArgumentError) { Pathname.new("\0") }
+ end
+
+ def test_taint
+ obj = Pathname.new("a"); assert_same(obj, obj.taint)
+ obj = Pathname.new("a"); assert_same(obj, obj.untaint)
+
+ assert_equal(false, Pathname.new("a" ) .tainted?)
+ assert_equal(false, Pathname.new("a" ) .to_s.tainted?)
+ assert_equal(true, Pathname.new("a" ).taint .tainted?)
+ assert_equal(true, Pathname.new("a" ).taint.to_s.tainted?)
+ assert_equal(true, Pathname.new("a".taint) .tainted?)
+ assert_equal(true, Pathname.new("a".taint) .to_s.tainted?)
+ assert_equal(true, Pathname.new("a".taint).taint .tainted?)
+ assert_equal(true, Pathname.new("a".taint).taint.to_s.tainted?)
+
+ str = "a"
+ path = Pathname.new(str)
+ str.taint
+ assert_equal(false, path .tainted?)
+ assert_equal(false, path.to_s.tainted?)
+ end
+
+ def test_untaint
+ obj = Pathname.new("a"); assert_same(obj, obj.untaint)
+
+ assert_equal(false, Pathname.new("a").taint.untaint .tainted?)
+ assert_equal(false, Pathname.new("a").taint.untaint.to_s.tainted?)
+
+ str = "a".taint
+ path = Pathname.new(str)
+ str.untaint
+ assert_equal(true, path .tainted?)
+ assert_equal(true, path.to_s.tainted?)
+ end
+
+ def test_freeze
+ obj = Pathname.new("a"); assert_same(obj, obj.freeze)
+
+ assert_equal(false, Pathname.new("a" ) .frozen?)
+ assert_equal(false, Pathname.new("a".freeze) .frozen?)
+ assert_equal(true, Pathname.new("a" ).freeze .frozen?)
+ assert_equal(true, Pathname.new("a".freeze).freeze .frozen?)
+ assert_equal(false, Pathname.new("a" ) .to_s.frozen?)
+ assert_equal(false, Pathname.new("a".freeze) .to_s.frozen?)
+ assert_equal(false, Pathname.new("a" ).freeze.to_s.frozen?)
+ assert_equal(false, Pathname.new("a".freeze).freeze.to_s.frozen?)
+ end
+
+ def test_to_s
+ str = "a"
+ obj = Pathname.new(str)
+ assert_equal(str, obj.to_s)
+ assert_not_same(str, obj.to_s)
+ assert_not_same(obj.to_s, obj.to_s)
+ end
+
+ def test_kernel_open
+ count = 0
+ result = Kernel.open(Pathname.new(__FILE__)) {|f|
+ assert(File.identical?(__FILE__, f))
+ count += 1
+ 2
+ }
+ assert_equal(1, count)
+ assert_equal(2, result)
+ end
+
+ def test_each_filename
+ result = []
+ Pathname.new("/usr/bin/ruby").each_filename {|f| result << f }
+ assert_equal(%w[usr bin ruby], result)
+ end
+
+ def test_kernel_pathname
+ assert_equal(Pathname.new("a"), Pathname("a"))
+ end
+
+ def test_file_basename
+ assert_equal("bar", File.basename(Pathname.new("foo/bar")))
+ end
+
+ def test_file_dirname
+ assert_equal("foo", File.dirname(Pathname.new("foo/bar")))
+ end
+
+ def test_file_split
+ assert_equal(["foo", "bar"], File.split(Pathname.new("foo/bar")))
+ end
+
+ def test_file_extname
+ assert_equal(".baz", File.extname(Pathname.new("bar.baz")))
+ end
+
+ def test_file_fnmatch
+ assert(File.fnmatch("*.*", Pathname.new("bar.baz")))
+ end
+
+ def test_file_join
+ assert_equal("foo/bar", File.join(Pathname.new("foo"), Pathname.new("bar")))
+ lambda {
+ $SAFE = 1
+ assert_equal("foo/bar", File.join(Pathname.new("foo"), Pathname.new("bar").taint))
+ }.call
+ end
+end
diff --git a/trunk/test/rdoc/test_rdoc_info_formatting.rb b/trunk/test/rdoc/test_rdoc_info_formatting.rb
new file mode 100644
index 0000000000..6c024f7454
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_info_formatting.rb
@@ -0,0 +1,175 @@
+require 'fileutils'
+require 'tmpdir'
+require 'test/unit'
+
+require 'rdoc/generator/texinfo'
+
+# From chapter 18 of the Pickaxe 3rd ed. and the TexInfo manual.
+class TestRdocInfoFormatting < Test::Unit::TestCase
+ def setup
+ @output_dir = File.join Dir.tmpdir, "test_rdoc_info_formatting_#{$$}"
+ @output_file = File.join @output_dir, 'rdoc.texinfo'
+
+ RDoc::RDoc.new.document(['--fmt=texinfo', '--quiet',
+ File.expand_path(__FILE__),
+ "--op=#{@output_dir}"])
+ @text = File.read @output_file
+
+ # File.open('rdoc.texinfo', 'w') { |f| f.puts @text }
+ end
+
+ def teardown
+ FileUtils.rm_rf @output_dir
+ end
+
+ # Make sure tags like *this* do not make HTML
+ def test_descriptions_are_not_html
+ assert_no_match Regexp.new("\<b\>this\<\/b\>"), @text, "We had some HTML; icky!"
+ end
+
+ # Ensure we get a reasonable amount
+ #
+ # of space in between paragraphs.
+ def test_paragraphs_are_spaced
+ assert_match(/amount\n\n\nof space/, @text)
+ end
+
+ # @ and {} should be at-sign-prefixed
+ def test_escaping
+ assert_match(/@@ and @\{@\} should be at-sign-prefixed/)
+ end
+
+ # This tests that *bold* and <b>bold me</b> become @strong{bolded}
+ def test_bold
+ # Seems like a limitation of the Info format: @strong{bold}
+ # becomes *bold* when read in Info or M-x info. highly lame!
+ assert_match(/@strong\{bold\}/)
+ assert_match(/@strong\{bold me\}/)
+ end
+
+ # Test that _italics_ and <em>italicize me</em> becomes @emph{italicized}
+ def test_italics
+ assert_match(/@emph\{italics\}/)
+ assert_match(/@emph\{italicize me\}/)
+ end
+
+ # And that typewriter +text+ and <tt>typewriter me</tt> becomes @code{typewriter}
+ def test_tt
+ assert_match(/@code\{text\}/)
+ assert_match(/@code\{typewriter me\}/)
+ end
+
+ # Check that
+ # anything indented is
+ # verbatim @verb{|foo bar baz|}
+ def test_literal_code
+ assert_match("@verb{| anything indented is
+ verbatim @@verb@{|foo bar baz|@}
+|}")
+ end
+
+ # = Huge heading should be a @majorheading
+ # == There is also @chapheading
+ # === Everything deeper becomes a regular @heading
+ # ====== Regardless of its nesting level
+ def test_headings
+ assert_match(/@majorheading\{Huge heading should be a @@majorheading\}/)
+ assert_match(/@chapheading\{There is also @@chapheading\}/)
+ assert_match(/@heading\{Everything deeper becomes a regular @@heading\}/)
+ assert_match(/@heading\{Regardless of its nesting level\}/)
+ end
+
+ # * list item
+ # * list item2
+ #
+ # with a paragraph in between
+ #
+ # - hyphen lists
+ # - are also allowed
+ # and items may flow over lines
+ def test_bullet_lists
+ assert_match("@itemize @bullet
+@item
+list item
+@item
+list item2
+@end itemize")
+ assert_match("@itemize @bullet
+@item
+hyphen lists
+@item
+are also allowed and items may flow over lines
+@end itemize")
+ end
+
+ # 2. numbered lists
+ # 8. are made by
+ # 9. a digit followed by a period
+ def test_numbered_lists
+ end
+
+ # a. alpha lists
+ # b. should be parsed too
+ def test_alpha_lists
+ end
+
+ # [cat] small domestic animal
+ # [+cat+] command to copy standard input
+ # to standard output
+ def test_labelled_lists
+ end
+
+ # * First item.
+ # * Inner item.
+ # * Second inner item.
+ # * Second outer item.
+ def test_nested_lists
+ assert_match("@itemize @bullet
+@item
+First item.
+@itemize @bullet
+@item
+Inner item.
+@item
+Second inner item.
+@end itemize
+@item
+Second outer item.
+@end itemize")
+ end
+
+ def test_internal_hyperlinks
+ # be sure to test multi-word hyperlinks as well.
+ end
+
+ def test_hyperlink_targets
+ end
+
+ def test_web_links
+ # An example of the two-argument form: The official
+ # @uref{ftp://ftp.gnu.org/gnu, GNU ftp site} holds programs and texts.
+
+ # produces:
+ # The official GNU ftp site (ftp://ftp.gnu.org/gnu)
+ # holds programs and texts.
+ # and the HTML output is this:
+ # The official <a href="ftp://ftp.gnu.org/gnu">GNU ftp site</a>
+ # holds programs and texts.
+ end
+
+ # three or more hyphens
+ # ----
+ # should produce a horizontal rule
+ def test_horizontal_rule
+ # gah; not sure texinfo supports horizontal rules
+ end
+
+ private
+
+ # We don't want the whole string inspected if we pass our own
+ # message in.
+ def assert_match(regex, string = @text,
+ message = "Didn't find #{regex.inspect} in #{string}.")
+ assert string[regex] #, message
+ end
+end
diff --git a/trunk/test/rdoc/test_rdoc_info_sections.rb b/trunk/test/rdoc/test_rdoc_info_sections.rb
new file mode 100644
index 0000000000..cceba186c1
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_info_sections.rb
@@ -0,0 +1,136 @@
+require 'fileutils'
+require 'tempfile'
+require 'test/unit'
+require 'tmpdir'
+
+require 'rdoc/generator/texinfo'
+
+# give us access to check this stuff before it's rendered
+class RDoc::Generator::Texinfo; attr_reader :files, :classes; end
+class RDoc::RDoc; attr_reader :options; attr_reader :gen; end
+
+class TestRdocInfoSections < Test::Unit::TestCase
+
+ def setup
+ @output_dir = File.join Dir.tmpdir, "test_rdoc_info_sections_#{$$}"
+ @output_file = File.join @output_dir, 'rdoc.texinfo'
+
+ @input_file = Tempfile.new 'my_file.rb'
+
+ open @input_file.path, 'w' do |io|
+ io.write TEST_DOC
+ end
+
+ RDoc::Parser.alias_extension '.rb', File.extname(@input_file.path)
+
+ @rdoc = RDoc::RDoc.new
+ @rdoc.document(['--fmt=texinfo', '--quiet', @input_file.path,
+ "--op=#{@output_dir}"])
+
+ @text = File.read @output_file
+ end
+
+ def teardown
+ @input_file.close
+ FileUtils.rm_rf @output_dir
+ end
+
+ def test_output_exists
+ assert ! @text.empty?
+ end
+
+ def test_each_class_has_a_chapter
+ assert_section "Class MyClass", '@chapter'
+ end
+
+ def test_class_descriptions_are_given
+ assert_match(/Documentation for my class/, @text.gsub("\n", ' '))
+ end
+
+ def test_included_modules_are_given
+ assert_match(/Includes.* MyModule/m, @text)
+ end
+
+ def test_class_methods_are_given
+ assert_match(/my_class_method\(my_first_argument\)/, @text)
+ end
+
+ def test_classes_instance_methods_are_given
+ assert_section 'Class MyClass#my_method'
+ assert_match(/my_method\(my_first_argument\)/, @text)
+ end
+
+ def test_each_module_has_a_chapter
+ assert_section 'MyModule', '@chapter'
+ end
+
+ def test_methods_are_shown_only_once
+ methods = @rdoc.gen.classes.map do |c|
+ c.methods.map do |m|
+ c.name + '#' + m.name
+ end
+ end.flatten
+
+ assert_equal methods, methods.uniq
+ end
+
+# if system "makeinfo --version > /dev/null"
+# def test_compiles_to_info
+# makeinfo_output = `cd #{@output_dir} && makeinfo rdoc.texinfo`
+# assert(File.exist?(File.join(@output_dir, 'rdoc.info')),
+# "Info file was not compiled: #{makeinfo_output}")
+# end
+# end
+
+# def test_constants_are_documented_somehow
+# assert_section 'DEFAULT_FILENAME' # what kind of section?
+# assert_section 'DEFAULT_INFO_FILENAME'
+# end
+
+# def test_oh_yeah_dont_forget_files
+# end
+
+ def assert_section(name, command = '@section')
+ assert_match Regexp.new("^#{command}.*#{Regexp.escape name}"), @text, "Could not find a #{command} #{name}"
+ end
+
+ TEST_DOC = <<-DOC
+##
+# Documentation for my module
+
+module MyModule
+
+ ##
+ # Documentation for my included method
+
+ def my_included_method() end
+
+end
+
+##
+# Documentation for my class
+
+class MyClass
+
+ include MyModule
+
+ ##
+ # Documentation for my constant
+
+ MY_CONSTANT = 'my value'
+
+ ##
+ # Documentation for my class method
+
+ def self.my_class_method(my_first_argument) end
+
+ ##
+ # Documentation for my method
+
+ def my_method(my_first_argument) end
+
+end
+
+ DOC
+
+end
diff --git a/trunk/test/rdoc/test_rdoc_markup.rb b/trunk/test/rdoc/test_rdoc_markup.rb
new file mode 100644
index 0000000000..d88743858a
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_markup.rb
@@ -0,0 +1,613 @@
+require 'test/unit'
+require 'rdoc/markup'
+require 'rdoc/markup/to_test'
+
+class TestRDocMarkup < Test::Unit::TestCase
+
+ def basic_conv(str)
+ sm = RDoc::Markup.new
+ mock = RDoc::Markup::ToTest.new
+ sm.convert(str, mock)
+ sm.content
+ end
+
+ def line_groups(str, expected)
+ m = RDoc::Markup.new
+ mock = RDoc::Markup::ToTest.new
+
+ block = m.convert(str, mock)
+
+ if block != expected
+ rows = (0...([expected.size, block.size].max)).collect{|i|
+ [expected[i]||"nil", block[i]||"nil"]
+ }
+ printf "\n\n%35s %35s\n", "Expected", "Got"
+ rows.each {|e,g| printf "%35s %35s\n", e.dump, g.dump }
+ end
+
+ assert_equal(expected, block)
+ end
+
+ def line_types(str, expected)
+ m = RDoc::Markup.new
+ mock = RDoc::Markup::ToTest.new
+ m.convert(str, mock)
+ assert_equal(expected, m.get_line_types.map{|type| type.to_s[0,1]}.join(''))
+ end
+
+ def test_groups
+ str = "now is the time"
+ line_groups(str, ["L0: Paragraph\nnow is the time"] )
+
+ str = "now is the time\nfor all good men"
+ line_groups(str, ["L0: Paragraph\nnow is the time for all good men"] )
+
+ str = %{\
+ now is the time
+ code _line_ here
+ for all good men}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is the time",
+ "L0: Verbatim\n code _line_ here\n",
+ "L0: Paragraph\nfor all good men"
+ ] )
+
+ str = "now is the time\n code\n more code\nfor all good men"
+ line_groups(str,
+ [ "L0: Paragraph\nnow is the time",
+ "L0: Verbatim\n code\n more code\n",
+ "L0: Paragraph\nfor all good men"
+ ] )
+
+ str = %{\
+ now is
+ * l1
+ * l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl1",
+ "L1: BULLET ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+ str = %{\
+ now is
+ * l1
+ l1+
+ * l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl1 l1+",
+ "L1: BULLET ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+ str = %{\
+ now is
+ * l1
+ * l1.1
+ * l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl1",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\nl1.1",
+ "L2: ListEnd\n",
+ "L1: BULLET ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ * l1
+ * l1.1
+ text
+ code
+ code
+
+ text
+ * l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl1",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\nl1.1 text",
+ "L2: Verbatim\n code\n code\n",
+ "L2: Paragraph\ntext",
+ "L2: ListEnd\n",
+ "L1: BULLET ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ 1. l1
+ * l1.1
+ 2. l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: NUMBER ListItem\nl1",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\nl1.1",
+ "L2: ListEnd\n",
+ "L1: NUMBER ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+ str = %{\
+ now is
+ [cat] l1
+ * l1.1
+ [dog] l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: LABELED ListItem\ncat: l1",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\nl1.1",
+ "L2: ListEnd\n",
+ "L1: LABELED ListItem\ndog: l2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+ str = %{\
+ now is
+ [cat] l1
+ continuation
+ [dog] l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: LABELED ListItem\ncat: l1 continuation",
+ "L1: LABELED ListItem\ndog: l2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+ end
+
+ def test_headings
+ str = "= heading one"
+ line_groups(str,
+ [ "L0: Heading\nheading one"
+ ])
+
+ str = "=== heading three"
+ line_groups(str,
+ [ "L0: Heading\nheading three"
+ ])
+
+ str = "text\n === heading three"
+ line_groups(str,
+ [ "L0: Paragraph\ntext",
+ "L0: Verbatim\n === heading three\n"
+ ])
+
+ str = "text\n code\n === heading three"
+ line_groups(str,
+ [ "L0: Paragraph\ntext",
+ "L0: Verbatim\n code\n === heading three\n"
+ ])
+
+ str = "text\n code\n=== heading three"
+ line_groups(str,
+ [ "L0: Paragraph\ntext",
+ "L0: Verbatim\n code\n",
+ "L0: Heading\nheading three"
+ ])
+
+ end
+
+ def test_list_alpha
+ str = "a. alpha\nb. baker\nB. ALPHA\nA. BAKER"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: LOWERALPHA ListItem\nalpha",
+ "L1: LOWERALPHA ListItem\nbaker",
+ "L1: ListEnd\n",
+ "L1: ListStart\n",
+ "L1: UPPERALPHA ListItem\nALPHA",
+ "L1: UPPERALPHA ListItem\nBAKER",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_bullet_dash
+ str = "- one\n- two\n"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: BULLET ListItem\none",
+ "L1: BULLET ListItem\ntwo",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_bullet_star
+ str = "* one\n* two\n"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: BULLET ListItem\none",
+ "L1: BULLET ListItem\ntwo",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_labeled_bracket
+ str = "[one] item one\n[two] item two"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: LABELED ListItem\none: item one",
+ "L1: LABELED ListItem\ntwo: item two",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_labeled_bracket_continued
+ str = "[one]\n item one\n[two]\n item two"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: LABELED ListItem\none: item one",
+ "L1: LABELED ListItem\ntwo: item two",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_labeled_colon
+ str = "one:: item one\ntwo:: item two"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: NOTE ListItem\none:: item one",
+ "L1: NOTE ListItem\ntwo:: item two",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_labeled_colon_continued
+ str = "one::\n item one\ntwo::\n item two"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: NOTE ListItem\none:: item one",
+ "L1: NOTE ListItem\ntwo:: item two",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_nested_bullet_bullet
+ str = "* one\n* two\n * cat\n * dog"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: BULLET ListItem\none",
+ "L1: BULLET ListItem\ntwo",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\ncat",
+ "L2: BULLET ListItem\ndog",
+ "L2: ListEnd\n",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_nested_labeled_bullet
+ str = "[one]\n * cat\n * dog"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: LABELED ListItem\none: ",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\ncat",
+ "L2: BULLET ListItem\ndog",
+ "L2: ListEnd\n",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_nested_labeled_bullet_bullet
+ str = "[one]\n * cat\n * dog"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: LABELED ListItem\none: ",
+ "L2: ListStart\n",
+ "L2: BULLET ListItem\ncat",
+ "L3: ListStart\n",
+ "L3: BULLET ListItem\ndog",
+ "L3: ListEnd\n",
+ "L2: ListEnd\n",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_nested_number_number
+ str = "1. one\n1. two\n 1. cat\n 1. dog"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: NUMBER ListItem\none",
+ "L1: NUMBER ListItem\ntwo",
+ "L2: ListStart\n",
+ "L2: NUMBER ListItem\ncat",
+ "L2: NUMBER ListItem\ndog",
+ "L2: ListEnd\n",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_number
+ str = "1. one\n2. two\n1. three"
+
+ line_groups(str,
+ [ "L1: ListStart\n",
+ "L1: NUMBER ListItem\none",
+ "L1: NUMBER ListItem\ntwo",
+ "L1: NUMBER ListItem\nthree",
+ "L1: ListEnd\n" ])
+ end
+
+ def test_list_split
+ str = %{\
+ now is
+ * l1
+ 1. n1
+ 2. n2
+ * l2
+ the time}
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl1",
+ "L1: ListEnd\n",
+ "L1: ListStart\n",
+ "L1: NUMBER ListItem\nn1",
+ "L1: NUMBER ListItem\nn2",
+ "L1: ListEnd\n",
+ "L1: ListStart\n",
+ "L1: BULLET ListItem\nl2",
+ "L1: ListEnd\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+ end
+
+ def test_paragraph
+ str = "paragraph\n\n*bold* paragraph\n"
+
+ line_groups str, [
+ "L0: Paragraph\nparagraph",
+ "L0: BlankLine\n",
+ "L0: Paragraph\n*bold* paragraph"
+ ]
+ end
+
+ def test_tabs
+ str = "hello\n dave"
+ assert_equal(str, basic_conv(str))
+ str = "hello\n\tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = "hello\n \tdave"
+ assert_equal("hello\n dave", basic_conv(str))
+ str = ".\t\t."
+ assert_equal(". .", basic_conv(str))
+ end
+
+ def test_types
+ str = "now is the time"
+ line_types(str, 'P')
+
+ str = "now is the time\nfor all good men"
+ line_types(str, 'PP')
+
+ str = "now is the time\n code\nfor all good men"
+ line_types(str, 'PVP')
+
+ str = "now is the time\n code\n more code\nfor all good men"
+ line_types(str, 'PVVP')
+
+ str = "now is\n---\nthe time"
+ line_types(str, 'PRP')
+
+ str = %{\
+ now is
+ * l1
+ * l2
+ the time}
+ line_types(str, 'PLLP')
+
+ str = %{\
+ now is
+ * l1
+ l1+
+ * l2
+ the time}
+ line_types(str, 'PLPLP')
+
+ str = %{\
+ now is
+ * l1
+ * l1.1
+ * l2
+ the time}
+ line_types(str, 'PLLLP')
+
+ str = %{\
+ now is
+ * l1
+ * l1.1
+ text
+ code
+ code
+
+ text
+ * l2
+ the time}
+ line_types(str, 'PLLPVVBPLP')
+
+ str = %{\
+ now is
+ 1. l1
+ * l1.1
+ 2. l2
+ the time}
+ line_types(str, 'PLLLP')
+
+ str = %{\
+ now is
+ [cat] l1
+ * l1.1
+ [dog] l2
+ the time}
+ line_types(str, 'PLLLP')
+
+ str = %{\
+ now is
+ [cat] l1
+ continuation
+ [dog] l2
+ the time}
+ line_types(str, 'PLPLP')
+ end
+
+ def test_verbatim
+ str = "paragraph\n *bold* verbatim\n"
+
+ line_groups str, [
+ "L0: Paragraph\nparagraph",
+ "L0: Verbatim\n *bold* verbatim\n"
+ ]
+ end
+
+ def test_verbatim_merge
+ str = %{\
+ now is
+ code
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ code
+ code1
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n code1\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ code
+
+ code1
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n\n code1\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ code
+
+ code1
+
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n\n code1\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ str = %{\
+ now is
+ code
+
+ code1
+
+ code2
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n\n code1\n\n code2\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ # Folds multiple blank lines
+ str = %{\
+ now is
+ code
+
+
+ code1
+
+ the time}
+
+ line_groups(str,
+ [ "L0: Paragraph\nnow is",
+ "L0: Verbatim\n code\n\n code1\n",
+ "L0: Paragraph\nthe time"
+ ])
+
+
+ end
+
+ def test_whitespace
+ assert_equal("hello", basic_conv("hello"))
+ assert_equal("hello", basic_conv(" hello "))
+ assert_equal("hello", basic_conv(" \t \t hello\t\t"))
+
+ assert_equal("1\n 2\n 3", basic_conv("1\n 2\n 3"))
+ assert_equal("1\n 2\n 3", basic_conv(" 1\n 2\n 3"))
+
+ assert_equal("1\n 2\n 3\n1\n 2", basic_conv("1\n 2\n 3\n1\n 2"))
+ assert_equal("1\n 2\n 3\n1\n 2", basic_conv(" 1\n 2\n 3\n 1\n 2"))
+
+ assert_equal("1\n 2\n\n 3", basic_conv(" 1\n 2\n\n 3"))
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_markup_attribute_manager.rb b/trunk/test/rdoc/test_rdoc_markup_attribute_manager.rb
new file mode 100644
index 0000000000..8ba9d7440a
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -0,0 +1,224 @@
+require "test/unit"
+require "rdoc/markup/inline"
+
+class TestRDocMarkupAttributeManager < Test::Unit::TestCase
+
+ def setup
+ @am = RDoc::Markup::AttributeManager.new
+
+ @bold_on = @am.changed_attribute_by_name([], [:BOLD])
+ @bold_off = @am.changed_attribute_by_name([:BOLD], [])
+
+ @tt_on = @am.changed_attribute_by_name([], [:TT])
+ @tt_off = @am.changed_attribute_by_name([:TT], [])
+
+ @em_on = @am.changed_attribute_by_name([], [:EM])
+ @em_off = @am.changed_attribute_by_name([:EM], [])
+
+ @bold_em_on = @am.changed_attribute_by_name([], [:BOLD] | [:EM])
+ @bold_em_off = @am.changed_attribute_by_name([:BOLD] | [:EM], [])
+
+ @em_then_bold = @am.changed_attribute_by_name([:EM], [:EM] | [:BOLD])
+
+ @em_to_bold = @am.changed_attribute_by_name([:EM], [:BOLD])
+
+ @am.add_word_pair("{", "}", :WOMBAT)
+ @wombat_on = @am.changed_attribute_by_name([], [:WOMBAT])
+ @wombat_off = @am.changed_attribute_by_name([:WOMBAT], [])
+ end
+
+ def crossref(text)
+ crossref_bitmap = RDoc::Markup::Attribute.bitmap_for(:_SPECIAL_) |
+ RDoc::Markup::Attribute.bitmap_for(:CROSSREF)
+
+ [ @am.changed_attribute_by_name([], [:CROSSREF, :_SPECIAL_]),
+ RDoc::Markup::Special.new(crossref_bitmap, text),
+ @am.changed_attribute_by_name([:CROSSREF, :_SPECIAL_], [])
+ ]
+ end
+
+ def test_adding
+ assert_equal(["cat ", @wombat_on, "and", @wombat_off, " dog" ],
+ @am.flow("cat {and} dog"))
+ #assert_equal(["cat {and} dog" ], @am.flow("cat \\{and} dog"))
+ end
+
+ def test_add_word_pair
+ @am.add_word_pair '%', '&', 'percent and'
+
+ assert RDoc::Markup::AttributeManager::WORD_PAIR_MAP.include?(/(%)(\S+)(&)/)
+ assert RDoc::Markup::AttributeManager::PROTECTABLE.include?('%')
+ assert !RDoc::Markup::AttributeManager::PROTECTABLE.include?('&')
+ end
+
+ def test_add_word_pair_angle
+ e = assert_raise ArgumentError do
+ @am.add_word_pair '<', '>', 'angles'
+ end
+
+ assert_equal "Word flags may not start with '<'", e.message
+ end
+
+ def test_add_word_pair_matching
+ @am.add_word_pair '^', '^', 'caret'
+
+ assert RDoc::Markup::AttributeManager::MATCHING_WORD_PAIRS.include?('^')
+ assert RDoc::Markup::AttributeManager::PROTECTABLE.include?('^')
+ end
+
+ def test_basic
+ assert_equal(["cat"], @am.flow("cat"))
+
+ assert_equal(["cat ", @bold_on, "and", @bold_off, " dog"],
+ @am.flow("cat *and* dog"))
+
+ assert_equal(["cat ", @bold_on, "AND", @bold_off, " dog"],
+ @am.flow("cat *AND* dog"))
+
+ assert_equal(["cat ", @em_on, "And", @em_off, " dog"],
+ @am.flow("cat _And_ dog"))
+
+ assert_equal(["cat *and dog*"], @am.flow("cat *and dog*"))
+
+ assert_equal(["*cat and* dog"], @am.flow("*cat and* dog"))
+
+ assert_equal(["cat *and ", @bold_on, "dog", @bold_off],
+ @am.flow("cat *and *dog*"))
+
+ assert_equal(["cat ", @em_on, "and", @em_off, " dog"],
+ @am.flow("cat _and_ dog"))
+
+ assert_equal(["cat_and_dog"],
+ @am.flow("cat_and_dog"))
+
+ assert_equal(["cat ", @tt_on, "and", @tt_off, " dog"],
+ @am.flow("cat +and+ dog"))
+
+ assert_equal(["cat ", @bold_on, "a_b_c", @bold_off, " dog"],
+ @am.flow("cat *a_b_c* dog"))
+
+ assert_equal(["cat __ dog"],
+ @am.flow("cat __ dog"))
+
+ assert_equal(["cat ", @em_on, "_", @em_off, " dog"],
+ @am.flow("cat ___ dog"))
+ end
+
+ def test_bold
+ assert_equal [@bold_on, 'bold', @bold_off],
+ @am.flow("*bold*")
+
+ assert_equal [@bold_on, 'Bold:', @bold_off],
+ @am.flow("*Bold:*")
+
+ assert_equal [@bold_on, '\\bold', @bold_off],
+ @am.flow("*\\bold*")
+ end
+
+ def test_combined
+ assert_equal(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
+ @am.flow("cat _and_ *dog*"))
+
+ assert_equal(["cat ", @em_on, "a__nd", @em_off, " ", @bold_on, "dog", @bold_off],
+ @am.flow("cat _a__nd_ *dog*"))
+ end
+
+ def test_convert_attrs
+ str = '+foo+'
+ attrs = RDoc::Markup::AttrSpan.new str.length
+
+ @am.convert_attrs str, attrs
+
+ assert_equal "\000foo\000", str
+
+ str = '+:foo:+'
+ attrs = RDoc::Markup::AttrSpan.new str.length
+
+ @am.convert_attrs str, attrs
+
+ assert_equal "\000:foo:\000", str
+
+ str = '+x-y+'
+ attrs = RDoc::Markup::AttrSpan.new str.length
+
+ @am.convert_attrs str, attrs
+
+ assert_equal "\000x-y\000", str
+ end
+
+ def test_html_like_em_bold
+ assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
+ @am.flow("cat <i>and </i><b>dog</b>")
+ end
+
+ def test_html_like_em_bold_SGML
+ assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
+ @am.flow("cat <i>and <b></i>dog</b>")
+ end
+
+ def test_html_like_em_bold_nested_1
+ assert_equal(["cat ", @bold_em_on, "and", @bold_em_off, " dog"],
+ @am.flow("cat <i><b>and</b></i> dog"))
+ end
+
+ def test_html_like_em_bold_nested_2
+ assert_equal ["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off],
+ @am.flow("cat <i>and <b>dog</b></i>")
+ end
+
+ def test_html_like_em_bold_nested_mixed_case
+ assert_equal ["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off],
+ @am.flow("cat <i>and <B>dog</B></I>")
+ end
+
+ def test_html_like_em_bold_mixed_case
+ assert_equal ["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
+ @am.flow("cat <i>and</i> <B>dog</b>")
+ end
+
+ def test_html_like_teletype
+ assert_equal ["cat ", @tt_on, "dog", @tt_off],
+ @am.flow("cat <tt>dog</Tt>")
+ end
+
+ def test_html_like_teletype_em_bold_SGML
+ assert_equal [@tt_on, "cat", @tt_off, " ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
+ @am.flow("<tt>cat</tt> <i>and <b></i>dog</b>")
+ end
+
+ def test_protect
+ assert_equal(['cat \\ dog'], @am.flow('cat \\ dog'))
+
+ assert_equal(["cat <tt>dog</Tt>"], @am.flow("cat \\<tt>dog</Tt>"))
+
+ assert_equal(["cat ", @em_on, "and", @em_off, " <B>dog</b>"],
+ @am.flow("cat <i>and</i> \\<B>dog</b>"))
+
+ assert_equal(["*word* or <b>text</b>"], @am.flow("\\*word* or \\<b>text</b>"))
+
+ assert_equal(["_cat_", @em_on, "dog", @em_off],
+ @am.flow("\\_cat_<i>dog</i>"))
+ end
+
+ def test_special
+ # class names, variable names, file names, or instance variables
+ @am.add_special(/(
+ \b([A-Z]\w+(::\w+)*)
+ | \#\w+[!?=]?
+ | \b\w+([_\/\.]+\w+)+[!?=]?
+ )/x,
+ :CROSSREF)
+
+ assert_equal(["cat"], @am.flow("cat"))
+
+ assert_equal(["cat ", crossref("#fred"), " dog"].flatten,
+ @am.flow("cat #fred dog"))
+
+ assert_equal([crossref("#fred"), " dog"].flatten,
+ @am.flow("#fred dog"))
+
+ assert_equal(["cat ", crossref("#fred")].flatten, @am.flow("cat #fred"))
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_markup_to_html.rb b/trunk/test/rdoc/test_rdoc_markup_to_html.rb
new file mode 100644
index 0000000000..463228cc4a
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_markup_to_html.rb
@@ -0,0 +1,30 @@
+require 'test/unit'
+require 'rdoc/markup'
+require 'rdoc/markup/to_html'
+
+class TestRdocMarkupToHtml < Test::Unit::TestCase
+
+ def setup
+ @am = RDoc::Markup::AttributeManager.new
+ @th = RDoc::Markup::ToHtml.new
+ end
+
+ def test_tt_formatting
+ assert_equal "<p>\n<tt>--</tt> &#8212; <tt>(c)</tt> &#169;\n</p>\n",
+ util_format("<tt>--</tt> -- <tt>(c)</tt> (c)")
+ assert_equal "<p>\n<b>&#8212;</b>\n</p>\n", util_format("<b>--</b>")
+ end
+
+ def util_fragment(text)
+ RDoc::Markup::Fragment.new 0, nil, nil, text
+ end
+
+ def util_format(text)
+ fragment = util_fragment text
+
+ @th.start_accepting
+ @th.accept_paragraph @am, fragment
+ @th.end_accepting
+ end
+
+end
diff --git a/trunk/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/trunk/test/rdoc/test_rdoc_markup_to_html_crossref.rb
new file mode 100644
index 0000000000..ab4c3e7e9c
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_markup_to_html_crossref.rb
@@ -0,0 +1,18 @@
+require 'test/unit'
+require 'rdoc/generator'
+require 'rdoc/markup/to_html_crossref'
+
+class TestRdocMarkupToHtmlCrossref < Test::Unit::TestCase
+
+ def setup
+ @xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', nil, nil
+ end
+
+ def test_handle_special_CROSSREF_no_underscore
+ out = @xref.convert 'foo'
+
+ assert_equal "<p>\nfoo\n</p>\n", out
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_parser_c.rb b/trunk/test/rdoc/test_rdoc_parser_c.rb
new file mode 100644
index 0000000000..fd750070d8
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_parser_c.rb
@@ -0,0 +1,258 @@
+require 'stringio'
+require 'tempfile'
+require 'test/unit'
+require 'rdoc/options'
+require 'rdoc/parser/c'
+
+class RDoc::Parser::C
+ attr_accessor :classes
+
+ public :do_classes, :do_constants
+end
+
+class TestRdocParserC < Test::Unit::TestCase
+
+ def setup
+ @tempfile = Tempfile.new self.class.name
+ filename = @tempfile.path
+
+ @top_level = RDoc::TopLevel.new filename
+ @fn = filename
+ @options = RDoc::Options.new
+ @stats = RDoc::Stats.new 0
+ end
+
+ def teardown
+ @tempfile.close
+ end
+
+ def test_do_classes_boot_class
+ content = <<-EOF
+/* Document-class: Foo
+ * this is the Foo boot class
+ */
+VALUE cFoo = boot_defclass("Foo", 0);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal " this is the Foo boot class\n ", klass.comment
+ end
+
+ def test_do_classes_class
+ content = <<-EOF
+/* Document-class: Foo
+ * this is the Foo class
+ */
+VALUE cFoo = rb_define_class("Foo", rb_cObject);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal " this is the Foo class\n ", klass.comment
+ end
+
+ def test_do_classes_class_under
+ content = <<-EOF
+/* Document-class: Kernel::Foo
+ * this is the Foo class under Kernel
+ */
+VALUE cFoo = rb_define_class_under(rb_mKernel, "Foo", rb_cObject);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal " this is the Foo class under Kernel\n ", klass.comment
+ end
+
+ def test_do_classes_module
+ content = <<-EOF
+/* Document-module: Foo
+ * this is the Foo module
+ */
+VALUE mFoo = rb_define_module("Foo");
+ EOF
+
+ klass = util_get_class content, 'mFoo'
+ assert_equal " this is the Foo module\n ", klass.comment
+ end
+
+ def test_do_classes_module_under
+ content = <<-EOF
+/* Document-module: Kernel::Foo
+ * this is the Foo module under Kernel
+ */
+VALUE mFoo = rb_define_module_under(rb_mKernel, "Foo");
+ EOF
+
+ klass = util_get_class content, 'mFoo'
+ assert_equal " this is the Foo module under Kernel\n ", klass.comment
+ end
+
+ def test_do_constants
+ content = <<-EOF
+#include <ruby.h>
+
+void Init_foo(){
+ VALUE cFoo = rb_define_class("Foo", rb_cObject);
+
+ /* 300: The highest possible score in bowling */
+ rb_define_const(cFoo, "PERFECT", INT2FIX(300));
+
+ /* Huzzah!: What you cheer when you roll a perfect game */
+ rb_define_const(cFoo, "CHEER", rb_str_new2("Huzzah!"));
+
+ /* TEST\:TEST: Checking to see if escaped semicolon works */
+ rb_define_const(cFoo, "TEST", rb_str_new2("TEST:TEST"));
+
+ /* \\: The file separator on MS Windows */
+ rb_define_const(cFoo, "MSEPARATOR", rb_str_new2("\\"));
+
+ /* /: The file separator on Unix */
+ rb_define_const(cFoo, "SEPARATOR", rb_str_new2("/"));
+
+ /* C:\\Program Files\\Stuff: A directory on MS Windows */
+ rb_define_const(cFoo, "STUFF", rb_str_new2("C:\\Program Files\\Stuff"));
+
+ /* Default definition */
+ rb_define_const(cFoo, "NOSEMI", INT2FIX(99));
+
+ rb_define_const(cFoo, "NOCOMMENT", rb_str_new2("No comment"));
+
+ /*
+ * Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE", INT2FIX(1));
+
+ /*
+ * 1: Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE_VALUE", INT2FIX(1));
+
+ /* Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE_NOT_EMPTY", INT2FIX(1));
+
+}
+ EOF
+
+ parser = util_parser content
+
+ parser.do_classes
+ parser.do_constants
+
+ klass = parser.classes['cFoo']
+ assert klass
+
+ constants = klass.constants
+ assert !klass.constants.empty?
+
+ constants = constants.map { |c| [c.name, c.value, c.comment] }
+
+ assert_equal ['PERFECT', '300',
+ "\n The highest possible score in bowling \n "],
+ constants.shift
+ assert_equal ['CHEER', 'Huzzah!',
+ "\n What you cheer when you roll a perfect game \n "],
+ constants.shift
+ assert_equal ['TEST', 'TEST:TEST',
+ "\n Checking to see if escaped semicolon works \n "],
+ constants.shift
+ assert_equal ['MSEPARATOR', '\\',
+ "\n The file separator on MS Windows \n "],
+ constants.shift
+ assert_equal ['SEPARATOR', '/',
+ "\n The file separator on Unix \n "],
+ constants.shift
+ assert_equal ['STUFF', 'C:\\Program Files\\Stuff',
+ "\n A directory on MS Windows \n "],
+ constants.shift
+ assert_equal ['NOSEMI', 'INT2FIX(99)',
+ "\n Default definition \n "],
+ constants.shift
+ assert_equal ['NOCOMMENT', 'rb_str_new2("No comment")', nil],
+ constants.shift
+
+ comment = <<-EOF.chomp
+
+
+ Multiline comment goes here because this comment spans multiple lines.
+ Multiline comment goes here because this comment spans multiple lines.
+
+
+ EOF
+ assert_equal ['MULTILINE', 'INT2FIX(1)', comment], constants.shift
+ assert_equal ['MULTILINE_VALUE', '1', comment], constants.shift
+
+ comment = <<-EOF.chomp
+
+ Multiline comment goes here because this comment spans multiple lines.
+ Multiline comment goes here because this comment spans multiple lines.
+
+
+ EOF
+ assert_equal ['MULTILINE_NOT_EMPTY', 'INT2FIX(1)', comment], constants.shift
+
+ assert constants.empty?, constants.inspect
+ end
+
+ def test_find_class_comment_init
+ content = <<-EOF
+/*
+ * a comment for class Foo
+ */
+void
+Init_Foo(void) {
+ VALUE foo = rb_define_class("Foo", rb_cObject);
+}
+ EOF
+
+ klass = util_get_class content, 'foo'
+
+ assert_equal " \n a comment for class Foo\n \n", klass.comment
+ end
+
+ def test_find_class_comment_define_class
+ content = <<-EOF
+/*
+ * a comment for class Foo
+ */
+VALUE foo = rb_define_class("Foo", rb_cObject);
+ EOF
+
+ klass = util_get_class content, 'foo'
+
+ assert_equal " \n a comment for class Foo\n ", klass.comment
+ end
+
+ def test_find_class_comment_define_class_Init_Foo
+ content = <<-EOF
+/*
+ * a comment for class Foo on Init
+ */
+void
+Init_Foo(void) {
+ /*
+ * a comment for class Foo on rb_define_class
+ */
+ VALUE foo = rb_define_class("Foo", rb_cObject);
+}
+ EOF
+
+ klass = util_get_class content, 'foo'
+
+ assert_equal " \n a comment for class Foo on Init\n \n", klass.comment
+ end
+
+ def util_get_class(content, name)
+ parser = util_parser content
+ parser.do_classes
+ parser.classes[name]
+ end
+
+ def util_parser(content)
+ RDoc::Parser::C.new @top_level, @fn, content, @options, @stats
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_parser_ruby.rb b/trunk/test/rdoc/test_rdoc_parser_ruby.rb
new file mode 100644
index 0000000000..77d8bd24fc
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_parser_ruby.rb
@@ -0,0 +1,539 @@
+require 'stringio'
+require 'tempfile'
+require 'test/unit'
+
+require 'rdoc/options'
+require 'rdoc/parser/ruby'
+require 'rdoc/stats'
+
+class TestRdocParserRuby < Test::Unit::TestCase
+
+ def setup
+ @tempfile = Tempfile.new self.class.name
+ @filename = @tempfile.path
+
+ util_toplevel
+ @options = RDoc::Options.new
+ @options.quiet = true
+ @stats = RDoc::Stats.new 0
+ end
+
+ def teardown
+ @tempfile.close
+ end
+
+ def test_look_for_directives_in_commented
+ util_parser ""
+
+ comment = "# how to make a section:\n# # :section: new section\n"
+
+ @parser.look_for_directives_in @top_level, comment
+
+ section = @top_level.current_section
+ assert_equal nil, section.title
+ assert_equal nil, section.comment
+
+ assert_equal "# how to make a section:\n# # :section: new section\n",
+ comment
+ end
+
+ def test_look_for_directives_in_enddoc
+ util_parser ""
+
+ assert_throws :enddoc do
+ @parser.look_for_directives_in @top_level, "# :enddoc:\n"
+ end
+ end
+
+ def test_look_for_directives_in_main
+ util_parser ""
+
+ @parser.look_for_directives_in @top_level, "# :main: new main page\n"
+
+ assert_equal 'new main page', @options.main_page
+ end
+
+ def test_look_for_directives_in_method
+ util_parser ""
+
+ comment = "# :method: my_method\n"
+
+ @parser.look_for_directives_in @top_level, comment
+
+ assert_equal "# :method: my_method\n", comment
+
+ comment = "# :singleton-method: my_method\n"
+
+ @parser.look_for_directives_in @top_level, comment
+
+ assert_equal "# :singleton-method: my_method\n", comment
+ end
+
+ def test_look_for_directives_in_startdoc
+ util_parser ""
+
+ @top_level.stop_doc
+ assert !@top_level.document_self
+ assert !@top_level.document_children
+ assert !@top_level.force_documentation
+
+ @parser.look_for_directives_in @top_level, "# :startdoc:\n"
+
+ assert @top_level.document_self
+ assert @top_level.document_children
+ assert @top_level.force_documentation
+ end
+
+ def test_look_for_directives_in_stopdoc
+ util_parser ""
+
+ assert @top_level.document_self
+ assert @top_level.document_children
+
+ @parser.look_for_directives_in @top_level, "# :stopdoc:\n"
+
+ assert !@top_level.document_self
+ assert !@top_level.document_children
+ end
+
+ def test_look_for_directives_in_section
+ util_parser ""
+
+ comment = "# :section: new section\n# woo stuff\n"
+
+ @parser.look_for_directives_in @top_level, comment
+
+ section = @top_level.current_section
+ assert_equal 'new section', section.title
+ assert_equal "# woo stuff\n", section.comment
+
+ assert_equal '', comment
+ end
+
+ def test_look_for_directives_in_title
+ util_parser ""
+
+ @parser.look_for_directives_in @top_level, "# :title: new title\n"
+
+ assert_equal 'new title', @options.title
+ end
+
+ def test_look_for_directives_in_unhandled
+ util_parser ""
+
+ comment = "# :unhandled: \n# :title: hi\n"
+
+ @parser.look_for_directives_in @top_level, comment
+
+ assert_equal "# :unhandled: \n", comment
+
+ assert_equal 'hi', @options.title
+ end
+
+ def test_parse_class
+ comment = "##\n# my method\n"
+
+ util_parser 'class Foo; end'
+
+ tk = @parser.get_tk
+
+ @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal comment, foo.comment
+ end
+
+ def test_parse_class_nested_superclass
+ foo = RDoc::NormalModule.new 'Foo'
+ foo.parent = @top_level
+
+ util_parser "class Bar < Super\nend"
+
+ tk = @parser.get_tk
+
+ @parser.parse_class foo, RDoc::Parser::Ruby::NORMAL, tk, ''
+
+ bar = foo.classes.first
+ assert_equal 'Super', bar.superclass
+ end
+
+ def test_parse_comment
+ content = <<-EOF
+class Foo
+ ##
+ # :method: my_method
+ # my method comment
+
+end
+ EOF
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# :method: foo\n# my method\n"
+
+ util_parser "\n"
+
+ tk = @parser.get_tk
+
+ @parser.parse_comment klass, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal comment, foo.comment
+
+ assert_equal [], foo.aliases
+ assert_equal nil, foo.block_params
+ assert_equal nil, foo.call_seq
+ assert_equal nil, foo.is_alias_for
+ assert_equal nil, foo.viewer
+ assert_equal true, foo.document_children
+ assert_equal true, foo.document_self
+ assert_equal '', foo.params
+ assert_equal false, foo.done_documenting
+ assert_equal false, foo.dont_rename_initialize
+ assert_equal false, foo.force_documentation
+ assert_equal klass, foo.parent
+ assert_equal false, foo.singleton
+ assert_equal :public, foo.visibility
+ assert_equal "\n", foo.text
+ assert_equal klass.current_section, foo.section
+
+ stream = [
+ tk(:COMMENT, 1, 1, nil, "# File #{@top_level.file_absolute_name}, line 1"),
+ RDoc::Parser::Ruby::NEWLINE_TOKEN,
+ tk(:SPACE, 1, 1, nil, ''),
+ ]
+
+ assert_equal stream, foo.token_stream
+ end
+
+ def test_parse_meta_method
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# my method\n"
+
+ util_parser "add_my_method :foo, :bar\nadd_my_method :baz"
+
+ tk = @parser.get_tk
+
+ @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal comment, foo.comment
+
+ assert_equal [], foo.aliases
+ assert_equal nil, foo.block_params
+ assert_equal nil, foo.call_seq
+ assert_equal true, foo.document_children
+ assert_equal true, foo.document_self
+ assert_equal false, foo.done_documenting
+ assert_equal false, foo.dont_rename_initialize
+ assert_equal false, foo.force_documentation
+ assert_equal nil, foo.is_alias_for
+ assert_equal '', foo.params
+ assert_equal klass, foo.parent
+ assert_equal false, foo.singleton
+ assert_equal 'add_my_method :foo', foo.text
+ assert_equal nil, foo.viewer
+ assert_equal :public, foo.visibility
+ assert_equal klass.current_section, foo.section
+
+ stream = [
+ tk(:COMMENT, 1, 1, nil, "# File #{@top_level.file_absolute_name}, line 1"),
+ RDoc::Parser::Ruby::NEWLINE_TOKEN,
+ tk(:SPACE, 1, 1, nil, ''),
+ tk(:IDENTIFIER, 1, 0, 'add_my_method', 'add_my_method'),
+ tk(:SPACE, 1, 13, nil, ' '),
+ tk(:SYMBOL, 1, 14, nil, ':foo'),
+ tk(:COMMA, 1, 18, nil, ','),
+ tk(:SPACE, 1, 19, nil, ' '),
+ tk(:SYMBOL, 1, 20, nil, ':bar'),
+ tk(:NL, 1, 24, nil, "\n"),
+ ]
+
+ assert_equal stream, foo.token_stream
+ end
+
+ def test_parse_meta_method_name
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# :method: woo_hoo!\n# my method\n"
+
+ util_parser "add_my_method :foo, :bar\nadd_my_method :baz"
+
+ tk = @parser.get_tk
+
+ @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'woo_hoo!', foo.name
+ assert_equal "##\n# my method\n", foo.comment
+ end
+
+ def test_parse_meta_method_singleton
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# :singleton-method:\n# my method\n"
+
+ util_parser "add_my_method :foo, :bar\nadd_my_method :baz"
+
+ tk = @parser.get_tk
+
+ @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal true, foo.singleton, 'singleton method'
+ assert_equal "##\n# my method\n", foo.comment
+ end
+
+ def test_parse_meta_method_singleton_name
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# :singleton-method: woo_hoo!\n# my method\n"
+
+ util_parser "add_my_method :foo, :bar\nadd_my_method :baz"
+
+ tk = @parser.get_tk
+
+ @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'woo_hoo!', foo.name
+ assert_equal true, foo.singleton, 'singleton method'
+ assert_equal "##\n# my method\n", foo.comment
+ end
+
+ def test_parse_meta_method_string_name
+ klass = RDoc::NormalClass.new 'Foo'
+ comment = "##\n# my method\n"
+
+ util_parser "add_my_method 'foo'"
+
+ tk = @parser.get_tk
+
+ @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal comment, foo.comment
+ end
+
+ def test_parse_method
+ klass = RDoc::NormalClass.new 'Foo'
+ klass.parent = @top_level
+
+ comment = "##\n# my method\n"
+
+ util_parser "def foo() :bar end"
+
+ tk = @parser.get_tk
+
+ @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = klass.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal comment, foo.comment
+
+ assert_equal [], foo.aliases
+ assert_equal nil, foo.block_params
+ assert_equal nil, foo.call_seq
+ assert_equal nil, foo.is_alias_for
+ assert_equal nil, foo.viewer
+ assert_equal true, foo.document_children
+ assert_equal true, foo.document_self
+ assert_equal '()', foo.params
+ assert_equal false, foo.done_documenting
+ assert_equal false, foo.dont_rename_initialize
+ assert_equal false, foo.force_documentation
+ assert_equal klass, foo.parent
+ assert_equal false, foo.singleton
+ assert_equal :public, foo.visibility
+ assert_equal 'def foo', foo.text
+ assert_equal klass.current_section, foo.section
+
+ stream = [
+ tk(:COMMENT, 1, 1, nil, "# File #{@top_level.file_absolute_name}, line 1"),
+ RDoc::Parser::Ruby::NEWLINE_TOKEN,
+ tk(:SPACE, 1, 1, nil, ''),
+ tk(:DEF, 1, 0, 'def', 'def'),
+ tk(:SPACE, 1, 3, nil, ' '),
+ tk(:IDENTIFIER, 1, 4, 'foo', 'foo'),
+ tk(:LPAREN, 1, 7, nil, '('),
+ tk(:RPAREN, 1, 8, nil, ')'),
+ tk(:SPACE, 1, 9, nil, ' '),
+ tk(:COLON, 1, 10, nil, ':'),
+ tk(:IDENTIFIER, 1, 11, 'bar', 'bar'),
+ tk(:SPACE, 1, 14, nil, ' '),
+ tk(:END, 1, 15, 'end', 'end'),
+ ]
+
+ assert_equal stream, foo.token_stream
+ end
+
+ def test_parse_statements_class_nested
+ comment = "##\n# my method\n"
+
+ util_parser "module Foo\n#{comment}class Bar\nend\nend"
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.modules.first
+ assert_equal 'Foo', foo.full_name, 'module Foo'
+
+ bar = foo.classes.first
+ assert_equal 'Foo::Bar', bar.full_name, 'class Foo::Bar'
+ assert_equal comment, bar.comment
+ end
+
+ def test_parse_statements_identifier_meta_method
+ content = <<-EOF
+class Foo
+ ##
+ # this is my method
+ add_my_method :foo
+end
+ EOF
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.method_list.first
+ assert_equal 'foo', foo.name
+ end
+
+ def test_parse_statements_identifier_alias_method
+ content = "class Foo def foo() end; alias_method :foo2, :foo end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo2 = @top_level.classes.first.method_list.last
+ assert_equal 'foo2', foo2.name
+ assert_equal 'foo', foo2.is_alias_for.name
+ end
+
+ def test_parse_statements_identifier_attr
+ content = "class Foo; attr :foo; end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.attributes.first
+ assert_equal 'foo', foo.name
+ assert_equal 'R', foo.rw
+ end
+
+ def test_parse_statements_identifier_attr_accessor
+ content = "class Foo; attr_accessor :foo; end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.attributes.first
+ assert_equal 'foo', foo.name
+ assert_equal 'RW', foo.rw
+ end
+
+ def test_parse_statements_identifier_extra_accessors
+ @options.extra_accessors = /^my_accessor$/
+
+ content = "class Foo; my_accessor :foo; end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.attributes.first
+ assert_equal 'foo', foo.name
+ assert_equal '?', foo.rw
+ end
+
+ def test_parse_statements_identifier_include
+ content = "class Foo; include Bar; end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.name
+ assert_equal 1, foo.includes.length
+ end
+
+ def test_parse_statements_identifier_module_function
+ content = "module Foo def foo() end; module_function :foo; end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo, s_foo = @top_level.modules.first.method_list
+ assert_equal 'foo', foo.name, 'instance method name'
+ assert_equal :private, foo.visibility, 'instance method visibility'
+ assert_equal false, foo.singleton, 'instance method singleton'
+
+ assert_equal 'foo', s_foo.name, 'module function name'
+ assert_equal :public, s_foo.visibility, 'module function visibility'
+ assert_equal true, s_foo.singleton, 'module function singleton'
+ end
+
+ def test_parse_statements_identifier_private
+ content = "class Foo private; def foo() end end"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal :private, foo.visibility
+ end
+
+ def test_parse_statements_identifier_require
+ content = "require 'bar'"
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ assert_equal 1, @top_level.requires.length
+ end
+
+ def tk(klass, line, char, name, text)
+ klass = RDoc::RubyToken.const_get "Tk#{klass.to_s.upcase}"
+
+ token = if klass.instance_method(:initialize).arity == 2 then
+ raise ArgumentError, "name not used for #{klass}" unless name.nil?
+ klass.new line, char
+ else
+ klass.new line, char, name
+ end
+
+ token.set_text text
+
+ token
+ end
+
+ def util_parser(content)
+ @parser = RDoc::Parser::Ruby.new @top_level, @filename, content, @options,
+ @stats
+ end
+
+ def util_toplevel
+ RDoc::TopLevel.reset
+ @top_level = RDoc::TopLevel.new @filename
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_ri_attribute_formatter.rb b/trunk/test/rdoc/test_rdoc_ri_attribute_formatter.rb
new file mode 100644
index 0000000000..d61a6f5cbc
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_ri_attribute_formatter.rb
@@ -0,0 +1,42 @@
+require 'stringio'
+require 'test/unit'
+require 'rdoc/ri/formatter'
+
+class TestRDocRIAttributeFormatter < Test::Unit::TestCase
+
+ def setup
+ @output = StringIO.new
+ @width = 78
+ @indent = ' '
+
+ @f = RDoc::RI::AttributeFormatter.new @output, @width, @indent
+ end
+
+ def test_wrap_empty
+ @f.wrap ''
+ assert_equal '', @output.string
+ end
+
+ def test_wrap_long
+ @f.wrap 'a ' * (@width / 2)
+ assert_equal " a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \n a \n",
+ @output.string
+ end
+
+ def test_wrap_markup
+ @f.wrap 'a <tt>b</tt> c'
+ assert_equal " a b c\n", @output.string
+ end
+
+ def test_wrap_nil
+ @f.wrap nil
+ assert_equal '', @output.string
+ end
+
+ def test_wrap_short
+ @f.wrap 'a b c'
+ assert_equal " a b c\n", @output.string
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_ri_default_display.rb b/trunk/test/rdoc/test_rdoc_ri_default_display.rb
new file mode 100644
index 0000000000..97fa6c94ae
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_ri_default_display.rb
@@ -0,0 +1,296 @@
+require 'stringio'
+require 'test/unit'
+require 'rdoc/ri/formatter'
+require 'rdoc/ri/display'
+require 'rdoc/ri/driver'
+
+class TestRdocRiDefaultDisplay < Test::Unit::TestCase
+
+ def setup
+ @output = StringIO.new
+ @width = 78
+ @indent = ' '
+
+ @dd = RDoc::RI::DefaultDisplay.new RDoc::RI::Formatter, @width, true,
+ @output
+
+ @some_method = h \
+ 'aliases' => [{'name' => 'some_method_alias'}],
+ 'block_params' => 'block_param',
+ 'comment' => [RDoc::Markup::Flow::P.new('some comment')],
+ 'full_name' => 'SomeClass#some_method',
+ 'is_singleton' => false,
+ 'name' => 'some_method',
+ 'params' => '(arg1, arg2) {|block_param| ...}',
+ 'source_path' => '/nonexistent',
+ 'visibility' => 'public'
+ end
+
+ def test_display_class_info
+ ri_reader = nil
+ klass = h \
+ 'attributes' => [
+ { 'name' => 'attribute', 'rw' => 'RW',
+ 'comment' => [RDoc::Markup::Flow::P.new('attribute comment')] },
+ { 'name' => 'attribute_no_comment', 'rw' => 'RW',
+ 'comment' => nil },
+ ],
+ 'class_methods' => [
+ { 'name' => 'class_method' },
+ ],
+ 'class_method_extensions' => [
+ { 'name' => 'class_method_extension' },
+ ],
+ 'comment' => [RDoc::Markup::Flow::P.new('SomeClass comment')],
+ 'constants' => [
+ { 'name' => 'CONSTANT', 'value' => '"value"',
+ 'comment' => [RDoc::Markup::Flow::P.new('CONSTANT value')] },
+ { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value"',
+ 'comment' => nil },
+ ],
+ 'display_name' => 'Class',
+ 'full_name' => 'SomeClass',
+ 'includes' => [],
+ 'instance_methods' => [
+ { 'name' => 'instance_method' },
+ ],
+ 'instance_method_extensions' => [
+ { 'name' => 'instance_method_extension' },
+ ],
+ 'superclass_string' => 'Object'
+
+ @dd.display_class_info klass, ri_reader
+
+ expected = <<-EOF
+---------------------------------------------------- Class: SomeClass < Object
+ SomeClass comment
+
+------------------------------------------------------------------------------
+
+
+Constants:
+----------
+
+ CONSTANT:
+ CONSTANT value
+
+ CONSTANT_NOCOMMENT
+
+
+Class methods:
+--------------
+
+ class_method
+
+
+Class method extensions:
+------------------------
+
+ class_method_extension
+
+
+Instance methods:
+-----------------
+
+ instance_method
+
+
+Instance method extensions:
+---------------------------
+
+ instance_method_extension
+
+
+Attributes:
+-----------
+
+ attribute (RW):
+ attribute comment
+
+ attribute_no_comment (RW)
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_flow
+ flow = [RDoc::Markup::Flow::P.new('flow')]
+
+ @dd.display_flow flow
+
+ assert_equal " flow\n\n", @output.string
+ end
+
+ def test_display_flow_empty
+ @dd.display_flow []
+
+ assert_equal " [no description]\n", @output.string
+ end
+
+ def test_display_flow_nil
+ @dd.display_flow nil
+
+ assert_equal " [no description]\n", @output.string
+ end
+
+ def test_display_method_info
+ @dd.display_method_info @some_method
+
+ expected = <<-EOF
+-------------------------------------------------------- SomeClass#some_method
+ some_method(arg1, arg2) {|block_param| ...}
+
+ Extension from /nonexistent
+------------------------------------------------------------------------------
+ some comment
+
+
+ (also known as some_method_alias)
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_method_info_singleton
+ method = RDoc::RI::Driver::Hash.new.update \
+ 'aliases' => [],
+ 'block_params' => nil,
+ 'comment' => nil,
+ 'full_name' => 'SomeClass::some_method',
+ 'is_singleton' => true,
+ 'name' => 'some_method',
+ 'params' => '(arg1, arg2)',
+ 'visibility' => 'public'
+
+ @dd.display_method_info method
+
+ expected = <<-EOF
+------------------------------------------------------- SomeClass::some_method
+ SomeClass::some_method(arg1, arg2)
+------------------------------------------------------------------------------
+ [no description]
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_method_list
+ methods = [
+ RDoc::RI::Driver::Hash.new.update(
+ "aliases" => [],
+ "block_params" => nil,
+ "comment" => nil,
+ "full_name" => "SomeClass#some_method",
+ "is_singleton" => false,
+ "name" => "some_method",
+ "params" => "()",
+ "visibility" => "public"
+ ),
+ RDoc::RI::Driver::Hash.new.update(
+ "aliases" => [],
+ "block_params" => nil,
+ "comment" => nil,
+ "full_name" => "SomeClass#some_other_method",
+ "is_singleton" => false,
+ "name" => "some_other_method",
+ "params" => "()",
+ "visibility" => "public"
+ ),
+ ]
+
+ @dd.display_method_list methods
+
+ expected = <<-EOF
+ More than one method matched your request. You can refine your search by
+ asking for information on one of:
+
+ SomeClass#some_method, SomeClass#some_other_method
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_params
+ @dd.display_params @some_method
+
+ expected = <<-EOF
+ some_method(arg1, arg2) {|block_param| ...}
+
+ Extension from /nonexistent
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_params_multiple
+ @some_method['params'] = <<-EOF
+some_method(index)
+some_method(start, length)
+ EOF
+
+ @dd.display_params @some_method
+
+ expected = <<-EOF
+ some_method(index)
+ some_method(start, length)
+
+ Extension from /nonexistent
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_display_params_singleton
+ @some_method['is_singleton'] = true
+ @some_method['full_name'] = 'SomeClass::some_method'
+
+ @dd.display_params @some_method
+
+ expected = <<-EOF
+ SomeClass::some_method(arg1, arg2) {|block_param| ...}
+
+ Extension from /nonexistent
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_list_known_classes
+ klasses = %w[SomeClass SomeModule]
+
+ @dd.list_known_classes klasses
+
+ expected = <<-EOF
+---------------------------------------------------- Known classes and modules
+
+ SomeClass, SomeModule
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def test_list_known_classes_empty
+ @dd.list_known_classes []
+
+ expected = <<-EOF
+No ri data found
+
+If you've installed Ruby yourself, you need to generate documentation using:
+
+ make install-doc
+
+from the same place you ran `make` to build ruby.
+
+If you installed Ruby from a packaging system, then you may need to
+install an additional package, or ask the packager to enable ri generation.
+ EOF
+
+ assert_equal expected, @output.string
+ end
+
+ def h(hash)
+ RDoc::RI::Driver::Hash.convert hash
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_ri_driver.rb b/trunk/test/rdoc/test_rdoc_ri_driver.rb
new file mode 100644
index 0000000000..cddd4e60d1
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_ri_driver.rb
@@ -0,0 +1,92 @@
+require 'test/unit'
+require 'tmpdir'
+require 'rdoc/ri/driver'
+
+class TestRDocRIDriver < Test::Unit::TestCase
+
+ def setup
+ @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_driver_#{$$}"
+ @home_ri = File.join @tmpdir, 'dot_ri'
+ @cache_dir = File.join @home_ri, 'cache'
+ @class_cache = File.join @cache_dir, 'classes'
+
+ FileUtils.mkdir_p @tmpdir
+ FileUtils.mkdir_p @home_ri
+ FileUtils.mkdir_p @cache_dir
+
+ @driver = RDoc::RI::Driver.new
+ @driver.homepath = @home_ri
+ end
+
+ def teardown
+ FileUtils.rm_rf @tmpdir
+ end
+
+ def test_lookup_method
+ def @driver.load_cache_for(klassname)
+ { 'Foo#bar' => :found }
+ end
+
+ assert @driver.lookup_method('Foo#bar', 'Foo')
+ end
+
+ def test_lookup_method_class_method
+ def @driver.load_cache_for(klassname)
+ { 'Foo::Bar' => :found }
+ end
+
+ assert @driver.lookup_method('Foo::Bar', 'Foo::Bar')
+ end
+
+ def test_lookup_method_class_missing
+ def @driver.load_cache_for(klassname) end
+
+ assert_nil @driver.lookup_method('Foo#bar', 'Foo')
+ end
+
+ def test_lookup_method_dot_instance
+ def @driver.load_cache_for(klassname)
+ { 'Foo#bar' => :instance, 'Foo::bar' => :klass }
+ end
+
+ assert_equal :instance, @driver.lookup_method('Foo.bar', 'Foo')
+ end
+
+ def test_lookup_method_dot_class
+ def @driver.load_cache_for(klassname)
+ { 'Foo::bar' => :found }
+ end
+
+ assert @driver.lookup_method('Foo.bar', 'Foo')
+ end
+
+ def test_lookup_method_method_missing
+ def @driver.load_cache_for(klassname) {} end
+
+ assert_nil @driver.lookup_method('Foo#bar', 'Foo')
+ end
+
+ def test_parse_name
+ klass, meth = @driver.parse_name 'Foo::Bar'
+
+ assert_equal 'Foo::Bar', klass, 'Foo::Bar class'
+ assert_equal nil, meth, 'Foo::Bar method'
+
+ klass, meth = @driver.parse_name 'Foo#Bar'
+
+ assert_equal 'Foo', klass, 'Foo#Bar class'
+ assert_equal 'Bar', meth, 'Foo#Bar method'
+
+ klass, meth = @driver.parse_name 'Foo.Bar'
+
+ assert_equal 'Foo', klass, 'Foo#Bar class'
+ assert_equal 'Bar', meth, 'Foo#Bar method'
+
+ klass, meth = @driver.parse_name 'Foo::bar'
+
+ assert_equal 'Foo', klass, 'Foo::bar class'
+ assert_equal 'bar', meth, 'Foo::bar method'
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_ri_formatter.rb b/trunk/test/rdoc/test_rdoc_ri_formatter.rb
new file mode 100644
index 0000000000..ed2ccba22d
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_ri_formatter.rb
@@ -0,0 +1,318 @@
+require 'stringio'
+require 'test/unit'
+require 'rdoc/ri/formatter'
+require 'rdoc/markup/to_flow'
+
+class TestRDocRIFormatter < Test::Unit::TestCase
+
+ def setup
+ @output = StringIO.new
+ @width = 78
+ @indent = ' '
+
+ @f = RDoc::RI::Formatter.new @output, @width, @indent
+ @markup = RDoc::Markup.new
+ @flow = RDoc::Markup::ToFlow.new
+ end
+
+ def test_blankline
+ @f.blankline
+
+ assert_equal "\n", @output.string
+ end
+
+ def test_bold_print
+ @f.bold_print 'a b c'
+
+ assert_equal 'a b c', @output.string
+ end
+
+ def test_break_to_newline
+ @f.break_to_newline
+
+ assert_equal '', @output.string
+ end
+
+ def test_conv_html
+ assert_equal '> < " &', @f.conv_html('&gt; &lt; &quot; &amp;')
+ end
+
+ def test_conv_markup
+ text = '<tt>a</tt> <code>b</code> <b>c</b> <em>d</em>'
+
+ expected = '+a+ +b+ *c* _d_'
+
+ assert_equal expected, @f.conv_markup(text)
+ end
+
+ def test_display_flow
+ flow = [
+ RDoc::Markup::Flow::H.new(1, 'heading'),
+ RDoc::Markup::Flow::P.new('paragraph'),
+ ]
+
+ @f.display_flow flow
+
+ assert_equal "\nHEADING\n=======\n\n paragraph\n\n", @output.string
+ end
+
+ def test_display_flow_item_h
+ item = RDoc::Markup::Flow::H.new 1, 'heading'
+
+ @f.display_flow_item item
+
+ assert_equal "\nHEADING\n=======\n\n", @output.string
+ end
+
+ def test_display_flow_item_li
+ item = RDoc::Markup::Flow::LI.new nil, 'paragraph'
+
+ @f.display_flow_item item
+
+ assert_equal " paragraph\n\n", @output.string
+ end
+
+ def test_display_flow_item_list
+ item = RDoc::Markup::Flow::LIST.new :NUMBER
+
+ @f.display_flow_item item
+
+ assert_equal "", @output.string
+ end
+
+ def test_display_flow_item_p
+ item = RDoc::Markup::Flow::P.new 'paragraph'
+
+ @f.display_flow_item item
+
+ assert_equal " paragraph\n\n", @output.string
+ end
+
+ def test_display_flow_item_rule
+ item = RDoc::Markup::Flow::RULE.new 1
+
+ @f.display_flow_item item
+
+ assert_equal "#{'-' * 78}\n", @output.string
+ end
+
+ def test_display_flow_item_unknown
+ e = assert_raise RDoc::Error do
+ @f.display_flow_item Object.new
+ end
+
+ assert_equal "Unknown flow element: Object", e.message
+ end
+
+ def test_display_flow_item_verb
+ item = RDoc::Markup::Flow::VERB.new 'a b c'
+
+ @f.display_flow_item item
+
+ assert_equal " a b c\n\n", @output.string
+ end
+
+ def test_display_heading_1
+ @f.display_heading 'heading', 1, ' '
+
+ assert_equal "\nHEADING\n=======\n\n", @output.string
+ end
+
+ def test_display_heading_2
+ @f.display_heading 'heading', 2, ' '
+
+ assert_equal "\nheading\n-------\n\n", @output.string
+ end
+
+ def test_display_heading_3
+ @f.display_heading 'heading', 3, ' '
+
+ assert_equal " heading\n\n", @output.string
+ end
+
+ def test_display_list
+ list = RDoc::Markup::Flow::LIST.new :NUMBER
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+ list << RDoc::Markup::Flow::LI.new(nil, 'd e f')
+
+ @f.display_list list
+
+ assert_equal " 1. a b c\n\n 2. d e f\n\n", @output.string
+ end
+
+ def test_display_list_bullet
+ list = RDoc::Markup::Flow::LIST.new :BULLET
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+
+ @f.display_list list
+
+ assert_equal " * a b c\n\n", @output.string
+ end
+
+ def test_display_list_labeled
+ list = RDoc::Markup::Flow::LIST.new :LABELED
+ list << RDoc::Markup::Flow::LI.new('label', 'a b c')
+
+ @f.display_list list
+
+ assert_equal " label a b c\n\n", @output.string
+ end
+
+ def test_display_list_lower_alpha
+ list = RDoc::Markup::Flow::LIST.new :LOWERALPHA
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+
+ @f.display_list list
+
+ assert_equal " a. a b c\n\n", @output.string
+ end
+
+ def test_display_list_note
+ list = RDoc::Markup::Flow::LIST.new :NOTE
+ list << RDoc::Markup::Flow::LI.new('note:', 'a b c')
+
+ @f.display_list list
+
+ assert_equal " note: a b c\n\n", @output.string
+ end
+
+ def test_display_list_number
+ list = RDoc::Markup::Flow::LIST.new :NUMBER
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+
+ @f.display_list list
+
+ assert_equal " 1. a b c\n\n", @output.string
+ end
+
+ def test_display_list_unknown
+ list = RDoc::Markup::Flow::LIST.new :UNKNOWN
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+
+ e = assert_raise ArgumentError do
+ @f.display_list list
+ end
+
+ assert_equal 'unknown list type UNKNOWN', e.message
+ end
+
+ def test_display_list_upper_alpha
+ list = RDoc::Markup::Flow::LIST.new :UPPERALPHA
+ list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
+
+ @f.display_list list
+
+ assert_equal " A. a b c\n\n", @output.string
+ end
+
+ def test_display_verbatim_flow_item
+ verbatim = RDoc::Markup::Flow::VERB.new "a b c\nd e f"
+
+ @f.display_verbatim_flow_item verbatim
+
+ assert_equal " a b c\n d e f\n\n", @output.string
+ end
+
+ def test_display_verbatim_flow_item_bold
+ verbatim = RDoc::Markup::Flow::VERB.new "*a* b c"
+
+ @f.display_verbatim_flow_item verbatim
+
+ assert_equal " *a* b c\n\n", @output.string
+ end
+
+ def test_draw_line
+ @f.draw_line
+
+ expected = '-' * @width + "\n"
+ assert_equal expected, @output.string
+ end
+
+ def test_draw_line_label
+ @f.draw_line 'label'
+
+ expected = '-' * (@width - 6) + " label\n"
+ assert_equal expected, @output.string
+ end
+
+ def test_draw_line_label_long
+ @f.draw_line 'a' * @width
+
+ expected = '-' * @width + "\n" + ('a' * @width) + "\n"
+ assert_equal expected, @output.string
+ end
+
+ def test_raw_print_line
+ @f.raw_print_line 'a b c'
+
+ assert_equal "a b c\n", @output.string
+ end
+
+ def test_strip_attributes_b
+ text = @f.strip_attributes 'hello <b>world</b>'
+
+ expected = 'hello world'
+
+ assert_equal expected, text
+ end
+
+ def test_strip_attributes_code
+ text = @f.strip_attributes 'hello <code>world</code>'
+
+ expected = 'hello world'
+
+ assert_equal expected, text
+ end
+
+ def test_strip_attributes_em
+ text = @f.strip_attributes 'hello <em>world</em>'
+
+ expected = 'hello world'
+
+ assert_equal expected, text
+ end
+
+ def test_strip_attributes_i
+ text = @f.strip_attributes 'hello <i>world</i>'
+
+ expected = 'hello world'
+
+ assert_equal expected, text
+ end
+
+ def test_strip_attributes_tt
+ text = @f.strip_attributes 'hello <tt>world</tt>'
+
+ expected = 'hello world'
+
+ assert_equal expected, text
+ end
+
+ def test_wrap_empty
+ @f.wrap ''
+ assert_equal '', @output.string
+ end
+
+ def test_wrap_long
+ @f.wrap 'a ' * (@width / 2)
+ assert_equal " a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a\n a \n",
+ @output.string
+ end
+
+ def test_wrap_markup
+ @f.wrap 'a <tt>b</tt> c'
+ assert_equal " a +b+ c\n", @output.string
+ end
+
+ def test_wrap_nil
+ @f.wrap nil
+ assert_equal '', @output.string
+ end
+
+ def test_wrap_short
+ @f.wrap 'a b c'
+ assert_equal " a b c\n", @output.string
+ end
+
+end
+
diff --git a/trunk/test/rdoc/test_rdoc_ri_overstrike_formatter.rb b/trunk/test/rdoc/test_rdoc_ri_overstrike_formatter.rb
new file mode 100644
index 0000000000..050e92a4fe
--- /dev/null
+++ b/trunk/test/rdoc/test_rdoc_ri_overstrike_formatter.rb
@@ -0,0 +1,69 @@
+require 'stringio'
+require 'test/unit'
+require 'rdoc/ri/formatter'
+require 'rdoc/markup/fragments'
+require 'rdoc/markup/to_flow'
+
+class TestRDocRIOverstrikeFormatter < Test::Unit::TestCase
+
+ def setup
+ @output = StringIO.new
+ @width = 78
+ @indent = ' '
+
+ @f = RDoc::RI::OverstrikeFormatter.new @output, @width, @indent
+ @markup = RDoc::Markup.new
+ @flow = RDoc::Markup::ToFlow.new
+
+ @af = RDoc::RI::AttributeFormatter
+ end
+
+ def test_display_verbatim_flow_item_bold
+ verbatim = RDoc::Markup::Flow::VERB.new "*a* b c"
+
+ @f.display_verbatim_flow_item verbatim
+
+ assert_equal " *a* b c\n\n", @output.string
+ end
+
+ def test_write_attribute_text_bold
+ line = [RDoc::RI::AttributeFormatter::AttrChar.new('b', @af::BOLD)]
+
+ @f.write_attribute_text ' ', line
+
+ assert_equal " b\bb\n", @output.string
+ end
+
+ def test_write_attribute_text_bold_italic
+ attr = @af::BOLD | @af::ITALIC
+ line = [RDoc::RI::AttributeFormatter::AttrChar.new('d', attr)]
+
+ @f.write_attribute_text ' ', line
+
+ assert_equal " _\bd\bd\n", @output.string
+ end
+
+ def test_write_attribute_text_code
+ line = [RDoc::RI::AttributeFormatter::AttrChar.new('c', @af::CODE)]
+
+ @f.write_attribute_text ' ', line
+
+ assert_equal " _\bc\n", @output.string
+ end
+
+ def test_write_attribute_text_italic
+ line = [RDoc::RI::AttributeFormatter::AttrChar.new('a', @af::ITALIC)]
+
+ @f.write_attribute_text ' ', line
+
+ assert_equal " _\ba\n", @output.string
+ end
+
+ def test_bold_print
+ @f.bold_print 'a b c'
+
+ assert_equal "a\ba \b b\bb \b c\bc", @output.string
+ end
+
+end
+
diff --git a/trunk/test/readline/test_readline.rb b/trunk/test/readline/test_readline.rb
new file mode 100644
index 0000000000..071accf68b
--- /dev/null
+++ b/trunk/test/readline/test_readline.rb
@@ -0,0 +1,233 @@
+begin
+ require "readline"
+=begin
+ class << Readline
+ [
+ "vi_editing_mode",
+ "emacs_editing_mode",
+ "completion_append_character=",
+ "completion_append_character",
+ "basic_word_break_characters=",
+ "basic_word_break_characters",
+ "completer_word_break_characters=",
+ "completer_word_break_characters",
+ "basic_quote_characters=",
+ "basic_quote_characters",
+ "completer_quote_characters=",
+ "completer_quote_characters",
+ "filename_quote_characters=",
+ "filename_quote_characters",
+ ].each do |method_name|
+ define_method(method_name.to_sym) do |*args|
+ raise NotImplementedError
+ end
+ end
+ end
+=end
+rescue LoadError
+else
+ require "test/unit"
+ require "tempfile"
+end
+
+class TestReadline < Test::Unit::TestCase
+ def teardown
+ Readline.instance_variable_set("@completion_proc", nil)
+ end
+
+ def test_safe_level_4
+ method_args =
+ [
+ ["readline"],
+ ["input=", $stdin],
+ ["output=", $stdout],
+ ["completion_proc=", proc {}],
+ ["completion_proc"],
+ ["completion_case_fold=", true],
+ ["completion_case_fold"],
+ ["vi_editing_mode"],
+ ["vi_editing_mode?"],
+ ["emacs_editing_mode"],
+ ["emacs_editing_mode?"],
+ ["completion_append_character=", "s"],
+ ["completion_append_character"],
+ ["basic_word_break_characters=", "s"],
+ ["basic_word_break_characters"],
+ ["completer_word_break_characters=", "s"],
+ ["completer_word_break_characters"],
+ ["basic_quote_characters=", "\\"],
+ ["basic_quote_characters"],
+ ["completer_quote_characters=", "\\"],
+ ["completer_quote_characters"],
+ ["filename_quote_characters=", "\\"],
+ ["filename_quote_characters"],
+ ]
+ method_args.each do |method_name, *args|
+ assert_raises(SecurityError, NotImplementedError,
+ "method=<#{method_name}>") do
+ Thread.start {
+ $SAFE = 4
+ Readline.send(method_name.to_sym, *args)
+ assert(true)
+ }.join
+ end
+ end
+ end
+
+ def test_readline
+ stdin = Tempfile.new("test_readline_stdin")
+ stdout = Tempfile.new("test_readline_stdout")
+ begin
+ stdin.write("hello\n")
+ stdin.close
+ stdout.close
+ line = replace_stdio(stdin.path, stdout.path) {
+ Readline.readline("> ", true)
+ }
+ assert_equal("hello", line)
+ assert_equal(true, line.tainted?)
+ stdout.open
+ assert_equal("> ", stdout.read(2))
+ assert_equal(1, Readline::HISTORY.length)
+ assert_equal("hello", Readline::HISTORY[0])
+ assert_raises(SecurityError) do
+ Thread.start {
+ $SAFE = 1
+ replace_stdio(stdin.path, stdout.path) do
+ Readline.readline("> ".taint)
+ end
+ }.join
+ end
+ assert_raises(SecurityError) do
+ Thread.start {
+ $SAFE = 4
+ replace_stdio(stdin.path, stdout.path) { Readline.readline("> ") }
+ }.join
+ end
+ ensure
+ stdin.close(true)
+ stdout.close(true)
+ end
+ end if !/EditLine/n.match(Readline::VERSION)
+
+ def test_input=
+ assert_raise(TypeError) do
+ Readline.input = "This is not a file."
+ end
+ end
+
+ def test_output=
+ assert_raise(TypeError) do
+ Readline.output = "This is not a file."
+ end
+ end
+
+ def test_completion_proc
+ expected = proc { |input| input }
+ Readline.completion_proc = expected
+ assert_equal(expected, Readline.completion_proc)
+
+ assert_raise(ArgumentError) do
+ Readline.completion_proc = "This does not have call method."
+ end
+ end
+
+ def test_completion_case_fold
+ expected = [true, false, "string", {"a" => "b"}]
+ expected.each do |e|
+ Readline.completion_case_fold = e
+ assert_equal(e, Readline.completion_case_fold)
+ end
+ end
+
+ # vi_editing_mode
+ # emacs_editing_mode
+ def test_editing_mode
+ begin
+ assert_equal(false, Readline.vi_editing_mode?)
+ assert_equal(true, Readline.emacs_editing_mode?)
+
+ assert_equal(nil, Readline.vi_editing_mode)
+ assert_equal(true, Readline.vi_editing_mode?)
+ assert_equal(false, Readline.emacs_editing_mode?)
+ assert_equal(nil, Readline.vi_editing_mode)
+ assert_equal(true, Readline.vi_editing_mode?)
+ assert_equal(false, Readline.emacs_editing_mode?)
+
+ assert_equal(nil, Readline.emacs_editing_mode)
+ assert_equal(false, Readline.vi_editing_mode?)
+ assert_equal(true, Readline.emacs_editing_mode?)
+ assert_equal(nil, Readline.emacs_editing_mode)
+ assert_equal(false, Readline.vi_editing_mode?)
+ assert_equal(true, Readline.emacs_editing_mode?)
+ rescue NotImplementedError
+ end
+ end
+
+ def test_completion_append_character
+ begin
+ Readline.completion_append_character = "x"
+ assert_equal("x", Readline.completion_append_character)
+ Readline.completion_append_character = "xyz"
+ assert_equal("x", Readline.completion_append_character)
+ Readline.completion_append_character = nil
+ assert_equal(nil, Readline.completion_append_character)
+ Readline.completion_append_character = ""
+ assert_equal(nil, Readline.completion_append_character)
+ rescue NotImplementedError
+ end
+ end
+
+ # basic_word_break_characters
+ # completer_word_break_characters
+ # basic_quote_characters
+ # completer_quote_characters
+ # filename_quote_characters
+ def test_some_characters_methods
+ method_names = [
+ "basic_word_break_characters",
+ "completer_word_break_characters",
+ "basic_quote_characters",
+ "completer_quote_characters",
+ "filename_quote_characters",
+ ]
+ method_names.each do |method_name|
+ begin
+ begin
+ saved = Readline.send(method_name.to_sym)
+ expecteds = [" ", " .,|\t", ""]
+ expecteds.each do |e|
+ Readline.send((method_name + "=").to_sym, e)
+ assert_equal(e, Readline.send(method_name.to_sym))
+ end
+ ensure
+ Readline.send((method_name + "=").to_sym, saved) if saved
+ end
+ rescue NotImplementedError
+ end
+ end
+ end
+
+ private
+
+ def replace_stdio(stdin_path, stdout_path)
+ open(stdin_path, "r"){|stdin|
+ open(stdout_path, "w"){|stdout|
+ orig_stdin = STDIN.dup
+ orig_stdout = STDOUT.dup
+ STDIN.reopen(stdin)
+ STDOUT.reopen(stdout)
+ begin
+ Readline.input = STDIN
+ Readline.output = STDOUT
+ yield
+ ensure
+ STDIN.reopen(orig_stdin)
+ STDOUT.reopen(orig_stdout)
+ orig_stdin.close
+ orig_stdout.close
+ end
+ }
+ }
+ end
+end if defined?(::Readline)
diff --git a/trunk/test/readline/test_readline_history.rb b/trunk/test/readline/test_readline_history.rb
new file mode 100644
index 0000000000..8033a9a827
--- /dev/null
+++ b/trunk/test/readline/test_readline_history.rb
@@ -0,0 +1,313 @@
+begin
+ require "readline"
+=begin
+ class << Readline::HISTORY
+ def []=(index, str)
+ raise NotImplementedError
+ end
+
+ def pop
+ raise NotImplementedError
+ end
+
+ def shift
+ raise NotImplementedError
+ end
+
+ def delete_at(index)
+ raise NotImplementedError
+ end
+ end
+=end
+
+=begin
+ class << Readline::HISTORY
+ def clear
+ raise NotImplementedError
+ end
+ end
+=end
+rescue LoadError
+else
+ require "test/unit"
+end
+
+class Readline::TestHistory < Test::Unit::TestCase
+ include Readline
+
+ def setup
+ HISTORY.clear
+ end
+
+ def test_safe_level_4
+ method_args =
+ [
+ ["[]", [0]],
+ ["[]=", [0, "s"]],
+ ["\<\<", ["s"]],
+ ["push", ["s"]],
+ ["pop", []],
+ ["shift", []],
+ ["length", []],
+ ["delete_at", [0]],
+ ["clear", []],
+ ]
+ method_args.each do |method_name, args|
+ assert_raises(SecurityError, NotImplementedError,
+ "method=<#{method_name}>") do
+ Thread.start {
+ $SAFE = 4
+ HISTORY.send(method_name.to_sym, *args)
+ assert(true)
+ }.join
+ end
+ end
+
+ assert_raises(SecurityError, NotImplementedError,
+ "method=<each>") do
+ Thread.start {
+ $SAFE = 4
+ HISTORY.each { |s|
+ assert(true)
+ }
+ }.join
+ end
+ end
+
+ def test_to_s
+ assert_equal("HISTORY", HISTORY.to_s)
+ end
+
+ def test_get
+ lines = push_history(5)
+ lines.each_with_index do |s, i|
+ assert_equal(s, HISTORY[i])
+ end
+ end
+
+ def test_get__negative
+ lines = push_history(5)
+ (1..5).each do |i|
+ assert_equal(lines[-i], HISTORY[-i])
+ end
+ end
+
+ def test_get__out_of_range
+ lines = push_history(5)
+ invalid_indexes = [5, 6, 100, -6, -7, -100]
+ invalid_indexes.each do |i|
+ assert_raise(IndexError, "i=<#{i}>") do
+ HISTORY[i]
+ end
+ end
+
+ invalid_indexes = [100_000_000_000_000_000_000,
+ -100_000_000_000_000_000_000]
+ invalid_indexes.each do |i|
+ assert_raise(RangeError, "i=<#{i}>") do
+ HISTORY[i]
+ end
+ end
+ end
+
+ def test_set
+ begin
+ lines = push_history(5)
+ 5.times do |i|
+ expected = "set: #{i}"
+ HISTORY[i] = expected
+ assert_equal(expected, HISTORY[i])
+ end
+ rescue NotImplementedError
+ end
+ end
+
+ def test_set__out_of_range
+ assert_raises(IndexError, NotImplementedError, "index=<0>") do
+ HISTORY[0] = "set: 0"
+ end
+
+ lines = push_history(5)
+ invalid_indexes = [5, 6, 100, -6, -7, -100]
+ invalid_indexes.each do |i|
+ assert_raises(IndexError, NotImplementedError, "index=<#{i}>") do
+ HISTORY[i] = "set: #{i}"
+ end
+ end
+
+ invalid_indexes = [100_000_000_000_000_000_000,
+ -100_000_000_000_000_000_000]
+ invalid_indexes.each do |i|
+ assert_raise(RangeError, NotImplementedError, "index=<#{i}>") do
+ HISTORY[i] = "set: #{i}"
+ end
+ end
+ end
+
+ def test_push
+ 5.times do |i|
+ assert_equal(HISTORY, HISTORY.push(i.to_s))
+ assert_equal(i.to_s, HISTORY[i])
+ end
+ assert_equal(5, HISTORY.length)
+ end
+
+ def test_push__operator
+ 5.times do |i|
+ assert_equal(HISTORY, HISTORY << i.to_s)
+ assert_equal(i.to_s, HISTORY[i])
+ end
+ assert_equal(5, HISTORY.length)
+ end
+
+ def test_push__plural
+ assert_equal(HISTORY, HISTORY.push("0", "1", "2", "3", "4"))
+ (0..4).each do |i|
+ assert_equal(i.to_s, HISTORY[i])
+ end
+ assert_equal(5, HISTORY.length)
+
+ assert_equal(HISTORY, HISTORY.push("5", "6", "7", "8", "9"))
+ (5..9).each do |i|
+ assert_equal(i.to_s, HISTORY[i])
+ end
+ assert_equal(10, HISTORY.length)
+ end
+
+ def test_pop
+ begin
+ assert_equal(nil, HISTORY.pop)
+
+ lines = push_history(5)
+ (1..5).each do |i|
+ assert_equal(lines[-i], HISTORY.pop)
+ assert_equal(lines.length - i, HISTORY.length)
+ end
+
+ assert_equal(nil, HISTORY.pop)
+ rescue NotImplementedError
+ end
+ end
+
+ def test_shift
+ begin
+ assert_equal(nil, HISTORY.shift)
+
+ lines = push_history(5)
+ (0..4).each do |i|
+ assert_equal(lines[i], HISTORY.shift)
+ assert_equal(lines.length - (i + 1), HISTORY.length)
+ end
+
+ assert_equal(nil, HISTORY.shift)
+ rescue NotImplementedError
+ end
+ end
+
+ def test_each
+ HISTORY.each do |s|
+ assert(false) # not reachable
+ end
+ lines = push_history(5)
+ i = 0
+ HISTORY.each do |s|
+ assert_equal(HISTORY[i], s)
+ assert_equal(lines[i], s)
+ i += 1
+ end
+ end
+
+ def test_each__enumerator
+ e = HISTORY.each
+ assert_instance_of(Enumerator, e)
+ end
+
+ def test_length
+ assert_equal(0, HISTORY.length)
+ push_history(1)
+ assert_equal(1, HISTORY.length)
+ push_history(4)
+ assert_equal(5, HISTORY.length)
+ HISTORY.clear
+ assert_equal(0, HISTORY.length)
+ end
+
+ def test_empty_p
+ 2.times do
+ assert(HISTORY.empty?)
+ HISTORY.push("s")
+ assert_equal(false, HISTORY.empty?)
+ HISTORY.clear
+ assert(HISTORY.empty?)
+ end
+ end
+
+ def test_delete_at
+ begin
+ lines = push_history(5)
+ (0..4).each do |i|
+ assert_equal(lines[i], HISTORY.delete_at(0))
+ end
+ assert(HISTORY.empty?)
+
+ lines = push_history(5)
+ (1..5).each do |i|
+ assert_equal(lines[lines.length - i], HISTORY.delete_at(-1))
+ end
+ assert(HISTORY.empty?)
+
+ lines = push_history(5)
+ assert_equal(lines[0], HISTORY.delete_at(0))
+ assert_equal(lines[4], HISTORY.delete_at(3))
+ assert_equal(lines[1], HISTORY.delete_at(0))
+ assert_equal(lines[3], HISTORY.delete_at(1))
+ assert_equal(lines[2], HISTORY.delete_at(0))
+ assert(HISTORY.empty?)
+ rescue NotImplementedError
+ end
+ end
+
+ def test_delete_at__out_of_range
+ assert_raises(IndexError, NotImplementedError, "index=<0>") do
+ HISTORY.delete_at(0)
+ end
+
+ lines = push_history(5)
+ invalid_indexes = [5, 6, 100, -6, -7, -100]
+ invalid_indexes.each do |i|
+ assert_raises(IndexError, NotImplementedError, "index=<#{i}>") do
+ HISTORY.delete_at(i)
+ end
+ end
+
+ invalid_indexes = [100_000_000_000_000_000_000,
+ -100_000_000_000_000_000_000]
+ invalid_indexes.each do |i|
+ assert_raises(RangeError, NotImplementedError, "index=<#{i}>") do
+ HISTORY.delete_at(i)
+ end
+ end
+ end
+
+ private
+
+ def push_history(num)
+ lines = []
+ num.times do |i|
+ s = "a"
+ i.times do
+ s = s.succ
+ end
+ lines.push("#{i + 1}:#{s}")
+ end
+ HISTORY.push(*lines)
+ return lines
+ end
+end if defined?(::Readline) && defined?(::Readline::HISTORY) &&
+ (
+ begin
+ Readline::HISTORY.clear
+ rescue NotImplementedError
+ false
+ end
+ )
diff --git a/trunk/test/rinda/test_rinda.rb b/trunk/test/rinda/test_rinda.rb
new file mode 100644
index 0000000000..14d3c31499
--- /dev/null
+++ b/trunk/test/rinda/test_rinda.rb
@@ -0,0 +1,544 @@
+require 'test/unit'
+
+require 'drb/drb'
+require 'drb/eq'
+require 'rinda/tuplespace'
+
+require 'singleton'
+
+module Rinda
+
+class MockClock
+ include Singleton
+
+ class MyTS < Rinda::TupleSpace
+ def keeper_thread
+ nil
+ end
+ end
+
+ def initialize
+ @now = 2
+ @reso = 1
+ @ts = MyTS.new
+ @ts.write([2, :now])
+ @inf = 2**31 - 1
+ end
+
+ def now
+ @now.to_f
+ end
+
+ def at(n)
+ n
+ end
+
+ def _forward(n=nil)
+ now ,= @ts.take([nil, :now])
+ @now = now + n
+ n = @reso if n.nil?
+ @ts.write([@now, :now])
+ end
+
+ def forward(n)
+ while n > 0
+ _forward(@reso)
+ n -= @reso
+ Thread.pass
+ end
+ end
+
+ def rewind
+ now ,= @ts.take([nil, :now])
+ @ts.write([@inf, :now])
+ @ts.take([nil, :now])
+ @now = 2
+ @ts.write([2, :now])
+ end
+
+ def sleep(n=nil)
+ now ,= @ts.read([nil, :now])
+ @ts.read([(now + n)..@inf, :now])
+ 0
+ end
+end
+
+module Time
+ def sleep(n)
+ @m.sleep(n)
+ end
+ module_function :sleep
+
+ def at(n)
+ n
+ end
+ module_function :at
+
+ def now
+ @m ? @m.now : 2
+ end
+ module_function :now
+
+ def rewind
+ @m.rewind
+ end
+ module_function :rewind
+
+ def forward(n)
+ @m.forward(n)
+ end
+ module_function :forward
+
+ @m = MockClock.instance
+end
+
+class TupleSpace
+ def sleep(n)
+ Time.sleep(n)
+ end
+end
+
+module TupleSpaceTestModule
+ def sleep(n)
+ if Thread.current == Thread.main
+ Time.forward(n)
+ else
+ Time.sleep(n)
+ end
+ end
+
+ def thread_join(th)
+ while th.alive?
+ Kernel.sleep(0.1)
+ sleep(1)
+ end
+ th.value
+ end
+
+ def test_00_tuple
+ tuple = Rinda::TupleEntry.new([1,2,3])
+ assert(!tuple.canceled?)
+ assert(!tuple.expired?)
+ assert(tuple.alive?)
+ end
+
+ def test_00_template
+ tmpl = Rinda::Template.new([1,2,3])
+ assert_equal(3, tmpl.size)
+ assert_equal(3, tmpl[2])
+ assert(tmpl.match([1,2,3]))
+ assert(!tmpl.match([1,nil,3]))
+
+ tmpl = Rinda::Template.new([/^rinda/i, nil, :hello])
+ assert_equal(3, tmpl.size)
+ assert(tmpl.match(['Rinda', 2, :hello]))
+ assert(!tmpl.match(['Rinda', 2, Symbol]))
+ assert(!tmpl.match([1, 2, :hello]))
+ assert(tmpl.match([/^rinda/i, 2, :hello]))
+
+ tmpl = Rinda::Template.new([Symbol])
+ assert_equal(1, tmpl.size)
+ assert(tmpl.match([:hello]))
+ assert(tmpl.match([Symbol]))
+ assert(!tmpl.match(['Symbol']))
+
+ tmpl = Rinda::Template.new({"message"=>String, "name"=>String})
+ assert_equal(2, tmpl.size)
+ assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2}))
+ assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
+ assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
+
+ assert_raises(Rinda::InvalidHashTupleKey) do
+ tmpl = Rinda::Template.new({:message=>String, "name"=>String})
+ end
+ tmpl = Rinda::Template.new({"name"=>String})
+ assert_equal(1, tmpl.size)
+ assert(tmpl.match({"name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>:symbol, "name"=>"Foo", "1"=>2}))
+ assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
+ assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
+
+ tmpl = Rinda::Template.new({"message"=>String, "name"=>String})
+ assert_equal(2, tmpl.size)
+ assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2}))
+ assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
+ assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
+
+ tmpl = Rinda::Template.new({"message"=>String})
+ assert_equal(1, tmpl.size)
+ assert(tmpl.match({"message"=>"Hello"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2}))
+ assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
+ assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
+
+ tmpl = Rinda::Template.new({"message"=>String, "name"=>nil})
+ assert_equal(2, tmpl.size)
+ assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"}))
+ assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2}))
+ assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
+ assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
+
+ assert_raises(Rinda::InvalidHashTupleKey) do
+ @ts.write({:message=>String, "name"=>String})
+ end
+
+ @ts.write([1, 2, 3])
+ assert_equal([1, 2, 3], @ts.take([1, 2, 3]))
+
+ @ts.write({'1'=>1, '2'=>2, '3'=>3})
+ assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.take({'1'=>1, '2'=>2, '3'=>3}))
+
+ entry = @ts.write(['1'=>1, '2'=>2, '3'=>3])
+ assert_raises(Rinda::RequestExpiredError) do
+ assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.read({'1'=>1}, 0))
+ end
+ entry.cancel
+ end
+
+ def test_00_DRbObject
+ ro = DRbObject.new(nil, "druby://host:1234")
+ tmpl = Rinda::DRbObjectTemplate.new
+ assert(tmpl === ro)
+
+ tmpl = Rinda::DRbObjectTemplate.new("druby://host:1234")
+ assert(tmpl === ro)
+
+ tmpl = Rinda::DRbObjectTemplate.new("druby://host:12345")
+ assert(!(tmpl === ro))
+
+ tmpl = Rinda::DRbObjectTemplate.new(/^druby:\/\/host:/)
+ assert(tmpl === ro)
+
+ ro = DRbObject.new_with(12345, 1234)
+ assert(!(tmpl === ro))
+
+ ro = DRbObject.new_with("druby://foo:12345", 1234)
+ assert(!(tmpl === ro))
+
+ tmpl = Rinda::DRbObjectTemplate.new(/^druby:\/\/(foo|bar):/)
+ assert(tmpl === ro)
+
+ ro = DRbObject.new_with("druby://bar:12345", 1234)
+ assert(tmpl === ro)
+
+ ro = DRbObject.new_with("druby://baz:12345", 1234)
+ assert(!(tmpl === ro))
+ end
+
+ def test_inp_rdp
+ assert_raises(Rinda::RequestExpiredError) do
+ @ts.take([:empty], 0)
+ end
+
+ assert_raises(Rinda::RequestExpiredError) do
+ @ts.read([:empty], 0)
+ end
+ end
+
+ def test_ruby_talk_264062
+ th = Thread.new { @ts.take([:empty], 1) }
+ sleep(10)
+ assert_raises(Rinda::RequestExpiredError) do
+ thread_join(th)
+ end
+
+ th = Thread.new { @ts.read([:empty], 1) }
+ sleep(10)
+ assert_raises(Rinda::RequestExpiredError) do
+ thread_join(th)
+ end
+ end
+
+ def test_symbol_tuple
+ @ts.write([:symbol, :symbol])
+ @ts.write(['string', :string])
+ assert_equal([[:symbol, :symbol]], @ts.read_all([:symbol, nil]))
+ assert_equal([[:symbol, :symbol]], @ts.read_all([Symbol, nil]))
+ assert_equal([], @ts.read_all([:nil, nil]))
+ end
+
+ def test_core_01
+ 5.times do |n|
+ @ts.write([:req, 2])
+ end
+
+ assert_equal([[:req, 2], [:req, 2], [:req, 2], [:req, 2], [:req, 2]],
+ @ts.read_all([nil, nil]))
+
+ taker = Thread.new do
+ s = 0
+ while true
+ begin
+ tuple = @ts.take([:req, Integer], 1)
+ assert_equal(2, tuple[1])
+ s += tuple[1]
+ rescue Rinda::RequestExpiredError
+ break
+ end
+ end
+ @ts.write([:ans, s])
+ s
+ end
+
+ assert_equal(10, thread_join(taker))
+ tuple = @ts.take([:ans, nil])
+ assert_equal(10, tuple[1])
+ end
+
+ def test_core_02
+ taker = Thread.new do
+ s = 0
+ while true
+ begin
+ tuple = @ts.take([:req, Integer], 1)
+ assert_equal(2, tuple[1])
+ s += tuple[1]
+ rescue Rinda::RequestExpiredError
+ break
+ end
+ end
+ @ts.write([:ans, s])
+ s
+ end
+
+ 5.times do |n|
+ @ts.write([:req, 2])
+ end
+
+ assert_equal(10, thread_join(taker))
+ tuple = @ts.take([:ans, nil])
+ assert_equal(10, tuple[1])
+ assert_equal([], @ts.read_all([nil, nil]))
+ end
+
+ def test_core_03_notify
+ notify1 = @ts.notify(nil, [:req, Integer])
+ notify2 = @ts.notify(nil, [:ans, Integer], 5)
+ notify3 = @ts.notify(nil, {"message"=>String, "name"=>String}, 5)
+
+ @ts.write({"message"=>"first", "name"=>"3"}, 3)
+ @ts.write({"message"=>"second", "name"=>"1"}, 1)
+ @ts.write({"message"=>"third", "name"=>"0"})
+ @ts.take({"message"=>"third", "name"=>"0"})
+
+ listener1 = Thread.new do
+ lv = 0
+ n = 0
+ notify1.each do |ev, tuple|
+ n += 1
+ if ev == 'write'
+ lv = lv + 1
+ elsif ev == 'take'
+ lv = lv - 1
+ else
+ break
+ end
+ assert(lv >= 0)
+ assert_equal([:req, 2], tuple)
+ end
+ [lv, n]
+ end
+
+ listener2 = Thread.new do
+ result = nil
+ lv = 0
+ n = 0
+ notify2.each do |ev|
+ n += 1
+ if ev[0] == 'write'
+ lv = lv + 1
+ elsif ev[0] == 'take'
+ lv = lv - 1
+ elsif ev[0] == 'close'
+ result = [lv, n]
+ else
+ break
+ end
+ assert(lv >= 0)
+ assert_equal([:ans, 10], ev[1])
+ end
+ result
+ end
+
+ taker = Thread.new do
+ s = 0
+ while true
+ begin
+ tuple = @ts.take([:req, Integer], 1)
+ s += tuple[1]
+ rescue Rinda::RequestExpiredError
+ break
+ end
+ end
+ @ts.write([:ans, s])
+ s
+ end
+
+ 5.times do |n|
+ @ts.write([:req, 2])
+ end
+
+ @ts.take({"message"=>"first", "name"=>"3"})
+
+ sleep(4)
+ assert_equal(10, thread_join(taker))
+ tuple = @ts.take([:ans, nil])
+ assert_equal(10, tuple[1])
+ assert_equal([], @ts.read_all([nil, nil]))
+
+ notify1.cancel
+ sleep(3) # notify2 expired
+
+ assert_equal([0, 11], thread_join(listener1))
+ assert_equal([0, 3], thread_join(listener2))
+
+ ary = []
+ ary.push(["write", {"message"=>"first", "name"=>"3"}])
+ ary.push(["write", {"message"=>"second", "name"=>"1"}])
+ ary.push(["write", {"message"=>"third", "name"=>"0"}])
+ ary.push(["take", {"message"=>"third", "name"=>"0"}])
+ ary.push(["take", {"message"=>"first", "name"=>"3"}])
+ ary.push(["delete", {"message"=>"second", "name"=>"1"}])
+ ary.push(["close"])
+
+ notify3.each do |ev|
+ assert_equal(ary.shift, ev)
+ end
+ assert_equal([], ary)
+ end
+
+ def test_cancel_01
+ entry = @ts.write([:removeme, 1])
+ assert_equal([[:removeme, 1]], @ts.read_all([nil, nil]))
+ entry.cancel
+ assert_equal([], @ts.read_all([nil, nil]))
+
+ template = nil
+ taker = Thread.new do
+ @ts.take([:take, nil], 10) do |t|
+ template = t
+ Thread.new do
+ template.cancel
+ end
+ end
+ end
+
+ sleep(2)
+
+ assert_raises(Rinda::RequestCanceledError) do
+ assert_nil(thread_join(taker))
+ end
+
+ assert(template.canceled?)
+
+ @ts.write([:take, 1])
+
+ assert_equal([[:take, 1]], @ts.read_all([nil, nil]))
+ end
+
+ def test_cancel_02
+ entry = @ts.write([:removeme, 1])
+ assert_equal([[:removeme, 1]], @ts.read_all([nil, nil]))
+ entry.cancel
+ assert_equal([], @ts.read_all([nil, nil]))
+
+ template = nil
+ reader = Thread.new do
+ @ts.read([:take, nil], 10) do |t|
+ template = t
+ Thread.new do
+ template.cancel
+ end
+ end
+ end
+
+ sleep(2)
+
+ assert_raises(Rinda::RequestCanceledError) do
+ assert_nil(thread_join(reader))
+ end
+
+ assert(template.canceled?)
+
+ @ts.write([:take, 1])
+
+ assert_equal([[:take, 1]], @ts.read_all([nil, nil]))
+ end
+
+ class SimpleRenewer
+ def initialize(sec, n = 1)
+ @sec = sec
+ @n = n
+ end
+
+ def renew
+ return -1 if @n <= 0
+ @n -= 1
+ return @sec
+ end
+ end
+
+ def test_00_renewer
+ tuple = Rinda::TupleEntry.new([1,2,3], true)
+ assert(!tuple.canceled?)
+ assert(tuple.expired?)
+ assert(!tuple.alive?)
+
+ tuple = Rinda::TupleEntry.new([1,2,3], 1)
+ assert(!tuple.canceled?)
+ assert(!tuple.expired?)
+ assert(tuple.alive?)
+ sleep(2)
+ assert(tuple.expired?)
+ assert(!tuple.alive?)
+
+ @renewer = SimpleRenewer.new(1,2)
+ tuple = Rinda::TupleEntry.new([1,2,3], @renewer)
+ assert(!tuple.canceled?)
+ assert(!tuple.expired?)
+ assert(tuple.alive?)
+ sleep(1)
+ assert(!tuple.canceled?)
+ assert(!tuple.expired?)
+ assert(tuple.alive?)
+ sleep(2)
+ assert(tuple.expired?)
+ assert(!tuple.alive?)
+ end
+end
+
+class TupleSpaceTest < Test::Unit::TestCase
+ include TupleSpaceTestModule
+
+ def setup
+ ThreadGroup.new.add(Thread.current)
+ @ts = Rinda::TupleSpace.new(1)
+ end
+end
+
+class TupleSpaceProxyTest < Test::Unit::TestCase
+ include TupleSpaceTestModule
+
+ def setup
+ ThreadGroup.new.add(Thread.current)
+ @ts_base = Rinda::TupleSpace.new(1)
+ @ts = Rinda::TupleSpaceProxy.new(@ts_base)
+ end
+
+ def test_remote_array_and_hash
+ @ts.write(DRbObject.new([1, 2, 3]))
+ assert_equal([1, 2, 3], @ts.take([1, 2, 3], 0))
+ @ts.write(DRbObject.new({'head' => 1, 'tail' => 2}))
+ assert_equal({'head' => 1, 'tail' => 2},
+ @ts.take({'head' => 1, 'tail' => 2}, 0))
+ end
+
+ @server = DRb.primary_server || DRb.start_service
+end
+
+end
+
diff --git a/trunk/test/rinda/test_tuplebag.rb b/trunk/test/rinda/test_tuplebag.rb
new file mode 100644
index 0000000000..eccf372125
--- /dev/null
+++ b/trunk/test/rinda/test_tuplebag.rb
@@ -0,0 +1,172 @@
+require 'test/unit'
+require 'rinda/tuplespace'
+
+class TestTupleBag < Test::Unit::TestCase
+
+ def setup
+ @tb = Rinda::TupleBag.new
+ end
+
+ def test_delete
+ assert_nothing_raised do
+ val = @tb.delete tup(:val, 1)
+ assert_equal nil, val
+ end
+
+ t = tup(:val, 1)
+ @tb.push t
+
+ val = @tb.delete t
+
+ assert_equal t, val
+
+ assert_equal [], @tb.find_all(tem(:val, 1))
+
+ t1 = tup(:val, 1)
+ t2 = tup(:val, 1)
+ @tb.push t1
+ @tb.push t2
+
+ val = @tb.delete t1
+
+ assert_equal t1, val
+
+ assert_equal [t2], @tb.find_all(tem(:val, 1))
+ end
+
+ def test_delete_unless_alive
+ assert_equal [], @tb.delete_unless_alive
+
+ t1 = tup(:val, nil)
+ t2 = tup(:val, nil)
+
+ @tb.push t1
+ @tb.push t2
+
+ assert_equal [], @tb.delete_unless_alive
+
+ t1.cancel
+
+ assert_equal [t1], @tb.delete_unless_alive, 'canceled'
+
+ t2.renew Object.new
+
+ assert_equal [t2], @tb.delete_unless_alive, 'expired'
+ end
+
+ def test_find
+ template = tem(:val, nil)
+
+ assert_equal nil, @tb.find(template)
+
+ t1 = tup(:other, 1)
+ @tb.push t1
+
+ assert_equal nil, @tb.find(template)
+
+ t2 = tup(:val, 1)
+ @tb.push t2
+
+ assert_equal t2, @tb.find(template)
+
+ t2.cancel
+
+ assert_equal nil, @tb.find(template), 'canceled'
+
+ t3 = tup(:val, 3)
+ @tb.push t3
+
+ assert_equal t3, @tb.find(template)
+
+ t3.renew Object.new
+
+ assert_equal nil, @tb.find(template), 'expired'
+ end
+
+ def test_find_all
+ template = tem(:val, nil)
+
+ t1 = tup(:other, 1)
+ @tb.push t1
+
+ assert_equal [], @tb.find_all(template)
+
+ t2 = tup(:val, 2)
+ t3 = tup(:val, 3)
+
+ @tb.push t2
+ @tb.push t3
+
+ assert_equal [t2, t3], @tb.find_all(template)
+
+ t2.cancel
+
+ assert_equal [t3], @tb.find_all(template), 'canceled'
+
+ t3.renew Object.new
+
+ assert_equal [], @tb.find_all(template), 'expired'
+ end
+
+ def test_find_all_template
+ tuple = tup(:val, 1)
+
+ t1 = tem(:other, nil)
+ @tb.push t1
+
+ assert_equal [], @tb.find_all_template(tuple)
+
+ t2 = tem(:val, nil)
+ t3 = tem(:val, nil)
+
+ @tb.push t2
+ @tb.push t3
+
+ assert_equal [t2, t3], @tb.find_all_template(tuple)
+
+ t2.cancel
+
+ assert_equal [t3], @tb.find_all_template(tuple), 'canceled'
+
+ t3.renew Object.new
+
+ assert_equal [], @tb.find_all_template(tuple), 'expired'
+ end
+
+ def test_has_expires_eh
+ assert_equal false, @tb.has_expires?
+
+ t = tup(:val, 1)
+ @tb.push t
+
+ assert_equal true, @tb.has_expires?
+
+ t.renew Object.new
+
+ assert_equal false, @tb.has_expires?
+ end
+
+ def test_push
+ t = tup(:val, 1)
+
+ @tb.push t
+
+ assert_equal t, @tb.find(tem(:val, 1))
+ end
+
+ ##
+ # Create a tuple with +ary+ for its contents
+
+ def tup(*ary)
+ Rinda::TupleEntry.new ary
+ end
+
+ ##
+ # Create a template with +ary+ for its contents
+
+ def tem(*ary)
+ Rinda::TemplateEntry.new ary
+ end
+
+end
+
diff --git a/trunk/test/ripper/dummyparser.rb b/trunk/test/ripper/dummyparser.rb
new file mode 100644
index 0000000000..483ac0d013
--- /dev/null
+++ b/trunk/test/ripper/dummyparser.rb
@@ -0,0 +1,571 @@
+#
+# dummyparser.rb
+#
+
+require 'ripper'
+
+class Node
+ def initialize(name, *nodes)
+ @name = name
+ @children = nodes
+ end
+
+ attr_reader :children
+
+ def to_s
+ "#{@name}(#{@children.map {|n| n.to_s }.join(',')})"
+ end
+end
+
+class NodeList
+ def initialize
+ @list = []
+ end
+
+ attr_reader :list
+
+ def push(item)
+ @list.push item
+ self
+ end
+
+ def prepend(items)
+ @list.unshift items
+ end
+
+ def to_s
+ '[' + @list.join(',') + ']'
+ end
+end
+
+class DummyParser < Ripper
+
+ def on_program(stmts)
+ $thru_program = true
+ stmts
+ end
+
+ def on_stmts_new
+ NodeList.new
+ end
+
+ def on_stmts_add(stmts, st)
+ stmts.push st
+ stmts
+ end
+
+ def on_void_stmt
+ Node.new('void')
+ end
+
+ def on_BEGIN(stmts)
+ Node.new('BEGIN', stmts)
+ end
+
+ def on_END(stmts)
+ Node.new('END', stmts)
+ end
+
+ def on_var_ref(name)
+ Node.new('ref', name)
+ end
+
+ def on_alias(a, b)
+ Node.new('alias', a, b)
+ end
+
+ def on_var_alias(a, b)
+ Node.new('valias', a, b)
+ end
+
+ def on_alias_error(a)
+ Node.new('aliaserr', a)
+ end
+
+ def on_aref(a, b)
+ Node.new('aref', a, b)
+ end
+
+ def on_aref_field(a, b)
+ Node.new('aref_field', a, b)
+ end
+
+ def on_arg_ambiguous
+ Node.new('arg_ambiguous')
+ end
+
+ def on_arg_paren(args)
+ args
+ end
+
+ def on_args_new
+ NodeList.new
+ end
+
+ def on_args_add(list, arg)
+ list.push(arg)
+ end
+
+ def on_args_add_block(list, blk)
+ if blk
+ list.push('&' + blk.to_s)
+ else
+ list
+ end
+ end
+
+ def on_args_add_star(list, arg)
+ list.push('*' + arg.to_s)
+ end
+
+ def on_args_prepend(list, args)
+ list.prepend args
+ list
+ end
+
+ def on_method_add_arg(m, arg)
+ if arg == nil
+ arg = on_args_new
+ end
+ m.children.push arg
+ m
+ end
+
+ def on_method_add_block(m, b)
+ on_args_add_block(m.children, b)
+ m
+ end
+
+ def on_assoc_new(a, b)
+ Node.new('assoc', a, b)
+ end
+
+ def on_bare_assoc_hash(assoc_list)
+ Node.new('assocs', *assoc_list)
+ end
+
+ def on_assoclist_from_args(a)
+ Node.new('assocs', *a.list)
+ end
+
+ ######## untested
+
+ def on_array(a)
+ Node.new('array', a)
+ end
+
+ def on_assign(a, b)
+ Node.new('assign', a, b)
+ end
+
+ def on_assign_error(a)
+ Node.new('assign_error', a)
+ end
+
+ def on_begin(a)
+ Node.new('begin', a)
+ end
+
+ def on_binary(a, b, c)
+ Node.new('binary', a, b, c)
+ end
+
+ def on_block_var(a)
+ Node.new('block_var', a)
+ end
+
+ def on_bodystmt(a, b, c, d)
+ Node.new('bodystmt', a, b, c, d)
+ end
+
+ def on_brace_block(a, b)
+ Node.new('brace_block', a, b)
+ end
+
+ def on_break(a)
+ Node.new('break', a)
+ end
+
+ def on_call(a, b, c)
+ Node.new('call', a, b, c)
+ end
+
+ def on_case(a, b)
+ Node.new('case', a, b)
+ end
+
+ def on_class(a, b, c)
+ Node.new('class', a, b, c)
+ end
+
+ def on_class_name_error(a)
+ Node.new('class_name_error', a)
+ end
+
+ def on_command(a, b)
+ Node.new('command', a, b)
+ end
+
+ def on_command_call(a, b, c, d)
+ Node.new('command_call', a, b, c, d)
+ end
+
+ def on_const_ref(a)
+ Node.new('const_ref', a)
+ end
+
+ def on_constpath_field(a, b)
+ Node.new('constpath_field', a, b)
+ end
+
+ def on_constpath_ref(a, b)
+ Node.new('constpath_ref', a, b)
+ end
+
+ def on_def(a, b, c)
+ Node.new('def', a, b, c)
+ end
+
+ def on_defined(a)
+ Node.new('defined', a)
+ end
+
+ def on_defs(a, b, c, d, e)
+ Node.new('defs', a, b, c, d, e)
+ end
+
+ def on_do_block(a, b)
+ Node.new('do_block', a, b)
+ end
+
+ def on_dot2(a, b)
+ Node.new('dot2', a, b)
+ end
+
+ def on_dot3(a, b)
+ Node.new('dot3', a, b)
+ end
+
+ def on_dyna_symbol(a)
+ Node.new('dyna_symbol', a)
+ end
+
+ def on_else(a)
+ Node.new('else', a)
+ end
+
+ def on_elsif(a, b, c)
+ Node.new('elsif', a, b, c)
+ end
+
+ def on_ensure(a)
+ Node.new('ensure', a)
+ end
+
+ def on_fcall(a)
+ Node.new('fcall', a)
+ end
+
+ def on_field(a, b, c)
+ Node.new('field', a, b, c)
+ end
+
+ def on_for(a, b, c)
+ Node.new('for', a, b, c)
+ end
+
+ def on_hash(a)
+ Node.new('hash', a)
+ end
+
+ def on_if(a, b, c)
+ Node.new('if', a, b, c)
+ end
+
+ def on_if_mod(a, b)
+ Node.new('if_mod', a, b)
+ end
+
+ def on_ifop(a, b, c)
+ Node.new('ifop', a, b, c)
+ end
+
+ def on_iter_block(a, b)
+ Node.new('iter_block', a, b)
+ end
+
+ def on_massign(a, b)
+ Node.new('massign', a, b)
+ end
+
+ def on_mlhs_add(a, b)
+ Node.new('mlhs_add', a, b)
+ end
+
+ def on_mlhs_add_star(a, b)
+ Node.new('mlhs_add_star', a, b)
+ end
+
+ def on_mlhs_new
+ Node.new('mlhs_new')
+ end
+
+ def on_mlhs_paren(a)
+ Node.new('mlhs_paren', a)
+ end
+
+ def on_module(a, b)
+ Node.new('module', a, b)
+ end
+
+ def on_mrhs_add(a, b)
+ Node.new('mrhs_add', a, b)
+ end
+
+ def on_mrhs_add_star(a, b)
+ Node.new('mrhs_add_star', a, b)
+ end
+
+ def on_mrhs_new
+ Node.new('mrhs_new')
+ end
+
+ def on_mrhs_new_from_arglist(a)
+ Node.new('mrhs_new_from_arglist', a)
+ end
+
+ def on_next(a)
+ Node.new('next', a)
+ end
+
+ def on_opassign(a, b, c)
+ Node.new('opassign', a, b, c)
+ end
+
+ def on_param_error(a)
+ Node.new('param_error', a)
+ end
+
+ def on_params(a, b, c, d)
+ Node.new('params', a, b, c, d)
+ end
+
+ def on_paren(a)
+ Node.new('paren', a)
+ end
+
+ def on_parse_error(a)
+ Node.new('parse_error', a)
+ end
+
+ def on_qwords_add(a, b)
+ Node.new('qwords_add', a, b)
+ end
+
+ def on_qwords_new
+ Node.new('qwords_new')
+ end
+
+ def on_redo
+ Node.new('redo')
+ end
+
+ def on_regexp_literal(a)
+ Node.new('regexp_literal', a)
+ end
+
+ def on_rescue(a, b, c, d)
+ Node.new('rescue', a, b, c, d)
+ end
+
+ def on_rescue_mod(a, b)
+ Node.new('rescue_mod', a, b)
+ end
+
+ def on_restparam(a)
+ Node.new('restparam', a)
+ end
+
+ def on_retry
+ Node.new('retry')
+ end
+
+ def on_return(a)
+ Node.new('return', a)
+ end
+
+ def on_return0
+ Node.new('return0')
+ end
+
+ def on_sclass(a, b)
+ Node.new('sclass', a, b)
+ end
+
+ def on_sp(a)
+ Node.new('space', a)
+ end
+
+ def on_string_add(a, b)
+ Node.new('string_add', a, b)
+ end
+
+ def on_string_concat(a, b)
+ Node.new('string_concat', a, b)
+ end
+
+ def on_string_content
+ Node.new('string_content')
+ end
+
+ def on_string_dvar(a)
+ Node.new('string_dvar', a)
+ end
+
+ def on_string_embexpr(a)
+ Node.new('string_embexpr', a)
+ end
+
+ def on_string_literal(a)
+ Node.new('string_literal', a)
+ end
+
+ def on_super(a)
+ Node.new('super', a)
+ end
+
+ def on_symbol(a)
+ Node.new('symbol', a)
+ end
+
+ def on_symbol_literal(a)
+ Node.new('symbol_literal', a)
+ end
+
+ def on_topconst_field(a)
+ Node.new('topconst_field', a)
+ end
+
+ def on_topconst_ref(a)
+ Node.new('topconst_ref', a)
+ end
+
+ def on_unary(a, b)
+ Node.new('unary', a, b)
+ end
+
+ def on_undef(a)
+ Node.new('undef', a)
+ end
+
+ def on_unless(a, b, c)
+ Node.new('unless', a, b, c)
+ end
+
+ def on_unless_mod(a, b)
+ Node.new('unless_mod', a, b)
+ end
+
+ def on_until_mod(a, b)
+ Node.new('until_mod', a, b)
+ end
+
+ def on_var_field(a)
+ Node.new('var_field', a)
+ end
+
+ def on_when(a, b, c)
+ Node.new('when', a, b, c)
+ end
+
+ def on_while(a, b)
+ Node.new('while', a, b)
+ end
+
+ def on_while_mod(a, b)
+ Node.new('while_mod', a, b)
+ end
+
+ def on_word_add(a, b)
+ Node.new('word_add', a, b)
+ end
+
+ def on_word_new
+ Node.new('word_new')
+ end
+
+ def on_words_add(a, b)
+ Node.new('words_add', a, b)
+ end
+
+ def on_words_new
+ Node.new('words_new')
+ end
+
+ def on_xstring_add(a, b)
+ Node.new('xstring_add', a, b)
+ end
+
+ def on_xstring_literal(a)
+ Node.new('xstring_literal', a)
+ end
+
+ def on_xstring_new
+ Node.new('xstring_new')
+ end
+
+ def on_yield(a)
+ Node.new('yield', a)
+ end
+
+ def on_yield0
+ Node.new('yield0')
+ end
+
+ def on_zsuper
+ Node.new('zsuper')
+ end
+
+ def on_backref(a)
+ a
+ end
+ def on_comma(a)
+ a
+ end
+ def on_gvar(a)
+ a
+ end
+ def on_ident(a)
+ a
+ end
+ def on_int(a)
+ a
+ end
+ def on_kw(a)
+ a
+ end
+ def on_lbrace(a)
+ a
+ end
+ def on_rbrace(a)
+ a
+ end
+ def on_lbracket(a)
+ a
+ end
+ def on_rbracket(a)
+ a
+ end
+ def on_lparen(a)
+ a
+ end
+ def on_rparen(a)
+ a
+ end
+ def on_op(a)
+ a
+ end
+ def on_semicolon(a)
+ a
+ end
+end
diff --git a/trunk/test/ripper/test_files.rb b/trunk/test/ripper/test_files.rb
new file mode 100644
index 0000000000..c2d7a50a3f
--- /dev/null
+++ b/trunk/test/ripper/test_files.rb
@@ -0,0 +1,25 @@
+begin
+
+require 'ripper'
+require 'find'
+require 'test/unit'
+
+class TestRipper_Generic < Test::Unit::TestCase
+ SRCDIR = File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))
+
+ class Parser < Ripper
+ PARSER_EVENTS.each {|n| eval "def on_#{n}(*args) r = [:#{n}, *args]; r.inspect; Object.new end" }
+ SCANNER_EVENTS.each {|n| eval "def on_#{n}(*args) r = [:#{n}, *args]; r.inspect; Object.new end" }
+ end
+
+ def test_parse_files
+ Find.find("#{SRCDIR}/lib", "#{SRCDIR}/ext", "#{SRCDIR}/sample", "#{SRCDIR}/test") {|n|
+ next if /\.rb\z/ !~ n || !File.file?(n)
+ assert_nothing_raised("ripper failed to parse: #{n.inspect}") { Parser.new(File.read(n)).parse }
+ }
+ end
+end
+
+rescue LoadError
+end
+
diff --git a/trunk/test/ripper/test_parser_events.rb b/trunk/test/ripper/test_parser_events.rb
new file mode 100644
index 0000000000..fa640a37ec
--- /dev/null
+++ b/trunk/test/ripper/test_parser_events.rb
@@ -0,0 +1,498 @@
+begin
+
+require 'dummyparser'
+require 'test/unit'
+
+class TestRipper_ParserEvents < Test::Unit::TestCase
+
+ # should be enabled
+=begin
+ def test_event_coverage
+ dispatched = Ripper::PARSER_EVENTS.map {|event,*| event }
+ dispatched.each do |e|
+ assert_equal true, respond_to?("test_#{e}", true),
+ "event not tested: #{e.inspect}"
+ end
+ end
+=end
+
+ def parse(str)
+ DummyParser.new(str).parse.to_s
+ end
+
+ $thru_program = false
+
+ def test_program
+ assert_equal '[void()]', parse('')
+ assert_equal true, $thru_program
+ end
+
+ def test_stmts_new
+ assert_equal '[void()]', parse('')
+ end
+
+ def test_stmts_add
+ assert_equal '[ref(nil)]', parse('nil')
+ assert_equal '[ref(nil),ref(nil)]', parse('nil;nil')
+ assert_equal '[ref(nil),ref(nil),ref(nil)]', parse('nil;nil;nil')
+ end
+
+ def test_void_stmt
+ assert_equal '[void()]', parse('')
+ assert_equal '[void()]', parse('; ;')
+ end
+
+ def test_var_ref
+ assert_equal '[ref(a)]', parse('a')
+ assert_equal '[ref(nil)]', parse('nil')
+ assert_equal '[ref(true)]', parse('true')
+ end
+
+ def test_BEGIN
+ assert_equal '[BEGIN([void()])]', parse('BEGIN{}')
+ assert_equal '[BEGIN([ref(nil)])]', parse('BEGIN{nil}')
+ end
+
+ def test_END
+ assert_equal '[END([void()])]', parse('END{}')
+ assert_equal '[END([ref(nil)])]', parse('END{nil}')
+ end
+
+ def test_alias
+ assert_equal '[alias(symbol_literal(a),symbol_literal(b))]', parse('alias a b')
+ end
+
+ def test_var_alias
+ assert_equal '[valias($a,$g)]', parse('alias $a $g')
+ end
+
+ def test_alias_error
+ assert_equal '[aliaserr(valias($a,$1))]', parse('alias $a $1')
+ end
+
+ def test_arglist
+ assert_equal '[fcall(m,[])]', parse('m()')
+ assert_equal '[fcall(m,[1])]', parse('m(1)')
+ assert_equal '[fcall(m,[1,2])]', parse('m(1,2)')
+ assert_equal '[fcall(m,[*ref(r)])]', parse('m(*r)')
+ assert_equal '[fcall(m,[1,*ref(r)])]', parse('m(1,*r)')
+ assert_equal '[fcall(m,[1,2,*ref(r)])]', parse('m(1,2,*r)')
+ assert_equal '[fcall(m,[&ref(r)])]', parse('m(&r)')
+ assert_equal '[fcall(m,[1,&ref(r)])]', parse('m(1,&r)')
+ assert_equal '[fcall(m,[1,2,&ref(r)])]', parse('m(1,2,&r)')
+ assert_equal '[fcall(m,[*ref(a),&ref(b)])]', parse('m(*a,&b)')
+ assert_equal '[fcall(m,[1,*ref(a),&ref(b)])]', parse('m(1,*a,&b)')
+ assert_equal '[fcall(m,[1,2,*ref(a),&ref(b)])]', parse('m(1,2,*a,&b)')
+ end
+
+ def test_arg_paren
+ # FIXME
+ end
+
+ def test_aref
+ assert_equal '[aref(ref(v),[1])]', parse('v[1]')
+ assert_equal '[aref(ref(v),[1,2])]', parse('v[1,2]')
+ end
+
+ def test_assocs
+ assert_equal '[fcall(m,[assocs(assoc(1,2))])]', parse('m(1=>2)')
+ assert_equal '[fcall(m,[assocs(assoc(1,2),assoc(3,4))])]', parse('m(1=>2,3=>4)')
+ assert_equal '[fcall(m,[3,assocs(assoc(1,2))])]', parse('m(3,1=>2)')
+ end
+
+ def test_aref_field
+ assert_equal '[assign(aref_field(ref(a),[1]),2)]', parse('a[1]=2')
+ end
+
+=begin
+ def test_arg_ambiguous
+ assert_equal true, $thru__arg_ambiguous
+ end
+=end
+
+ def test_array # array literal
+ assert_equal '[array([1,2,3])]', parse('[1,2,3]')
+ end
+
+ def test_assign # generic assignment
+ assert_equal '[assign(var_field(v),1)]', parse('v=1')
+ end
+
+=begin
+ def test_assign_error
+ assert_equal true, $thru__assign_error
+ end
+
+ def test_begin
+ assert_equal true, $thru__begin
+ end
+
+ def test_binary
+ assert_equal true, $thru__binary
+ end
+
+ def test_block_var
+ assert_equal true, $thru__block_var
+ end
+
+ def test_bodystmt
+ assert_equal true, $thru__bodystmt
+ end
+
+ def test_brace_block
+ assert_equal true, $thru__brace_block
+ end
+
+ def test_break
+ assert_equal true, $thru__break
+ end
+
+ def test_call
+ assert_equal true, $thru__call
+ end
+
+ def test_case
+ assert_equal true, $thru__case
+ end
+
+ def test_class
+ assert_equal true, $thru__class
+ end
+
+ def test_class_name_error
+ assert_equal true, $thru__class_name_error
+ end
+
+ def test_command
+ assert_equal true, $thru__command
+ end
+
+ def test_command_call
+ assert_equal true, $thru__command_call
+ end
+
+ def test_const_ref
+ assert_equal true, $thru__const_ref
+ end
+
+ def test_constpath_field
+ assert_equal true, $thru__constpath_field
+ end
+
+ def test_constpath_ref
+ assert_equal true, $thru__constpath_ref
+ end
+
+ def test_def
+ assert_equal true, $thru__def
+ end
+
+ def test_defined
+ assert_equal true, $thru__defined
+ end
+
+ def test_defs
+ assert_equal true, $thru__defs
+ end
+
+ def test_do_block
+ assert_equal true, $thru__do_block
+ end
+
+ def test_dot2
+ assert_equal true, $thru__dot2
+ end
+
+ def test_dot3
+ assert_equal true, $thru__dot3
+ end
+
+ def test_dyna_symbol
+ assert_equal true, $thru__dyna_symbol
+ end
+
+ def test_else
+ assert_equal true, $thru__else
+ end
+
+ def test_elsif
+ assert_equal true, $thru__elsif
+ end
+
+ def test_ensure
+ assert_equal true, $thru__ensure
+ end
+
+ def test_fcall
+ assert_equal true, $thru__fcall
+ end
+
+ def test_field
+ assert_equal true, $thru__field
+ end
+
+ def test_for
+ assert_equal true, $thru__for
+ end
+
+ def test_hash
+ assert_equal true, $thru__hash
+ end
+
+ def test_if
+ assert_equal true, $thru__if
+ end
+
+ def test_if_mod
+ assert_equal true, $thru__if_mod
+ end
+
+ def test_ifop
+ assert_equal true, $thru__ifop
+ end
+
+ def test_iter_block
+ assert_equal true, $thru__iter_block
+ end
+
+ def test_massign
+ assert_equal true, $thru__massign
+ end
+
+ def test_method_add_arg
+ assert_equal true, $thru__method_add_arg
+ end
+
+ def test_mlhs_add
+ assert_equal true, $thru__mlhs_add
+ end
+
+ def test_mlhs_add_star
+ assert_equal true, $thru__mlhs_add_star
+ end
+
+ def test_mlhs_new
+ assert_equal true, $thru__mlhs_new
+ end
+
+ def test_mlhs_paren
+ assert_equal true, $thru__mlhs_paren
+ end
+
+ def test_module
+ assert_equal true, $thru__module
+ end
+
+ def test_mrhs_add
+ assert_equal true, $thru__mrhs_add
+ end
+
+ def test_mrhs_add_star
+ assert_equal true, $thru__mrhs_add_star
+ end
+
+ def test_mrhs_new
+ assert_equal true, $thru__mrhs_new
+ end
+
+ def test_mrhs_new_from_arglist
+ assert_equal true, $thru__mrhs_new_from_arglist
+ end
+
+ def test_next
+ assert_equal true, $thru__next
+ end
+
+ def test_opassign
+ assert_equal true, $thru__opassign
+ end
+
+ def test_param_error
+ assert_equal true, $thru__param_error
+ end
+
+ def test_params
+ assert_equal true, $thru__params
+ end
+
+ def test_paren
+ assert_equal true, $thru__paren
+ end
+
+ def test_parse_error
+ assert_equal true, $thru__parse_error
+ end
+
+ def test_qwords_add
+ assert_equal true, $thru__qwords_add
+ end
+
+ def test_qwords_new
+ assert_equal true, $thru__qwords_new
+ end
+
+ def test_redo
+ assert_equal true, $thru__redo
+ end
+
+ def test_regexp_literal
+ assert_equal true, $thru__regexp_literal
+ end
+
+ def test_rescue
+ assert_equal true, $thru__rescue
+ end
+
+ def test_rescue_mod
+ assert_equal true, $thru__rescue_mod
+ end
+
+ def test_restparam
+ assert_equal true, $thru__restparam
+ end
+
+ def test_retry
+ assert_equal true, $thru__retry
+ end
+
+ def test_return
+ assert_equal true, $thru__return
+ end
+
+ def test_return0
+ assert_equal true, $thru__return0
+ end
+
+ def test_sclass
+ assert_equal true, $thru__sclass
+ end
+
+ def test_space
+ assert_equal true, $thru__space
+ end
+
+ def test_string_add
+ assert_equal true, $thru__string_add
+ end
+
+ def test_string_concat
+ assert_equal true, $thru__string_concat
+ end
+
+ def test_string_content
+ assert_equal true, $thru__string_content
+ end
+
+ def test_string_dvar
+ assert_equal true, $thru__string_dvar
+ end
+
+ def test_string_embexpr
+ assert_equal true, $thru__string_embexpr
+ end
+
+ def test_string_literal
+ assert_equal true, $thru__string_literal
+ end
+
+ def test_super
+ assert_equal true, $thru__super
+ end
+
+ def test_symbol
+ assert_equal true, $thru__symbol
+ end
+
+ def test_symbol_literal
+ assert_equal true, $thru__symbol_literal
+ end
+
+ def test_topconst_field
+ assert_equal true, $thru__topconst_field
+ end
+
+ def test_topconst_ref
+ assert_equal true, $thru__topconst_ref
+ end
+
+ def test_unary
+ assert_equal true, $thru__unary
+ end
+
+ def test_undef
+ assert_equal true, $thru__undef
+ end
+
+ def test_unless
+ assert_equal true, $thru__unless
+ end
+
+ def test_unless_mod
+ assert_equal true, $thru__unless_mod
+ end
+
+ def test_until_mod
+ assert_equal true, $thru__until_mod
+ end
+
+ def test_var_field
+ assert_equal true, $thru__var_field
+ end
+
+ def test_when
+ assert_equal true, $thru__when
+ end
+
+ def test_while
+ assert_equal true, $thru__while
+ end
+
+ def test_while_mod
+ assert_equal true, $thru__while_mod
+ end
+
+ def test_word_add
+ assert_equal true, $thru__word_add
+ end
+
+ def test_word_new
+ assert_equal true, $thru__word_new
+ end
+
+ def test_words_add
+ assert_equal true, $thru__words_add
+ end
+
+ def test_words_new
+ assert_equal true, $thru__words_new
+ end
+
+ def test_xstring_add
+ assert_equal true, $thru__xstring_add
+ end
+
+ def test_xstring_literal
+ assert_equal true, $thru__xstring_literal
+ end
+
+ def test_xstring_new
+ assert_equal true, $thru__xstring_new
+ end
+
+ def test_yield
+ assert_equal true, $thru__yield
+ end
+
+ def test_yield0
+ assert_equal true, $thru__yield0
+ end
+
+ def test_zsuper
+ assert_equal true, $thru__zsuper
+ end
+=end
+
+end
+
+rescue LoadError
+end
diff --git a/trunk/test/ripper/test_scanner_events.rb b/trunk/test/ripper/test_scanner_events.rb
new file mode 100644
index 0000000000..4389946104
--- /dev/null
+++ b/trunk/test/ripper/test_scanner_events.rb
@@ -0,0 +1,807 @@
+#
+# test_scanner_events.rb
+#
+begin
+
+require 'ripper'
+require 'test/unit'
+
+class TestRipper_ScannerEvents < Test::Unit::TestCase
+
+ def test_event_coverage
+ dispatched = Ripper::SCANNER_EVENTS.map {|event,_| event }
+ dispatched.each do |e|
+ assert_equal true, respond_to?("test_#{e}", true), "event not tested: #{e}"
+ end
+ end
+
+ def scan(target, str)
+ sym = "on_#{target}".intern
+ Ripper.lex(str).select {|_1,type,_2| type == sym }.map {|_1,_2,tok| tok }
+ end
+
+ def test_tokenize
+ assert_equal [],
+ Ripper.tokenize('')
+ assert_equal ['a'],
+ Ripper.tokenize('a')
+ assert_equal ['1'],
+ Ripper.tokenize('1')
+ assert_equal ['1', ';', 'def', ' ', 'm', '(', 'arg', ')', 'end'],
+ Ripper.tokenize("1;def m(arg)end")
+ assert_equal ['print', '(', '<<EOS', ')', "\n", "heredoc\n", "EOS\n"],
+ Ripper.tokenize("print(<<EOS)\nheredoc\nEOS\n")
+ assert_equal ['print', '(', ' ', '<<EOS', ')', "\n", "heredoc\n", "EOS\n"],
+ Ripper.tokenize("print( <<EOS)\nheredoc\nEOS\n")
+ assert_equal ["\#\n", "\n", "\#\n", "\n", "nil", "\n"],
+ Ripper.tokenize("\#\n\n\#\n\nnil\n")
+ end
+
+ def test_lex
+ assert_equal [],
+ Ripper.lex('')
+ assert_equal [[[1,0], :on_ident, "a"]],
+ Ripper.lex('a')
+ assert_equal [[[1, 0], :on_kw, "nil"]],
+ Ripper.lex("nil")
+ assert_equal [[[1, 0], :on_kw, "def"],
+ [[1, 3], :on_sp, " "],
+ [[1, 4], :on_ident, "m"],
+ [[1, 5], :on_lparen, "("],
+ [[1, 6], :on_ident, "a"],
+ [[1, 7], :on_rparen, ")"],
+ [[1, 8], :on_kw, "end"]],
+ Ripper.lex("def m(a)end")
+ assert_equal [[[1, 0], :on_int, "1"],
+ [[1, 1], :on_nl, "\n"],
+ [[2, 0], :on_int, "2"],
+ [[2, 1], :on_nl, "\n"],
+ [[3, 0], :on_int, "3"]],
+ Ripper.lex("1\n2\n3")
+ assert_equal [[[1, 0], :on_heredoc_beg, "<<EOS"],
+ [[1, 5], :on_nl, "\n"],
+ [[2, 0], :on_tstring_content, "heredoc\n"],
+ [[3, 0], :on_heredoc_end, "EOS"]],
+ Ripper.lex("<<EOS\nheredoc\nEOS")
+ end
+
+ def test_location
+ validate_location ""
+ validate_location " "
+ validate_location "@"
+ validate_location "\n"
+ validate_location "\r\n"
+ validate_location "\n\n\n\n\n\r\n\n\n"
+ validate_location "\n;\n;\n;\n;\n"
+ validate_location "nil"
+ validate_location "@ivar"
+ validate_location "1;2;3"
+ validate_location "1\n2\n3"
+ validate_location "1\n2\n3\n"
+ validate_location "def m(a) nil end"
+ validate_location "if true then false else nil end"
+ validate_location "BEGIN{print nil}"
+ validate_location "%w(a b\nc\r\nd \ne )"
+ validate_location %Q["a\nb\r\nc"]
+ validate_location "print(<<EOS)\nheredoc\nEOS\n"
+ validate_location %Q[print(<<-"EOS")\nheredoc\n EOS\n]
+ end
+
+ def validate_location(src)
+ buf = ''
+ Ripper.lex(src).each do |pos, type, tok|
+ line, col = *pos
+ assert_equal buf.count("\n") + 1, line,
+ "wrong lineno: #{tok.inspect} (#{type}) [#{line}:#{col}]"
+ assert_equal buf.sub(/\A.*\n/m, '').size, col,
+ "wrong column: #{tok.inspect} (#{type}) [#{line}:#{col}]"
+ buf << tok
+ end
+ assert_equal src, buf
+ end
+
+ def test_backref
+ assert_equal ["$`", "$&", "$'", '$1', '$2', '$3'],
+ scan('backref', %q[m($~, $`, $&, $', $1, $2, $3)])
+ end
+
+ def test_backtick
+ assert_equal ["`"],
+ scan('backtick', %q[p `make all`])
+ end
+
+ def test_comma
+ assert_equal [','] * 6,
+ scan('comma', %q[ m(0,1,2,3,4,5,6) ])
+ assert_equal [],
+ scan('comma', %q[".,.,.,.,.,.,.."])
+ assert_equal [],
+ scan('comma', %Q[<<EOS\n,,,,,,,,,,\nEOS])
+ end
+
+ def test_period
+ assert_equal [],
+ scan('period', '')
+ assert_equal ['.'],
+ scan('period', 'a.b')
+ assert_equal ['.'],
+ scan('period', 'Object.new')
+ assert_equal [],
+ scan('period', '"."')
+ assert_equal [],
+ scan('period', '1..2')
+ assert_equal [],
+ scan('period', '1...3')
+ end
+
+ def test_const
+ assert_equal ['CONST'],
+ scan('const', 'CONST')
+ assert_equal ['C'],
+ scan('const', 'C')
+ assert_equal ['CONST_A'],
+ scan('const', 'CONST_A')
+ assert_equal ['Const', 'Const2', 'Const3'],
+ scan('const', 'Const; Const2; Const3')
+ assert_equal ['Const'],
+ scan('const', 'Const(a)')
+ assert_equal ['M', 'A', 'A2'],
+ scan('const', 'M(A,A2)')
+ assert_equal [],
+ scan('const', '')
+ assert_equal [],
+ scan('const', 'm(lvar, @ivar, @@cvar, $gvar)')
+ end
+
+ def test_cvar
+ assert_equal [],
+ scan('cvar', '')
+ assert_equal ['@@cvar'],
+ scan('cvar', '@@cvar')
+ assert_equal ['@@__cvar__'],
+ scan('cvar', '@@__cvar__')
+ assert_equal ['@@CVAR'],
+ scan('cvar', '@@CVAR')
+ assert_equal ['@@cvar'],
+ scan('cvar', ' @@cvar#comment')
+ assert_equal ['@@cvar'],
+ scan('cvar', ':@@cvar')
+ assert_equal ['@@cvar'],
+ scan('cvar', 'm(lvar, @ivar, @@cvar, $gvar)')
+ assert_equal [],
+ scan('cvar', '"@@cvar"')
+ end
+
+ def test_embexpr_beg
+ assert_equal [],
+ scan('embexpr_beg', '')
+ assert_equal ['#{'],
+ scan('embexpr_beg', '"#{expr}"')
+ assert_equal [],
+ scan('embexpr_beg', '%q[#{expr}]')
+ assert_equal ['#{'],
+ scan('embexpr_beg', '%Q[#{expr}]')
+ assert_equal ['#{'],
+ scan('embexpr_beg', "m(<<EOS)\n\#{expr}\nEOS")
+ end
+
+ def test_embexpr_end
+=begin
+ # currently detected as "rbrace"
+ assert_equal [],
+ scan('embexpr_end', '')
+ assert_equal ['}'],
+ scan('embexpr_end', '"#{expr}"')
+ assert_equal [],
+ scan('embexpr_end', '%q[#{expr}]')
+ assert_equal ['}'],
+ scan('embexpr_end', '%Q[#{expr}]')
+ assert_equal ['}'],
+ scan('embexpr_end', "m(<<EOS)\n\#{expr}\nEOS")
+=end
+ end
+
+ def test_embvar
+ assert_equal [],
+ scan('embvar', '')
+ assert_equal ['#'],
+ scan('embvar', '"#$gvar"')
+ assert_equal ['#'],
+ scan('embvar', '"#@ivar"')
+ assert_equal ['#'],
+ scan('embvar', '"#@@cvar"')
+ assert_equal [],
+ scan('embvar', '"#lvar"')
+ assert_equal [],
+ scan('embvar', '"#"')
+ assert_equal [],
+ scan('embvar', '"\#$gvar"')
+ assert_equal [],
+ scan('embvar', '"\#@ivar"')
+ assert_equal [],
+ scan('embvar', '%q[#@ivar]')
+ assert_equal ['#'],
+ scan('embvar', '%Q[#@ivar]')
+ end
+
+ def test_float
+ assert_equal [],
+ scan('float', '')
+ assert_equal ['1.000'],
+ scan('float', '1.000')
+ assert_equal ['123.456'],
+ scan('float', '123.456')
+ assert_equal ['1.2345678901234567890123456789'],
+ scan('float', '1.2345678901234567890123456789')
+ assert_equal ['1.000'],
+ scan('float', ' 1.000# comment')
+ assert_equal ['1.234e5'],
+ scan('float', '1.234e5')
+ assert_equal ['1.234e1234567890'],
+ scan('float', '1.234e1234567890')
+ assert_equal ['1.0'],
+ scan('float', 'm(a,b,1.0,c,d)')
+ end
+
+ def test_gvar
+ assert_equal [],
+ scan('gvar', '')
+ assert_equal ['$a'],
+ scan('gvar', '$a')
+ assert_equal ['$A'],
+ scan('gvar', '$A')
+ assert_equal ['$gvar'],
+ scan('gvar', 'm(lvar, @ivar, @@cvar, $gvar)')
+ assert_equal %w($_ $~ $* $$ $? $! $@ $/ $\\ $; $, $. $= $: $< $> $"),
+ scan('gvar', 'm($_, $~, $*, $$, $?, $!, $@, $/, $\\, $;, $,, $., $=, $:, $<, $>, $")')
+ end
+
+ def test_ident
+ assert_equal [],
+ scan('ident', '')
+ assert_equal ['lvar'],
+ scan('ident', 'lvar')
+ assert_equal ['m', 'lvar'],
+ scan('ident', 'm(lvar, @ivar, @@cvar, $gvar)')
+ end
+
+ def test_int
+ assert_equal [],
+ scan('int', '')
+ assert_equal ['1', '10', '100000000000000'],
+ scan('int', 'm(1,10,100000000000000)')
+ end
+
+ def test_ivar
+ assert_equal [],
+ scan('ivar', '')
+ assert_equal ['@ivar'],
+ scan('ivar', '@ivar')
+ assert_equal ['@__ivar__'],
+ scan('ivar', '@__ivar__')
+ assert_equal ['@IVAR'],
+ scan('ivar', '@IVAR')
+ assert_equal ['@ivar'],
+ scan('ivar', 'm(lvar, @ivar, @@cvar, $gvar)')
+ end
+
+ def test_kw
+ assert_equal [],
+ scan('kw', '')
+ assert_equal %w(not),
+ scan('kw', 'not 1')
+ assert_equal %w(and),
+ scan('kw', '1 and 2')
+ assert_equal %w(or),
+ scan('kw', '1 or 2')
+ assert_equal %w(if then else end),
+ scan('kw', 'if 1 then 2 else 3 end')
+ assert_equal %w(if then elsif else end),
+ scan('kw', 'if 1 then 2 elsif 3 else 4 end')
+ assert_equal %w(unless then end),
+ scan('kw', 'unless 1 then end')
+ assert_equal %w(if true),
+ scan('kw', '1 if true')
+ assert_equal %w(unless false),
+ scan('kw', '2 unless false')
+ assert_equal %w(case when when else end),
+ scan('kw', 'case n; when 1; when 2; else 3 end')
+ assert_equal %w(while do nil end),
+ scan('kw', 'while 1 do nil end')
+ assert_equal %w(until do nil end),
+ scan('kw', 'until 1 do nil end')
+ assert_equal %w(while),
+ scan('kw', '1 while 2')
+ assert_equal %w(until),
+ scan('kw', '1 until 2')
+ assert_equal %w(while break next retry end),
+ scan('kw', 'while 1; break; next; retry end')
+ assert_equal %w(for in next break end),
+ scan('kw', 'for x in obj; next 1; break 2 end')
+ assert_equal %w(begin rescue retry end),
+ scan('kw', 'begin 1; rescue; retry; end')
+ assert_equal %w(rescue),
+ scan('kw', '1 rescue 2')
+ assert_equal %w(def redo return end),
+ scan('kw', 'def m() redo; return end')
+ assert_equal %w(def yield yield end),
+ scan('kw', 'def m() yield; yield 1 end')
+ assert_equal %w(def super super super end),
+ scan('kw', 'def m() super; super(); super(1) end')
+ assert_equal %w(alias),
+ scan('kw', 'alias a b')
+ assert_equal %w(undef),
+ scan('kw', 'undef public')
+ assert_equal %w(class end),
+ scan('kw', 'class A < Object; end')
+ assert_equal %w(module end),
+ scan('kw', 'module M; end')
+ assert_equal %w(class end),
+ scan('kw', 'class << obj; end')
+ assert_equal %w(BEGIN),
+ scan('kw', 'BEGIN { }')
+ assert_equal %w(END),
+ scan('kw', 'END { }')
+ assert_equal %w(self),
+ scan('kw', 'self.class')
+ assert_equal %w(nil true false),
+ scan('kw', 'p(nil, true, false)')
+ assert_equal %w(__FILE__ __LINE__),
+ scan('kw', 'p __FILE__, __LINE__')
+ assert_equal %w(defined?),
+ scan('kw', 'defined?(Object)')
+ end
+
+ def test_lbrace
+ assert_equal [],
+ scan('lbrace', '')
+ assert_equal ['{'],
+ scan('lbrace', '3.times{ }')
+ assert_equal ['{'],
+ scan('lbrace', '3.times { }')
+ assert_equal ['{'],
+ scan('lbrace', '3.times{}')
+ assert_equal [],
+ scan('lbrace', '"{}"')
+ assert_equal ['{'],
+ scan('lbrace', '{1=>2}')
+ end
+
+ def test_rbrace
+ assert_equal [],
+ scan('rbrace', '')
+ assert_equal ['}'],
+ scan('rbrace', '3.times{ }')
+ assert_equal ['}'],
+ scan('rbrace', '3.times { }')
+ assert_equal ['}'],
+ scan('rbrace', '3.times{}')
+ assert_equal [],
+ scan('rbrace', '"{}"')
+ assert_equal ['}'],
+ scan('rbrace', '{1=>2}')
+ end
+
+ def test_lbracket
+ assert_equal [],
+ scan('lbracket', '')
+ assert_equal ['['],
+ scan('lbracket', '[]')
+ assert_equal ['['],
+ scan('lbracket', 'a[1]')
+ assert_equal [],
+ scan('lbracket', 'm(%q[])')
+ end
+
+ def test_rbracket
+ assert_equal [],
+ scan('rbracket', '')
+ assert_equal [']'],
+ scan('rbracket', '[]')
+ assert_equal [']'],
+ scan('rbracket', 'a[1]')
+ assert_equal [],
+ scan('rbracket', 'm(%q[])')
+ end
+
+ def test_lparen
+ assert_equal [],
+ scan('lparen', '')
+ assert_equal ['('],
+ scan('lparen', '()')
+ assert_equal ['('],
+ scan('lparen', 'm()')
+ assert_equal ['('],
+ scan('lparen', 'm (a)')
+ assert_equal [],
+ scan('lparen', '"()"')
+ assert_equal [],
+ scan('lparen', '"%w()"')
+ end
+
+ def test_rparen
+ assert_equal [],
+ scan('rparen', '')
+ assert_equal [')'],
+ scan('rparen', '()')
+ assert_equal [')'],
+ scan('rparen', 'm()')
+ assert_equal [')'],
+ scan('rparen', 'm (a)')
+ assert_equal [],
+ scan('rparen', '"()"')
+ assert_equal [],
+ scan('rparen', '"%w()"')
+ end
+
+ def test_op
+ assert_equal [],
+ scan('op', '')
+ assert_equal ['|'],
+ scan('op', '1 | 1')
+ assert_equal ['^'],
+ scan('op', '1 ^ 1')
+ assert_equal ['&'],
+ scan('op', '1 & 1')
+ assert_equal ['<=>'],
+ scan('op', '1 <=> 1')
+ assert_equal ['=='],
+ scan('op', '1 == 1')
+ assert_equal ['==='],
+ scan('op', '1 === 1')
+ assert_equal ['=~'],
+ scan('op', '1 =~ 1')
+ assert_equal ['>'],
+ scan('op', '1 > 1')
+ assert_equal ['>='],
+ scan('op', '1 >= 1')
+ assert_equal ['<'],
+ scan('op', '1 < 1')
+ assert_equal ['<='],
+ scan('op', '1 <= 1')
+ assert_equal ['<<'],
+ scan('op', '1 << 1')
+ assert_equal ['>>'],
+ scan('op', '1 >> 1')
+ assert_equal ['+'],
+ scan('op', '1 + 1')
+ assert_equal ['-'],
+ scan('op', '1 - 1')
+ assert_equal ['*'],
+ scan('op', '1 * 1')
+ assert_equal ['/'],
+ scan('op', '1 / 1')
+ assert_equal ['%'],
+ scan('op', '1 % 1')
+ assert_equal ['**'],
+ scan('op', '1 ** 1')
+ assert_equal ['~'],
+ scan('op', '~1')
+ assert_equal ['-'],
+ scan('op', '-a')
+ assert_equal ['+'],
+ scan('op', '+a')
+ assert_equal ['[]'],
+ scan('op', ':[]')
+ assert_equal ['[]='],
+ scan('op', ':[]=')
+ assert_equal [],
+ scan('op', %q[`make all`])
+ end
+
+ def test_symbeg
+ assert_equal [],
+ scan('symbeg', '')
+ assert_equal [':'],
+ scan('symbeg', ':sym')
+ assert_equal [':'],
+ scan('symbeg', '[1,2,3,:sym]')
+ assert_equal [],
+ scan('symbeg', '":sym"')
+ assert_equal [],
+ scan('symbeg', 'a ? b : c')
+ end
+
+ def test_tstring_beg
+ assert_equal [],
+ scan('tstring_beg', '')
+ assert_equal ['"'],
+ scan('tstring_beg', '"abcdef"')
+ assert_equal ['%q['],
+ scan('tstring_beg', '%q[abcdef]')
+ assert_equal ['%Q['],
+ scan('tstring_beg', '%Q[abcdef]')
+ end
+
+ def test_tstring_content
+ assert_equal [],
+ scan('tstring_content', '')
+ assert_equal ['abcdef'],
+ scan('tstring_content', '"abcdef"')
+ assert_equal ['abcdef'],
+ scan('tstring_content', '%q[abcdef]')
+ assert_equal ['abcdef'],
+ scan('tstring_content', '%Q[abcdef]')
+ assert_equal ['abc', 'def'],
+ scan('tstring_content', '"abc#{1}def"')
+ assert_equal ['sym'],
+ scan('tstring_content', ':"sym"')
+ end
+
+ def test_tstring_end
+ assert_equal [],
+ scan('tstring_end', '')
+ assert_equal ['"'],
+ scan('tstring_end', '"abcdef"')
+ assert_equal [']'],
+ scan('tstring_end', '%q[abcdef]')
+ assert_equal [']'],
+ scan('tstring_end', '%Q[abcdef]')
+ end
+
+ def test_regexp_beg
+ assert_equal [],
+ scan('regexp_beg', '')
+ assert_equal ['/'],
+ scan('regexp_beg', '/re/')
+ assert_equal ['%r<'],
+ scan('regexp_beg', '%r<re>')
+ assert_equal [],
+ scan('regexp_beg', '5 / 5')
+ end
+
+ def test_regexp_end
+ assert_equal [],
+ scan('regexp_end', '')
+ assert_equal ['/'],
+ scan('regexp_end', '/re/')
+ assert_equal ['>'],
+ scan('regexp_end', '%r<re>')
+ end
+
+ def test_words_beg
+ assert_equal [],
+ scan('words_beg', '')
+ assert_equal ['%W('],
+ scan('words_beg', '%W()')
+ assert_equal ['%W('],
+ scan('words_beg', '%W(w w w)')
+ assert_equal ['%W( '],
+ scan('words_beg', '%W( w w w )')
+ end
+
+ def test_qwords_beg
+ assert_equal [],
+ scan('qwords_beg', '')
+ assert_equal ['%w('],
+ scan('qwords_beg', '%w()')
+ assert_equal ['%w('],
+ scan('qwords_beg', '%w(w w w)')
+ assert_equal ['%w( '],
+ scan('qwords_beg', '%w( w w w )')
+ end
+
+ # FIXME: Close paren must not present (`words_end' scanner event?).
+ def test_words_sep
+ assert_equal [],
+ scan('words_sep', '')
+ assert_equal [')'],
+ scan('words_sep', '%w()')
+ assert_equal [' ', ' ', ')'],
+ scan('words_sep', '%w(w w w)')
+ assert_equal [' ', ' ', ' )'],
+ scan('words_sep', '%w( w w w )')
+ assert_equal ["\n", ' ', ' )'],
+ scan('words_sep', "%w( w\nw w )")
+ end
+
+ def test_heredoc_beg
+ assert_equal [],
+ scan('heredoc_beg', '')
+ assert_equal ['<<EOS'],
+ scan('heredoc_beg', "<<EOS\nheredoc\nEOS")
+ assert_equal ['<<EOS'],
+ scan('heredoc_beg', "<<EOS\nheredoc\nEOS\n")
+ assert_equal ['<<EOS'],
+ scan('heredoc_beg', "<<EOS\nheredoc\nEOS \n")
+ assert_equal ['<<-EOS'],
+ scan('heredoc_beg', "<<-EOS\nheredoc\n\tEOS \n")
+ assert_equal ['<<"EOS"'],
+ scan('heredoc_beg', %Q[<<"EOS"\nheredoc\nEOS])
+ assert_equal [%q(<<'EOS')],
+ scan('heredoc_beg', "<<'EOS'\nheredoc\nEOS")
+ assert_equal [%q(<<`EOS`)],
+ scan('heredoc_beg', "<<`EOS`\nheredoc\nEOS")
+ assert_equal [%q(<<" ")],
+ scan('heredoc_beg', %Q[<<" "\nheredoc\nEOS])
+ end
+
+ def test_tstring_content_HEREDOC
+ assert_equal [],
+ scan('tstring_content', '')
+ assert_equal ["heredoc\n"],
+ scan('tstring_content', "<<EOS\nheredoc\nEOS")
+ assert_equal ["heredoc\n"],
+ scan('tstring_content', "<<EOS\nheredoc\nEOS\n")
+ assert_equal ["heredoc \n"],
+ scan('tstring_content', "<<EOS\nheredoc \nEOS \n")
+ assert_equal ["heredoc\n"],
+ scan('tstring_content', "<<-EOS\nheredoc\n\tEOS \n")
+ end
+
+ def test_heredoc_end
+ assert_equal [],
+ scan('heredoc_end', '')
+ assert_equal ["EOS"],
+ scan('heredoc_end', "<<EOS\nheredoc\nEOS")
+ assert_equal ["EOS\n"],
+ scan('heredoc_end', "<<EOS\nheredoc\nEOS\n")
+ assert_equal ["EOS \n"],
+ scan('heredoc_end', "<<EOS\nheredoc\nEOS \n")
+ assert_equal ["\tEOS \n"],
+ scan('heredoc_end', "<<-EOS\nheredoc\n\tEOS \n")
+ end
+
+ def test_semicolon
+ assert_equal [],
+ scan('semicolon', '')
+ assert_equal %w(;),
+ scan('semicolon', ';')
+ assert_equal %w(; ;),
+ scan('semicolon', '; ;')
+ assert_equal %w(; ; ;),
+ scan('semicolon', 'nil;nil;nil;')
+ assert_equal %w(; ; ;),
+ scan('semicolon', 'nil;nil;nil;nil')
+ assert_equal [],
+ scan('semicolon', '";"')
+ assert_equal [],
+ scan('semicolon', '%w(;)')
+ assert_equal [],
+ scan('semicolon', '/;/')
+ end
+
+ def test_comment
+ assert_equal [],
+ scan('comment', '')
+ assert_equal ['# comment'],
+ scan('comment', '# comment')
+ assert_equal ["# comment\n"],
+ scan('comment', "# comment\n")
+ assert_equal ["# comment\n"],
+ scan('comment', "# comment\n1 + 1")
+ assert_equal ["# comment\n"],
+ scan('comment', "1 + 1 + 1# comment\n1 + 1")
+ end
+
+ def test_embdoc_beg
+ assert_equal [],
+ scan('embdoc_beg', '')
+ assert_equal ["=begin\n"],
+ scan('embdoc_beg', "=begin\ndoc\n=end")
+ assert_equal ["=begin \n"],
+ scan('embdoc_beg', "=begin \ndoc\n=end\n")
+ assert_equal ["=begin comment\n"],
+ scan('embdoc_beg', "=begin comment\ndoc\n=end\n")
+ end
+
+ def test_embdoc
+ assert_equal [],
+ scan('embdoc', '')
+ assert_equal ["doc\n"],
+ scan('embdoc', "=begin\ndoc\n=end")
+ assert_equal ["doc\n"],
+ scan('embdoc', "=begin\ndoc\n=end\n")
+ end
+
+ def test_embdoc_end
+ assert_equal [],
+ scan('embdoc_end', '')
+ assert_equal ["=end"],
+ scan('embdoc_end', "=begin\ndoc\n=end")
+ assert_equal ["=end\n"],
+ scan('embdoc_end', "=begin\ndoc\n=end\n")
+ end
+
+ def test_sp
+ assert_equal [],
+ scan('sp', '')
+ assert_equal [' '],
+ scan('sp', ' ')
+ assert_equal [' '],
+ scan('sp', ' 1')
+ assert_equal [],
+ scan('sp', "\n")
+ assert_equal [' '],
+ scan('sp', " \n")
+ assert_equal [' ', ' '],
+ scan('sp', "1 + 1")
+ assert_equal [],
+ scan('sp', "' '")
+ assert_equal [],
+ scan('sp', "%w( )")
+ assert_equal [],
+ scan('sp', "%w( w )")
+ assert_equal [],
+ scan('sp', "p(/ /)")
+ end
+
+ # `nl' event always means End-Of-Statement.
+ def test_nl
+ assert_equal [],
+ scan('nl', '')
+ assert_equal [],
+ scan('nl', "\n")
+ assert_equal ["\n"],
+ scan('nl', "1 + 1\n")
+ assert_equal ["\n", "\n"],
+ scan('nl', "1 + 1\n2 + 2\n")
+ assert_equal [],
+ scan('nl', "1 +\n1")
+ assert_equal [],
+ scan('nl', "1;\n")
+ assert_equal ["\r\n"],
+ scan('nl', "1 + 1\r\n")
+ assert_equal [],
+ scan('nl', "1;\r\n")
+ end
+
+ def test_ignored_nl
+ assert_equal [],
+ scan('ignored_nl', '')
+ assert_equal ["\n"],
+ scan('ignored_nl', "\n")
+ assert_equal [],
+ scan('ignored_nl', "1 + 1\n")
+ assert_equal [],
+ scan('ignored_nl', "1 + 1\n2 + 2\n")
+ assert_equal ["\n"],
+ scan('ignored_nl', "1 +\n1")
+ assert_equal ["\n"],
+ scan('ignored_nl', "1;\n")
+ assert_equal [],
+ scan('ignored_nl', "1 + 1\r\n")
+ assert_equal ["\r\n"],
+ scan('ignored_nl', "1;\r\n")
+ end
+
+ def test___end__
+ assert_equal [],
+ scan('__end__', "")
+ assert_equal ["__END__"],
+ scan('__end__', "__END__")
+ assert_equal ["__END__\n"],
+ scan('__end__', "__END__\n")
+ assert_equal ["__END__\n"],
+ Ripper.tokenize("__END__\njunk junk junk")
+ assert_equal ["__END__"],
+ scan('__end__', "1\n__END__")
+ assert_equal [],
+ scan('__end__', "print('__END__')")
+ end
+
+ def test_CHAR
+ assert_equal [],
+ scan('CHAR', "")
+ assert_equal ["@"],
+ scan('CHAR', "@")
+ assert_equal [],
+ scan('CHAR', "@ivar")
+ end
+
+ def test_label
+ end
+
+ def test_tlambda
+ end
+
+ def test_tlambeg
+ end
+
+ def test_tlambda_arg
+ end
+
+end
+
+rescue LoadError
+end
diff --git a/trunk/test/rss/dot.png b/trunk/test/rss/dot.png
new file mode 100644
index 0000000000..9c6960fa2f
--- /dev/null
+++ b/trunk/test/rss/dot.png
Binary files differ
diff --git a/trunk/test/rss/rss-assertions.rb b/trunk/test/rss/rss-assertions.rb
new file mode 100644
index 0000000000..12e53f7cd5
--- /dev/null
+++ b/trunk/test/rss/rss-assertions.rb
@@ -0,0 +1,2086 @@
+require 'erb'
+
+module RSS
+ module Assertions
+ def assert_parse(rss, assert_method, *args)
+ __send__("assert_#{assert_method}", *args) do
+ ::RSS::Parser.parse(rss)
+ end
+ __send__("assert_#{assert_method}", *args) do
+ ::RSS::Parser.parse(rss, false).validate
+ end
+ end
+
+ def assert_ns(prefix, uri)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise NSError")
+ rescue ::RSS::NSError => e
+ assert_equal(prefix, e.prefix)
+ assert_equal(uri, e.uri)
+ end
+ end
+ end
+
+ def assert_missing_tag(tag, parent)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise MissingTagError")
+ rescue ::RSS::MissingTagError => e
+ assert_equal(tag, e.tag)
+ assert_equal(parent, e.parent)
+ end
+ end
+ end
+
+ def assert_too_much_tag(tag, parent)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise TooMuchTagError")
+ rescue ::RSS::TooMuchTagError => e
+ assert_equal(tag, e.tag)
+ assert_equal(parent, e.parent)
+ end
+ end
+ end
+
+ def assert_missing_attribute(tag, attrname)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise MissingAttributeError")
+ rescue ::RSS::MissingAttributeError => e
+ assert_equal(tag, e.tag)
+ assert_equal(attrname, e.attribute)
+ end
+ end
+ end
+
+ def assert_not_expected_tag(tag, uri, parent)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise NotExpectedTagError")
+ rescue ::RSS::NotExpectedTagError => e
+ assert_equal(tag, e.tag)
+ assert_equal(uri, e.uri)
+ assert_equal(parent, e.parent)
+ end
+ end
+ end
+
+ def assert_not_available_value(tag, value, attribute=nil)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise NotAvailableValueError")
+ rescue ::RSS::NotAvailableValueError => e
+ assert_equal(tag, e.tag)
+ assert_equal(value, e.value)
+ assert_equal(attribute, e.attribute)
+ end
+ end
+ end
+
+ def assert_not_set_error(name, variables)
+ _wrap_assertion do
+ begin
+ yield
+ flunk("Not raise NotSetError")
+ rescue ::RSS::NotSetError => e
+ assert_equal(name, e.name)
+ assert_kind_of(Array, variables)
+ assert_equal(variables.sort, e.variables.sort)
+ end
+ end
+ end
+
+ def assert_xml_declaration(version, encoding, standalone, rss)
+ _wrap_assertion do
+ assert_equal(version, rss.version)
+ assert_equal(encoding, rss.encoding)
+ assert_equal(standalone, rss.standalone)
+ end
+ end
+
+ def assert_xml_stylesheet_attrs(attrs, xsl)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+ ::RSS::XMLStyleSheet::ATTRIBUTES.each do |name|
+ assert_equal(n_attrs[name], xsl.__send__(name))
+ end
+ end
+ end
+
+ def assert_xml_stylesheet(target, attrs, xsl)
+ _wrap_assertion do
+ if attrs.has_key?(:href)
+ if !attrs.has_key?(:type) and attrs.has_key?(:guess_type)
+ attrs[:type] = attrs[:guess_type]
+ end
+ assert_equal("xml-stylesheet", target)
+ assert_xml_stylesheet_attrs(attrs, xsl)
+ else
+ assert_nil(target)
+ assert_equal("", xsl.to_s)
+ end
+ end
+ end
+
+ def assert_xml_stylesheet_pis(attrs_ary, rss=nil)
+ _wrap_assertion do
+ if rss.nil?
+ rss = ::RSS::RDF.new
+ setup_rss10(rss)
+ end
+ xss_strs = []
+ attrs_ary.each do |attrs|
+ xss = ::RSS::XMLStyleSheet.new(attrs)
+ xss_strs.push(xss.to_s)
+ rss.xml_stylesheets.push(xss)
+ end
+ pi_str = rss.to_s.gsub(/<\?xml .*\n/, "").gsub(/\s*<[^\?].*\z/m, "")
+ assert_equal(xss_strs.join("\n"), pi_str)
+ end
+ end
+
+ def assert_xml_stylesheets(attrs, xss)
+ _wrap_assertion do
+ xss.each_with_index do |xs, i|
+ assert_xml_stylesheet_attrs(attrs[i], xs)
+ end
+ end
+ end
+
+
+ def assert_atom_person(tag_name, generator)
+ _wrap_assertion do
+ name = "Mark Pilgrim"
+ uri = "http://example.org/"
+ email = "f8dy@example.com"
+
+ assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name)
+ <#{tag_name}/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name)
+ <#{tag_name}>
+ <uri>#{uri}</uri>
+ <email>#{email}</email>
+ </#{tag_name}>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <#{tag_name}>
+ <name>#{name}</name>
+ </#{tag_name}>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <#{tag_name}>
+ <name>#{name}</name>
+ <uri>#{uri}</uri>
+ <email>#{email}</email>
+ </#{tag_name}>
+EOA
+
+ person = yield(feed)
+ assert_not_nil(person)
+ assert_equal(name, person.name.content)
+ assert_equal(uri, person.uri.content)
+ assert_equal(email, person.email.content)
+ end
+ end
+
+ def assert_atom_category(generator)
+ _wrap_assertion do
+ term = "Music"
+ scheme = "http://xmlns.com/wordnet/1.6/"
+ label = "music"
+
+ missing_args = [:missing_attribute, "category", "term"]
+ assert_parse(generator.call(<<-EOA), *missing_args)
+ <category/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), *missing_args)
+ <category scheme="#{scheme}" label="#{label}"/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <category term="#{term}"/>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <category term="#{term}" scheme="#{scheme}" label="#{label}"/>
+EOA
+
+ category = yield(feed)
+ assert_not_nil(category)
+ assert_equal(term, category.term)
+ assert_equal(scheme, category.scheme)
+ assert_equal(label, category.label)
+ end
+ end
+
+ def assert_atom_link(generator)
+ _wrap_assertion do
+ href = "http://example.org/feed.atom"
+ rel = "self"
+ type = "application/atom+xml"
+ hreflang = "en"
+ title = "Atom"
+ length = "1024"
+
+ assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href")
+ <link/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href")
+ <link rel="#{rel}" type="#{type}" hreflang="#{hreflang}"
+ title="#{title}" length="#{length}"/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <link href="#{href}"/>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <link href="#{href}" rel="#{rel}" type="#{type}" hreflang="#{hreflang}"
+ title="#{title}" length="#{length}"/>
+EOA
+
+ link = yield(feed)
+ assert_not_nil(link)
+ assert_equal(href, link.href)
+ assert_equal(rel, link.rel)
+ assert_equal(type, link.type)
+ assert_equal(hreflang, link.hreflang)
+ assert_equal(title, link.title)
+ assert_equal(length, link.length)
+
+
+ href = "http://example.org/index.html.ja"
+ parent = link.parent.tag_name
+ return if parent == "source"
+
+ optional_attributes = %w(hreflang="ja" type="text/html")
+ 0.upto(optional_attributes.size) do |i|
+ combination(optional_attributes, i).each do |attributes|
+ attrs = attributes.join(" ")
+ assert_parse(generator.call(<<-EOA), :too_much_tag, "link", parent)
+ <link rel="alternate" #{attrs} href="#{href}"/>
+ <link rel="alternate" #{attrs} href="#{href}"/>
+EOA
+ end
+ end
+ end
+ end
+
+ def assert_atom_generator(generator)
+ _wrap_assertion do
+ uri = "http://www.example.com/"
+ version = "1.0"
+ content = "Example Toolkit"
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <generator/>
+EOA
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <generator uri="#{uri}" version="#{version}"/>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <generator uri="#{uri}" version="#{version}">#{content}</generator>
+EOA
+
+ gen = yield(feed)
+ assert_not_nil(gen)
+ assert_equal(uri, gen.uri)
+ assert_equal(version, gen.version)
+ assert_equal(content, gen.content)
+ end
+ end
+
+ def assert_atom_icon(generator)
+ _wrap_assertion do
+ content = "http://www.example.com/example.png"
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <icon/>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <icon>#{content}</icon>
+EOA
+
+ icon = yield(feed)
+ assert_not_nil(icon)
+ assert_equal(content, icon.content)
+ end
+ end
+
+ def assert_atom_text_construct(tag_name, generator)
+ _wrap_assertion do
+ [nil, "text", "html"].each do |type|
+ attr = ""
+ attr = " type=\"#{type}\""if type
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <#{tag_name}#{attr}/>
+EOA
+ end
+
+ assert_parse(generator.call(<<-EOA), :missing_tag, "div", tag_name)
+ <#{tag_name} type="xhtml"/>
+EOA
+
+ args = ["x", Atom::URI, tag_name]
+ assert_parse(generator.call(<<-EOA), :not_expected_tag, *args)
+ <#{tag_name} type="xhtml"><x/></#{tag_name}>
+EOA
+
+ invalid_value = "invalid"
+ args = ["type", invalid_value]
+ assert_parse(generator.call(<<-EOA), :not_available_value, *args)
+ <#{tag_name} type="#{invalid_value}"/>
+EOA
+
+ [
+ [nil, "A lot of effort went into making this effortless"],
+ ["text", "A lot of effort went into making this effortless"],
+ ["html", "A <em>lot</em> of effort went into making this effortless"],
+ ].each do |type, content|
+ attr = ""
+ attr = " type=\"#{type}\"" if type
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <#{tag_name}#{attr}>#{h content}</#{tag_name}>
+EOA
+
+ element = yield(feed)
+ assert_not_nil(element)
+ assert_equal(type, element.type)
+ assert_equal(content, element.content)
+ end
+
+ [false, true].each do |with_space|
+ xhtml_uri = "http://www.w3.org/1999/xhtml"
+ xhtml_content = "<div xmlns=\"#{xhtml_uri}\">abc</div>"
+ xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ ["abc"])
+ content = xhtml_content
+ content = " #{content} " if with_space
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <#{tag_name} type="xhtml">#{content}</#{tag_name}>
+EOA
+
+ element = yield(feed)
+ assert_not_nil(element)
+ assert_equal("xhtml", element.type)
+ assert_equal(xhtml_content, element.content)
+ assert_equal(xhtml_element, element.xhtml)
+ end
+ end
+ end
+
+ def assert_atom_date_construct(tag_name, generator)
+ _wrap_assertion do
+ args = [tag_name, ""]
+ assert_parse(generator.call(<<-EOR), :not_available_value, *args)
+ <#{tag_name}/>
+EOR
+
+ [
+ ["xxx", false],
+ ["2007", false],
+ ["2007/02/09", true],
+ ].each do |invalid_value, can_parse|
+ assert_not_available_value(tag_name, invalid_value) do
+ RSS::Parser.parse(generator.call(<<-EOR))
+ <#{tag_name}>#{invalid_value}</#{tag_name}>
+EOR
+ end
+
+ feed = RSS::Parser.parse(generator.call(<<-EOR), false)
+ <#{tag_name}>#{invalid_value}</#{tag_name}>
+EOR
+ value = yield(feed).content
+ if can_parse
+ assert_equal(Time.parse(invalid_value), value)
+ else
+ assert_nil(value)
+ end
+ end
+
+ [
+ "2003-12-13T18:30:02Z",
+ "2003-12-13T18:30:02.25Z",
+ "2003-12-13T18:30:02+01:00",
+ "2003-12-13T18:30:02.25+01:00",
+ ].each do |valid_value|
+ assert_parse(generator.call(<<-EOR), :nothing_raised)
+ <#{tag_name}>#{valid_value}</#{tag_name}>
+EOR
+
+ feed = RSS::Parser.parse(generator.call(<<-EOR))
+ <#{tag_name}>#{valid_value}</#{tag_name}>
+EOR
+ assert_equal(Time.parse(valid_value), yield(feed).content)
+ end
+ end
+ end
+
+ def assert_atom_logo(generator)
+ _wrap_assertion do
+ content = "http://www.example.com/example.png"
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <logo/>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <logo>#{content}</logo>
+EOA
+
+ logo = yield(feed)
+ assert_not_nil(logo)
+ assert_equal(content, logo.content)
+ end
+ end
+
+ def assert_atom_content(generator, &getter)
+ _wrap_assertion do
+ assert_atom_content_inline_text(generator, &getter)
+ assert_atom_content_inline_xhtml(generator, &getter)
+ assert_atom_content_inline_other(generator, &getter)
+ assert_atom_content_out_of_line(generator, &getter)
+ end
+ end
+
+ def assert_atom_content_inline_text(generator)
+ _wrap_assertion do
+ [nil, "text", "html"].each do |type|
+ content = "<content"
+ content << " type='#{type}'" if type
+
+ suffix = "/>"
+ assert_parse(generator.call(content + suffix), :nothing_raised)
+ suffix = ">xxx</content>"
+ assert_parse(generator.call(content + suffix), :nothing_raised)
+ end
+
+ [
+ ["text", "sample content"],
+ ["text/plain", "sample content"],
+ ["html", "<em>sample</em> content"]
+ ].each do |type, content_content|
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <content type="#{type}">#{h content_content}</content>
+EOA
+ content = yield(feed)
+ assert_equal(type, content.type)
+ if %w(text html).include?(type)
+ assert(content.inline_text?)
+ else
+ assert(!content.inline_text?)
+ end
+ if type == "html"
+ assert(content.inline_html?)
+ else
+ assert(!content.inline_html?)
+ end
+ assert(!content.inline_xhtml?)
+ if type == "text/plain"
+ assert(content.inline_other?)
+ assert(content.inline_other_text?)
+ else
+ assert(!content.inline_other?)
+ assert(!content.inline_other_text?)
+ end
+ assert(!content.inline_other_xml?)
+ assert(!content.inline_other_base64?)
+ assert(!content.out_of_line?)
+ assert(!content.have_xml_content?)
+ assert_equal(content_content, content.content)
+ end
+ end
+ end
+
+ def assert_atom_content_inline_xhtml(generator)
+ _wrap_assertion do
+ args = ["div", "content"]
+ assert_parse(generator.call(<<-EOA), :missing_tag, *args)
+ <content type="xhtml"/>
+EOA
+
+ args = ["x", Atom::URI, "content"]
+ assert_parse(generator.call(<<-EOA), :not_expected_tag, *args)
+ <content type="xhtml"><x/></content>
+EOA
+
+ xhtml_uri = "http://www.w3.org/1999/xhtml"
+ xhtml_content = "<div xmlns=\"#{xhtml_uri}\">abc</div>"
+ xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ ["abc"])
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <content type="xhtml">#{xhtml_content}</content>
+EOA
+
+ content = yield(feed)
+ assert_not_nil(content)
+ assert_equal("xhtml", content.type)
+ assert(!content.inline_text?)
+ assert(!content.inline_html?)
+ assert(content.inline_xhtml?)
+ assert(!content.inline_other?)
+ assert(!content.inline_other_text?)
+ assert(!content.inline_other_xml?)
+ assert(!content.inline_other_base64?)
+ assert(!content.out_of_line?)
+ assert(content.have_xml_content?)
+ assert_equal(xhtml_content, content.content)
+ assert_equal(xhtml_element, content.xhtml)
+ end
+ end
+
+ def assert_atom_content_inline_other(generator, &getter)
+ _wrap_assertion do
+ assert_atom_content_inline_other_text(generator, &getter)
+ assert_atom_content_inline_other_xml(generator, &getter)
+ end
+ end
+
+ def assert_atom_content_inline_other_text(generator)
+ _wrap_assertion do
+ type = "image/png"
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <content type="#{type}"/>
+EOA
+
+ png_file = File.join(File.dirname(__FILE__), "dot.png")
+ png = File.open(png_file, "rb") do |file|
+ file.read.force_encoding("binary")
+ end
+ base64_content = [png].pack("m").delete("\n")
+
+ [false, true].each do |with_space|
+ xml_content = base64_content
+ xml_content = " #{base64_content}" if with_space
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <content type="#{type}">#{xml_content}</content>
+EOA
+
+ content = yield(feed)
+ assert_not_nil(content)
+ assert_equal(type, content.type)
+ assert(!content.inline_text?)
+ assert(!content.inline_html?)
+ assert(!content.inline_xhtml?)
+ assert(content.inline_other?)
+ assert(!content.inline_other_text?)
+ assert(!content.inline_other_xml?)
+ assert(content.inline_other_base64?)
+ assert(!content.out_of_line?)
+ assert(!content.have_xml_content?)
+ assert_equal(png, content.content)
+
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([], {"type" => type}, base64_content, xml)
+ end
+ end
+ end
+
+ def assert_atom_content_inline_other_xml(generator)
+ _wrap_assertion do
+ type = "image/svg+xml"
+
+ assert_parse(generator.call(<<-EOA), :nothing_raised)
+ <content type="#{type}"/>
+EOA
+
+ svg_uri = "http://www.w3.org/2000/svg"
+ svg_width = "50pt"
+ svg_height = "20pt"
+ svg_version = "1.0"
+ text_x = "15"
+ text_y = "15"
+ text = "text"
+ svg_content = <<-EOS
+<svg
+ xmlns="#{svg_uri}"
+ width="#{svg_width}"
+ height="#{svg_height}"
+ version="#{svg_version}"
+><text x="#{text_x}" y="#{text_y}">#{text}</text
+></svg>
+EOS
+
+ text_element = RSS::XML::Element.new("text", nil, svg_uri,
+ {
+ "x" => text_x,
+ "y" => text_y,
+ },
+ [text])
+ svg_element = RSS::XML::Element.new("svg", nil, svg_uri,
+ {
+ "xmlns" => svg_uri,
+ "width" => svg_width,
+ "height" => svg_height,
+ "version" => svg_version,
+ },
+ [text_element])
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <content type="#{type}">#{svg_content}</content>
+EOA
+
+ content = yield(feed)
+ assert_not_nil(content)
+ assert_equal(type, content.type)
+ assert(!content.inline_text?)
+ assert(!content.inline_html?)
+ assert(!content.inline_xhtml?)
+ assert(content.inline_other?)
+ assert(!content.inline_other_text?)
+ assert(content.inline_other_xml?)
+ assert(!content.inline_other_base64?)
+ assert(!content.out_of_line?)
+ assert(content.have_xml_content?)
+ assert_equal(REXML::Document.new(svg_content).to_s.chomp,
+ REXML::Document.new(content.content).to_s.chomp)
+ assert_equal(svg_element, content.xml)
+ assert_nil(content.xhtml)
+ end
+ end
+
+ def assert_atom_content_out_of_line(generator)
+ _wrap_assertion do
+ text_type = "text/plain"
+ text_src = "http://example.com/README.txt"
+
+ missing_args = [:missing_attribute, "content", "type"]
+ # RSS Parser raises error even if this is "should" not "must".
+ assert_parse(generator.call(<<-EOA), *missing_args)
+ <content src="#{text_src}"/>
+EOA
+
+ content_content = "xxx"
+ not_available_value_args = [:not_available_value,
+ "content", content_content]
+ assert_parse(generator.call(<<-EOA), *not_available_value_args)
+ <content type="#{text_type}" src="#{text_src}">#{content_content}</content>
+EOA
+
+ feed = RSS::Parser.parse(generator.call(<<-EOA))
+ <content type="#{text_type}" src="#{text_src}"/>
+EOA
+ content = yield(feed)
+ assert_not_nil(content)
+ assert_equal(text_type, content.type)
+ assert_equal(text_src, content.src)
+ assert(!content.inline_text?)
+ assert(!content.inline_html?)
+ assert(!content.inline_xhtml?)
+ assert(!content.inline_other?)
+ assert(!content.inline_other_text?)
+ assert(!content.inline_other_xml?)
+ assert(!content.inline_other_base64?)
+ assert(content.out_of_line?)
+ assert(!content.have_xml_content?)
+ assert_nil(content.xml)
+ assert_nil(content.xhtml)
+ assert_equal("", content.content)
+ end
+ end
+
+ def assert_atom_source(generator, &getter)
+ _wrap_assertion do
+ assert_atom_source_author(generator, &getter)
+ assert_atom_source_category(generator, &getter)
+ assert_atom_source_contributor(generator, &getter)
+ assert_atom_source_generator(generator, &getter)
+ assert_atom_source_icon(generator, &getter)
+ assert_atom_source_id(generator, &getter)
+ assert_atom_source_link(generator, &getter)
+ assert_atom_source_logo(generator, &getter)
+ assert_atom_source_rights(generator, &getter)
+ assert_atom_source_subtitle(generator, &getter)
+ assert_atom_source_title(generator, &getter)
+ assert_atom_source_updated(generator, &getter)
+ end
+ end
+
+ def assert_atom_source_author(generator)
+ assert_atom_person("author", generator) do |feed|
+ source = yield(feed)
+ assert_equal(1, source.authors.size)
+ source.author
+ end
+ end
+
+ def assert_atom_source_category(generator)
+ assert_atom_category(generator) do |feed|
+ source = yield(feed)
+ assert_equal(1, source.categories.size)
+ source.category
+ end
+ end
+
+ def assert_atom_source_contributor(generator)
+ assert_atom_person("contributor", generator) do |feed|
+ source = yield(feed)
+ assert_equal(1, source.contributors.size)
+ source.contributor
+ end
+ end
+
+ def assert_atom_source_generator(generator)
+ assert_atom_generator(generator) do |feed|
+ yield(feed).generator
+ end
+ end
+
+ def assert_atom_source_icon(generator)
+ assert_atom_icon(generator) do |feed|
+ yield(feed).icon
+ end
+ end
+
+ def assert_atom_source_id(generator)
+ id_content = "urn:uuid:a2fb588b-5674-4898-b420-265a734fea69"
+ id = "<id>#{id_content}</id>"
+ feed = RSS::Parser.parse(generator.call(id))
+ assert_equal(id_content, yield(feed).id.content)
+ end
+
+ def assert_atom_source_link(generator)
+ assert_atom_link(generator) do |feed|
+ source = yield(feed)
+ assert_equal(1, source.links.size)
+ source.link
+ end
+ end
+
+ def assert_atom_source_logo(generator)
+ assert_atom_logo(generator) do |feed|
+ yield(feed).logo
+ end
+ end
+
+ def assert_atom_source_rights(generator)
+ assert_atom_text_construct("rights", generator) do |feed|
+ yield(feed).rights
+ end
+ end
+
+ def assert_atom_source_subtitle(generator)
+ assert_atom_text_construct("subtitle", generator) do |feed|
+ yield(feed).subtitle
+ end
+ end
+
+ def assert_atom_source_title(generator)
+ assert_atom_text_construct("title", generator) do |feed|
+ yield(feed).title
+ end
+ end
+
+ def assert_atom_source_updated(generator)
+ assert_atom_date_construct("updated", generator) do |feed|
+ yield(feed).updated
+ end
+ end
+
+ def assert_dublin_core(elems, target)
+ _wrap_assertion do
+ elems.each do |name, value|
+ assert_equal(value, target.__send__("dc_#{name}"))
+ end
+ end
+ end
+
+ def assert_multiple_dublin_core(elems, target)
+ _wrap_assertion do
+ elems.each do |name, values, plural|
+ plural ||= "#{name}s"
+ actual = target.__send__("dc_#{plural}").collect{|x| x.value}
+ assert_equal(values, actual)
+ end
+ end
+ end
+
+ def assert_syndication(elems, target)
+ _wrap_assertion do
+ elems.each do |name, value|
+ meth = "sy_#{name}"
+ value = value.to_i if meth == "sy_updateFrequency"
+ assert_equal(value, target.__send__(meth ))
+ end
+ end
+ end
+
+ def assert_content(elems, target)
+ _wrap_assertion do
+ elems.each do |name, value|
+ assert_equal(value, target.__send__("content_#{name}"))
+ end
+ end
+ end
+
+ def assert_trackback(attrs, target)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+ if n_attrs["ping"]
+ assert_equal(n_attrs["ping"], target.trackback_ping)
+ end
+ if n_attrs["abouts"]
+ n_attrs["abouts"].each_with_index do |about, i|
+ assert_equal(about, target.trackback_abouts[i].value)
+ end
+ end
+ end
+ end
+
+ def assert_taxo_topic(topics, target)
+ _wrap_assertion do
+ topics.each_with_index do |topic, i|
+ taxo_topic = target.taxo_topics[i]
+ topic.each do |name, value|
+ case name
+ when :link
+ assert_equal(value, taxo_topic.about)
+ assert_equal(value, taxo_topic.taxo_link)
+ when :topics
+ assert_equal(value, taxo_topic.taxo_topics.resources)
+ else
+ assert_equal(value, taxo_topic.__send__("dc_#{name}"))
+ end
+ end
+ end
+ end
+ end
+
+
+ def assert_attributes(attrs, names, target)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+ names.each do |info|
+ if info.is_a?(String)
+ name = info
+ type = nil
+ else
+ name, type = info
+ end
+ value = n_attrs[name]
+ if value.is_a?(Time)
+ actual = target.__send__(name)
+ assert_instance_of(Time, actual)
+ assert_equal(value.to_i, actual.to_i)
+ elsif value
+ case type
+ when :integer
+ value = value.to_i
+ when :boolean
+ value = value == "true" if value.is_a?(String)
+ end
+ assert_equal(value, target.__send__(name))
+ end
+ end
+ end
+ end
+
+ def assert_rexml_element(children, attrs, text, element, text_type=nil)
+ _wrap_assertion do
+ if children
+ children_info = element.elements.collect {|e| [e.namespace, e.name]}
+ assert_equal(children.collect {|uri, name| [uri, name]}.sort,
+ children_info.sort)
+ end
+ if attrs
+ assert_equal(attrs.collect {|k, v| [k, v]}.sort,
+ element.attributes.collect {|k, v| [k, v]}.sort)
+ end
+ case text_type
+ when :time
+ assert_not_nil(element.text)
+ assert_equal(Time.parse(text).to_s, Time.parse(element.text).to_s)
+ else
+ assert_equal(text, element.text)
+ end
+ end
+ end
+
+ def _assert_maker_atom_persons(feed_type, maker_readers, feed_readers)
+ _wrap_assertion do
+ persons = []
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ targets.each do |target|
+ person = {
+ :name => target.name,
+ :uri => target.uri,
+ :email => target.email,
+ }
+ persons << person if person[:name]
+ end
+ end
+
+ actual_persons = chain_reader(feed, feed_readers) || []
+ actual_persons = actual_persons.collect do |person|
+ {
+ :name => person.name ? person.name.content : nil,
+ :uri => person.uri ? person.uri.content : nil,
+ :email => person.email ? person.email.content : nil,
+ }
+ end
+ assert_equal(persons, actual_persons)
+ end
+ end
+
+ def assert_maker_atom_persons(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil,
+ parent_not_set_error_name=nil,
+ parent_not_set_variable=nil)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ args = [feed_type, maker_readers, feed_readers]
+ if parent_not_set_error_name or parent_not_set_variable
+ assert_not_set_error(parent_not_set_error_name,
+ parent_not_set_variable) do
+ _assert_maker_atom_persons(*args) do |maker|
+ yield maker
+ end
+ end
+ else
+ _assert_maker_atom_persons(*args) do |maker|
+ yield maker
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(name)) do
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(name)) do
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.uri = "http://example.com/~me/"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(name)) do
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.email = "me@example.com"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(name)) do
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.uri = "http://example.com/~me/"
+ target.email = "me@example.com"
+ end
+ end
+
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.name = "me"
+ end
+
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.name = "me"
+ target.uri = "http://example.com/~me/"
+ end
+
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.name = "me"
+ target.email = "me@example.com"
+ end
+
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ target = targets.new_child
+ target.name = "me"
+ target.uri = "http://example.com/~me/"
+ target.email = "me@example.com"
+ end
+
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+
+ target = targets.new_child
+ target.name = "me"
+ target.uri = "http://example.com/~me/"
+ target.email = "me@example.com"
+
+ target = targets.new_child
+ target.name = "you"
+ target.uri = "http://example.com/~you/"
+ target.email = "you@example.com"
+ end
+
+ assert_not_set_error(not_set_error_name, %w(name)) do
+ _assert_maker_atom_persons(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+
+ target = targets.new_child
+ target.name = "me"
+ target.uri = "http://example.com/~me/"
+ target.email = "me@example.com"
+
+ target = targets.new_child
+ end
+ end
+ end
+ end
+
+ def _assert_maker_atom_text_construct(feed_type, maker_readers,
+ feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ text = {
+ :type => target.type,
+ :content => target.content,
+ :xml_content => target.xml_content,
+ }
+ if text[:type] == "xhtml"
+ if text[:xml_content]
+ xml_content = text[:xml_content]
+ xhtml_uri = "http://www.w3.org/1999/xhtml"
+ unless xml_content.is_a?(RSS::XML::Element) and
+ ["div", xhtml_uri] == [xml_content.name, xml_content.uri]
+ children = xml_content
+ children = [children] unless children.is_a?(Array)
+ xml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ children)
+ text[:xml_content] = xml_content
+ end
+ text
+ else
+ nil
+ end
+ else
+ text[:content] ? text : nil
+ end
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :type => target.type,
+ :content => target.content,
+ :xml_content => target.xhtml,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_text_construct(feed_type, maker_readers, feed_readers,
+ parent_not_set_error_name=nil,
+ parent_not_set_variable=nil,
+ not_set_error_name=nil)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ args = [feed_type, maker_readers, feed_readers]
+ if parent_not_set_error_name or parent_not_set_variable
+ assert_not_set_error(parent_not_set_error_name,
+ parent_not_set_variable) do
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ end
+ end
+ else
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "text"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "html"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "xhtml"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "xhtml"
+ target.content = "Content"
+ end
+ end
+
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "text"
+ target.content = "Content"
+ end
+
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "html"
+ target.content = "<em>Content</em>"
+ end
+
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "xhtml"
+ target.xml_content = "text only"
+ end
+
+ _assert_maker_atom_text_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ target.type = "xhtml"
+ target.xml_content = RSS::XML::Element.new("unknown")
+ end
+ end
+ end
+
+ def _assert_maker_atom_date_construct(feed_type, maker_readers,
+ feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ date = {
+ :content => target,
+ }
+ date[:content] ? date : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :content => target.content,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_date_construct(feed_type, maker_readers, feed_readers,
+ parent_not_set_error_name=nil,
+ parent_not_set_variable=nil)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ if parent_not_set_error_name or parent_not_set_variable
+ assert_not_set_error(parent_not_set_error_name,
+ parent_not_set_variable) do
+ _assert_maker_atom_date_construct(*args) do |maker|
+ yield maker
+ end
+ end
+ else
+ _assert_maker_atom_date_construct(*args) do |maker|
+ yield maker
+ end
+ end
+
+ maker_readers = maker_readers.dup
+ writer = "#{maker_readers.pop}="
+ _assert_maker_atom_date_construct(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.__send__(writer, Time.now)
+ end
+ end
+ end
+
+ def _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor)
+ _wrap_assertion do
+ element = nil
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ element = maker_extractor.call(target)
+ end
+
+ target = chain_reader(feed, feed_readers)
+ if target
+ actual_element = feed_extractor.call(target)
+ else
+ actual_element = nil
+ end
+ assert_equal(element, actual_element)
+ end
+ end
+
+ def _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ invalid_feed_checker=nil)
+ _wrap_assertion do
+ elements = []
+ invalid_feed_exception = nil
+ feed = nil
+ begin
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ targets.each do |target|
+ element = maker_extractor.call(target)
+ elements << element if element
+ end
+ if invalid_feed_checker
+ invalid_feed_exception = invalid_feed_checker.call(targets)
+ end
+ end
+ rescue RSS::Error
+ if invalid_feed_exception.is_a?(RSS::TooMuchTagError)
+ assert_too_much_tag(invalid_feed_exception.tag,
+ invalid_feed_exception.parent) do
+ raise
+ end
+ else
+ raise
+ end
+ end
+
+ if invalid_feed_exception.nil?
+ actual_elements = chain_reader(feed, feed_readers) || []
+ actual_elements = actual_elements.collect do |target|
+ feed_extractor.call(target)
+ end
+ assert_equal(elements, actual_elements)
+ end
+ end
+ end
+
+ def assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ setup_target, optional_variables,
+ required_variable, assert_method_name,
+ not_set_error_name=nil,
+ *additional_args)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ 0.upto(optional_variables.size) do |i|
+ combination(optional_variables, i).each do |names|
+ have = {}
+ names.each do |name|
+ have[name.intern] = true
+ end
+ have_required_variable_too =
+ have.merge({required_variable.intern => true})
+
+ assert_not_set_error(not_set_error_name, [required_variable]) do
+ __send__(assert_method_name, feed_type, maker_readers,
+ feed_readers, *additional_args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ setup_target.call(target, have)
+ end
+ end
+
+ __send__(assert_method_name, feed_type, maker_readers, feed_readers,
+ *additional_args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers) {|x| x}
+ setup_target.call(target, have_required_variable_too)
+ end
+ end
+ end
+ end
+ end
+
+ def assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ setup_target, optional_variables,
+ required_variable, assert_method_name,
+ not_set_error_name=nil,
+ *additional_args)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ 0.upto(optional_variables.size) do |i|
+ combination(optional_variables, i).each do |names|
+ have = {}
+ names.each do |name|
+ have[name.intern] = true
+ end
+ have_required_variable_too =
+ have.merge({required_variable.intern => true})
+
+ assert_not_set_error(not_set_error_name, [required_variable]) do
+ __send__(assert_method_name, feed_type, maker_readers,
+ feed_readers, *additional_args) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ setup_target.call(targets, have)
+ end
+ end
+
+ __send__(assert_method_name, feed_type, maker_readers, feed_readers,
+ *additional_args) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ setup_target.call(targets, have_required_variable_too)
+ end
+
+ __send__(assert_method_name, feed_type, maker_readers, feed_readers,
+ *additional_args) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ setup_target.call(targets, have_required_variable_too)
+ setup_target.call(targets, have_required_variable_too)
+ end
+
+ assert_not_set_error(not_set_error_name, [required_variable]) do
+ __send__(assert_method_name, feed_type, maker_readers, feed_readers,
+ *additional_args) do |maker|
+ yield maker
+ targets = chain_reader(maker, maker_readers)
+ setup_target.call(targets, have_required_variable_too)
+ setup_target.call(targets, have)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def _assert_maker_atom_categories(feed_type, maker_readers,
+ feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ category = {
+ :term => target.term,
+ :scheme => target.scheme,
+ :label => target.label,
+ }
+ category[:term] ? category : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :term => target.term,
+ :scheme => target.scheme,
+ :label => target.label,
+ }
+ end
+ _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor, &block)
+ end
+
+ def assert_maker_atom_categories(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil, &block)
+ _wrap_assertion do
+ _assert_maker_atom_categories(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ end
+
+ setup_target = Proc.new do |targets, have|
+ target = targets.new_child
+ target.term = "music" if have[:term]
+ target.scheme = "http://example.com/category/music" if have[:scheme]
+ target.label = "Music" if have[:label]
+ end
+
+ optional_variables = %w(scheme label)
+
+ assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ setup_target, optional_variables,
+ "term", :_assert_maker_atom_categories,
+ not_set_error_name, &block)
+ end
+ end
+
+ def _assert_maker_atom_generator(feed_type, maker_readers,
+ feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ generator = {
+ :uri => target.uri,
+ :version => target.version,
+ :content => target.content,
+ }
+ generator[:content] ? generator : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :uri => target.uri,
+ :version => target.version,
+ :content => target.content,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_generator(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil, &block)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ _assert_maker_atom_generator(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ end
+
+ setup_target = Proc.new do |target, have|
+ target.content = "RSS Maker" if have[:content]
+ target.uri = "http://example.com/rss/maker" if have[:uri]
+ target.version = "0.0.1" if have[:version]
+ end
+
+ optional_variables = %w(uri version)
+
+ assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ setup_target, optional_variables,
+ "content", :_assert_maker_atom_generator,
+ not_set_error_name, &block)
+ end
+ end
+
+ def _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
+ accessor_base, &block)
+ maker_extractor = Proc.new do |target|
+ icon = {
+ :content => target.__send__(accessor_base),
+ }
+ icon[:content] ? icon : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :content => target.content,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
+ accessor_base=nil, not_set_error_name=nil)
+ _wrap_assertion do
+ accessor_base ||= "url"
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
+ accessor_base) do |maker|
+ yield maker
+ end
+
+ _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
+ accessor_base) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.__send__("#{accessor_base}=", "http://example.com/icon.png")
+ end
+ end
+ end
+
+ def _assert_maker_atom_links(feed_type, maker_readers, feed_readers,
+ allow_duplication=false, &block)
+ maker_extractor = Proc.new do |target|
+ link = {
+ :href => target.href,
+ :rel => target.rel,
+ :type => target.type,
+ :hreflang => target.hreflang,
+ :title => target.title,
+ :length => target.length,
+ }
+ link[:href] ? link : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :href => target.href,
+ :rel => target.rel,
+ :type => target.type,
+ :hreflang => target.hreflang,
+ :title => target.title,
+ :length => target.length,
+ }
+ end
+
+ if feed_readers.first == "entries"
+ parent = "entry"
+ else
+ parent = feed_type
+ end
+ invalid_feed_checker = Proc.new do |targets|
+ infos = {}
+ invalid_exception = nil
+ targets.each do |target|
+ key = [target.hreflang, target.type]
+ if infos.has_key?(key)
+ invalid_exception = RSS::TooMuchTagError.new("link", parent)
+ break
+ end
+ infos[key] = true if target.rel.nil? or target.rel == "alternate"
+ end
+ invalid_exception
+ end
+ invalid_feed_checker = nil if allow_duplication
+ _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ invalid_feed_checker,
+ &block)
+ end
+
+ def assert_maker_atom_links(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil, allow_duplication=false,
+ &block)
+ _wrap_assertion do
+ _assert_maker_atom_links(feed_type, maker_readers,
+ feed_readers) do |maker|
+ yield maker
+ end
+
+ langs = %(ja en fr zh po)
+ setup_target = Proc.new do |targets, have|
+ target = targets.new_child
+ lang = langs[targets.size % langs.size]
+ target.href = "http://example.com/index.html.#{lang}" if have[:href]
+ target.rel = "alternate" if have[:rel]
+ target.type = "text/xhtml" if have[:type]
+ target.hreflang = lang if have[:hreflang]
+ target.title = "FrontPage(#{lang})" if have[:title]
+ target.length = 1024 if have[:length]
+ end
+
+ optional_variables = %w(rel type hreflang title length)
+
+ assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
+ setup_target, optional_variables,
+ "href", :_assert_maker_atom_links,
+ not_set_error_name, allow_duplication,
+ &block)
+ end
+ end
+
+ def _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
+ accessor_base, &block)
+ maker_extractor = Proc.new do |target|
+ logo = {
+ :uri => target.__send__(accessor_base),
+ }
+ logo[:uri] ? logo : nil
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :uri => target.content,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
+ accessor_base=nil, not_set_error_name=nil)
+ _wrap_assertion do
+ accessor_base ||= "uri"
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
+ accessor_base) do |maker|
+ yield maker
+ end
+
+ _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
+ accessor_base) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.__send__("#{accessor_base}=", "http://example.com/logo.png")
+ end
+ end
+ end
+
+ def _assert_maker_atom_id(feed_type, maker_readers, feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ id = {
+ :uri => target.id,
+ }
+ id[:uri] ? id : nil
+ end
+ feed_extractor = Proc.new do |target|
+ if target.id
+ {
+ :uri => target.id.content,
+ }
+ else
+ nil
+ end
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_id(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+
+ args = [feed_type, maker_readers, feed_readers]
+ _assert_maker_atom_id(*args) do |maker|
+ yield maker
+ end
+
+ _assert_maker_atom_id(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.id = "http://example.com/id/1"
+ end
+ end
+ end
+
+ def _assert_maker_atom_content(feed_type, maker_readers,
+ feed_readers, &block)
+ maker_extractor = Proc.new do |target|
+ content = {
+ :type => target.type,
+ :src => target.src,
+ :content => target.content,
+ :xml => target.xml,
+ :inline_text => target.inline_text?,
+ :inline_html => target.inline_html?,
+ :inline_xhtml => target.inline_xhtml?,
+ :inline_other => target.inline_other?,
+ :inline_other_text => target.inline_other_text?,
+ :inline_other_xml => target.inline_other_xml?,
+ :inline_other_base64 => target.inline_other_base64?,
+ :out_of_line => target.out_of_line?,
+ }
+ content[:src] = nil if content[:src] and content[:content]
+ if content[:type] or content[:content]
+ content
+ else
+ nil
+ end
+ end
+ feed_extractor = Proc.new do |target|
+ {
+ :type => target.type,
+ :src => target.src,
+ :content => target.content,
+ :xml => target.xml,
+ :inline_text => target.inline_text?,
+ :inline_html => target.inline_html?,
+ :inline_xhtml => target.inline_xhtml?,
+ :inline_other => target.inline_other?,
+ :inline_other_text => target.inline_other_text?,
+ :inline_other_xml => target.inline_other_xml?,
+ :inline_other_base64 => target.inline_other_base64?,
+ :out_of_line => target.out_of_line?,
+ }
+ end
+ _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
+ maker_extractor, feed_extractor,
+ &block)
+ end
+
+ def assert_maker_atom_content(feed_type, maker_readers, feed_readers,
+ not_set_error_name=nil, &block)
+ _wrap_assertion do
+ not_set_error_name ||= "maker.#{maker_readers.join('.')}"
+ args = [feed_type, maker_readers, feed_readers, not_set_error_name]
+ assert_maker_atom_content_inline_text(*args, &block)
+ assert_maker_atom_content_inline_xhtml(*args, &block)
+ assert_maker_atom_content_inline_other(*args, &block)
+ assert_maker_atom_content_out_of_line(*args, &block)
+ end
+ end
+
+ def assert_maker_atom_content_inline_text(feed_type, maker_readers,
+ feed_readers, not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ end
+
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "text"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "html"
+ end
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.content = ""
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "text"
+ target.content = "example content"
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "html"
+ target.content = "<em>text</em>"
+ end
+ end
+ end
+
+ def assert_maker_atom_content_inline_xhtml(feed_type, maker_readers,
+ feed_readers, not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.content = "dummy"
+ end
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml_content = "text"
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml = "text"
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml_content =
+ RSS::XML::Element.new("em", nil, nil, {}, ["text"])
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml = RSS::XML::Element.new("em", nil, nil, {}, ["text"])
+ end
+
+
+ xhtml_uri = "http://www.w3.org/1999/xhtml"
+ em = RSS::XML::Element.new("em", nil, nil, {}, ["text"])
+ em_with_xhtml_uri =
+ RSS::XML::Element.new("em", nil, xhtml_uri, {}, ["text"])
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml = em
+ end
+ assert_equal(RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ [em_with_xhtml_uri]),
+ chain_reader(feed, feed_readers).xml)
+
+ div = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri,
+ "class" => "sample"},
+ ["text"])
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "xhtml"
+ target.xml = div
+ end
+ assert_equal(div, chain_reader(feed, feed_readers).xml)
+ end
+ end
+
+ def assert_maker_atom_content_inline_other(*args, &block)
+ _wrap_assertion do
+ assert_maker_atom_content_inline_other_xml(*args, &block)
+ assert_maker_atom_content_inline_other_text(*args, &block)
+ assert_maker_atom_content_inline_other_base64(*args, &block)
+ end
+ end
+
+ def assert_maker_atom_content_inline_other_xml(feed_type, maker_readers,
+ feed_readers,
+ not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "application/xml"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(xml_content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "svg/image+xml"
+ end
+ end
+
+ svg_uri = "http://www.w3.org/2000/svg"
+ rect = RSS::XML::Element.new("rect", nil, svg_uri,
+ {"x" => "0.5cm",
+ "y" => "0.5cm",
+ "width" => "2cm",
+ "height" => "1cm"})
+ svg = RSS::XML::Element.new("svg", nil, svg_uri,
+ {"xmlns" => svg_uri,
+ "version" => "1.1",
+ "width" => "5cm",
+ "height" => "4cm"},
+ [rect])
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/svg+xml"
+ target.xml = svg
+ end
+
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/svg+xml"
+ target.xml = svg
+ end
+ assert_equal(svg, chain_reader(feed, feed_readers).xml)
+ end
+ end
+
+ def assert_maker_atom_content_inline_other_text(feed_type, maker_readers,
+ feed_readers,
+ not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "text/plain"
+ end
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "text/plain"
+ target.content = "text"
+ end
+ end
+ end
+
+ def assert_maker_atom_content_inline_other_base64(feed_type, maker_readers,
+ feed_readers,
+ not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ content = "\211PNG\r\n\032\n"
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ target.content = content
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ target.src = "http://example.com/logo.png"
+ target.content = content
+ end
+
+ feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ target.src = "http://example.com/logo.png"
+ target.content = content
+ end
+ target = chain_reader(feed, feed_readers)
+ assert_nil(target.src)
+ assert_equal(content, target.content)
+ end
+ end
+
+ def assert_maker_atom_content_out_of_line(feed_type, maker_readers,
+ feed_readers, not_set_error_name)
+ _wrap_assertion do
+ args = [feed_type, maker_readers, feed_readers]
+ assert_not_set_error(not_set_error_name, %w(content)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ end
+ end
+
+ assert_not_set_error(not_set_error_name, %w(type)) do
+ RSS::Maker.make("atom:#{feed_type}") do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.src = "http://example.com/logo.png"
+ end
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ target.src = "http://example.com/logo.png"
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "image/png"
+ target.content = "\211PNG\r\n\032\n"
+ end
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "application/xml"
+ target.src = "http://example.com/sample.xml"
+ end
+
+
+ _assert_maker_atom_content(*args) do |maker|
+ yield maker
+ target = chain_reader(maker, maker_readers)
+ target.type = "text/plain"
+ target.src = "http://example.com/README.txt"
+ end
+ end
+ end
+
+ def assert_slash_elements(expected, target)
+ assert_equal(expected,
+ {
+ "section" => target.slash_section,
+ "department" => target.slash_department,
+ "comments" => target.slash_comments,
+ "hit_parades" => target.slash_hit_parades,
+ })
+ assert_equal(expected["hit_parades"].join(","),
+ target.slash_hit_parade)
+ end
+
+ def chain_reader(target, readers, &block)
+ readers.inject(target) do |result, reader|
+ return nil if result.nil?
+ result.__send__(reader, &block)
+ end
+ end
+
+ def normalized_attrs(attrs)
+ n_attrs = {}
+ attrs.each do |name, value|
+ n_attrs[name.to_s] = value
+ end
+ n_attrs
+ end
+
+ def combination(elements, n)
+ if n <= 0 or elements.size < n
+ []
+ elsif n == 1
+ elements.collect {|element| [element]}
+ else
+ first, *rest = elements
+ combination(rest, n - 1).collect do |sub_elements|
+ [first, *sub_elements]
+ end + combination(rest, n)
+ end
+ end
+
+ def tag(name, content=nil, attributes={})
+ attributes = attributes.collect do |key, value|
+ "#{ERB::Util.h(key)}=\"#{ERB::Util.h(value)}\""
+ end.join(" ")
+ begin_tag = "<#{name}"
+ begin_tag << " #{attributes}" unless attributes.empty?
+ if content
+ "#{begin_tag}>#{content}</#{name}>\n"
+ else
+ "#{begin_tag}/>\n"
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/rss-testcase.rb b/trunk/test/rss/rss-testcase.rb
new file mode 100644
index 0000000000..79f8cb87e8
--- /dev/null
+++ b/trunk/test/rss/rss-testcase.rb
@@ -0,0 +1,478 @@
+require "erb"
+
+require "test/unit"
+require 'rss-assertions'
+
+require "rss"
+
+module RSS
+ class TestCase < Test::Unit::TestCase
+ include ERB::Util
+
+ include RSS
+ include Assertions
+
+ XMLDECL_VERSION = "1.0"
+ XMLDECL_ENCODING = "UTF-8"
+ XMLDECL_STANDALONE = "no"
+
+ RDF_ABOUT = "http://www.xml.com/xml/news.rss"
+ RDF_RESOURCE = "http://xml.com/universal/images/xml_tiny.gif"
+ TITLE_VALUE = "XML.com"
+ LINK_VALUE = "http://xml.com/pub"
+ URL_VALUE = "http://xml.com/universal/images/xml_tiny.gif"
+ NAME_VALUE = "hogehoge"
+ LANGUAGE_VALUE = "ja"
+ DESCRIPTION_VALUE = "
+ XML.com features a rich mix of information and services
+ for the XML community.
+ "
+ RESOURCES = [
+ "http://xml.com/pub/2000/08/09/xslt/xslt.html",
+ "http://xml.com/pub/2000/08/09/rdfdb/index.html",
+ ]
+
+ CLOUD_DOMAIN = "data.ourfavoritesongs.com"
+ CLOUD_PORT = "80"
+ CLOUD_PATH = "/RPC2"
+ CLOUD_REGISTER_PROCEDURE = "ourFavoriteSongs.rssPleaseNotify"
+ CLOUD_PROTOCOL = "xml-rpc"
+
+ ENCLOSURE_URL = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
+ ENCLOSURE_LENGTH = "12216320"
+ ENCLOSURE_TYPE = "audio/mpeg"
+
+ CATEGORY_DOMAIN = "http://www.superopendirectory.com/"
+
+ FEED_TITLE = "dive into mark"
+ FEED_UPDATED = "2003-12-13T18:30:02Z"
+ FEED_AUTHOR_NAME = "John Doe"
+ FEED_ID = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"
+
+ ENTRY_TITLE = "Atom-Powered Robots Run Amok"
+ ENTRY_LINK = "http://example.org/2003/12/13/atom03"
+ ENTRY_ID = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
+ ENTRY_UPDATED = "2003-12-13T18:30:02Z"
+ ENTRY_SUMMARY = "Some text."
+
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ DC_ELEMENTS = {
+ :title => "hoge",
+ :description =>
+ " XML is placing increasingly heavy loads on
+ the existing technical infrastructure of the Internet.",
+ :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
+ :subject => "XML",
+ :publisher => "The O'Reilly Network",
+ :contributor => "hogehoge",
+ :type => "fugafuga",
+ :format => "hohoho",
+ :identifier => "fufufu",
+ :source => "barbar",
+ :language => "ja",
+ :relation => "cococo",
+ :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
+ :date => t,
+ }
+
+ DC_NODES = DC_ELEMENTS.collect do |name, value|
+ "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
+ end.join("\n")
+
+ def default_test
+ # This class isn't tested
+ end
+
+ private
+ def make_xmldecl(v=XMLDECL_VERSION, e=XMLDECL_ENCODING, s=XMLDECL_STANDALONE)
+ rv = "<?xml version='#{v}'"
+ rv << " encoding='#{e}'" if e
+ rv << " standalone='#{s}'" if s
+ rv << "?>"
+ rv
+ end
+
+ def make_RDF(content=nil, xmlns=[])
+ <<-EORSS
+#{make_xmldecl}
+<rdf:RDF xmlns="#{URI}" xmlns:rdf="#{RDF::URI}"
+#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
+#{block_given? ? yield : content}
+</rdf:RDF>
+EORSS
+ end
+
+ def make_channel(content=nil)
+ <<-EOC
+<channel rdf:about="#{RDF_ABOUT}">
+ <title>#{TITLE_VALUE}</title>
+ <link>#{LINK_VALUE}</link>
+ <description>#{DESCRIPTION_VALUE}</description>
+
+ <image rdf:resource="#{RDF_RESOURCE}" />
+
+ <items>
+ <rdf:Seq>
+#{RESOURCES.collect do |res| '<rdf:li resource="' + res + '" />' end.join("\n")}
+ </rdf:Seq>
+ </items>
+
+ <textinput rdf:resource="#{RDF_RESOURCE}" />
+
+#{block_given? ? yield : content}
+</channel>
+EOC
+ end
+
+ def make_image(content=nil)
+ <<-EOI
+<image rdf:about="#{RDF_ABOUT}">
+ <title>#{TITLE_VALUE}</title>
+ <url>#{URL_VALUE}</url>
+ <link>#{LINK_VALUE}</link>
+#{block_given? ? yield : content}
+</image>
+EOI
+ end
+
+ def make_item(content=nil)
+ <<-EOI
+<item rdf:about="#{RDF_ABOUT}">
+ <title>#{TITLE_VALUE}</title>
+ <link>#{LINK_VALUE}</link>
+ <description>#{DESCRIPTION_VALUE}</description>
+#{block_given? ? yield : content}
+</item>
+EOI
+ end
+
+ def make_textinput(content=nil)
+ <<-EOT
+<textinput rdf:about="#{RDF_ABOUT}">
+ <title>#{TITLE_VALUE}</title>
+ <description>#{DESCRIPTION_VALUE}</description>
+ <name>#{NAME_VALUE}</name>
+ <link>#{LINK_VALUE}</link>
+#{block_given? ? yield : content}
+</textinput>
+EOT
+ end
+
+ def make_sample_RDF
+ make_RDF(<<-EOR)
+#{make_channel}
+#{make_image}
+#{make_item}
+#{make_textinput}
+EOR
+ end
+
+ def make_rss20(content=nil, xmlns=[])
+ <<-EORSS
+#{make_xmldecl}
+<rss version="2.0"
+#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
+#{block_given? ? yield : content}
+</rss>
+EORSS
+ end
+
+ def make_sample_items20
+ RESOURCES.collect do |res|
+ elems = ["<link>#{res}</link>"]
+ elems << "<title>title of #{res}</title>"
+ elems = elems.join("\n")
+ item = "<item>\n#{elems}\n</item>"
+ end.join("\n")
+ end
+
+ def make_channel20(content=nil)
+ <<-EOC
+<channel>
+ <title>#{TITLE_VALUE}</title>
+ <link>#{LINK_VALUE}</link>
+ <description>#{DESCRIPTION_VALUE}</description>
+ <language>#{LANGUAGE_VALUE}</language>
+
+ <image>
+ <url>#{RDF_RESOURCE}</url>
+ <title>#{TITLE_VALUE}</title>
+ <link>#{LINK_VALUE}</link>
+ </image>
+
+#{make_sample_items20}
+
+ <textInput>
+ <title>#{TITLE_VALUE}</title>
+ <description>#{DESCRIPTION_VALUE}</description>
+ <name>#{NAME_VALUE}</name>
+ <link>#{RDF_RESOURCE}</link>
+ </textInput>
+
+#{block_given? ? yield : content}
+</channel>
+EOC
+ end
+
+ def make_item20(content=nil)
+ <<-EOI
+<item>
+ <title>#{TITLE_VALUE}</title>
+ <link>#{LINK_VALUE}</link>
+ <description>#{DESCRIPTION_VALUE}</description>
+#{block_given? ? yield : content}
+</item>
+EOI
+ end
+
+ def make_cloud20
+ <<-EOC
+<cloud
+ domain="#{CLOUD_DOMAIN}"
+ port="#{CLOUD_PORT}"
+ path="#{CLOUD_PATH}"
+ registerProcedure="#{CLOUD_REGISTER_PROCEDURE}"
+ protocol="#{CLOUD_PROTOCOL}" />
+EOC
+ end
+
+ def make_sample_rss20
+ make_rss20(<<-EOR)
+#{make_channel20}
+EOR
+ end
+
+ def make_feed_without_entry(content=nil, xmlns=[])
+ <<-EOA
+<feed xmlns="#{Atom::URI}"
+#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
+ <id>#{FEED_ID}</id>
+ <title>#{FEED_TITLE}</title>
+ <updated>#{FEED_UPDATED}</updated>
+ <author>
+ <name>#{FEED_AUTHOR_NAME}</name>
+ </author>
+#{block_given? ? yield : content}
+</feed>
+EOA
+ end
+
+ def make_entry(content=nil)
+ <<-EOA
+ <entry>
+ <title>#{ENTRY_TITLE}</title>
+ <id>#{ENTRY_ID}</id>
+ <updated>#{ENTRY_UPDATED}</updated>
+#{block_given? ? yield : content}
+ </entry>
+EOA
+ end
+
+ def make_feed_with_open_entry(content=nil, xmlns=[], &block)
+ make_feed_without_entry(<<-EOA, xmlns)
+#{make_entry(content, &block)}
+EOA
+ end
+
+ def make_feed_with_open_entry_source(content=nil, xmlns=[])
+ make_feed_with_open_entry(<<-EOA, xmlns)
+ <source>
+#{block_given? ? yield : content}
+ </source>
+EOA
+ end
+
+ def make_feed(content=nil, xmlns=[])
+ make_feed_without_entry(<<-EOA, xmlns)
+ <entry>
+ <title>#{ENTRY_TITLE}</title>
+ <link href="#{ENTRY_LINK}"/>
+ <id>#{ENTRY_ID}</id>
+ <updated>#{ENTRY_UPDATED}</updated>
+ <summary>#{ENTRY_SUMMARY}</summary>
+ </entry>
+#{block_given? ? yield : content}
+EOA
+ end
+
+ def make_entry_document(content=nil, xmlns=[])
+ <<-EOA
+<entry xmlns="#{Atom::URI}"
+#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
+ <id>#{ENTRY_ID}</id>
+ <title>#{ENTRY_TITLE}</title>
+ <updated>#{ENTRY_UPDATED}</updated>
+ <author>
+ <name>#{FEED_AUTHOR_NAME}</name>
+ </author>
+#{block_given? ? yield : content}
+</entry>
+EOA
+ end
+
+ def make_entry_document_with_open_source(content=nil, xmlns=[])
+ make_entry_document(<<-EOA, xmlns)
+ <source>
+#{block_given? ? yield : content}
+ </source>
+EOA
+ end
+
+ def make_element(elem_name, attrs, contents)
+ attrs_str = attrs.collect do |name, value|
+ "#{h name}='#{h value}'"
+ end.join(" ")
+ attrs_str = " #{attrs_str}" unless attrs_str.empty?
+
+ if contents.is_a?(String)
+ contents_str = h(contents)
+ else
+ contents_str = contents.collect do |name, value|
+ "#{Element::INDENT}<#{h name}>#{h value}</#{h name}>"
+ end.join("\n")
+ contents_str = "\n#{contents_str}\n"
+ end
+
+ "<#{h elem_name}#{attrs_str}>#{contents_str}</#{h elem_name}>"
+ end
+
+ def xmlns_container(xmlns_decls, content)
+ attributes = xmlns_decls.collect do |prefix, uri|
+ "xmlns:#{h prefix}=\"#{h uri}\""
+ end.join(" ")
+ "<dummy #{attributes}>#{content}</dummy>"
+ end
+
+ private
+ def setup_rss10(rdf)
+ assert_equal("", rdf.to_s)
+
+ channel = RDF::Channel.new
+ assert_equal("", channel.to_s)
+ channel.about = "http://example.com/index.rdf"
+ channel.title = "title"
+ channel.link = "http://example.com/"
+ channel.description = "description"
+ assert_equal("", channel.to_s)
+
+ item_title = "item title"
+ item_link = "http://example.com/item"
+ channel.items = RDF::Channel::Items.new
+ channel.items.Seq.lis << RDF::Channel::Items::Seq::Li.new(item_link)
+ assert_not_equal("", channel.to_s)
+
+ rdf.channel = channel
+ assert_equal("", rdf.to_s)
+
+ item = RDF::Item.new
+ item.title = item_title
+ item.link = item_link
+ item.about = item_link
+ rdf.items << item
+ assert_not_equal("", rdf.to_s)
+ end
+
+ def setup_rss20(rss)
+ assert_equal("", rss.to_s)
+
+ channel = Rss::Channel.new
+ assert_equal("", channel.to_s)
+ channel.title = "title"
+ channel.link = "http://example.com/"
+ channel.description = "description"
+ assert_not_equal("", channel.to_s)
+
+ rss.channel = channel
+ assert_not_equal("", rss.to_s)
+ end
+
+ def setup_dummy_channel(maker)
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com/feed.xml"
+ description = "fugafugafugafuga"
+ language = "ja"
+
+ maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ end
+
+ def setup_dummy_channel_atom(maker)
+ updated = Time.now
+ author = "Foo"
+
+ setup_dummy_channel(maker)
+ maker.channel.links.first.rel = "self"
+ maker.channel.links.first.type = "application/atom+xml"
+ maker.channel.updated = updated
+ maker.channel.author = author
+ end
+
+ def setup_dummy_image(maker)
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+
+ maker.channel.link = link if maker.channel.link.nil?
+
+ maker.image.title = title
+ maker.image.url = url
+ end
+
+ def setup_dummy_textinput(maker)
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com/search.cgi"
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+
+ def setup_dummy_item(maker)
+ title = "TITLE"
+ link = "http://hoge.com/"
+
+ item = maker.items.new_item
+ item.title = title
+ item.link = link
+ end
+
+ def setup_dummy_item_atom(maker)
+ setup_dummy_item(maker)
+
+ item = maker.items.first
+ item.id = "http://example.net/xxx"
+ item.updated = Time.now
+ end
+
+ def setup_taxo_topic(target, topics)
+ topics.each do |topic|
+ taxo_topic = target.taxo_topics.new_taxo_topic
+ topic.each do |name, value|
+ case name
+ when :link
+ taxo_topic.taxo_link = value
+ when :topics
+ value.each do |t|
+ taxo_topic.taxo_topics << t
+ end
+ else
+ dc_elems = taxo_topic.__send__("dc_#{name}s")
+ dc_elem = dc_elems.__send__("new_#{name}")
+ dc_elem.value = value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_1.0.rb b/trunk/test/rss/test_1.0.rb
new file mode 100644
index 0000000000..9cb7607590
--- /dev/null
+++ b/trunk/test/rss/test_1.0.rb
@@ -0,0 +1,296 @@
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+
+module RSS
+ class TestRSS10Core < TestCase
+
+ def setup
+ @rdf_prefix = "rdf"
+ @rdf_uri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ @uri = "http://purl.org/rss/1.0/"
+ end
+
+ def test_RDF
+ version = "1.0"
+ encoding = "UTF-8"
+ standalone = false
+
+ rdf = RDF.new(version, encoding, standalone)
+ setup_rss10(rdf)
+ doc = REXML::Document.new(rdf.to_s)
+
+ xmldecl = doc.xml_decl
+
+ %w(version encoding).each do |x|
+ assert_equal(instance_eval(x), xmldecl.__send__(x))
+ end
+ assert_equal(standalone, !xmldecl.standalone.nil?)
+
+ assert_equal(@rdf_uri, doc.root.namespace)
+ end
+
+ def test_not_displayed_xml_stylesheets
+ rdf = RDF.new()
+ plain_rdf = rdf.to_s
+ 3.times do
+ rdf.xml_stylesheets.push(XMLStyleSheet.new)
+ assert_equal(plain_rdf, rdf.to_s)
+ end
+ end
+
+ def test_xml_stylesheets
+ [
+ [{:href => "a.xsl", :type => "text/xsl"}],
+ [
+ {:href => "a.xsl", :type => "text/xsl"},
+ {:href => "a.css", :type => "text/css"},
+ ],
+ ].each do |attrs_ary|
+ assert_xml_stylesheet_pis(attrs_ary)
+ end
+ end
+
+ def test_channel
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ resource = "http://hoge.com/hoge.png"
+
+ item_title = "item title"
+ item_link = "http://hoge.com/item"
+
+ image = RDF::Channel::Image.new(resource)
+ items = RDF::Channel::Items.new
+ items.Seq.lis << items.class::Seq::Li.new(item_link)
+ textinput = RDF::Channel::Textinput.new(resource)
+
+ rss_item = RDF::Item.new
+ rss_item.title = item_title
+ rss_item.link = item_link
+ rss_item.about = item_link
+
+ channel = RDF::Channel.new(about)
+ %w(title link description image items textinput).each do |x|
+ channel.__send__("#{x}=", instance_eval(x))
+ end
+
+ doc = REXML::Document.new(make_RDF(<<-EOR))
+#{channel}
+<items>
+#{rss_item}
+</items>
+EOR
+ c = doc.root.elements[1]
+
+ assert_equal(about, c.attributes["about"])
+ %w(title link description image textinput).each do |x|
+ elem = c.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal(@uri, elem.namespace)
+ if x == "image" or x == "textinput"
+ excepted = resource
+ res = elem.attributes.get_attribute("resource")
+ assert_equal(@rdf_uri, res.namespace)
+ value = res.value
+ else
+ excepted = instance_eval(x)
+ value = elem.text
+ end
+ assert_equal(excepted, value)
+ end
+ assert_equal(@uri, c.elements["items"].namespace)
+ assert_equal("items", c.elements["items"].name)
+ end
+
+ def test_channel_image
+ resource = "http://hoge.com/hoge.png"
+ image = RDF::Channel::Image.new(resource)
+
+ doc = REXML::Document.new(make_RDF(image.to_s))
+ i = doc.root.elements[1]
+
+ assert_equal("image", i.name)
+ assert_equal(@uri, i.namespace)
+
+ res = i.attributes.get_attribute("resource")
+
+ assert_equal(@rdf_uri, res.namespace)
+ assert_equal(resource, res.value)
+ end
+
+ def test_channel_textinput
+ resource = "http://hoge.com/hoge.png"
+ textinput = RDF::Channel::Textinput.new(resource)
+
+ doc = REXML::Document.new(make_RDF(textinput.to_s))
+ t = doc.root.elements[1]
+
+ assert_equal("textinput", t.name)
+ assert_equal(@uri, t.namespace)
+
+ res = t.attributes.get_attribute("resource")
+
+ assert_equal(@rdf_uri, res.namespace)
+ assert_equal(resource, res.value)
+ end
+
+ def test_channel_items
+ item_link = "http://example.com/item"
+
+ items = RDF::Channel::Items.new
+ li = items.Seq.class::Li.new(item_link)
+ items.Seq.lis << li
+
+ doc = REXML::Document.new(make_RDF(items.to_s))
+ i = doc.root.elements[1]
+
+ assert_equal("items", i.name)
+ assert_equal(@uri, i.namespace)
+
+ assert_equal(1, i.elements.size)
+ seq = i.elements[1]
+ assert_equal("Seq", seq.name)
+ assert_equal(@rdf_uri, seq.namespace)
+
+ assert_equal(1, seq.elements.size)
+ l = seq.elements[1]
+ assert_equal("li", l.name)
+ assert_equal(@rdf_uri, l.namespace)
+ assert_equal(item_link, l.attributes["resource"])
+ end
+
+ def test_seq
+ item_link = "http://example.com/item"
+ seq = RDF::Seq.new
+ li = seq.class::Li.new(item_link)
+ seq.lis << li
+
+ doc = REXML::Document.new(make_RDF(seq.to_s))
+ s = doc.root.elements[1]
+
+ assert_equal("Seq", s.name)
+ assert_equal(@rdf_uri, s.namespace)
+
+ assert_equal(1, s.elements.size)
+ l = s.elements[1]
+ assert_equal("li", l.name)
+ assert_equal(@rdf_uri, l.namespace)
+ assert_equal(item_link, l.attributes["resource"])
+ end
+
+ def test_li
+ resource = "http://hoge.com/"
+ li = RDF::Li.new(resource)
+
+ doc = REXML::Document.new(make_RDF(li.to_s))
+ l = doc.root.elements[1]
+
+ assert_equal("li", l.name)
+ assert_equal(@rdf_uri, l.namespace(l.prefix))
+
+ res = l.attributes.get_attribute("resource")
+
+ assert_equal('', res.instance_eval("@prefix"))
+ assert_equal(resource, res.value)
+ end
+
+ def test_image
+ about = "http://hoge.com"
+ title = "fugafuga"
+ url = "http://hoge.com/hoge"
+ link = "http://hoge.com/fuga"
+
+ image = RDF::Image.new(about)
+ %w(title url link).each do |x|
+ image.__send__("#{x}=", instance_eval(x))
+ end
+
+ doc = REXML::Document.new(make_RDF(image.to_s))
+ i = doc.root.elements[1]
+
+ assert_equal(about, i.attributes["about"])
+ %w(title url link).each do |x|
+ elem = i.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal(@uri, elem.namespace)
+ assert_equal(instance_eval(x), elem.text)
+ end
+ end
+
+ def test_item
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com/fuga"
+ description = "hogehogehoge"
+
+ item = RDF::Item.new(about)
+ %w(title link description).each do |x|
+ item.__send__("#{x}=", instance_eval(x))
+ end
+
+ doc = REXML::Document.new(make_RDF(item.to_s))
+ i = doc.root.elements[1]
+
+ assert_equal(about, i.attributes["about"])
+ %w(title link description).each do |x|
+ elem = i.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal(@uri, elem.namespace)
+ assert_equal(instance_eval(x), elem.text)
+ end
+ end
+
+ def test_textinput
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com/fuga"
+ name = "foo"
+ description = "hogehogehoge"
+
+ textinput = RDF::Textinput.new(about)
+ %w(title link name description).each do |x|
+ textinput.__send__("#{x}=", instance_eval(x))
+ end
+
+ doc = REXML::Document.new(make_RDF(textinput.to_s))
+ t = doc.root.elements[1]
+
+ assert_equal(about, t.attributes["about"])
+ %w(title link name description).each do |x|
+ elem = t.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal(@uri, elem.namespace)
+ assert_equal(instance_eval(x), elem.text)
+ end
+ end
+
+ def test_to_xml
+ rss = RSS::Parser.parse(make_sample_RDF)
+ assert_equal(rss.to_s, rss.to_xml)
+ assert_equal(rss.to_s, rss.to_xml("1.0"))
+ rss09 = rss.to_xml("0.91") do |maker|
+ maker.channel.language = "en-us"
+ end
+ rss09 = RSS::Parser.parse(rss09)
+ assert_equal("0.91", rss09.rss_version)
+ assert_equal(["rss", "0.91", nil], rss09.feed_info)
+ rss20 = RSS::Parser.parse(rss.to_xml("2.0"))
+ assert_equal("2.0", rss20.rss_version)
+ assert_equal(["rss", "2.0", nil], rss20.feed_info)
+
+ atom_xml = rss.to_xml("atom") do |maker|
+ maker.channel.author = "Alice"
+ maker.channel.updated ||= Time.now
+ maker.items.each do |item|
+ item.updated ||= Time.now
+ end
+ end
+ atom = RSS::Parser.parse(atom_xml)
+ assert_equal(["atom", "1.0", "feed"], atom.feed_info)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_2.0.rb b/trunk/test/rss/test_2.0.rb
new file mode 100644
index 0000000000..5a63efbcb9
--- /dev/null
+++ b/trunk/test/rss/test_2.0.rb
@@ -0,0 +1,410 @@
+require "rexml/document"
+
+require "rss-testcase"
+
+module RSS
+ class TestRSS20Core < TestCase
+
+ def setup
+ @rss_version = "2.0"
+ end
+
+ def test_Rss
+ version = "1.0"
+ encoding = "UTF-8"
+ standalone = false
+
+ rss = Rss.new(@rss_version, version, encoding, standalone)
+ setup_rss20(rss)
+
+ doc = REXML::Document.new(rss.to_s(false))
+
+ xmldecl = doc.xml_decl
+
+ %w(version encoding).each do |x|
+ assert_equal(instance_eval(x), xmldecl.__send__(x))
+ end
+ assert_equal(standalone, !xmldecl.standalone.nil?)
+
+ assert_equal("", doc.root.namespace)
+ assert_equal(@rss_version, doc.root.attributes["version"])
+ end
+
+ def test_not_displayed_xml_stylesheets
+ rss = Rss.new(@rss_version)
+ plain_rss = rss.to_s
+ 3.times do
+ rss.xml_stylesheets.push(XMLStyleSheet.new)
+ assert_equal(plain_rss, rss.to_s)
+ end
+ end
+
+ def test_xml_stylesheets
+ [
+ [{:href => "a.xsl", :type => "text/xsl"}],
+ [
+ {:href => "a.xsl", :type => "text/xsl"},
+ {:href => "a.css", :type => "text/css"},
+ ],
+ ].each do |attrs_ary|
+ rss = Rss.new(@rss_version)
+ setup_rss20(rss)
+ assert_xml_stylesheet_pis(attrs_ary, rss)
+ end
+ end
+
+ def test_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+
+ language = "en-us"
+ copyright = "Copyright 2002, Spartanburg Herald-Journal"
+ managingEditor = "geo@herald.com (George Matesky)"
+ webMaster = "betty@herald.com (Betty Guernsey)"
+ pubDate = Time.parse("Sat, 07 Sep 2002 00:00:01 GMT")
+ lastBuildDate = Time.parse("Sat, 07 Sep 2002 09:42:31 GMT")
+ categories = [
+ {
+ :content => "Newspapers",
+ },
+ {
+ :domain => "Syndic8",
+ :content => "1765",
+ }
+ ]
+ generator = "MightyInHouse Content System v2.3"
+ docs = "http://blogs.law.harvard.edu/tech/rss"
+
+ ttl = "60"
+
+ rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
+
+ channel = Rss::Channel.new
+
+ elems = %w(title link description language copyright
+ managingEditor webMaster pubDate lastBuildDate
+ generator docs ttl rating)
+ elems.each do |x|
+ value = instance_eval(x)
+ value = value.rfc822 if %w(pubDate lastBuildDate).include?(x)
+ channel.__send__("#{x}=", value)
+ end
+ categories.each do |cat|
+ channel.categories << Rss::Channel::Category.new(cat[:domain],
+ cat[:content])
+ end
+
+ doc = REXML::Document.new(make_rss20(channel.to_s))
+ c = doc.root.elements[1]
+
+ elems.each do |x|
+ elem = c.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal("", elem.namespace)
+ expected = instance_eval(x)
+ case x
+ when "pubDate", "lastBuildDate"
+ assert_equal(expected, Time.parse(elem.text))
+ when "ttl"
+ expected = channel.__send__(x)
+ assert_equal(expected, elem.text.to_i)
+ else
+ assert_equal(expected, elem.text)
+ end
+ end
+ categories.each_with_index do |cat, i|
+ cat = cat.dup
+ cat[:domain] ||= nil
+ category = c.elements["category[#{i+1}]"]
+ actual = {
+ :domain => category.attributes["domain"],
+ :content => category.text,
+ }
+ assert_equal(cat, actual)
+ end
+ end
+
+ def test_channel_cloud
+ cloud_params = {
+ :domain => "rpc.sys.com",
+ :port => "80",
+ :path => "/RPC2",
+ :registerProcedure => "myCloud.rssPleaseNotify",
+ :protocol => "xml-rpc",
+ }
+ cloud = Rss::Channel::Cloud.new(cloud_params[:domain],
+ cloud_params[:port],
+ cloud_params[:path],
+ cloud_params[:registerProcedure],
+ cloud_params[:protocol])
+ cloud_params[:port] = cloud.port
+
+ doc = REXML::Document.new(cloud.to_s)
+ cloud_elem = doc.root
+
+ actual = {}
+ cloud_elem.attributes.each do |name, value|
+ value = value.to_i if name == "port"
+ actual[name.intern] = value
+ end
+ assert_equal(cloud_params, actual)
+ end
+
+ def test_channel_image
+ image_params = {
+ :url => "http://hoge.com/hoge.png",
+ :title => "fugafuga",
+ :link => "http://hoge.com",
+ :width => "144",
+ :height => "400",
+ :description => "an image",
+ }
+ image = Rss::Channel::Image.new(image_params[:url],
+ image_params[:title],
+ image_params[:link],
+ image_params[:width],
+ image_params[:height],
+ image_params[:description])
+
+ doc = REXML::Document.new(image.to_s)
+ image_elem = doc.root
+
+ image_params.each do |name, value|
+ value = image.__send__(name)
+ actual = image_elem.elements[name.to_s].text
+ actual = actual.to_i if [:width, :height].include?(name)
+ assert_equal(value, actual)
+ end
+ end
+
+ def test_channel_textInput
+ textInput_params = {
+ :title => "fugafuga",
+ :description => "text hoge fuga",
+ :name => "hoge",
+ :link => "http://hoge.com",
+ }
+ textInput = Rss::Channel::TextInput.new(textInput_params[:title],
+ textInput_params[:description],
+ textInput_params[:name],
+ textInput_params[:link])
+
+ doc = REXML::Document.new(textInput.to_s)
+ input_elem = doc.root
+
+ textInput_params.each do |name, value|
+ actual = input_elem.elements[name.to_s].text
+ assert_equal(value, actual)
+ end
+ end
+
+ def test_channel_skip_days
+ skipDays_values = [
+ "Sunday",
+ "Monday",
+ ]
+ skipDays = Rss::Channel::SkipDays.new
+ skipDays_values.each do |value|
+ skipDays.days << Rss::Channel::SkipDays::Day.new(value)
+ end
+
+ doc = REXML::Document.new(skipDays.to_s)
+ days_elem = doc.root
+
+ skipDays_values.each_with_index do |value, i|
+ assert_equal(value, days_elem.elements[i + 1].text)
+ end
+ end
+
+ def test_channel_skip_hours
+ skipHours_values = [
+ "0",
+ "13",
+ ]
+ skipHours = Rss::Channel::SkipHours.new
+ skipHours_values.each do |value|
+ skipHours.hours << Rss::Channel::SkipHours::Hour.new(value)
+ end
+
+ doc = REXML::Document.new(skipHours.to_s)
+ hours_elem = doc.root
+
+ skipHours_values.each_with_index do |value, i|
+ expected = skipHours.hours[i].content
+ assert_equal(expected, hours_elem.elements[i + 1].text.to_i)
+ end
+ end
+
+ def test_item
+ title = "fugafuga"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ author = "oprah@oxygen.net"
+ categories = [
+ {
+ :content => "Newspapers",
+ },
+ {
+ :domain => "Syndic8",
+ :content => "1765",
+ }
+ ]
+ comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
+ pubDate = Time.parse("Sat, 07 Sep 2002 00:00:01 GMT")
+
+ channel = Rss::Channel.new
+ channel.title = "title"
+ channel.link = "http://example.com/"
+ channel.description = "description"
+
+ item = Rss::Channel::Item.new
+ channel.items << item
+
+ elems = %w(title link description author comments pubDate)
+ elems.each do |x|
+ value = instance_eval(x)
+ value = value.rfc822 if x == "pubDate"
+ item.__send__("#{x}=", value)
+ end
+ categories.each do |cat|
+ item.categories << Rss::Channel::Category.new(cat[:domain],
+ cat[:content])
+ end
+
+ doc = REXML::Document.new(channel.to_s)
+ channel_elem = doc.root
+
+ item_elem = channel_elem.elements["item[1]"]
+ elems.each do |x|
+ elem = item_elem.elements[x]
+ assert_equal(x, elem.name)
+ assert_equal("", elem.namespace)
+ expected = instance_eval(x)
+ case x
+ when "pubDate"
+ assert_equal(expected, Time.parse(elem.text))
+ else
+ assert_equal(expected, elem.text)
+ end
+ end
+ categories.each_with_index do |cat, i|
+ cat = cat.dup
+ cat[:domain] ||= nil
+ category = item_elem.elements["category[#{i+1}]"]
+ actual = {
+ :domain => category.attributes["domain"],
+ :content => category.text,
+ }
+ assert_equal(cat, actual)
+ end
+ end
+
+ def test_item_enclosure
+ enclosure_params = {
+ :url => "http://www.scripting.com/mp3s/weatherReportSuite.mp3",
+ :length => "12216320",
+ :type => "audio/mpeg",
+ }
+
+ enclosure = Rss::Channel::Item::Enclosure.new(enclosure_params[:url],
+ enclosure_params[:length],
+ enclosure_params[:type])
+ enclosure_params[:length] = enclosure.length
+
+ doc = REXML::Document.new(enclosure.to_s)
+ enclosure_elem = doc.root
+
+ actual = {}
+ enclosure_elem.attributes.each do |name, value|
+ value = value.to_i if name == "length"
+ actual[name.intern] = value
+ end
+ assert_equal(enclosure_params, actual)
+ end
+
+ def test_item_guid
+ test_params = [
+ {
+ :content => "http://some.server.com/weblogItem3207",
+ },
+ {
+ :isPermaLink => "true",
+ :content => "http://inessential.com/2002/09/01.php#a2",
+ },
+ ]
+
+ test_params.each do |guid_params|
+ guid = Rss::Channel::Item::Guid.new(guid_params[:isPermaLink],
+ guid_params[:content])
+ if guid_params.has_key?(:isPermaLink)
+ guid_params[:isPermaLink] = guid.isPermaLink
+ end
+ if guid.isPermaLink.nil?
+ assert_equal(true, guid.PermaLink?)
+ else
+ assert_equal(guid.isPermaLink, guid.PermaLink?)
+ end
+
+ doc = REXML::Document.new(guid.to_s)
+ guid_elem = doc.root
+
+ actual = {}
+ actual[:content] = guid_elem.text if guid_elem.text
+ guid_elem.attributes.each do |name, value|
+ value = value == "true" if name == "isPermaLink"
+ actual[name.intern] = value
+ end
+ assert_equal(guid_params, actual)
+ end
+ end
+
+ def test_item_source
+ source_params = {
+ :url => "http://www.tomalak.org/links2.xml",
+ :content => "Tomalak's Realm",
+ }
+
+ source = Rss::Channel::Item::Source.new(source_params[:url],
+ source_params[:content])
+
+ doc = REXML::Document.new(source.to_s)
+ source_elem = doc.root
+
+ actual = {}
+ actual[:content] = source_elem.text
+ source_elem.attributes.each do |name, value|
+ actual[name.intern] = value
+ end
+ assert_equal(source_params, actual)
+ end
+
+ def test_to_xml
+ rss = RSS::Parser.parse(make_sample_rss20)
+ assert_equal(rss.to_s, rss.to_xml)
+ assert_equal(rss.to_s, rss.to_xml("2.0"))
+ rss09_xml = rss.to_xml("0.91") do |maker|
+ setup_dummy_image(maker)
+ end
+ rss09 = RSS::Parser.parse(rss09_xml)
+ assert_equal("0.91", rss09.rss_version)
+ rss10 = rss.to_xml("1.0") do |maker|
+ maker.channel.about = "http://www.example.com/index.rdf"
+ end
+ rss10 = RSS::Parser.parse(rss10)
+ assert_equal("1.0", rss10.rss_version)
+
+ atom_xml = rss.to_xml("atom1.0") do |maker|
+ maker.channel.id = "http://www.example.com/atom.xml"
+ maker.channel.author = "Alice"
+ maker.channel.updated = Time.now
+ maker.items.each do |item|
+ item.author = "Bob"
+ item.updated = Time.now
+ end
+ end
+ atom = RSS::Parser.parse(atom_xml)
+ assert_equal(["atom", "1.0", "feed"], atom.feed_info)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_accessor.rb b/trunk/test/rss/test_accessor.rb
new file mode 100644
index 0000000000..ceb31fc9c2
--- /dev/null
+++ b/trunk/test/rss/test_accessor.rb
@@ -0,0 +1,103 @@
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/2.0"
+require "rss/syndication"
+require "rss/image"
+
+module RSS
+ class TestAccessor < TestCase
+ def test_date
+ channel = Rss::Channel.new
+ channel.pubDate = nil
+ assert_nil(channel.pubDate)
+
+ time = Time.now
+ channel.pubDate = time
+ assert_equal(time, channel.pubDate)
+
+ time = Time.parse(Time.now.rfc822)
+ channel.pubDate = time.rfc822
+ assert_equal(time, channel.pubDate)
+
+ time = Time.parse(Time.now.iso8601)
+ value = time.iso8601
+ assert_not_available_value("pubDate", value) do
+ channel.pubDate = value
+ end
+
+ channel.do_validate = false
+ time = Time.parse(Time.now.iso8601)
+ value = time.iso8601
+ channel.pubDate = value
+ assert_equal(time, channel.pubDate)
+
+ channel.pubDate = nil
+ assert_nil(channel.pubDate)
+ end
+
+ def test_integer
+ image_item = RDF::Item::ImageItem.new
+
+ image_item.width = nil
+ assert_nil(image_item.width)
+
+ width = 10
+ image_item.width = width
+ assert_equal(width, image_item.width)
+
+ width = 10.0
+ image_item.width = width
+ assert_equal(width, image_item.width)
+
+ width = "10"
+ image_item.width = width
+ assert_equal(width.to_i, image_item.width)
+
+ width = "10.0"
+ assert_not_available_value("image:width", width) do
+ image_item.width = width
+ end
+
+ image_item.do_validate = false
+ width = "10.0"
+ image_item.width = width
+ assert_equal(width.to_i, image_item.width)
+
+ image_item.width = nil
+ assert_nil(image_item.width)
+ end
+
+ def test_positive_integer
+ channel = RDF::Channel.new
+
+ channel.sy_updateFrequency = nil
+ assert_nil(channel.sy_updateFrequency)
+
+ freq = 10
+ channel.sy_updateFrequency = freq
+ assert_equal(freq, channel.sy_updateFrequency)
+
+ freq = 10.0
+ channel.sy_updateFrequency = freq
+ assert_equal(freq, channel.sy_updateFrequency)
+
+ freq = "10"
+ channel.sy_updateFrequency = freq
+ assert_equal(freq.to_i, channel.sy_updateFrequency)
+
+ freq = "10.0"
+ assert_not_available_value("sy:updateFrequency", freq) do
+ channel.sy_updateFrequency = freq
+ end
+
+ channel.do_validate = false
+ freq = "10.0"
+ channel.sy_updateFrequency = freq
+ assert_equal(freq.to_i, channel.sy_updateFrequency)
+
+ channel.sy_updateFrequency = nil
+ assert_nil(channel.sy_updateFrequency)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_atom.rb b/trunk/test/rss/test_atom.rb
new file mode 100644
index 0000000000..71e0f44ea9
--- /dev/null
+++ b/trunk/test/rss/test_atom.rb
@@ -0,0 +1,683 @@
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/atom"
+
+module RSS
+ class TestAtomCore < TestCase
+ def setup
+ @uri = "http://www.w3.org/2005/Atom"
+ @xhtml_uri = "http://www.w3.org/1999/xhtml"
+ end
+
+ def test_feed
+ version = "1.0"
+ encoding = "UTF-8"
+ standalone = false
+
+ feed = Atom::Feed.new(version, encoding, standalone)
+ assert_equal("", feed.to_s)
+
+ author = feed.class::Author.new
+ name = feed.class::Author::Name.new
+ name.content = "an author"
+ author.name = name
+ assert_not_equal("", author.to_s)
+ feed.authors << author
+ assert_equal("", feed.to_s)
+
+ id = feed.class::Id.new
+ id.content = "http://example.com/atom.xml"
+ assert_not_equal("", id.to_s)
+ feed.id = id
+ assert_equal("", feed.to_s)
+
+ title = feed.class::Title.new
+ title.content = "a title"
+ assert_not_equal("", title.to_s)
+ feed.title = title
+ assert_equal("", feed.to_s)
+
+ updated = feed.class::Updated.new
+ updated.content = Time.now
+ assert_not_equal("", updated.to_s)
+ feed.updated = updated
+ assert_not_equal("", feed.to_s)
+
+
+ feed.authors.clear
+ assert_equal("", feed.to_s)
+ entry = Atom::Feed::Entry.new
+ setup_entry(entry)
+ assert_not_equal("", entry.to_s)
+
+ author = entry.authors.first
+ entry.authors.clear
+ assert_equal("", entry.to_s)
+ entry.parent = feed
+ assert_equal("", entry.to_s)
+ feed.authors << author
+ assert_not_equal("", entry.to_s)
+ feed.authors.clear
+ feed.entries << entry
+ assert_equal("", feed.to_s)
+ entry.authors << author
+ assert_not_equal("", entry.to_s)
+ assert_not_equal("", feed.to_s)
+
+ doc = REXML::Document.new(feed.to_s)
+ xmldecl = doc.xml_decl
+
+ %w(version encoding).each do |x|
+ assert_equal(instance_eval(x), xmldecl.__send__(x))
+ end
+ assert_equal(standalone, !xmldecl.standalone.nil?)
+
+ assert_equal(@uri, doc.root.namespace)
+ end
+
+ def test_entry
+ version = "1.0"
+ encoding = "UTF-8"
+ standalone = false
+
+ entry = Atom::Entry.new(version, encoding, standalone)
+ setup_entry(entry)
+
+ author = entry.authors.first
+ entry.authors.clear
+ assert_equal("", entry.to_s)
+ source = Atom::Entry::Source.new
+ source.authors << author
+ entry.source = source
+ assert_not_equal("", entry.to_s)
+
+ doc = REXML::Document.new(entry.to_s)
+ xmldecl = doc.xml_decl
+
+ %w(version encoding).each do |x|
+ assert_equal(instance_eval(x), xmldecl.__send__(x))
+ end
+ assert_equal(standalone, !xmldecl.standalone.nil?)
+
+ assert_equal(@uri, doc.root.namespace)
+ end
+
+ def test_not_displayed_xml_stylesheets
+ feed = Atom::Feed.new
+ plain_feed = feed.to_s
+ 3.times do
+ feed.xml_stylesheets.push(XMLStyleSheet.new)
+ assert_equal(plain_feed, feed.to_s)
+ end
+ end
+
+ def test_atom_author
+ assert_atom_person_to_s(Atom::Feed::Author)
+ assert_atom_person_to_s(Atom::Feed::Entry::Author)
+ assert_atom_person_to_s(Atom::Entry::Author)
+ assert_atom_person_to_s(Atom::Feed::Entry::Source::Author)
+ assert_atom_person_to_s(Atom::Entry::Source::Author)
+ end
+
+ def test_atom_category
+ assert_atom_category_to_s(Atom::Feed::Category)
+ assert_atom_category_to_s(Atom::Feed::Entry::Category)
+ assert_atom_category_to_s(Atom::Entry::Category)
+ assert_atom_category_to_s(Atom::Feed::Entry::Source::Category)
+ assert_atom_category_to_s(Atom::Entry::Source::Category)
+ end
+
+ def test_atom_contributor
+ assert_atom_person_to_s(Atom::Feed::Contributor)
+ assert_atom_person_to_s(Atom::Feed::Entry::Contributor)
+ assert_atom_person_to_s(Atom::Entry::Contributor)
+ assert_atom_person_to_s(Atom::Feed::Entry::Source::Contributor)
+ assert_atom_person_to_s(Atom::Entry::Source::Contributor)
+ end
+
+ def test_atom_generator
+ assert_atom_generator_to_s(Atom::Feed::Generator)
+ assert_atom_generator_to_s(Atom::Feed::Entry::Source::Generator)
+ assert_atom_generator_to_s(Atom::Entry::Source::Generator)
+ end
+
+ def test_atom_icon
+ assert_atom_icon_to_s(Atom::Feed::Icon)
+ assert_atom_icon_to_s(Atom::Feed::Entry::Source::Icon)
+ assert_atom_icon_to_s(Atom::Entry::Source::Icon)
+ end
+
+ def test_atom_id
+ assert_atom_id_to_s(Atom::Feed::Id)
+ assert_atom_id_to_s(Atom::Feed::Entry::Id)
+ assert_atom_id_to_s(Atom::Entry::Id)
+ assert_atom_id_to_s(Atom::Feed::Entry::Source::Id)
+ assert_atom_id_to_s(Atom::Entry::Source::Id)
+ end
+
+ def test_atom_link
+ assert_atom_link_to_s(Atom::Feed::Link)
+ assert_atom_link_to_s(Atom::Feed::Entry::Link)
+ assert_atom_link_to_s(Atom::Entry::Link)
+ assert_atom_link_to_s(Atom::Feed::Entry::Source::Link)
+ assert_atom_link_to_s(Atom::Entry::Source::Link)
+ end
+
+ def test_atom_logo
+ assert_atom_logo_to_s(Atom::Feed::Logo)
+ assert_atom_logo_to_s(Atom::Feed::Entry::Source::Logo)
+ assert_atom_logo_to_s(Atom::Entry::Source::Logo)
+ end
+
+ def test_atom_rights
+ assert_atom_text_construct_to_s(Atom::Feed::Rights)
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Rights)
+ assert_atom_text_construct_to_s(Atom::Entry::Rights)
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Rights)
+ assert_atom_text_construct_to_s(Atom::Entry::Source::Rights)
+ end
+
+ def test_atom_subtitle
+ assert_atom_text_construct_to_s(Atom::Feed::Subtitle)
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Subtitle)
+ assert_atom_text_construct_to_s(Atom::Entry::Source::Subtitle)
+ end
+
+ def test_atom_title
+ assert_atom_text_construct_to_s(Atom::Feed::Title)
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Title)
+ assert_atom_text_construct_to_s(Atom::Entry::Title)
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Title)
+ assert_atom_text_construct_to_s(Atom::Entry::Source::Title)
+ end
+
+ def test_atom_updated
+ assert_atom_date_construct_to_s(Atom::Feed::Updated)
+ assert_atom_date_construct_to_s(Atom::Feed::Entry::Updated)
+ assert_atom_date_construct_to_s(Atom::Entry::Updated)
+ assert_atom_date_construct_to_s(Atom::Feed::Entry::Source::Updated)
+ assert_atom_date_construct_to_s(Atom::Entry::Source::Updated)
+ end
+
+ def test_atom_content
+ assert_atom_content_to_s(Atom::Feed::Entry::Content)
+ assert_atom_content_to_s(Atom::Entry::Content)
+ end
+
+ def test_atom_published
+ assert_atom_date_construct_to_s(Atom::Feed::Entry::Published)
+ assert_atom_date_construct_to_s(Atom::Entry::Published)
+ end
+
+ def test_atom_summary
+ assert_atom_text_construct_to_s(Atom::Feed::Entry::Summary)
+ assert_atom_text_construct_to_s(Atom::Entry::Summary)
+ end
+
+
+ def test_to_xml(with_convenience_way=true)
+ atom = RSS::Parser.parse(make_feed)
+ assert_equal(atom.to_s, atom.to_xml)
+ assert_equal(atom.to_s, atom.to_xml("atom"))
+ assert_equal(atom.to_s, atom.to_xml("atom1.0"))
+ assert_equal(atom.to_s, atom.to_xml("atom1.0:feed"))
+ assert_equal(atom.to_s, atom.to_xml("atom:feed"))
+
+ rss09_xml = atom.to_xml("0.91") do |maker|
+ maker.channel.language = "en-us"
+ maker.channel.link = "http://example.com/"
+ if with_convenience_way
+ maker.channel.description = atom.title.content
+ else
+ maker.channel.description {|d| d.content = atom.title.content}
+ end
+
+ maker.image.url = "http://example.com/logo.png"
+ maker.image.title = "Logo"
+ end
+ rss09 = RSS::Parser.parse(rss09_xml)
+ assert_equal(["rss", "0.91", nil], rss09.feed_info)
+
+ rss20_xml = atom.to_xml("2.0") do |maker|
+ maker.channel.link = "http://example.com/"
+ if with_convenience_way
+ maker.channel.description = atom.title.content
+ else
+ maker.channel.description {|d| d.content = atom.title.content}
+ end
+ end
+ rss20 = RSS::Parser.parse(rss20_xml)
+ assert_equal("2.0", rss20.rss_version)
+ assert_equal(["rss", "2.0", nil], rss20.feed_info)
+ end
+
+ def test_to_xml_with_new_api_since_018
+ test_to_xml(false)
+ end
+
+ private
+ def setup_entry(entry)
+ _wrap_assertion do
+ assert_equal("", entry.to_s)
+
+ author = entry.class::Author.new
+ name = entry.class::Author::Name.new
+ name.content = "an author"
+ author.name = name
+ assert_not_equal("", author.to_s)
+ entry.authors << author
+ assert_equal("", entry.to_s)
+
+ id = entry.class::Id.new
+ id.content = "http://example.com/atom.xml"
+ assert_not_equal("", id.to_s)
+ entry.id = id
+ assert_equal("", entry.to_s)
+
+ title = entry.class::Title.new
+ title.content = "a title"
+ assert_not_equal("", title.to_s)
+ entry.title = title
+ assert_equal("", entry.to_s)
+
+ updated = entry.class::Updated.new
+ updated.content = Time.now
+ assert_not_equal("", updated.to_s)
+ entry.updated = updated
+ assert_not_equal("", entry.to_s)
+ end
+ end
+
+
+ def assert_atom_person_to_s(target_class)
+ _wrap_assertion do
+ name = "A person"
+ uri = "http://example.com/person/"
+ email = "person@example.com"
+
+ target = target_class.new
+ assert_equal("", target.to_s)
+
+ target = target_class.new
+ person_name = target_class::Name.new
+ person_name.content = name
+ target.name = person_name
+ xml_target = REXML::Document.new(target.to_s).root
+ assert_equal(["name"], xml_target.elements.collect {|e| e.name})
+ assert_equal([name], xml_target.elements.collect {|e| e.text})
+
+ person_uri = target_class::Uri.new
+ person_uri.content = uri
+ target.uri = person_uri
+ xml_target = REXML::Document.new(target.to_s).root
+ assert_equal(["name", "uri"], xml_target.elements.collect {|e| e.name})
+ assert_equal([name, uri], xml_target.elements.collect {|e| e.text})
+
+ person_email = target_class::Email.new
+ person_email.content = email
+ target.email = person_email
+ xml_target = REXML::Document.new(target.to_s).root
+ assert_equal(["name", "uri", "email"],
+ xml_target.elements.collect {|e| e.name})
+ assert_equal([name, uri, email],
+ xml_target.elements.collect {|e| e.text})
+ end
+ end
+
+ def assert_atom_category_to_s(target_class)
+ _wrap_assertion do
+ term = "music"
+ scheme = "http://example.com/music"
+ label = "Music"
+
+ category = target_class.new
+ assert_equal("", category.to_s)
+
+ category = target_class.new
+ category.scheme = scheme
+ assert_equal("", category.to_s)
+
+ category = target_class.new
+ category.label = label
+ assert_equal("", category.to_s)
+
+ category = target_class.new
+ category.scheme = scheme
+ category.label = label
+ assert_equal("", category.to_s)
+
+ category = target_class.new
+ category.term = term
+ xml = REXML::Document.new(category.to_s).root
+ assert_rexml_element([], {"term" => term}, nil, xml)
+
+ category = target_class.new
+ category.term = term
+ category.scheme = scheme
+ xml = REXML::Document.new(category.to_s).root
+ assert_rexml_element([], {"term" => term, "scheme" => scheme}, nil, xml)
+
+ category = target_class.new
+ category.term = term
+ category.label = label
+ xml = REXML::Document.new(category.to_s).root
+ assert_rexml_element([], {"term" => term, "label" => label}, nil, xml)
+
+ category = target_class.new
+ category.term = term
+ category.scheme = scheme
+ category.label = label
+ xml = REXML::Document.new(category.to_s).root
+ attrs = {"term" => term, "scheme" => scheme, "label" => label}
+ assert_rexml_element([], attrs, nil, xml)
+ end
+ end
+
+ def assert_atom_generator_to_s(target_class)
+ _wrap_assertion do
+ content = "Feed generator"
+ uri = "http://example.com/generator"
+ version = "0.0.1"
+
+ generator = target_class.new
+ assert_equal("", generator.to_s)
+
+ generator = target_class.new
+ generator.uri = uri
+ assert_equal("", generator.to_s)
+
+ generator = target_class.new
+ generator.version = version
+ assert_equal("", generator.to_s)
+
+ generator = target_class.new
+ generator.uri = uri
+ generator.version = version
+ assert_equal("", generator.to_s)
+
+ generator = target_class.new
+ generator.content = content
+ xml = REXML::Document.new(generator.to_s).root
+ assert_rexml_element([], {}, content, xml)
+
+ generator = target_class.new
+ generator.content = content
+ generator.uri = uri
+ xml = REXML::Document.new(generator.to_s).root
+ assert_rexml_element([], {"uri" => uri}, content, xml)
+
+ generator = target_class.new
+ generator.content = content
+ generator.version = version
+ xml = REXML::Document.new(generator.to_s).root
+ assert_rexml_element([], {"version" => version}, content, xml)
+
+ generator = target_class.new
+ generator.content = content
+ generator.uri = uri
+ generator.version = version
+ xml = REXML::Document.new(generator.to_s).root
+ assert_rexml_element([], {"uri" => uri, "version" => version},
+ content, xml)
+ end
+ end
+
+ def assert_atom_icon_to_s(target_class)
+ _wrap_assertion do
+ content = "http://example.com/icon.png"
+
+ icon = target_class.new
+ assert_equal("", icon.to_s)
+
+ icon = target_class.new
+ icon.content = content
+ xml = REXML::Document.new(icon.to_s).root
+ assert_rexml_element([], {}, content, xml)
+ end
+ end
+
+ def assert_atom_id_to_s(target_class)
+ _wrap_assertion do
+ content = "http://example.com/1"
+
+ id = target_class.new
+ assert_equal("", id.to_s)
+
+ id = target_class.new
+ id.content = content
+ xml = REXML::Document.new(id.to_s).root
+ assert_rexml_element([], {}, content, xml)
+ end
+ end
+
+ def assert_atom_link_to_s(target_class)
+ _wrap_assertion do
+ href = "http://example.com/atom.xml"
+ rel = "self"
+ type = "application/atom+xml"
+ hreflang = "ja"
+ title = "Atom Feed"
+ length = "801"
+
+ link = target_class.new
+ assert_equal("", link.to_s)
+
+ link = target_class.new
+ link.href = href
+ xml = REXML::Document.new(link.to_s).root
+ assert_rexml_element([], {"href" => href}, nil, xml)
+
+ optional_arguments = %w(rel type hreflang title length)
+ optional_arguments.each do |name|
+ rest = optional_arguments.reject {|x| x == name}
+
+ link = target_class.new
+ link.__send__("#{name}=", eval(name))
+ assert_equal("", link.to_s)
+
+ rest.each do |n|
+ link.__send__("#{n}=", eval(n))
+ assert_equal("", link.to_s)
+ end
+
+ link = target_class.new
+ link.href = href
+ link.__send__("#{name}=", eval(name))
+ attrs = [["href", href], [name, eval(name)]]
+ xml = REXML::Document.new(link.to_s).root
+ assert_rexml_element([], attrs, nil, xml)
+
+ rest.each do |n|
+ link.__send__("#{n}=", eval(n))
+ attrs << [n, eval(n)]
+ xml = REXML::Document.new(link.to_s).root
+ assert_rexml_element([], attrs, nil, xml)
+ end
+ end
+ end
+ end
+
+ def assert_atom_logo_to_s(target_class)
+ _wrap_assertion do
+ content = "http://example.com/logo.png"
+
+ logo = target_class.new
+ assert_equal("", logo.to_s)
+
+ logo = target_class.new
+ logo.content = content
+ xml = REXML::Document.new(logo.to_s).root
+ assert_rexml_element([], {}, content, xml)
+ end
+ end
+
+ def assert_atom_text_construct_to_s(target_class)
+ _wrap_assertion do
+ text_content = "plain text"
+ html_content = "<em>#{text_content}</em>"
+ xhtml_uri = "http://www.w3.org/1999/xhtml"
+ xhtml_em = RSS::XML::Element.new("em", nil, xhtml_uri, {}, text_content)
+ xhtml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ [xhtml_em])
+
+ text = target_class.new
+ assert_equal("", text.to_s)
+
+ text = target_class.new
+ text.type = "text"
+ assert_equal("", text.to_s)
+
+ text = target_class.new
+ text.content = text_content
+ xml = REXML::Document.new(text.to_s).root
+ assert_rexml_element([], {}, text_content, xml)
+
+ text = target_class.new
+ text.type = "text"
+ text.content = text_content
+ xml = REXML::Document.new(text.to_s).root
+ assert_rexml_element([], {"type" => "text"}, text_content, xml)
+
+ text = target_class.new
+ text.type = "html"
+ text.content = html_content
+ xml = REXML::Document.new(text.to_s).root
+ assert_rexml_element([], {"type" => "html"}, html_content, xml)
+
+ text = target_class.new
+ text.type = "xhtml"
+ text.content = xhtml_content
+ assert_equal("", text.to_s)
+
+ text = target_class.new
+ text.type = "xhtml"
+ text.__send__(target_class.xml_setter, xhtml_content)
+ xml = REXML::Document.new(text.to_s).root
+ assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
+ nil, xml)
+ assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
+ assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
+
+ text = target_class.new
+ text.type = "xhtml"
+ text.__send__(target_class.xml_setter, xhtml_em)
+ xml = REXML::Document.new(text.to_s).root
+ assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
+ nil, xml)
+ assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
+ assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
+ end
+ end
+
+ def assert_atom_date_construct_to_s(target_class)
+ _wrap_assertion do
+ date = target_class.new
+ assert_equal("", date.to_s)
+
+ [
+ "2003-12-13T18:30:02Z",
+ "2003-12-13T18:30:02.25Z",
+ "2003-12-13T18:30:02+01:00",
+ "2003-12-13T18:30:02.25+01:00",
+ ].each do |content|
+ date = target_class.new
+ date.content = content
+ xml = REXML::Document.new(date.to_s).root
+ assert_rexml_element([], {}, content, xml, :time)
+
+ date = target_class.new
+ date.content = Time.parse(content)
+ xml = REXML::Document.new(date.to_s).root
+ assert_rexml_element([], {}, content, xml, :time)
+ end
+ end
+ end
+
+ def assert_atom_content_to_s(target_class)
+ _wrap_assertion do
+ assert_atom_text_construct_to_s(target_class)
+ assert_atom_content_inline_other_xml_to_s(target_class)
+ assert_atom_content_inline_other_text_to_s(target_class)
+ assert_atom_content_inline_other_base64_to_s(target_class)
+ assert_atom_content_out_of_line_to_s(target_class)
+ end
+ end
+
+ def assert_atom_content_inline_other_xml_to_s(target_class)
+ _wrap_assertion do
+ content = target_class.new
+ content.type = "text/xml"
+ assert_equal("", content.to_s)
+
+ content = target_class.new
+ content.type = "text/xml"
+ content.xml = RSS::XML::Element.new("em")
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([["", "em"]], {"type" => "text/xml"}, nil, xml)
+ end
+ end
+
+ def assert_atom_content_inline_other_text_to_s(target_class)
+ _wrap_assertion do
+ content = target_class.new
+ content.type = "text/plain"
+ assert_equal("", content.to_s)
+
+ content = target_class.new
+ content.type = "text/plain"
+ content.xml = RSS::XML::Element.new("em")
+ assert_equal("", content.to_s)
+
+ content = target_class.new
+ content.type = "text/plain"
+ content.content = "content"
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([], {"type" => "text/plain"}, "content", xml)
+ end
+ end
+
+ def assert_atom_content_inline_other_base64_to_s(target_class)
+ _wrap_assertion do
+ type = "image/png"
+ png_file = File.join(File.dirname(__FILE__), "dot.png")
+ original_content = File.open(png_file, "rb") do |file|
+ file.read.force_encoding("binary")
+ end
+
+ content = target_class.new
+ content.type = type
+ content.content = original_content
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([], {"type" => type},
+ [original_content].pack("m").delete("\n"),
+ xml)
+ end
+ end
+
+ def assert_atom_content_out_of_line_to_s(target_class)
+ _wrap_assertion do
+ type = "application/zip"
+ src = "http://example.com/xxx.zip"
+
+ content = target_class.new
+ assert(!content.out_of_line?)
+ content.src = src
+ assert(content.out_of_line?)
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([], {"src" => src}, nil, xml)
+
+ content = target_class.new
+ assert(!content.out_of_line?)
+ content.type = type
+ assert(!content.out_of_line?)
+ content.src = src
+ assert(content.out_of_line?)
+ xml = REXML::Document.new(content.to_s).root
+ assert_rexml_element([], {"type" => type, "src" => src}, nil, xml)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_content.rb b/trunk/test/rss/test_content.rb
new file mode 100644
index 0000000000..02db59186b
--- /dev/null
+++ b/trunk/test/rss/test_content.rb
@@ -0,0 +1,104 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/content"
+
+module RSS
+ class TestContent < TestCase
+ def setup
+ @prefix = "content"
+ @uri = "http://purl.org/rss/1.0/modules/content/"
+
+ @elems = {
+ :encoded => "<em>ATTENTION</em>",
+ }
+
+ @content_nodes = @elems.collect do |name, value|
+ "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
+ end.join("\n")
+
+ @rss10_source = make_RDF(<<-EOR, {@prefix => @uri})
+#{make_channel()}
+#{make_image()}
+#{make_item(@content_nodes)}
+#{make_textinput()}
+EOR
+
+ @rss10 = Parser.parse(@rss10_source)
+
+
+ @rss20_source = make_rss20(<<-EOR, {@prefix => @uri})
+#{make_channel20(make_item20(@content_nodes))}
+EOR
+
+ @rss20 = Parser.parse(@rss20_source)
+ end
+
+ def test_parser
+ assert_nothing_raised do
+ Parser.parse(@rss10_source)
+ end
+
+ assert_nothing_raised do
+ Parser.parse(@rss20_source)
+ end
+
+ @elems.each do |tag, value|
+ tag_name = "#{@prefix}:#{tag}"
+ content_encodes = make_element(tag_name, {}, value) * 2
+
+ assert_too_much_tag(tag.to_s, "item") do
+ Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
+#{make_channel}
+#{make_item(content_encodes)}
+EOR
+ end
+
+ assert_too_much_tag(tag.to_s, "item") do
+ Parser.parse(make_rss20(<<-EOR, {@prefix => @uri}))
+#{make_channel20(make_item20(content_encodes))}
+EOR
+ end
+ end
+ end
+
+ def test_accessor
+ new_value = {
+ :encoded => "<![CDATA[<it>hoge</it>]]>",
+ }
+
+ @elems.each do |name, value|
+ [@rss10, @rss20].each do |rss|
+ meth = "#{RSS::CONTENT_PREFIX}_#{name}"
+ parent = rss.items.last
+ assert_equal(value, parent.__send__(meth))
+ parent.__send__("#{meth}=", new_value[name].to_s)
+ assert_equal(new_value[name], parent.__send__(meth))
+ end
+ end
+ end
+
+ def test_to_s
+ @elems.each do |name, value|
+ excepted = make_element("#{@prefix}:#{name}", {}, value)
+ meth = "#{RSS::CONTENT_PREFIX}_#{name}_element"
+ [@rss10, @rss20].each do |rss|
+ assert_equal(excepted, rss.items.last.__send__(meth))
+ end
+ end
+
+ [@rss10_source, @rss20_source].each do |source|
+ REXML::Document.new(source).root.each_element do |parent|
+ next unless parent.name != "item"
+ parent.each_element do |elem|
+ if elem.namespace == @uri
+ assert_equal(elem.text, @elems[elem.name.intern].to_s)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_dublincore.rb b/trunk/test/rss/test_dublincore.rb
new file mode 100644
index 0000000000..22b81483f4
--- /dev/null
+++ b/trunk/test/rss/test_dublincore.rb
@@ -0,0 +1,279 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/dublincore"
+
+module RSS
+ class TestDublinCore < TestCase
+ def setup
+ @rss10_parents = [%w(channel), %w(image), %w(item), %w(textinput)]
+
+ @rss10_source = make_RDF(<<-EOR, {DC_PREFIX => DC_URI})
+#{make_channel(DC_NODES)}
+#{make_image(DC_NODES)}
+#{make_item(DC_NODES)}
+#{make_textinput(DC_NODES)}
+EOR
+
+ @rss20_parents = [%w(channel), %w(items last)]
+
+ @rss20_source = make_rss20(<<-EOR, {DC_PREFIX => DC_URI})
+#{make_channel20(DC_NODES + make_item20(DC_NODES))}
+EOR
+
+ @atom_feed_parents = [[], %w(entries last)]
+
+ @atom_feed_source = make_feed(<<-EOR, {DC_PREFIX => DC_URI})
+#{DC_NODES}
+#{make_entry(DC_NODES)}
+EOR
+
+ @atom_entry_parents = [[]]
+
+ @atom_entry_source = make_entry_document(<<-EOR, {DC_PREFIX => DC_URI})
+#{DC_NODES}
+EOR
+ end
+
+ def test_parser
+ rss10_maker = Proc.new do |content, xmlns|
+ make_RDF(<<-EOR, xmlns)
+#{make_channel(content)}
+#{make_image(content)}
+#{make_item(content)}
+#{make_textinput(content)}
+EOR
+ end
+ assert_dc_parse(@rss10_source, @rss10_parents, false, &rss10_maker)
+ assert_dc_parse(@rss10_source, @rss10_parents, true, &rss10_maker)
+
+ rss20_maker = Proc.new do |content, xmlns|
+ make_rss20(<<-EOR, xmlns)
+#{make_channel20(content + make_item20(content))}
+EOR
+ end
+ assert_dc_parse(@rss20_source, @rss20_parents, false, &rss20_maker)
+ assert_dc_parse(@rss20_source, @rss20_parents, true, &rss20_maker)
+
+ atom_feed_maker = Proc.new do |content, xmlns|
+ make_feed(<<-EOR, xmlns)
+#{content}
+#{make_entry(content)}
+EOR
+ end
+ assert_dc_parse(@atom_feed_source, @atom_feed_parents, false,
+ &atom_feed_maker)
+ assert_dc_parse(@atom_feed_source, @atom_feed_parents, true,
+ &atom_feed_maker)
+
+ atom_entry_maker = Proc.new do |content, xmlns|
+ make_entry_document(<<-EOR, xmlns)
+#{content}
+EOR
+ end
+ assert_dc_parse(@atom_entry_source, @atom_entry_parents, false,
+ &atom_entry_maker)
+ assert_dc_parse(@atom_entry_source, @atom_entry_parents, true,
+ &atom_entry_maker)
+ end
+
+ def test_singular_accessor
+ assert_dc_singular_accessor(@rss10_source, @rss10_parents)
+ assert_dc_singular_accessor(@rss20_source, @rss20_parents)
+ assert_dc_singular_accessor(@atom_feed_source, @atom_feed_parents)
+ assert_dc_singular_accessor(@atom_entry_source, @atom_entry_parents)
+ end
+
+ def test_plural_accessor
+ assert_dc_plural_accessor(@rss10_source, @rss10_parents, false)
+ assert_dc_plural_accessor(@rss10_source, @rss10_parents, true)
+
+ assert_dc_plural_accessor(@rss20_source, @rss20_parents, false)
+ assert_dc_plural_accessor(@rss20_source, @rss20_parents, true)
+
+ assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, false)
+ assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, true)
+
+ assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, false)
+ assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, true)
+ end
+
+ def test_to_s
+ assert_dc_to_s(@rss10_source, @rss10_parents, false)
+ assert_dc_to_s(@rss10_source, @rss10_parents, true)
+
+ targets = ["channel", "channel/item[3]"]
+ assert_dc_to_s(@rss20_source, @rss20_parents, false, targets)
+ assert_dc_to_s(@rss20_source, @rss20_parents, true, targets)
+
+ targets = [".", "entry"]
+ assert_dc_to_s(@atom_feed_source, @atom_feed_parents, false, targets)
+ assert_dc_to_s(@atom_feed_source, @atom_feed_parents, true, targets)
+
+ targets = ["."]
+ assert_dc_to_s(@atom_entry_source, @atom_entry_parents, false, targets)
+ assert_dc_to_s(@atom_entry_source, @atom_entry_parents, true, targets)
+ end
+
+ private
+ def dc_plural_suffix(name, check_backward_compatibility)
+ if name == :rights
+ if check_backward_compatibility
+ "es"
+ else
+ "_list"
+ end
+ else
+ "s"
+ end
+ end
+
+ def assert_dc_parse(source, parents, check_backward_compatibility, &maker)
+ assert_nothing_raised do
+ Parser.parse(source)
+ end
+
+ DC_ELEMENTS.each do |name, value|
+ parents.each do |parent_readers|
+ feed = nil
+ assert_nothing_raised do
+ tag = "#{DC_PREFIX}:#{name}"
+ dc_content = "<#{tag}>#{value}</#{tag}>\n"
+ dc_content *= 2
+ feed = Parser.parse(maker.call(dc_content, {DC_PREFIX => DC_URI}))
+ end
+ parent = chain_reader(feed, parent_readers)
+
+ plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
+ plural_reader = "dc_#{name}#{plural_suffix}"
+ values = parent.__send__(plural_reader).collect do |x|
+ val = x.value
+ if val.kind_of?(String)
+ CGI.escapeHTML(val)
+ else
+ val
+ end
+ end
+ assert_equal([value, value], values)
+ end
+ end
+ end
+
+ def assert_dc_singular_accessor(source, parents)
+ feed = Parser.parse(source)
+ new_value = "hoge"
+
+ parents.each do |parent_readers|
+ parent = chain_reader(feed, parent_readers)
+ DC_ELEMENTS.each do |name, value|
+ parsed_value = parent.__send__("dc_#{name}")
+ if parsed_value.kind_of?(String)
+ parsed_value = CGI.escapeHTML(parsed_value)
+ end
+ assert_equal(value, parsed_value)
+ if name == :date
+ t = Time.iso8601("2003-01-01T02:30:23+09:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+ parent.__send__("dc_#{name}=", t.iso8601)
+ assert_equal(t, parent.__send__("dc_#{name}"))
+ if parent.class.method_defined?(:date_without_dc_date=)
+ assert_nil(parent.date)
+ else
+ assert_equal(t, parent.date)
+ end
+
+ parent.date = value
+ assert_equal(value, parent.date)
+ assert_equal(value, parent.__send__("dc_#{name}"))
+ else
+ parent.__send__("dc_#{name}=", new_value)
+ assert_equal(new_value, parent.__send__("dc_#{name}"))
+ end
+ end
+ end
+ end
+
+ def assert_dc_plural_accessor(source, parents, check_backward_compatibility)
+ feed = Parser.parse(source)
+ new_value = "hoge"
+
+ DC_ELEMENTS.each do |name, value|
+ parents.each do |parent_readers|
+ parent = chain_reader(feed, parent_readers)
+ parsed_value = parent.__send__("dc_#{name}")
+ if parsed_value.kind_of?(String)
+ parsed_value = CGI.escapeHTML(parsed_value)
+ end
+ assert_equal(value, parsed_value)
+
+ plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
+ plural_reader = "dc_#{name}#{plural_suffix}"
+ klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
+ klass = DublinCoreModel.const_get(klass_name)
+ if name == :date
+ t = Time.iso8601("2003-01-01T02:30:23+09:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+ elems = parent.__send__(plural_reader)
+ elems << klass.new(t.iso8601)
+ new_elems = parent.__send__(plural_reader)
+ values = new_elems.collect{|x| x.value}
+ assert_equal([parent.__send__("dc_#{name}"), t], values)
+ else
+ elems = parent.__send__(plural_reader)
+ elems << klass.new(new_value)
+ new_elems = parent.__send__(plural_reader)
+ values = new_elems.collect{|x| x.value}
+ assert_equal([parent.__send__("dc_#{name}"), new_value],
+ values)
+ end
+ end
+ end
+ end
+
+ def assert_dc_to_s(source, parents, check_backward_compatibility,
+ targets=nil)
+ feed = Parser.parse(source)
+
+ DC_ELEMENTS.each do |name, value|
+ excepted = "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
+ parents.each do |parent_readers|
+ parent = chain_reader(feed, parent_readers)
+ assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
+ end
+
+ plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
+ reader = "dc_#{name}#{plural_suffix}"
+ excepted = Array.new(2, excepted).join("\n")
+ parents.each do |parent_readers|
+ parent = chain_reader(feed, parent_readers)
+ elems = parent.__send__(reader)
+ klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
+ klass = DublinCoreModel.const_get(klass_name)
+ elems << klass.new(parent.__send__("dc_#{name}"))
+ assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
+ end
+ end
+
+ targets ||= parents.collect do |parent_readers|
+ parent_readers.first
+ end
+ feed_root = REXML::Document.new(source).root
+ targets.each do |target_xpath|
+ parent = feed_root.elements[target_xpath]
+ parent.each_element do |elem|
+ if elem.namespace == DC_URI
+ assert_equal(CGI.escapeHTML(elem.text),
+ DC_ELEMENTS[elem.name.intern].to_s)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_image.rb b/trunk/test/rss/test_image.rb
new file mode 100644
index 0000000000..101b7ffda2
--- /dev/null
+++ b/trunk/test/rss/test_image.rb
@@ -0,0 +1,214 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/image"
+
+module RSS
+ class TestImage < TestCase
+
+ def setup
+ @prefix = "image"
+ @uri = "http://purl.org/rss/1.0/modules/image/"
+
+ @favicon_attrs = {
+ "rdf:about" => "http://www.kuro5hin.org/favicon.ico",
+ "#{@prefix}:size" => "small",
+ }
+ @favicon_contents = {"dc:title" => "Kuro5hin",}
+ @items = [
+ [
+ {
+ "rdf:about" => "http://www.example.org/item.png",
+ "rdf:resource" => "http://www.example.org/item",
+ },
+ {
+ "dc:title" => "Example Image",
+ "#{@prefix}:width" => "100",
+ "#{@prefix}:height" => "65",
+ },
+ ],
+ [
+ {
+ "rdf:about" => "http://www.kuro5hin.org/images/topics/culture.jpg",
+ },
+ {
+ "dc:title" => "Culture",
+ "#{@prefix}:width" => "80",
+ "#{@prefix}:height" => "50",
+ },
+ ]
+ ]
+
+
+ @channel_nodes = make_element("#{@prefix}:favicon",
+ @favicon_attrs,
+ @favicon_contents)
+ items = ""
+ @items.each do |attrs, contents|
+ image_item = make_element("#{@prefix}:item", attrs, contents)
+ items << make_item(image_item)
+ end
+
+ @ns = {
+ @prefix => @uri,
+ DC_PREFIX => DC_URI,
+ }
+ @rss_source = make_RDF(<<-EOR, @ns)
+#{make_channel(@channel_nodes)}
+#{make_image}
+#{items}
+#{make_textinput}
+EOR
+
+ @rss = Parser.parse(@rss_source)
+ end
+
+ def test_parser
+ assert_nothing_raised do
+ Parser.parse(@rss_source)
+ end
+
+ assert_too_much_tag("favicon", "channel") do
+ Parser.parse(make_RDF(<<-EOR, @ns))
+#{make_channel(@channel_nodes * 2)}
+#{make_item}
+EOR
+ end
+
+ attrs = {"rdf:about" => "http://www.example.org/item.png"}
+ contents = [["#{@prefix}:width", "80"]] * 5
+ image_item = make_element("#{@prefix}:item", attrs, contents)
+ assert_too_much_tag("width", "item") do
+ Parser.parse(make_RDF(<<-EOR, @ns))
+#{make_channel}
+#{make_item(image_item)}
+EOR
+ end
+ end
+
+ def test_favicon_accessor
+ favicon = @rss.channel.image_favicon
+ [
+ %w(about rdf:about http://example.com/favicon.ico),
+ %w(size image:size large),
+ %w(image_size image:size medium),
+ ].each do |name, full_name, new_value|
+ assert_equal(@favicon_attrs[full_name], favicon.__send__(name))
+ favicon.__send__("#{name}=", new_value)
+ assert_equal(new_value, favicon.__send__(name))
+ favicon.__send__("#{name}=", @favicon_attrs[full_name])
+ assert_equal(@favicon_attrs[full_name], favicon.__send__(name))
+ end
+
+ %w(small medium large).each do |value|
+ assert_nothing_raised do
+ favicon.size = value
+ favicon.image_size = value
+ end
+ end
+
+ %w(aaa AAA SMALL MEDIUM LARGE).each do |value|
+ args = ["#{@prefix}:favicon", value, "#{@prefix}:size"]
+ assert_not_available_value(*args) do
+ favicon.size = value
+ end
+ assert_not_available_value(*args) do
+ favicon.image_size = value
+ end
+ end
+
+ [
+ %w(dc_title dc:title sample-favicon),
+ ].each do |name, full_name, new_value|
+ assert_equal(@favicon_contents[full_name], favicon.__send__(name))
+ favicon.__send__("#{name}=", new_value)
+ assert_equal(new_value, favicon.__send__(name))
+ favicon.__send__("#{name}=", @favicon_contents[full_name])
+ assert_equal(@favicon_contents[full_name], favicon.__send__(name))
+ end
+ end
+
+ def test_item_accessor
+ @rss.items.each_with_index do |item, i|
+ image_item = item.image_item
+ attrs, contents = @items[i]
+ [
+ %w(about rdf:about http://example.com/image.png),
+ %w(resource rdf:resource http://example.com/),
+ ].each do |name, full_name, new_value|
+ assert_equal(attrs[full_name], image_item.__send__(name))
+ image_item.__send__("#{name}=", new_value)
+ assert_equal(new_value, image_item.__send__(name))
+ image_item.__send__("#{name}=", attrs[full_name])
+ assert_equal(attrs[full_name], image_item.__send__(name))
+ end
+
+ [
+ ["width", "image:width", "111"],
+ ["image_width", "image:width", "44"],
+ ["height", "image:height", "222"],
+ ["image_height", "image:height", "88"],
+ ].each do |name, full_name, new_value|
+ assert_equal(contents[full_name].to_i, image_item.__send__(name))
+ image_item.__send__("#{name}=", new_value)
+ assert_equal(new_value.to_i, image_item.__send__(name))
+ image_item.__send__("#{name}=", contents[full_name])
+ assert_equal(contents[full_name].to_i, image_item.__send__(name))
+ end
+
+ [
+ ["dc_title", "dc:title", "sample-image"],
+ ].each do |name, full_name, new_value|
+ assert_equal(contents[full_name], image_item.__send__(name))
+ image_item.__send__("#{name}=", new_value)
+ assert_equal(new_value, image_item.__send__(name))
+ image_item.__send__("#{name}=", contents[full_name])
+ assert_equal(contents[full_name], image_item.__send__(name))
+ end
+ end
+ end
+
+ def test_favicon_to_s
+ favicon = @rss.channel.image_favicon
+ expected_xml = image_xmlns_container(make_element("#{@prefix}:favicon",
+ @favicon_attrs,
+ @favicon_contents))
+ expected = REXML::Document.new(expected_xml)
+ actual_xml = image_xmlns_container(favicon.to_s(false, ""))
+ actual = REXML::Document.new(actual_xml)
+ assert_equal(expected.to_s, actual.to_s)
+ end
+
+ def test_item_to_s
+ @rss.items.each_with_index do |item, i|
+ attrs, contents = @items[i]
+ expected_xml = make_element("#{@prefix}:item", attrs, contents)
+ expected_xml = image_xmlns_container(expected_xml)
+ expected = REXML::Document.new(expected_xml)
+ actual_xml = image_xmlns_container(item.image_item.to_s(false, ""))
+ actual = REXML::Document.new(actual_xml)
+
+ assert_equal(expected[0].attributes, actual[0].attributes)
+
+ %w(image:height image:width dc:title).each do |name|
+ actual_target = actual.elements["//#{name}"]
+ expected_target = expected.elements["//#{name}"]
+ assert_equal(expected_target.to_s, actual_target.to_s)
+ end
+ end
+ end
+
+ private
+ def image_xmlns_container(content)
+ xmlns_container({
+ @prefix => @uri,
+ "dc" => "http://purl.org/dc/elements/1.1/",
+ "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ },
+ content)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_inherit.rb b/trunk/test/rss/test_inherit.rb
new file mode 100644
index 0000000000..f73096f478
--- /dev/null
+++ b/trunk/test/rss/test_inherit.rb
@@ -0,0 +1,40 @@
+require "rss-testcase"
+
+require "rss/1.0"
+
+module RSS
+ class TestInherit < TestCase
+
+ class InheritedImage < RSS::RDF::Image
+ def self.indent_size; 1; end
+ def self.tag_name; 'image'; end
+ end
+
+ def setup
+ @rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_image}
+#{make_item}
+#{make_textinput}
+EOR
+ end
+
+ def test_inherit
+ rss = RSS::Parser.parse(@rss)
+ orig_image = rss.image
+ prefix = "[INHERIT]"
+ image = InheritedImage.new("#{prefix} #{orig_image.about}")
+ image.title = "#{prefix} #{orig_image.title}"
+ image.url = "#{prefix} #{orig_image.url}"
+ image.link = "#{prefix} #{orig_image.link}"
+ rss.image = image
+
+ new_rss = RSS::Parser.parse(rss.to_s)
+ new_image = new_rss.image
+ assert_equal("#{prefix} #{orig_image.about}", new_image.about)
+ assert_equal("#{prefix} #{orig_image.title}", new_image.title)
+ assert_equal("#{prefix} #{orig_image.url}", new_image.url)
+ assert_equal("#{prefix} #{orig_image.link}", new_image.link)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_itunes.rb b/trunk/test/rss/test_itunes.rb
new file mode 100644
index 0000000000..283459d910
--- /dev/null
+++ b/trunk/test/rss/test_itunes.rb
@@ -0,0 +1,347 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/2.0"
+require "rss/itunes"
+
+module RSS
+ class TestITunes < TestCase
+ def test_author
+ assert_itunes_author(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+
+ assert_itunes_author(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_block
+ assert_itunes_block(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_category
+ assert_itunes_category(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+ end
+
+ def test_image
+ assert_itunes_image(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+ end
+
+ def test_duration
+ assert_itunes_duration(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_explicit
+ assert_itunes_explicit(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+
+ assert_itunes_explicit(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_keywords
+ assert_itunes_keywords(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+
+ assert_itunes_keywords(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_new_feed_url
+ assert_itunes_new_feed_url(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+ end
+
+ def test_owner
+ assert_itunes_owner(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+ end
+
+ def test_subtitle
+ assert_itunes_subtitle(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+
+ assert_itunes_subtitle(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ def test_summary
+ assert_itunes_summary(%w(channel)) do |content, xmlns|
+ make_rss20(make_channel20(content), xmlns)
+ end
+
+ assert_itunes_summary(%w(items last)) do |content, xmlns|
+ make_rss20(make_channel20(make_item20(content)), xmlns)
+ end
+ end
+
+ private
+ def itunes_rss20_parse(content, &maker)
+ xmlns = {"itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd"}
+ rss20_xml = maker.call(content, xmlns)
+ ::RSS::Parser.parse(rss20_xml)
+ end
+
+ def assert_itunes_author(readers, &rss20_maker)
+ _wrap_assertion do
+ author = "John Lennon"
+ rss20 = itunes_rss20_parse(tag("itunes:author", author), &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(author, target.itunes_author)
+ end
+ end
+
+ def _assert_itunes_block(value, boolean_value, readers, &rss20_maker)
+ rss20 = itunes_rss20_parse(tag("itunes:block", value), &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(value, target.itunes_block)
+ assert_equal(boolean_value, target.itunes_block?)
+ end
+
+ def assert_itunes_block(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_block("yes", true, readers, &rss20_maker)
+ _assert_itunes_block("Yes", true, readers, &rss20_maker)
+ _assert_itunes_block("no", false, readers, &rss20_maker)
+ _assert_itunes_block("", false, readers, &rss20_maker)
+ end
+ end
+
+ def _assert_itunes_category(categories, readers, &rss20_maker)
+ cats = categories.collect do |category|
+ if category.is_a?(Array)
+ category, sub_category = category
+ tag("itunes:category",
+ tag("itunes:category", nil, {"text" => sub_category}),
+ {"text" => category})
+ else
+ tag("itunes:category", nil, {"text" => category})
+ end
+ end.join
+ rss20 = itunes_rss20_parse(cats, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ actual_categories = target.itunes_categories.collect do |category|
+ cat = category.text
+ if category.itunes_categories.empty?
+ cat
+ else
+ [cat, *category.itunes_categories.collect {|c| c.text}]
+ end
+ end
+ assert_equal(categories, actual_categories)
+ end
+
+ def assert_itunes_category(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_category(["Audio Blogs"], readers, &rss20_maker)
+ _assert_itunes_category([["Arts & Entertainment", "Games"]],
+ readers, &rss20_maker)
+ _assert_itunes_category([["Arts & Entertainment", "Games"],
+ ["Technology", "Computers"],
+ "Audio Blogs"],
+ readers, &rss20_maker)
+ end
+ end
+
+ def assert_itunes_image(readers, &rss20_maker)
+ _wrap_assertion do
+ url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
+ content = tag("itunes:image", nil, {"href" => url})
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_not_nil(target.itunes_image)
+ assert_equal(url, target.itunes_image.href)
+
+ assert_missing_attribute("image", "href") do
+ content = tag("itunes:image")
+ itunes_rss20_parse(content, &rss20_maker)
+ end
+ end
+ end
+
+ def _assert_itunes_duration(hour, minute, second, value,
+ readers, &rss20_maker)
+ content = tag("itunes:duration", value)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ duration = chain_reader(rss20, readers).itunes_duration
+ assert_equal(value, duration.content)
+ assert_equal(hour, duration.hour)
+ assert_equal(minute, duration.minute)
+ assert_equal(second, duration.second)
+ end
+
+ def _assert_itunes_duration_not_available_value(value, &rss20_maker)
+ assert_not_available_value("duration", value) do
+ content = tag("itunes:duration", value)
+ itunes_rss20_parse(content, &rss20_maker)
+ end
+ end
+
+ def assert_itunes_duration(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_duration(7, 14, 5, "07:14:05", readers, &rss20_maker)
+ _assert_itunes_duration(7, 14, 5, "7:14:05", readers, &rss20_maker)
+ _assert_itunes_duration(0, 4, 55, "04:55", readers, &rss20_maker)
+ _assert_itunes_duration(0, 4, 5, "4:05", readers, &rss20_maker)
+
+ _assert_itunes_duration_not_available_value("5", &rss20_maker)
+ _assert_itunes_duration_not_available_value("09:07:14:05", &rss20_maker)
+ _assert_itunes_duration_not_available_value("10:5", &rss20_maker)
+ _assert_itunes_duration_not_available_value("10:03:5", &rss20_maker)
+ _assert_itunes_duration_not_available_value("10:3:05", &rss20_maker)
+
+ _assert_itunes_duration_not_available_value("xx:xx:xx", &rss20_maker)
+ end
+ end
+
+ def _assert_itunes_explicit(explicit, value, readers, &rss20_maker)
+ content = tag("itunes:explicit", value)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(value, target.itunes_explicit)
+ assert_equal(explicit, target.itunes_explicit?)
+ end
+
+ def assert_itunes_explicit(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_explicit(true, "yes", readers, &rss20_maker)
+ _assert_itunes_explicit(false, "clean", readers, &rss20_maker)
+ _assert_itunes_explicit(nil, "no", readers, &rss20_maker)
+ end
+ end
+
+ def _assert_itunes_keywords(keywords, value, readers, &rss20_maker)
+ content = tag("itunes:keywords", value)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(keywords, target.itunes_keywords)
+ end
+
+ def assert_itunes_keywords(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_keywords(["salt"], "salt", readers, &rss20_maker)
+ _assert_itunes_keywords(["salt"], " salt ", readers, &rss20_maker)
+ _assert_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
+ "salt, pepper, shaker, exciting",
+ readers, &rss20_maker)
+ _assert_itunes_keywords(["metric", "socket", "wrenches", "toolsalt"],
+ "metric, socket, wrenches, toolsalt",
+ readers, &rss20_maker)
+ _assert_itunes_keywords(["olitics", "red", "blue", "state"],
+ "olitics, red, blue, state",
+ readers, &rss20_maker)
+ end
+ end
+
+ def assert_itunes_new_feed_url(readers, &rss20_maker)
+ _wrap_assertion do
+ url = "http://newlocation.com/example.rss"
+ content = tag("itunes:new-feed-url", url)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(url, target.itunes_new_feed_url)
+ end
+ end
+
+ def _assert_itunes_owner(name, email, readers, &rss20_maker)
+ content = tag("itunes:owner",
+ tag("itunes:name", name) + tag("itunes:email", email))
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ owner = chain_reader(rss20, readers).itunes_owner
+ assert_equal(name, owner.itunes_name)
+ assert_equal(email, owner.itunes_email)
+ end
+
+ def assert_itunes_owner(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_owner("John Doe", "john.doe@example.com",
+ readers, &rss20_maker)
+
+ assert_missing_tag("name", "owner") do
+ content = tag("itunes:owner")
+ itunes_rss20_parse(content, &rss20_maker)
+ end
+
+ assert_missing_tag("name", "owner") do
+ content = tag("itunes:owner",
+ tag("itunes:email", "john.doe@example.com"))
+ itunes_rss20_parse(content, &rss20_maker)
+ end
+
+ assert_missing_tag("email", "owner") do
+ content = tag("itunes:owner", tag("itunes:name", "John Doe"))
+ itunes_rss20_parse(content, &rss20_maker)
+ end
+ end
+ end
+
+ def _assert_itunes_subtitle(value, readers, &rss20_maker)
+ content = tag("itunes:subtitle", value)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(value, target.itunes_subtitle)
+ end
+
+ def assert_itunes_subtitle(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_subtitle("A show about everything", readers, &rss20_maker)
+ _assert_itunes_subtitle("A short primer on table spices",
+ readers, &rss20_maker)
+ _assert_itunes_subtitle("Comparing socket wrenches is fun!",
+ readers, &rss20_maker)
+ _assert_itunes_subtitle("Red + Blue != Purple", readers, &rss20_maker)
+ end
+ end
+
+ def _assert_itunes_summary(value, readers, &rss20_maker)
+ content = tag("itunes:summary", value)
+ rss20 = itunes_rss20_parse(content, &rss20_maker)
+ target = chain_reader(rss20, readers)
+ assert_equal(value, target.itunes_summary)
+ end
+
+ def assert_itunes_summary(readers, &rss20_maker)
+ _wrap_assertion do
+ _assert_itunes_summary("All About Everything is a show about " +
+ "everything. Each week we dive into any " +
+ "subject known to man and talk about it as " +
+ "much as we can. Look for our Podcast in " +
+ "the iTunes Music Store",
+ readers, &rss20_maker)
+ _assert_itunes_summary("This week we talk about salt and pepper " +
+ "shakers, comparing and contrasting pour " +
+ "rates, construction materials, and overall " +
+ "aesthetics. Come and join the party!",
+ readers, &rss20_maker)
+ _assert_itunes_summary("This week we talk about metric vs. old " +
+ "english socket wrenches. Which one is " +
+ "better? Do you really need both? Get all " +
+ "of your answers here.",
+ readers, &rss20_maker)
+ _assert_itunes_summary("This week we talk about surviving in a " +
+ "Red state if you're a Blue person. Or " +
+ "vice versa.",
+ readers, &rss20_maker)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_0.9.rb b/trunk/test/rss/test_maker_0.9.rb
new file mode 100644
index 0000000000..815f9e3952
--- /dev/null
+++ b/trunk/test/rss/test_maker_0.9.rb
@@ -0,0 +1,439 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMaker09 < TestCase
+
+ def test_rss
+ assert_raise(LocalJumpError) do
+ RSS::Maker.make("0.91")
+ end
+
+ rss = RSS::Maker.make("0.9") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+ end
+ assert_equal("0.92", rss.rss_version)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+ end
+ assert_equal("0.91", rss.rss_version)
+
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.encoding = "EUC-JP"
+ end
+ assert_equal("0.91", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.standalone = "yes"
+ end
+ assert_equal("0.91", rss.rss_version)
+ assert_equal("yes", rss.standalone)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.encoding = "EUC-JP"
+ maker.standalone = "yes"
+ end
+ assert_equal("0.91", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+ assert_equal("yes", rss.standalone)
+ end
+
+ def test_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+ copyright = "foo"
+ managingEditor = "bar"
+ webMaster = "web master"
+ rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
+ docs = "http://foo.com/doc"
+ skipDays = [
+ "Sunday",
+ "Monday",
+ ]
+ skipHours = [
+ "0",
+ "13",
+ ]
+ pubDate = Time.now
+ lastBuildDate = Time.now
+
+ image_url = "http://example.com/logo.png"
+ image_title = "Logo"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ maker.channel.copyright = copyright
+ maker.channel.managingEditor = managingEditor
+ maker.channel.webMaster = webMaster
+ maker.channel.rating = rating
+ maker.channel.docs = docs
+ maker.channel.pubDate = pubDate
+ maker.channel.lastBuildDate = lastBuildDate
+
+ skipDays.each do |day|
+ maker.channel.skipDays.new_day do |new_day|
+ new_day.content = day
+ end
+ end
+ skipHours.each do |hour|
+ maker.channel.skipHours.new_hour do |new_hour|
+ new_hour.content = hour
+ end
+ end
+
+ maker.image.url = image_url
+ maker.image.title = image_title
+ end
+ channel = rss.channel
+
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(language, channel.language)
+ assert_equal(copyright, channel.copyright)
+ assert_equal(managingEditor, channel.managingEditor)
+ assert_equal(webMaster, channel.webMaster)
+ assert_equal(rating, channel.rating)
+ assert_equal(docs, channel.docs)
+ assert_equal(pubDate, channel.pubDate)
+ assert_equal(pubDate, channel.date)
+ assert_equal(lastBuildDate, channel.lastBuildDate)
+
+ skipDays.each_with_index do |day, i|
+ assert_equal(day, channel.skipDays.days[i].content)
+ end
+ skipHours.each_with_index do |hour, i|
+ assert_equal(hour.to_i, channel.skipHours.hours[i].content)
+ end
+
+ assert(channel.items.empty?)
+
+ assert_equal(image_url, channel.image.url)
+ assert_equal(image_title, channel.image.title)
+ assert_equal(link, channel.image.link)
+
+ assert_nil(channel.textInput)
+ end
+
+ def test_not_valid_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+
+ assert_not_set_error("maker.channel", %w(title)) do
+ RSS::Maker.make("0.91") do |maker|
+ # maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("0.91") do |maker|
+ maker.channel.title = title
+ # maker.channel.link = link
+ maker.channel.link = nil
+ maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(description)) do
+ RSS::Maker.make("0.91") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ # maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(language)) do
+ RSS::Maker.make("0.91") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ # maker.channel.language = language
+ end
+ end
+ end
+
+ def test_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ image = rss.image
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+ assert_equal(width.to_i, image.width)
+ assert_equal(height.to_i, image.height)
+ assert_equal(description, image.description)
+
+ assert_not_set_error("maker.channel", %w(description title language)) do
+ RSS::Maker.make("0.91") do |maker|
+ # setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+ end
+
+ def test_not_valid_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ assert_not_set_error("maker.image", %w(title)) do
+ RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ # maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ # maker.channel.link = link
+ maker.channel.link = nil
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+
+ assert_not_set_error("maker.image", %w(url)) do
+ RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ # maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+ end
+
+ def test_items(with_convenience_way=true)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+ end
+ assert(rss.channel.items.empty?)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ item.title = title
+ item.link = link
+ # item.description = description
+ end
+
+ setup_dummy_image(maker)
+ end
+ assert_equal(1, rss.channel.items.size)
+ item = rss.channel.items.first
+ assert_equal(title, item.title)
+ assert_equal(link, item.link)
+ assert_nil(item.description)
+
+
+ item_size = 5
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.do_sort = true
+
+ setup_dummy_image(maker)
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.channel.items.each_with_index do |_item, i|
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.do_sort = Proc.new do |x, y|
+ if with_convenience_way
+ y.title[-1] <=> x.title[-1]
+ else
+ y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
+ end
+ end
+
+ setup_dummy_image(maker)
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.channel.items.reverse.each_with_index do |_item, i|
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+ end
+
+ def test_items_with_new_api_since_018
+ test_items(false)
+ end
+
+ def test_textInput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ textInput = rss.channel.textInput
+ assert_equal(title, textInput.title)
+ assert_equal(description, textInput.description)
+ assert_equal(name, textInput.name)
+ assert_equal(link, textInput.link)
+
+ assert_not_set_error("maker.channel",
+ %w(link language description title)) do
+ RSS::Maker.make("0.91") do |maker|
+ # setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ end
+ end
+
+ def test_not_valid_textInput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ # maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.textinput.title = title
+ # maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ # maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ # maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_1.0.rb b/trunk/test/rss/test_maker_1.0.rb
new file mode 100644
index 0000000000..49d506bf6f
--- /dev/null
+++ b/trunk/test/rss/test_maker_1.0.rb
@@ -0,0 +1,485 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMaker10 < TestCase
+
+ def test_rdf
+ assert_raise(LocalJumpError) do
+ RSS::Maker.make("1.0")
+ end
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+ assert_equal("1.0", rss.rss_version)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.encoding = "EUC-JP"
+
+ setup_dummy_item(maker)
+ end
+ assert_equal("1.0", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.standalone = "yes"
+
+ setup_dummy_item(maker)
+ end
+ assert_equal("1.0", rss.rss_version)
+ assert_equal("yes", rss.standalone)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.encoding = "EUC-JP"
+ maker.standalone = "yes"
+
+ setup_dummy_item(maker)
+ end
+ assert_equal("1.0", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+ assert_equal("yes", rss.standalone)
+ end
+
+ def test_channel
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+
+ setup_dummy_item(maker)
+ end
+ channel = rss.channel
+ assert_equal(about, channel.about)
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(1, channel.items.Seq.lis.size)
+ assert_nil(channel.image)
+ assert_nil(channel.textinput)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+
+ setup_dummy_image(maker)
+
+ setup_dummy_textinput(maker)
+
+ setup_dummy_item(maker)
+ end
+ channel = rss.channel
+ assert_equal(about, channel.about)
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(1, channel.items.Seq.lis.size)
+ assert_equal(rss.image.about, channel.image.resource)
+ assert_equal(rss.textinput.about, channel.textinput.resource)
+ end
+
+ def test_not_valid_channel
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+
+ assert_not_set_error("maker.channel", %w(about)) do
+ RSS::Maker.make("1.0") do |maker|
+ # maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(title)) do
+ RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ # maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ maker.channel.title = title
+ # maker.channel.link = link
+ maker.channel.description = description
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(description)) do
+ RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ # maker.channel.description = description
+ end
+ end
+ end
+
+
+ def test_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+
+ setup_dummy_item(maker)
+ end
+ image = rss.image
+ assert_equal(url, image.about)
+ assert_equal(url, rss.channel.image.resource)
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+
+ assert_not_set_error("maker.channel", %w(about title description)) do
+ RSS::Maker.make("1.0") do |maker|
+ # setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ end
+ end
+ end
+
+ def test_not_valid_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ # maker.image.url = url
+ maker.image.title = title
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.image)
+ assert_nil(rss.image)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.url = url
+ # maker.image.title = title
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.image)
+ assert_nil(rss.image)
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ # maker.channel.link = link
+ maker.channel.link = nil
+
+ maker.image.url = url
+ maker.image.title = title
+
+ setup_dummy_item(maker)
+ end
+ end
+ end
+
+ def test_items(with_convenience_way=true)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+
+ assert_not_set_error("maker", %w(items)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ end
+ end
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ item.title = title
+ item.link = link
+ # item.description = description
+ end
+ end
+ assert_equal(1, rss.items.size)
+ item = rss.items.first
+ assert_equal(link, item.about)
+ assert_equal(title, item.title)
+ assert_equal(link, item.link)
+ assert_nil(item.description)
+
+
+ item_size = 5
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.do_sort = true
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.items.each_with_index do |_item, i|
+ assert_equal("#{link}#{i}", _item.about)
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.do_sort = Proc.new do |x, y|
+ if with_convenience_way
+ y.title[-1] <=> x.title[-1]
+ else
+ y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
+ end
+ end
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.items.reverse.each_with_index do |_item, i|
+ assert_equal("#{link}#{i}", _item.about)
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+
+ max_size = item_size / 2
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.max_size = max_size
+ end
+ assert_equal(max_size, rss.items.size)
+ rss.items.each_with_index do |_item, i|
+ assert_equal("#{link}#{i}", _item.about)
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+
+ max_size = 0
+ assert_not_set_error("maker", %w(items)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.max_size = max_size
+ end
+ end
+
+ max_size = -2
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |_item|
+ _item.title = "#{title}#{i}"
+ _item.link = "#{link}#{i}"
+ _item.description = "#{description}#{i}"
+ end
+ end
+ maker.items.max_size = max_size
+ end
+ assert_equal(item_size + max_size + 1, rss.items.size)
+ rss.items.each_with_index do |_item, i|
+ assert_equal("#{link}#{i}", _item.about)
+ assert_equal("#{title}#{i}", _item.title)
+ assert_equal("#{link}#{i}", _item.link)
+ assert_equal("#{description}#{i}", _item.description)
+ end
+ end
+
+ def test_items_with_new_api_since_018
+ test_items(false)
+ end
+
+ def test_not_valid_items
+ title = "TITLE"
+ link = "http://hoge.com/"
+
+ assert_not_set_error("maker.item", %w(title)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ # item.title = title
+ item.link = link
+ end
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(link)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ item.title = title
+ # item.link = link
+ end
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(title link)) do
+ RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ # item.title = title
+ # item.link = link
+ end
+ end
+ end
+ end
+
+ def test_textinput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+
+ setup_dummy_item(maker)
+ end
+ textinput = rss.textinput
+ assert_equal(link, textinput.about)
+ assert_equal(link, rss.channel.textinput.resource)
+ assert_equal(title, textinput.title)
+ assert_equal(name, textinput.name)
+ assert_equal(description, textinput.description)
+ assert_equal(link, textinput.link)
+
+ assert_not_set_error("maker.channel", %w(about link description title)) do
+ RSS::Maker.make("1.0") do |maker|
+ # setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ end
+ end
+ end
+
+ def test_not_valid_textinput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ # maker.textinput.link = link
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.textinput)
+ assert_nil(rss.textinput)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ # maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.textinput)
+ assert_nil(rss.textinput)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ maker.textinput.title = title
+ # maker.textinput.description = description
+ maker.textinput.name = name
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.textinput)
+ assert_nil(rss.textinput)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ maker.textinput.title = title
+ maker.textinput.description = description
+ # maker.textinput.name = name
+
+ setup_dummy_item(maker)
+ end
+ assert_nil(rss.channel.textinput)
+ assert_nil(rss.textinput)
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_maker_2.0.rb b/trunk/test/rss/test_maker_2.0.rb
new file mode 100644
index 0000000000..f6d4a11dc3
--- /dev/null
+++ b/trunk/test/rss/test_maker_2.0.rb
@@ -0,0 +1,706 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMaker20 < TestCase
+
+ def test_rss
+ assert_raise(LocalJumpError) do
+ RSS::Maker.make("2.0")
+ end
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ end
+ assert_equal("2.0", rss.rss_version)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.encoding = "EUC-JP"
+ end
+ assert_equal("2.0", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.standalone = "yes"
+ end
+ assert_equal("2.0", rss.rss_version)
+ assert_equal("yes", rss.standalone)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.encoding = "EUC-JP"
+ maker.standalone = "yes"
+ end
+ assert_equal("2.0", rss.rss_version)
+ assert_equal("EUC-JP", rss.encoding)
+ assert_equal("yes", rss.standalone)
+ end
+
+ def test_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+ copyright = "foo"
+ managingEditor = "bar"
+ webMaster = "web master"
+ rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
+ docs = "http://foo.com/doc"
+ skipDays = [
+ "Sunday",
+ "Monday",
+ ]
+ skipHours = [
+ "0",
+ "13",
+ ]
+ pubDate = Time.now
+ lastBuildDate = Time.now
+ categories = [
+ "Nespapers",
+ "misc",
+ ]
+ generator = "RSS Maker"
+ ttl = "60"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ maker.channel.copyright = copyright
+ maker.channel.managingEditor = managingEditor
+ maker.channel.webMaster = webMaster
+ maker.channel.rating = rating
+ maker.channel.docs = docs
+ maker.channel.pubDate = pubDate
+ maker.channel.lastBuildDate = lastBuildDate
+
+ skipDays.each do |day|
+ maker.channel.skipDays.new_day do |new_day|
+ new_day.content = day
+ end
+ end
+ skipHours.each do |hour|
+ maker.channel.skipHours.new_hour do |new_hour|
+ new_hour.content = hour
+ end
+ end
+
+ categories.each do |category|
+ maker.channel.categories.new_category do |new_category|
+ new_category.content = category
+ end
+ end
+
+ maker.channel.generator = generator
+ maker.channel.ttl = ttl
+ end
+ channel = rss.channel
+
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(language, channel.language)
+ assert_equal(copyright, channel.copyright)
+ assert_equal(managingEditor, channel.managingEditor)
+ assert_equal(webMaster, channel.webMaster)
+ assert_equal(rating, channel.rating)
+ assert_equal(docs, channel.docs)
+ assert_equal(pubDate, channel.pubDate)
+ assert_equal(pubDate, channel.date)
+ assert_equal(lastBuildDate, channel.lastBuildDate)
+
+ skipDays.each_with_index do |day, i|
+ assert_equal(day, channel.skipDays.days[i].content)
+ end
+ skipHours.each_with_index do |hour, i|
+ assert_equal(hour.to_i, channel.skipHours.hours[i].content)
+ end
+
+ channel.categories.each_with_index do |category, i|
+ assert_equal(categories[i], category.content)
+ end
+
+ assert_equal(generator, channel.generator)
+ assert_equal(ttl.to_i, channel.ttl)
+
+ assert(channel.items.empty?)
+ assert_nil(channel.image)
+ assert_nil(channel.textInput)
+ end
+
+ def test_not_valid_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+
+ assert_not_set_error("maker.channel", %w(title)) do
+ RSS::Maker.make("2.0") do |maker|
+ # maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("2.0") do |maker|
+ maker.channel.title = title
+ # maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(description)) do
+ RSS::Maker.make("2.0") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ # maker.channel.description = description
+ maker.channel.language = language
+ end
+ end
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ # maker.channel.language = language
+ end
+ assert_not_nil(rss)
+ end
+
+
+ def test_cloud
+ domain = "rpc.sys.com"
+ port = "80"
+ path = "/RPC2"
+ registerProcedure = "myCloud.rssPleaseNotify"
+ protocol = "xml-rpc"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.channel.cloud.domain = domain
+ maker.channel.cloud.port = port
+ maker.channel.cloud.path = path
+ maker.channel.cloud.registerProcedure = registerProcedure
+ maker.channel.cloud.protocol = protocol
+ end
+ cloud = rss.channel.cloud
+ assert_equal(domain, cloud.domain)
+ assert_equal(port.to_i, cloud.port)
+ assert_equal(path, cloud.path)
+ assert_equal(registerProcedure, cloud.registerProcedure)
+ assert_equal(protocol, cloud.protocol)
+ end
+
+ def test_not_valid_cloud
+ domain = "rpc.sys.com"
+ port = "80"
+ path = "/RPC2"
+ registerProcedure = "myCloud.rssPleaseNotify"
+ protocol = "xml-rpc"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ # maker.channel.cloud.domain = domain
+ maker.channel.cloud.port = port
+ maker.channel.cloud.path = path
+ maker.channel.cloud.registerProcedure = registerProcedure
+ maker.channel.cloud.protocol = protocol
+ end
+ assert_nil(rss.channel.cloud)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.channel.cloud.domain = domain
+ # maker.channel.cloud.port = port
+ maker.channel.cloud.path = path
+ maker.channel.cloud.registerProcedure = registerProcedure
+ maker.channel.cloud.protocol = protocol
+ end
+ assert_nil(rss.channel.cloud)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.channel.cloud.domain = domain
+ maker.channel.cloud.port = port
+ # maker.channel.cloud.path = path
+ maker.channel.cloud.registerProcedure = registerProcedure
+ maker.channel.cloud.protocol = protocol
+ end
+ assert_nil(rss.channel.cloud)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.channel.cloud.domain = domain
+ maker.channel.cloud.port = port
+ maker.channel.cloud.path = path
+ # maker.channel.cloud.registerProcedure = registerProcedure
+ maker.channel.cloud.protocol = protocol
+ end
+ assert_nil(rss.channel.cloud)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.channel.cloud.domain = domain
+ maker.channel.cloud.port = port
+ maker.channel.cloud.path = path
+ maker.channel.cloud.registerProcedure = registerProcedure
+ # maker.channel.cloud.protocol = protocol
+ end
+ assert_nil(rss.channel.cloud)
+ end
+
+
+ def test_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ image = rss.image
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+ assert_equal(width.to_i, image.width)
+ assert_equal(height.to_i, image.height)
+ assert_equal(description, image.description)
+
+ assert_not_set_error("maker.channel", %w(title description)) do
+ RSS::Maker.make("2.0") do |maker|
+ # setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+ end
+
+ def test_not_valid_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ # maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ assert_nil(rss.image)
+
+ assert_not_set_error("maker.channel", %w(link)) do
+ RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ # maker.channel.link = link
+ maker.channel.link = nil
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ end
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ # maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+ assert_nil(rss.image)
+ end
+
+ def test_items(with_convenience_way=true)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ author = "oprah@oxygen.net"
+ comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
+ pubDate = Time.now
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ end
+ assert(rss.channel.items.empty?)
+
+ item_size = 5
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.author = "#{author}#{i}"
+ item.comments = "#{comments}#{i}"
+ item.date = pubDate
+ end
+ end
+ maker.items.do_sort = true
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.channel.items.each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ assert_equal("#{author}#{i}", item.author)
+ assert_equal("#{comments}#{i}", item.comments)
+ assert_equal(pubDate, item.pubDate)
+ assert_equal(pubDate, item.date)
+ end
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.author = "#{author}#{i}"
+ item.comments = "#{comments}#{i}"
+ item.date = pubDate
+ end
+ end
+ maker.items.do_sort = Proc.new do |x, y|
+ if with_convenience_way
+ y.title[-1] <=> x.title[-1]
+ else
+ y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
+ end
+ end
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.channel.items.reverse.each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ assert_equal("#{author}#{i}", item.author)
+ assert_equal("#{comments}#{i}", item.comments)
+ assert_equal(pubDate, item.pubDate)
+ assert_equal(pubDate, item.date)
+ end
+ end
+
+ def test_items_with_new_api_since_018
+ test_items(false)
+ end
+
+ def test_pubDate_without_description
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ author = "oprah@oxygen.net"
+ pubDate = Time.now
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.items.new_item do |item|
+ item.title = title
+ item.link = link
+ # item.description = description
+ item.author = author
+ item.pubDate = pubDate
+ end
+ end
+ assert_equal(1, rss.items.size)
+ rss.channel.items.each_with_index do |item, i|
+ assert_equal(title, item.title)
+ assert_equal(link, item.link)
+ # assert_equal(description, item.description)
+ assert_equal(author, item.author)
+ assert_equal(pubDate, item.pubDate)
+ assert_equal(pubDate, item.date)
+ end
+ end
+
+ def test_guid
+ isPermaLink = "true"
+ content = "http://inessential.com/2002/09/01.php#a2"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ guid = maker.items.last.guid
+ guid.isPermaLink = isPermaLink
+ guid.content = content
+ end
+ guid = rss.channel.items.last.guid
+ assert_equal(isPermaLink == "true", guid.isPermaLink)
+ assert_equal(content, guid.content)
+ end
+
+ def test_not_valid_guid
+ content = "http://inessential.com/2002/09/01.php#a2"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ guid = maker.items.last.guid
+ # guid.content = content
+ end
+ assert_nil(rss.channel.items.last.guid)
+ end
+
+ def test_enclosure
+ url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
+ length = "12216320"
+ type = "audio/mpeg"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ enclosure = maker.items.last.enclosure
+ enclosure.url = url
+ enclosure.length = length
+ enclosure.type = type
+ end
+ enclosure = rss.channel.items.last.enclosure
+ assert_equal(url, enclosure.url)
+ assert_equal(length.to_i, enclosure.length)
+ assert_equal(type, enclosure.type)
+ end
+
+ def test_not_valid_enclosure
+ url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
+ length = "12216320"
+ type = "audio/mpeg"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ enclosure = maker.items.last.enclosure
+ # enclosure.url = url
+ enclosure.length = length
+ enclosure.type = type
+ end
+ assert_nil(rss.channel.items.last.enclosure)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ enclosure = maker.items.last.enclosure
+ enclosure.url = url
+ # enclosure.length = length
+ enclosure.type = type
+ end
+ assert_nil(rss.channel.items.last.enclosure)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ enclosure = maker.items.last.enclosure
+ enclosure.url = url
+ enclosure.length = length
+ # enclosure.type = type
+ end
+ assert_nil(rss.channel.items.last.enclosure)
+ end
+
+
+ def test_source
+ url = "http://static.userland.com/tomalak/links2.xml"
+ content = "Tomalak's Realm"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ source = maker.items.last.source
+ source.url = url
+ source.content = content
+ end
+ source = rss.channel.items.last.source
+ assert_equal(url, source.url)
+ assert_equal(content, source.content)
+ end
+
+ def test_not_valid_source
+ url = "http://static.userland.com/tomalak/links2.xml"
+ content = "Tomalak's Realm"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ source = maker.items.last.source
+ # source.url = url
+ source.content = content
+ end
+ assert_nil(rss.channel.items.last.source)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ source = maker.items.last.source
+ source.url = url
+ # source.content = content
+ end
+ assert_nil(rss.channel.items.last.source)
+ end
+
+ def test_category
+ domain = "http://www.fool.com/cusips"
+ content = "MSFT"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ maker.items.last.categories.new_category do |category|
+ category.domain = domain
+ category.content = content
+ end
+ end
+ category = rss.channel.items.last.categories.last
+ assert_equal(domain, category.domain)
+ assert_equal(content, category.content)
+ end
+
+ def test_not_valid_category
+ content = "Grateful Dead"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ maker.items.last.categories.new_category do |category|
+ # category.content = content
+ end
+ end
+ assert(rss.channel.items.last.categories.empty?)
+ end
+
+ def test_textInput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ textInput = rss.channel.textInput
+ assert_equal(title, textInput.title)
+ assert_equal(description, textInput.description)
+ assert_equal(name, textInput.name)
+ assert_equal(link, textInput.link)
+
+ assert_not_set_error("maker.channel", %w(link description title)) do
+ RSS::Maker.make("2.0") do |maker|
+ # setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ end
+ end
+
+ def test_not_valid_textInput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ # maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ # maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ # maker.textinput.name = name
+ maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ # maker.textinput.link = link
+ end
+ assert_nil(rss.channel.textInput)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_atom_entry.rb b/trunk/test/rss/test_maker_atom_entry.rb
new file mode 100644
index 0000000000..ae0ab2d09f
--- /dev/null
+++ b/trunk/test/rss/test_maker_atom_entry.rb
@@ -0,0 +1,367 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerAtomEntry < TestCase
+ def test_root_element
+ entry = Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ assert_equal(["atom", "1.0", "entry"], entry.feed_info)
+
+ entry = Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.encoding = "EUC-JP"
+ end
+ assert_equal(["atom", "1.0", "entry"], entry.feed_info)
+ assert_equal("EUC-JP", entry.encoding)
+
+ entry = Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.standalone = "yes"
+ end
+ assert_equal(["atom", "1.0", "entry"], entry.feed_info)
+ assert_equal("yes", entry.standalone)
+
+ entry = Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.encoding = "EUC-JP"
+ maker.standalone = "yes"
+ end
+ assert_equal(["atom", "1.0", "entry"], entry.feed_info)
+ assert_equal("EUC-JP", entry.encoding)
+ assert_equal("yes", entry.standalone)
+ end
+
+ def test_invalid_feed
+ assert_not_set_error("maker.item", %w(id title author updated)) do
+ Maker.make("atom:entry") do |maker|
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(id title updated)) do
+ Maker.make("atom:entry") do |maker|
+ maker.channel.author = "foo"
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(title updated)) do
+ Maker.make("atom:entry") do |maker|
+ maker.channel.author = "foo"
+ maker.channel.id = "http://example.com"
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(updated)) do
+ Maker.make("atom:entry") do |maker|
+ maker.channel.author = "foo"
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ end
+ end
+
+ assert_not_set_error("maker.item", %w(author)) do
+ Maker.make("atom:entry") do |maker|
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ maker.channel.updated = Time.now
+ end
+ end
+
+ entry = Maker.make("atom:entry") do |maker|
+ maker.channel.author = "Foo"
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ maker.channel.updated = Time.now
+ end
+ assert_not_nil(entry)
+ end
+
+ def test_author
+ assert_maker_atom_persons("entry",
+ ["channel", "authors"],
+ ["authors"],
+ "maker.channel.author") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_persons("entry",
+ ["items", "first", "authors"],
+ ["authors"],
+ "maker.item.author",
+ "maker.item", ["author"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.authors.clear
+ maker.items.first.authors.clear
+ end
+
+ assert_maker_atom_persons("entry",
+ ["items", "first", "source", "authors"],
+ ["source", "authors"],
+ "maker.item.source.author") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_category
+ assert_maker_atom_categories("entry",
+ ["channel", "categories"],
+ ["categories"],
+ "maker.channel.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_categories("entry",
+ ["items", "first", "categories"],
+ ["categories"],
+ "maker.item.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_categories("entry",
+ ["items", "first", "source", "categories"],
+ ["source", "categories"],
+ "maker.item.source.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_content
+ assert_maker_atom_content("entry",
+ ["items", "first", "content"],
+ ["content"],
+ "maker.item.content") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_contributor
+ assert_maker_atom_persons("entry",
+ ["channel", "contributors"],
+ ["contributors"],
+ "maker.channel.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_persons("entry",
+ ["items", "first", "contributors"],
+ ["contributors"],
+ "maker.item.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_persons("entry",
+ ["items", "first", "source", "contributors"],
+ ["source", "contributors"],
+ "maker.item.source.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_link
+ assert_maker_atom_links("entry",
+ ["channel", "links"],
+ ["links"],
+ "maker.channel.link") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.links.clear
+ maker.items.first.links.clear
+ end
+
+ assert_maker_atom_links("entry",
+ ["items", "first", "links"],
+ ["links"],
+ "maker.item.link") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.links.clear
+ maker.items.first.links.clear
+ end
+
+ assert_maker_atom_links("entry",
+ ["items", "first", "source", "links"],
+ ["source", "links"],
+ "maker.item.source.link", true) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_published
+ assert_maker_atom_date_construct("entry",
+ ["items", "first", "published"],
+ ["published"]
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_rights
+ assert_maker_atom_text_construct("entry",
+ ["channel", "copyright"],
+ ["rights"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "rights"],
+ ["rights"],
+ nil, nil, "maker.item.rights"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "source", "rights"],
+ ["source", "rights"],
+ nil, nil, "maker.item.source.rights"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+
+ def test_source_generator
+ assert_maker_atom_generator("entry",
+ ["items", "first", "source", "generator"],
+ ["source", "generator"],
+ "maker.item.source.generator") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_source_icon
+ assert_maker_atom_icon("entry",
+ ["items", "first", "source", "icon"],
+ ["source", "icon"],
+ nil, "maker.item.source.icon") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_source_id
+ assert_maker_atom_id("entry",
+ ["items", "first", "source"],
+ ["source"],
+ "maker.item.source") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_source_logo
+ assert_maker_atom_logo("entry",
+ ["items", "first", "source", "logo"],
+ ["source", "logo"],
+ nil,
+ "maker.item.source.logo") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_source_subtitle
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "source", "subtitle"],
+ ["source", "subtitle"],
+ nil, nil,
+ "maker.item.source.subtitle") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_summary
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "description"],
+ ["summary"],
+ nil, nil, "maker.item.description"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_title
+ assert_maker_atom_text_construct("entry",
+ ["channel", "title"], ["title"],
+ "maker.item", ["title"],
+ "maker.channel.title") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.title = nil
+ maker.items.first.title = nil
+ end
+
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "title"],
+ ["title"],
+ "maker.item", ["title"],
+ "maker.item.title") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.title = nil
+ maker.items.first.title = nil
+ end
+
+ assert_maker_atom_text_construct("entry",
+ ["items", "first", "source", "title"],
+ ["source", "title"],
+ nil, nil, "maker.item.source.title"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_updated
+ assert_maker_atom_date_construct("entry",
+ ["channel", "updated"], ["updated"],
+ "maker.item", ["updated"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.updated = nil
+ maker.items.first.updated = nil
+ end
+
+ assert_maker_atom_date_construct("entry",
+ ["items", "first", "updated"],
+ ["updated"],
+ "maker.item", ["updated"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.updated = nil
+ maker.items.first.updated = nil
+ end
+
+ assert_maker_atom_date_construct("entry",
+ ["items", "first", "source", "updated"],
+ ["source", "updated"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_atom_feed.rb b/trunk/test/rss/test_maker_atom_feed.rb
new file mode 100644
index 0000000000..e5bf0e23b2
--- /dev/null
+++ b/trunk/test/rss/test_maker_atom_feed.rb
@@ -0,0 +1,389 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerAtomFeed < TestCase
+ def test_root_element
+ feed = Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+ assert_equal(["atom", "1.0", "feed"], feed.feed_info)
+
+ feed = Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.encoding = "EUC-JP"
+ end
+ assert_equal(["atom", "1.0", "feed"], feed.feed_info)
+ assert_equal("EUC-JP", feed.encoding)
+
+ feed = Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.standalone = "yes"
+ end
+ assert_equal(["atom", "1.0", "feed"], feed.feed_info)
+ assert_equal("yes", feed.standalone)
+
+ feed = Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.encoding = "EUC-JP"
+ maker.standalone = "yes"
+ end
+ assert_equal(["atom", "1.0", "feed"], feed.feed_info)
+ assert_equal("EUC-JP", feed.encoding)
+ assert_equal("yes", feed.standalone)
+ end
+
+ def test_invalid_feed
+ assert_not_set_error("maker.channel", %w(id title author updated)) do
+ Maker.make("atom") do |maker|
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(id title updated)) do
+ Maker.make("atom") do |maker|
+ maker.channel.author = "foo"
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(title updated)) do
+ Maker.make("atom") do |maker|
+ maker.channel.author = "foo"
+ maker.channel.id = "http://example.com"
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(updated)) do
+ Maker.make("atom") do |maker|
+ maker.channel.author = "foo"
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ end
+ end
+
+ assert_not_set_error("maker.channel", %w(author)) do
+ Maker.make("atom") do |maker|
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ maker.channel.updated = Time.now
+ end
+ end
+
+ feed = Maker.make("atom") do |maker|
+ maker.channel.author = "Foo"
+ maker.channel.id = "http://example.com"
+ maker.channel.title = "Atom Feed"
+ maker.channel.updated = Time.now
+ end
+ assert_not_nil(feed)
+ end
+
+ def test_author
+ assert_maker_atom_persons("feed",
+ ["channel", "authors"],
+ ["authors"],
+ "maker.channel.author") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_not_set_error("maker.channel", %w(author)) do
+ RSS::Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.channel.authors.clear
+ end
+ end
+
+ assert_maker_atom_persons("feed",
+ ["items", "first", "authors"],
+ ["entries", "first", "authors"],
+ "maker.item.author") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_persons("feed",
+ ["items", "first", "source", "authors"],
+ ["entries", "first", "source", "authors"],
+ "maker.item.source.author") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_category
+ assert_maker_atom_categories("feed",
+ ["channel", "categories"],
+ ["categories"],
+ "maker.channel.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_categories("feed",
+ ["items", "first", "categories"],
+ ["entries", "first", "categories"],
+ "maker.item.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_categories("feed",
+ ["items", "first", "source", "categories"],
+ ["entries", "first", "source", "categories"],
+ "maker.item.source.category") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_contributor
+ assert_maker_atom_persons("feed",
+ ["channel", "contributors"],
+ ["contributors"],
+ "maker.channel.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_persons("feed",
+ ["items", "first", "contributors"],
+ ["entries", "first", "contributors"],
+ "maker.item.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_persons("feed",
+ ["items", "first", "source", "contributors"],
+ ["entries", "first", "source", "contributors"],
+ "maker.item.source.contributor") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_generator
+ assert_maker_atom_generator("feed",
+ ["channel", "generator"],
+ ["generator"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_generator("feed",
+ ["items", "first", "source", "generator"],
+ ["entries", "first", "source", "generator"],
+ "maker.item.source.generator") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_icon
+ assert_maker_atom_icon("feed", ["channel"], ["icon"], "icon") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_icon("feed",
+ ["items", "first", "source", "icon"],
+ ["entries", "first", "source", "icon"],
+ nil, "maker.item.source.icon") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_link
+ assert_maker_atom_links("feed",
+ ["channel", "links"],
+ ["links"],
+ "maker.channel.link") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_links("feed",
+ ["items", "first", "links"],
+ ["entries", "first", "links"],
+ "maker.item.link") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_links("feed",
+ ["items", "first", "source", "links"],
+ ["entries", "first", "source", "links"],
+ "maker.item.source.link", true) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_logo
+ assert_maker_atom_logo("feed", ["channel"], ["logo"], "logo") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_logo("feed", ["image"], ["logo"], "url") do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_logo("feed",
+ ["items", "first", "source", "logo"],
+ ["entries", "first", "source", "logo"],
+ nil, "maker.item.source.logo") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_rights
+ assert_maker_atom_text_construct("feed",
+ ["channel", "copyright"],
+ ["rights"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "rights"],
+ ["entries", "first", "rights"],
+ nil, nil, "maker.item.rights"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "source", "rights"],
+ ["entries", "first", "source", "rights"],
+ nil, nil, "maker.item.source.rights"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_subtitle
+ assert_maker_atom_text_construct("feed",
+ ["channel", "subtitle"],
+ ["subtitle"],
+ nil, nil,
+ "maker.channel.description") do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.channel.description = nil
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["channel", "subtitle"],
+ ["subtitle"],
+ nil, nil,
+ "maker.channel.description") do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.channel.description {|d| d.content = nil}
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "source", "subtitle"],
+ ["entries", "first",
+ "source", "subtitle"],
+ nil, nil,
+ "maker.item.source.subtitle") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_title
+ assert_maker_atom_text_construct("feed",
+ ["channel", "title"], ["title"],
+ "maker.channel", ["title"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.channel.title = nil
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "title"],
+ ["entries", "first", "title"],
+ "maker.item", ["title"],
+ "maker.item.title") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.items.first.title = nil
+ end
+
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "source", "title"],
+ ["entries", "first", "source", "title"],
+ nil, nil, "maker.item.source.title"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_updated
+ assert_maker_atom_date_construct("feed",
+ ["channel", "updated"], ["updated"],
+ "maker.channel", ["updated"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ maker.channel.updated = nil
+ end
+
+ assert_maker_atom_date_construct("feed",
+ ["items", "first", "updated"],
+ ["entries", "first", "updated"],
+ "maker.item", ["updated"]) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ maker.items.first.updated = nil
+ end
+
+ assert_maker_atom_date_construct("feed",
+ ["items", "first", "source", "updated"],
+ ["entries", "first", "source", "updated"]
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_published
+ assert_maker_atom_date_construct("feed",
+ ["items", "first", "published"],
+ ["entries", "first", "published"]
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_summary
+ assert_maker_atom_text_construct("feed",
+ ["items", "first", "description"],
+ ["entries", "first", "summary"],
+ nil, nil, "maker.item.description"
+ ) do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_content
+ assert_maker_atom_content("feed",
+ ["items", "first", "content"],
+ ["entries", "first", "content"],
+ "maker.item.content") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+
+ def test_id
+ assert_maker_atom_id("feed",
+ ["items", "first", "source"],
+ ["entries", "first", "source"],
+ "maker.item.source") do |maker|
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_content.rb b/trunk/test/rss/test_maker_content.rb
new file mode 100644
index 0000000000..53750bb095
--- /dev/null
+++ b/trunk/test/rss/test_maker_content.rb
@@ -0,0 +1,47 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerContent < TestCase
+
+ def setup
+ @uri = "http://purl.org/rss/1.0/modules/content/"
+
+ @elements = {
+ :encoded => "<em>ATTENTION</em>",
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ @elements.each do |name, value|
+ item.__send__("#{accessor_name(name)}=", value)
+ end
+ end
+ assert_content(@elements, rss.items.last)
+ end
+
+ def test_rss20
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ @elements.each do |name, value|
+ item.__send__("#{accessor_name(name)}=", value)
+ end
+ end
+ assert_content(@elements, rss.items.last)
+ end
+
+ private
+ def accessor_name(name)
+ "content_#{name}"
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_dc.rb b/trunk/test/rss/test_maker_dc.rb
new file mode 100644
index 0000000000..72a967231a
--- /dev/null
+++ b/trunk/test/rss/test_maker_dc.rb
@@ -0,0 +1,149 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerDublinCore < TestCase
+
+ def setup
+ @uri = "http://purl.org/dc/elements/1.1/"
+
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @elements = {
+ :title => "hoge",
+ :description =>
+ " XML is placing increasingly heavy loads on
+ the existing technical infrastructure of the Internet.",
+ :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
+ :subject => "XML",
+ :publisher => "The O'Reilly Network",
+ :contributor => "hogehoge",
+ :type => "fugafuga",
+ :format => "hohoho",
+ :identifier => "fufufu",
+ :source => "barbar",
+ :language => "ja",
+ :relation => "cococo",
+ :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
+ :date => t,
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ set_elements(maker.channel)
+
+ setup_dummy_image(maker)
+ set_elements(maker.image)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ @elements.each do |name, value|
+ item.__send__("#{accessor_name(name)}=", value)
+ end
+
+ setup_dummy_textinput(maker)
+ set_elements(maker.textinput)
+ end
+ assert_dublin_core(@elements, rss.channel)
+ assert_dublin_core(@elements, rss.image)
+ assert_dublin_core(@elements, rss.items.last)
+ assert_dublin_core(@elements, rss.textinput)
+ end
+
+ def test_rss10_multiple
+ assert_multiple_dublin_core_rss10("_list")
+ assert_multiple_dublin_core_rss10("es")
+ end
+
+ def assert_multiple_dublin_core_rss10(multiple_rights_suffix)
+ elems = []
+ @elements.each do |name, value|
+ plural = name.to_s + (name == :rights ? multiple_rights_suffix : "s")
+ values = [value]
+ if name == :date
+ values << value + 60
+ else
+ values << value * 2
+ end
+ elems << [name, values, plural]
+ end
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ set_multiple_elements(maker.channel, elems)
+
+ setup_dummy_image(maker)
+ set_multiple_elements(maker.image, elems)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ elems.each do |name, values, plural|
+ dc_elems = item.__send__("dc_#{plural}")
+ values.each do |value|
+ elem = dc_elems.__send__("new_#{name}")
+ elem.value = value
+ end
+ end
+
+ setup_dummy_textinput(maker)
+ set_multiple_elements(maker.textinput, elems)
+ end
+ assert_multiple_dublin_core(elems, rss.channel)
+ assert_multiple_dublin_core(elems, rss.image)
+ assert_multiple_dublin_core(elems, rss.items.last)
+ assert_multiple_dublin_core(elems, rss.textinput)
+ end
+
+ def test_date
+ t1 = Time.iso8601("2000-01-01T12:00:05+00:00")
+ t2 = Time.iso8601("2005-01-01T12:00:05+00:00")
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.date = t1
+ maker.channel.dc_dates.new_date do |date|
+ date.value = t2
+ end
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ item.date = t2
+ item.dc_dates.new_date do |date|
+ date.value = t1
+ end
+ end
+ assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value})
+ assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value})
+ end
+
+ private
+ def accessor_name(name)
+ "dc_#{name}"
+ end
+
+ def set_elements(target, elems=@elements)
+ elems.each do |name, value|
+ target.__send__("#{accessor_name(name)}=", value)
+ end
+ end
+
+ def set_multiple_elements(target, elems)
+ elems.each do |name, values, plural|
+ plural ||= "#{name}s"
+ dc_elems = target.__send__("dc_#{plural}")
+ values.each do |value|
+ dc_elems.__send__("new_#{name}") do |new_dc_elem|
+ new_dc_elem.value = value
+ end
+ end
+ end
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_maker_image.rb b/trunk/test/rss/test_maker_image.rb
new file mode 100644
index 0000000000..1fc8076c46
--- /dev/null
+++ b/trunk/test/rss/test_maker_image.rb
@@ -0,0 +1,62 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerImage < TestCase
+
+ def setup
+ @uri = "http://web.resource.org/rss/1.0/modules/image/"
+
+ @favicon_infos = {
+ "about" => "http://www.kuro5hin.org/favicon.ico",
+ "image_size" => "small",
+ "dc_title" => "example",
+ }
+ @item_infos = {
+ "about" => "http://www.example.org/item.png",
+ "resource" => "http://www.example.org/item",
+ "dc_title" => "Example Image",
+ "image_width" => "100",
+ "image_height" => "65",
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ @favicon_infos.each do |name, value|
+ maker.channel.image_favicon.__send__("#{name}=", value)
+ end
+
+ setup_dummy_image(maker)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ @item_infos.each do |name, value|
+ item.image_item.__send__("#{name}=", value)
+ end
+
+ setup_dummy_textinput(maker)
+ end
+
+ setup_rss = RSS::Maker.make("1.0") do |maker|
+ rss.setup_maker(maker)
+ end
+
+ [rss, setup_rss].each_with_index do |target, i|
+ favicon = target.channel.image_favicon
+ assert_equal(@favicon_infos["about"], favicon.about)
+ assert_equal(@favicon_infos["image_size"], favicon.image_size)
+ assert_equal(@favicon_infos["dc_title"], favicon.dc_title)
+
+ item = target.items.last.image_item
+ assert_equal(@item_infos["about"], item.about)
+ assert_equal(@item_infos["resource"], item.resource)
+ assert_equal(@item_infos["image_width"].to_i, item.image_width)
+ assert_equal(@item_infos["image_height"].to_i, item.image_height)
+ assert_equal(@item_infos["dc_title"], item.dc_title)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_itunes.rb b/trunk/test/rss/test_maker_itunes.rb
new file mode 100644
index 0000000000..21a4dd1f29
--- /dev/null
+++ b/trunk/test/rss/test_maker_itunes.rb
@@ -0,0 +1,471 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerITunes < TestCase
+ def test_author
+ assert_maker_itunes_author(%w(channel))
+ assert_maker_itunes_author(%w(items last))
+ end
+
+ def test_block
+ assert_maker_itunes_block(%w(channel))
+ assert_maker_itunes_block(%w(items last))
+ end
+
+ def test_category
+ assert_maker_itunes_category(%w(channel))
+ end
+
+ def test_image
+ assert_maker_itunes_image(%w(channel))
+ end
+
+ def test_duration
+ assert_maker_itunes_duration(%w(items last))
+ end
+
+ def test_explicit
+ assert_maker_itunes_explicit(%w(channel))
+ assert_maker_itunes_explicit(%w(items last))
+ end
+
+ def test_keywords
+ assert_maker_itunes_keywords(%w(channel))
+ assert_maker_itunes_keywords(%w(items last))
+ end
+
+ def test_new_feed_url
+ assert_maker_itunes_new_feed_url(%w(channel))
+ end
+
+ def test_owner
+ assert_maker_itunes_owner(%w(channel))
+ end
+
+ def test_subtitle
+ assert_maker_itunes_subtitle(%w(channel))
+ assert_maker_itunes_subtitle(%w(items last))
+ end
+
+ def test_summary
+ assert_maker_itunes_summary(%w(channel))
+ assert_maker_itunes_summary(%w(items last))
+ end
+
+ private
+
+ def assert_maker_itunes_author(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ author = "John Doe"
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_author = author
+ end
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(author, target.itunes_author)
+ end
+ end
+
+ def _assert_maker_itunes_block(value, boolean_value, maker_readers,
+ feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_block = value
+ assert_equal(value, target.itunes_block)
+ assert_equal(boolean_value, target.itunes_block?)
+ end
+ target = chain_reader(rss20, feed_readers)
+ if [true, false].include?(value)
+ feed_expected_value = value = value ? "yes" : "no"
+ else
+ feed_expected_value = value
+ end
+ assert_equal(value, target.itunes_block)
+ assert_equal(boolean_value, target.itunes_block?)
+ end
+
+ def assert_maker_itunes_block(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_block("yes", true, maker_readers, feed_readers)
+ _assert_maker_itunes_block("Yes", true, maker_readers, feed_readers)
+ _assert_maker_itunes_block("no", false, maker_readers, feed_readers)
+ _assert_maker_itunes_block("", false, maker_readers, feed_readers)
+ _assert_maker_itunes_block(true, true, maker_readers, feed_readers)
+ _assert_maker_itunes_block(false, false, maker_readers, feed_readers)
+ _assert_maker_itunes_block(nil, false, maker_readers, feed_readers)
+ end
+ end
+
+ def _assert_maker_itunes_category(categories, maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ categories.each do |category|
+ sub_target = target.itunes_categories
+ if category.is_a?(Array)
+ category.each do |sub_category|
+ sub_target = sub_target.new_category
+ sub_target.text = sub_category
+ end
+ else
+ sub_target.new_category.text = category
+ end
+ end
+ end
+
+ target = chain_reader(rss20, feed_readers)
+ actual_categories = target.itunes_categories.collect do |category|
+ cat = category.text
+ if category.itunes_categories.empty?
+ cat
+ else
+ [cat, *category.itunes_categories.collect {|c| c.text}]
+ end
+ end
+ assert_equal(categories, actual_categories)
+ end
+
+ def assert_maker_itunes_category(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_category(["Audio Blogs"],
+ maker_readers, feed_readers)
+ _assert_maker_itunes_category([["Arts & Entertainment", "Games"]],
+ maker_readers, feed_readers)
+ _assert_maker_itunes_category([["Arts & Entertainment", "Games"],
+ ["Technology", "Computers"],
+ "Audio Blogs"],
+ maker_readers, feed_readers)
+ end
+ end
+
+ def assert_maker_itunes_image(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
+
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_image = url
+ end
+
+ target = chain_reader(rss20, feed_readers)
+ assert_not_nil(target.itunes_image)
+ assert_equal(url, target.itunes_image.href)
+ end
+ end
+
+ def _assert_maker_itunes_duration(hour, minute, second, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_duration_by_value(hour, minute, second, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
+ value,
+ maker_readers,
+ feed_readers)
+ end
+
+ def _assert_maker_itunes_duration_by(hour, minute, second, value,
+ maker_readers, feed_readers)
+ expected_value = nil
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ expected_value = yield(target)
+ assert_equal(expected_value, target.itunes_duration)
+ target.itunes_duration do |duration|
+ assert_equal([hour, minute, second, expected_value],
+ [duration.hour, duration.minute,
+ duration.second, duration.content])
+ end
+ end
+ target = chain_reader(rss20, feed_readers)
+ duration = target.itunes_duration
+ assert_not_nil(duration)
+ assert_equal([hour, minute, second, expected_value],
+ [duration.hour, duration.minute,
+ duration.second, duration.content])
+ end
+
+ def _assert_maker_itunes_duration_by_value(hour, minute, second, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_duration_by(hour, minute, second, value,
+ maker_readers, feed_readers) do |target|
+ target.itunes_duration = value
+ value
+ end
+ end
+
+ def _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
+ value,
+ maker_readers,
+ feed_readers)
+ _assert_maker_itunes_duration_by(hour, minute, second, value,
+ maker_readers, feed_readers) do |target|
+ target.itunes_duration do |duration|
+ duration.hour = hour
+ duration.minute = minute
+ duration.second = second
+ end
+ value.split(":").collect {|v| "%02d" % v.to_i}.join(":")
+ end
+ end
+
+ def _assert_maker_itunes_duration_invalid_value(value, maker_readers)
+ assert_raise(ArgumentError) do
+ ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_duration = value
+ end
+ end
+ end
+
+ def assert_maker_itunes_duration(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_duration(7, 14, 5, "07:14:05", maker_readers,
+ feed_readers)
+ _assert_maker_itunes_duration(7, 14, 5, "7:14:05", maker_readers,
+ feed_readers)
+ _assert_maker_itunes_duration(0, 4, 55, "04:55", maker_readers,
+ feed_readers)
+ _assert_maker_itunes_duration(0, 4, 5, "4:05", maker_readers,
+ feed_readers)
+
+ _assert_maker_itunes_duration_invalid_value("5", maker_readers)
+ _assert_maker_itunes_duration_invalid_value("09:07:14:05", maker_readers)
+ _assert_maker_itunes_duration_invalid_value("10:5", maker_readers)
+ _assert_maker_itunes_duration_invalid_value("10:03:5", maker_readers)
+ _assert_maker_itunes_duration_invalid_value("10:3:05", maker_readers)
+
+ _assert_maker_itunes_duration_invalid_value("xx:xx:xx", maker_readers)
+ end
+ end
+
+ def _assert_maker_itunes_explicit(explicit, value,
+ maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_explicit = value
+ assert_equal(explicit, target.itunes_explicit?)
+ end
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(value, target.itunes_explicit)
+ assert_equal(explicit, target.itunes_explicit?)
+ end
+
+ def assert_maker_itunes_explicit(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_explicit(true, "yes", maker_readers, feed_readers)
+ _assert_maker_itunes_explicit(false, "clean",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_explicit(nil, "no", maker_readers, feed_readers)
+ end
+ end
+
+ def _assert_maker_itunes_keywords(keywords, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords_by_value(keywords, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords_by_keywords(keywords, maker_readers,
+ feed_readers)
+ end
+
+ def _assert_maker_itunes_keywords_by(keywords, maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ yield(target)
+ end
+ assert_nothing_raised do
+ rss20 = ::RSS::Parser.parse(rss20.to_s)
+ end
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(keywords, target.itunes_keywords)
+ end
+
+ def _assert_maker_itunes_keywords_by_value(keywords, value,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords_by(keywords, maker_readers,
+ feed_readers) do |target|
+ target.itunes_keywords = value
+ end
+ end
+
+ def _assert_maker_itunes_keywords_by_keywords(keywords,
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords_by(keywords, maker_readers,
+ feed_readers) do |target|
+ target.itunes_keywords = keywords
+ end
+ end
+
+ def assert_maker_itunes_keywords(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_keywords(["salt"], "salt",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords(["salt"], " salt ",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
+ "salt, pepper, shaker, exciting",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords(["metric", "socket", "wrenches",
+ "toolsalt"],
+ "metric, socket, wrenches, toolsalt",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_keywords(["olitics", "red", "blue", "state"],
+ "olitics, red, blue, state",
+ maker_readers, feed_readers)
+ end
+ end
+
+ def assert_maker_itunes_new_feed_url(maker_readers, feed_readers=nil)
+ feed_readers ||= maker_readers
+ url = "http://newlocation.com/example.rss"
+
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_new_feed_url = url
+ end
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(url, target.itunes_new_feed_url)
+ end
+
+ def _assert_maker_itunes_owner(name, email, maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ owner = target.itunes_owner
+ owner.itunes_name = name
+ owner.itunes_email = email
+ end
+ owner = chain_reader(rss20, feed_readers).itunes_owner
+ if name.nil? and email.nil?
+ assert_nil(owner)
+ else
+ assert_not_nil(owner)
+ assert_equal(name, owner.itunes_name)
+ assert_equal(email, owner.itunes_email)
+ end
+ end
+
+ def assert_maker_itunes_owner(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_owner("John Doe", "john.doe@example.com",
+ maker_readers, feed_readers)
+
+ not_set_name = (["maker"] + maker_readers + ["itunes_owner"]).join(".")
+ assert_not_set_error(not_set_name, ["itunes_name"]) do
+ _assert_maker_itunes_owner(nil, "john.doe@example.com",
+ maker_readers, feed_readers)
+ end
+ assert_not_set_error(not_set_name, ["itunes_email"]) do
+ _assert_maker_itunes_owner("John Doe", nil,
+ maker_readers, feed_readers)
+ end
+
+ _assert_maker_itunes_owner(nil, nil, maker_readers, feed_readers)
+ end
+ end
+
+ def _assert_maker_itunes_subtitle(subtitle, maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_subtitle = subtitle
+ end
+
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(subtitle, target.itunes_subtitle)
+ end
+
+ def assert_maker_itunes_subtitle(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_subtitle("A show about everything",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_subtitle("A short primer on table spices",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_subtitle("Comparing socket wrenches is fun!",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_subtitle("Red + Blue != Purple",
+ maker_readers, feed_readers)
+ end
+ end
+
+ def _assert_maker_itunes_summary(summary, maker_readers, feed_readers)
+ rss20 = ::RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ target = chain_reader(maker, maker_readers)
+ target.itunes_summary = summary
+ end
+
+ target = chain_reader(rss20, feed_readers)
+ assert_equal(summary, target.itunes_summary)
+ end
+
+ def assert_maker_itunes_summary(maker_readers, feed_readers=nil)
+ _wrap_assertion do
+ feed_readers ||= maker_readers
+ _assert_maker_itunes_summary("All About Everything is a show about " +
+ "everything. Each week we dive into any " +
+ "subject known to man and talk about it " +
+ "as much as we can. Look for our Podcast " +
+ "in the iTunes Music Store",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_summary("This week we talk about salt and pepper " +
+ "shakers, comparing and contrasting pour " +
+ "rates, construction materials, and " +
+ "overall aesthetics. Come and join the " +
+ "party!",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_summary("This week we talk about metric vs. old " +
+ "english socket wrenches. Which one is " +
+ "better? Do you really need both? Get " +
+ "all of your answers here.",
+ maker_readers, feed_readers)
+ _assert_maker_itunes_summary("This week we talk about surviving in a " +
+ "Red state if you're a Blue person. Or " +
+ "vice versa.",
+ maker_readers, feed_readers)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_slash.rb b/trunk/test/rss/test_maker_slash.rb
new file mode 100644
index 0000000000..f2fbf9a231
--- /dev/null
+++ b/trunk/test/rss/test_maker_slash.rb
@@ -0,0 +1,37 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerSlash < TestCase
+ def setup
+ @elements = {
+ "section" => "articles",
+ "department" => "not-an-ocean-unless-there-are-lobsters",
+ "comments" => 177,
+ "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ @elements.each do |name, value|
+ item.send("slash_#{name}=", value)
+ end
+ end
+
+ item = rss.items.last
+ assert_not_nil(item)
+ assert_slash_elements(item)
+ end
+
+ private
+ def assert_slash_elements(target)
+ super(@elements, target)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_sy.rb b/trunk/test/rss/test_maker_sy.rb
new file mode 100644
index 0000000000..309a3b70fd
--- /dev/null
+++ b/trunk/test/rss/test_maker_sy.rb
@@ -0,0 +1,44 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerSyndication < TestCase
+
+ def setup
+ @uri = "http://purl.org/rss/1.0/modules/syndication/"
+
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @elements = {
+ :updatePeriod => "hourly",
+ :updateFrequency => "2",
+ :updateBase => t,
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ set_elements(maker.channel)
+ setup_dummy_item(maker)
+ end
+ assert_syndication(@elements, rss.channel)
+ end
+
+ private
+ def accessor_name(name)
+ "sy_#{name}"
+ end
+
+ def set_elements(target)
+ @elements.each do |name, value|
+ target.__send__("#{accessor_name(name)}=", value)
+ end
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_maker_taxo.rb b/trunk/test/rss/test_maker_taxo.rb
new file mode 100644
index 0000000000..8feb4e1d33
--- /dev/null
+++ b/trunk/test/rss/test_maker_taxo.rb
@@ -0,0 +1,81 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerTaxonomy < TestCase
+
+ def setup
+ @uri = "http://purl.org/rss/1.0/modules/taxonomy/"
+
+ @resources = [
+ "http://meerkat.oreillynet.com/?c=cat23",
+ "http://meerkat.oreillynet.com/?c=47",
+ "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
+ ]
+
+ @topics = [
+ {
+ :link => "http://meerkat.oreillynet.com/?c=cat23",
+ :title => "Data: XML",
+ :description => "A Meerkat channel",
+ },
+ {
+ :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
+ :title => "XML",
+ :subject => "XML",
+ :description => "DMOZ category",
+ :topics => [
+ "http://meerkat.oreillynet.com/?c=cat23",
+ "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
+ "http://dmoz.org/Computers/Programming/Internet/",
+ ]
+ },
+ ]
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ set_topics(maker.channel)
+
+ setup_dummy_item(maker)
+ set_topics(maker.items.last)
+
+ setup_taxo_topic(maker, @topics)
+ end
+ assert_equal(@resources, rss.channel.taxo_topics.resources)
+ assert_equal(@resources, rss.items.last.taxo_topics.resources)
+ assert_taxo_topic(@topics, rss)
+ end
+
+ def _test_date
+ t1 = Time.iso8601("2000-01-01T12:00:05+00:00")
+ t2 = Time.iso8601("2005-01-01T12:00:05+00:00")
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.date = t1
+ maker.channel.dc_dates.new_date do |date|
+ date.value = t2
+ end
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ item.date = t2
+ item.dc_dates.new_date do |date|
+ date.value = t1
+ end
+ end
+ assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value})
+ assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value})
+ end
+
+ private
+ def set_topics(target, resources=@resources)
+ resources.each do |value|
+ target.taxo_topics << value
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_trackback.rb b/trunk/test/rss/test_maker_trackback.rb
new file mode 100644
index 0000000000..58705c6f80
--- /dev/null
+++ b/trunk/test/rss/test_maker_trackback.rb
@@ -0,0 +1,41 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerTrackBack < TestCase
+
+ def setup
+ @uri = "http://madskills.com/public/xml/rss/module/trackback/"
+
+ @elements = {
+ :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
+ :abouts => [
+ "http://foo.com/trackback/tb.cgi?tb_id=20020923",
+ "http://bar.com/trackback/tb.cgi?tb_id=20041114",
+ ],
+ }
+ end
+
+ def test_rss10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ setup_dummy_item(maker)
+ item = maker.items.last
+ item.trackback_ping = @elements[:ping]
+ @elements[:abouts].each do |about|
+ item.trackback_abouts.new_about do |new_about|
+ new_about.value = about
+ end
+ end
+ end
+ assert_trackback(@elements, rss.items.last)
+ end
+
+ private
+ def accessor_name(name)
+ "trackback_#{name}"
+ end
+ end
+end
diff --git a/trunk/test/rss/test_maker_xml-stylesheet.rb b/trunk/test/rss/test_maker_xml-stylesheet.rb
new file mode 100644
index 0000000000..81d97ddc0e
--- /dev/null
+++ b/trunk/test/rss/test_maker_xml-stylesheet.rb
@@ -0,0 +1,83 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestMakerXMLStyleSheet < TestCase
+
+ def test_xml_stylesheet
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+
+ xss = rss.xml_stylesheets.first
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+
+
+ href = 'http://example.com/index.xsl'
+ type = 'text/xsl'
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.xml_stylesheets.new_xml_stylesheet do |_xss|
+ _xss.href = href
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+
+ xss = rss.xml_stylesheets.first
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ end
+
+ def test_not_valid_xml_stylesheet
+ href = 'xss.XXX'
+ type = "text/xsl"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ # xss.href = href
+ xss.type = type
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+ assert(rss.xml_stylesheets.empty?)
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ # xss.type = type
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+ assert(rss.xml_stylesheets.empty?)
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_parser.rb b/trunk/test/rss/test_parser.rb
new file mode 100644
index 0000000000..2e8c9be4d3
--- /dev/null
+++ b/trunk/test/rss/test_parser.rb
@@ -0,0 +1,62 @@
+require "fileutils"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/dublincore"
+
+module RSS
+ class TestParser < TestCase
+ def setup
+ @_default_parser = Parser.default_parser
+ @rss10 = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+#{make_textinput}
+#{make_image}
+EOR
+ @rss_file = "rss10.rdf"
+ File.open(@rss_file, "w") {|f| f.print(@rss10)}
+ end
+
+ def teardown
+ Parser.default_parser = @_default_parser
+ FileUtils.rm_f(@rss_file)
+ end
+
+ def test_default_parser
+ assert_nothing_raised do
+ Parser.default_parser = RSS::AVAILABLE_PARSERS.first
+ end
+
+ assert_raise(RSS::NotValidXMLParser) do
+ Parser.default_parser = RSS::Parser
+ end
+ end
+
+ def test_parse
+ assert_not_nil(RSS::Parser.parse(@rss_file))
+
+ garbage_rss_file = @rss_file + "-garbage"
+ if RSS::Parser.default_parser.name == "RSS::XMLParserParser"
+ assert_raise(RSS::NotWellFormedError) do
+ RSS::Parser.parse(garbage_rss_file)
+ end
+ else
+ assert_nil(RSS::Parser.parse(garbage_rss_file))
+ end
+ end
+
+ def test_parse_tag_includes_hyphen
+ assert_nothing_raised do
+ RSS::Parser.parse(make_RDF(<<-EOR))
+<xCal:x-calconnect-venue xmlns:xCal="urn:ietf:params:xml:ns:xcal" />
+#{make_channel}
+#{make_item}
+#{make_textinput}
+#{make_image}
+EOR
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_parser_1.0.rb b/trunk/test/rss/test_parser_1.0.rb
new file mode 100644
index 0000000000..216881b767
--- /dev/null
+++ b/trunk/test/rss/test_parser_1.0.rb
@@ -0,0 +1,512 @@
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/dublincore"
+
+module RSS
+ class TestParser10 < TestCase
+ def test_RDF
+ assert_ns("", RDF::URI) do
+ Parser.parse(<<-EOR)
+#{make_xmldecl}
+<RDF/>
+EOR
+ end
+
+ assert_ns("", RDF::URI) do
+ Parser.parse(<<-EOR)
+#{make_xmldecl}
+<RDF xmlns="hoge"/>
+EOR
+ end
+
+ assert_ns("rdf", RDF::URI) do
+ Parser.parse(<<-EOR)
+#{make_xmldecl}
+<rdf:RDF xmlns:rdf="hoge"/>
+EOR
+ end
+
+ assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
+#{make_xmldecl}
+<rdf:RDF xmlns:rdf="#{RSS::RDF::URI}"/>
+EOR
+
+ assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
+#{make_xmldecl}
+<RDF xmlns="#{RSS::RDF::URI}"/>
+EOR
+
+ assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
+#{make_xmldecl}
+<RDF xmlns="#{RSS::RDF::URI}"/>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+#{make_channel}
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+#{make_channel}
+#{make_image}
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+#{make_channel}
+#{make_textinput}
+EOR
+
+ assert_too_much_tag("image", "RDF") do
+ Parser.parse(make_RDF(<<-EOR))
+#{make_channel}
+#{make_image}
+#{make_image}
+#{make_item}
+#{make_textinput}
+EOR
+ end
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_item}
+#{make_image}
+#{make_textinput}
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_item}
+#{make_textinput}
+#{make_image}
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_image}
+#{make_item}
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_image}
+#{make_item}
+#{make_textinput}
+EOR
+
+ 1.step(15, 3) do |i|
+ rss = make_RDF() do
+ res = make_channel
+ i.times { res << make_item }
+ res
+ end
+ assert_parse(rss, :nothing_raised)
+ end
+ end
+
+ def test_undefined_entity
+ return unless RSS::Parser.default_parser.raise_for_undefined_entity?
+ assert_parse(make_RDF(<<-EOR), :raises, RSS::NotWellFormedError)
+#{make_channel}
+#{make_image}
+<item rdf:about="#{RDF_ABOUT}">
+ <title>#{TITLE_VALUE} &UNKNOWN_ENTITY;</title>
+ <link>#{LINK_VALUE}</link>
+ <description>#{DESCRIPTION_VALUE}</description>
+</item>
+#{make_textinput}
+EOR
+ end
+
+ def test_channel
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "channel", "rdf:about")
+<channel />
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "channel")
+<channel rdf:about="http://example.com/"/>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "channel")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<EOR), :missing_tag, "description", "channel")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:resource")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image/>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+</channel>
+EOR
+
+ rss = make_RDF(<<-EOR)
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+ <items/>
+</channel>
+EOR
+
+ assert_missing_tag("Seq", "items") do
+ Parser.parse(rss)
+ end
+
+ assert_missing_tag("item", "RDF") do
+ Parser.parse(rss, false).validate
+ end
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+ <items>
+ <rdf:Seq>
+ </rdf:Seq>
+ </items>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:resource")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+ <items>
+ <rdf:Seq>
+ </rdf:Seq>
+ </items>
+ <textinput/>
+</channel>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+ <items>
+ <rdf:Seq>
+ </rdf:Seq>
+ </items>
+ <textinput rdf:resource="http://example.com/search" />
+</channel>
+EOR
+ end
+
+ def test_rdf_li
+ rss = make_RDF(<<-EOR)
+<channel rdf:about="http://example.com/">
+ <title>hoge</title>
+ <link>http://example.com/</link>
+ <description>hogehoge</description>
+ <image rdf:resource="http://example.com/hoge.png" />
+ <items>
+ <rdf:Seq>
+ <rdf:li \#{rdf_li_attr}/>
+ </rdf:Seq>
+ </items>
+ <textinput rdf:resource="http://example.com/search" />
+</channel>
+#{make_item}
+EOR
+
+ source = Proc.new do |rdf_li_attr|
+ eval(%Q[%Q[#{rss}]], binding)
+ end
+
+ attr = %q[resource="http://example.com/hoge"]
+ assert_parse(source.call(attr), :nothing_raised)
+
+ attr = %q[rdf:resource="http://example.com/hoge"]
+ assert_parse(source.call(attr), :nothing_raised)
+
+ assert_parse(source.call(""), :missing_attribute, "li", "resource")
+ end
+
+ def test_image
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:about")
+#{make_channel}
+<image>
+</image>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "image")
+#{make_channel}
+<image rdf:about="http://example.com/hoge.png">
+</image>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "url", "image")
+#{make_channel}
+<image rdf:about="http://example.com/hoge.png">
+ <title>hoge</title>
+</image>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "image")
+#{make_channel}
+<image rdf:about="http://example.com/hoge.png">
+ <title>hoge</title>
+ <url>http://example.com/hoge.png</url>
+</image>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
+#{make_channel}
+<image rdf:about="http://example.com/hoge.png">
+ <title>hoge</title>
+ <url>http://example.com/hoge.png</url>
+ <link>http://example.com/</link>
+</image>
+EOR
+
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+<image rdf:about="http://example.com/hoge.png">
+ <link>http://example.com/</link>
+ <url>http://example.com/hoge.png</url>
+ <title>hoge</title>
+</image>
+EOR
+
+ assert_missing_tag("item", "RDF") do
+ Parser.parse(rss)
+ end
+
+ assert_missing_tag("item", "RDF") do
+ Parser.parse(rss, false).validate
+ end
+ end
+
+ def test_item
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "item", "rdf:about")
+#{make_channel}
+#{make_image}
+<item>
+</item>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "item")
+#{make_channel}
+#{make_image}
+<item rdf:about="http://example.com/hoge.html">
+</item>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "item")
+#{make_channel}
+#{make_image}
+<item rdf:about="http://example.com/hoge.html">
+ <title>hoge</title>
+</item>
+EOR
+
+ assert_too_much_tag("title", "item") do
+ Parser.parse(make_RDF(<<-EOR))
+#{make_channel}
+#{make_image}
+<item rdf:about="http://example.com/hoge.html">
+ <title>hoge</title>
+ <title>hoge</title>
+ <link>http://example.com/hoge.html</link>
+</item>
+EOR
+ end
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_image}
+<item rdf:about="http://example.com/hoge.html">
+ <title>hoge</title>
+ <link>http://example.com/hoge.html</link>
+</item>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_image}
+<item rdf:about="http://example.com/hoge.html">
+ <title>hoge</title>
+ <link>http://example.com/hoge.html</link>
+ <description>hogehoge</description>
+</item>
+EOR
+ end
+
+ def test_textinput
+ assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:about")
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput>
+</textinput>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "textinput")
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+</textinput>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "description", "textinput")
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+ <title>hoge</title>
+</textinput>
+EOR
+
+ assert_too_much_tag("title", "textinput") do
+ Parser.parse(make_RDF(<<-EOR))
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+ <title>hoge</title>
+ <title>hoge</title>
+ <description>hogehoge</description>
+</textinput>
+EOR
+ end
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "name", "textinput")
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+ <title>hoge</title>
+ <description>hogehoge</description>
+</textinput>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "textinput")
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+ <title>hoge</title>
+ <description>hogehoge</description>
+ <name>key</name>
+</textinput>
+EOR
+
+ assert_parse(make_RDF(<<-EOR), :nothing_raised)
+#{make_channel}
+#{make_image}
+#{make_item}
+<textinput rdf:about="http://example.com/search.html">
+ <title>hoge</title>
+ <description>hogehoge</description>
+ <name>key</name>
+ <link>http://example.com/search.html</link>
+</textinput>
+EOR
+ end
+
+ def test_ignore
+ name = "a"
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+<#{name}/>
+EOR
+ assert_not_expected_tag(name, ::RSS::URI, "RDF") do
+ Parser.parse(rss, true, false)
+ end
+
+ uri = ""
+ name = "a"
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+<#{name} xmlns=""/>
+EOR
+ assert_parse(rss, :nothing_raised)
+ assert_not_expected_tag(name, uri, "RDF") do
+ Parser.parse(rss, true, false)
+ end
+
+ uri = "http://example.com/"
+ name = "a"
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+<x:#{name} xmlns:x="#{uri}"/>
+EOR
+ assert_parse(rss, :nothing_raised)
+ assert_not_expected_tag(name, uri, "RDF") do
+ Parser.parse(rss, true, false)
+ end
+
+ uri = ::RSS::URI
+ name = "a"
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+#{make_image("<#{name}/>")}
+EOR
+ assert_parse(rss, :nothing_raised)
+ assert_not_expected_tag(name, uri, "image") do
+ Parser.parse(rss, true, false)
+ end
+
+ uri = CONTENT_URI
+ name = "encoded"
+ elem = "<#{name} xmlns='#{uri}'/>"
+ rss = make_RDF(<<-EOR)
+#{make_channel}
+#{make_item}
+#{make_image(elem)}
+EOR
+ assert_parse(rss, :nothing_raised)
+ assert_not_expected_tag(name, uri, "image") do
+ Parser.parse(rss, true, false)
+ end
+ end
+
+ def test_unknown_duplicated_element
+ xmlns = {"test" => "http://localhost/test"}
+ assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised)
+ #{make_channel("<test:string/>")}
+ #{make_item}
+ #{make_image}
+ EOR
+ end
+ end
+end
+
diff --git a/trunk/test/rss/test_parser_2.0.rb b/trunk/test/rss/test_parser_2.0.rb
new file mode 100644
index 0000000000..249347d3dc
--- /dev/null
+++ b/trunk/test/rss/test_parser_2.0.rb
@@ -0,0 +1,122 @@
+require "rss-testcase"
+
+require "rss/2.0"
+
+module RSS
+ class TestParser20 < TestCase
+ def test_rss20
+ assert_parse(make_rss20(<<-EOR), :missing_tag, "channel", "rss")
+EOR
+
+ assert_parse(make_rss20(<<-EOR), :nothing_raised)
+#{make_channel20("")}
+EOR
+ end
+
+ def test_cloud20
+ attrs = [
+ ["domain", CLOUD_DOMAIN],
+ ["port", CLOUD_PORT],
+ ["path", CLOUD_PATH],
+ ["registerProcedure", CLOUD_REGISTER_PROCEDURE],
+ ["protocol", CLOUD_PROTOCOL],
+ ]
+
+ (attrs.size + 1).times do |i|
+ missing_attr = attrs[i]
+ if missing_attr
+ meth = :missing_attribute
+ args = ["cloud", missing_attr[0]]
+ else
+ meth = :nothing_raised
+ args = []
+ end
+
+ cloud_attrs = []
+ attrs.each_with_index do |attr, j|
+ unless i == j
+ cloud_attrs << %Q[#{attr[0]}="#{attr[1]}"]
+ end
+ end
+
+ assert_parse(make_rss20(<<-EOR), meth, *args)
+#{make_channel20(%Q[<cloud #{cloud_attrs.join("\n")}/>])}
+EOR
+ end
+ end
+
+ def test_source20
+ assert_parse(make_rss20(<<-EOR), :missing_attribute, "source", "url")
+#{make_channel20(make_item20(%Q[<source>Example</source>]))}
+EOR
+
+ assert_parse(make_rss20(<<-EOR), :nothing_raised)
+#{make_channel20(make_item20(%Q[<source url="http://example.com/" />]))}
+EOR
+
+ assert_parse(make_rss20(<<-EOR), :nothing_raised)
+#{make_channel20(make_item20(%Q[<source url="http://example.com/">Example</source>]))}
+EOR
+ end
+
+ def test_enclosure20
+ attrs = [
+ ["url", ENCLOSURE_URL],
+ ["length", ENCLOSURE_LENGTH],
+ ["type", ENCLOSURE_TYPE],
+ ]
+
+ (attrs.size + 1).times do |i|
+ missing_attr = attrs[i]
+ if missing_attr
+ meth = :missing_attribute
+ args = ["enclosure", missing_attr[0]]
+ else
+ meth = :nothing_raised
+ args = []
+ end
+
+ enclosure_attrs = []
+ attrs.each_with_index do |attr, j|
+ unless i == j
+ enclosure_attrs << %Q[#{attr[0]}="#{attr[1]}"]
+ end
+ end
+
+ assert_parse(make_rss20(<<-EOR), meth, *args)
+#{make_channel20(%Q[
+#{make_item20(%Q[
+<enclosure
+ #{enclosure_attrs.join("\n")} />
+ ])}
+ ])}
+EOR
+ end
+ end
+
+ def test_category20
+ values = [nil, CATEGORY_DOMAIN]
+ values.each do |value|
+ domain = ""
+ domain << %Q[domain="#{value}"] if value
+
+ ["", "Example Text"].each do |text|
+ rss_src = make_rss20(<<-EOR)
+#{make_channel20(%Q[
+#{make_item20(%Q[
+<category #{domain}>#{text}</category>
+ ])}
+ ])}
+EOR
+ assert_parse(rss_src, :nothing_raised)
+
+ rss = RSS::Parser.parse(rss_src)
+ category = rss.items.last.categories.first
+ assert_equal(value, category.domain)
+ assert_equal(text, category.content)
+ end
+ end
+ end
+ end
+end
+
diff --git a/trunk/test/rss/test_parser_atom_entry.rb b/trunk/test/rss/test_parser_atom_entry.rb
new file mode 100644
index 0000000000..c2572d7a3b
--- /dev/null
+++ b/trunk/test/rss/test_parser_atom_entry.rb
@@ -0,0 +1,163 @@
+require "rss-testcase"
+
+require "rss/atom"
+
+module RSS
+ class TestParserAtom < TestCase
+ def test_entry_validation
+ assert_ns("", Atom::URI) do
+ Parser.parse(<<-EOA)
+<entry/>
+EOA
+ end
+
+ assert_ns("", Atom::URI) do
+ Parser.parse(<<-EOA)
+<entry xmlns="hoge"/>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "id", "entry") do
+<entry xmlns="#{Atom::URI}"/>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "title", "entry") do
+<entry xmlns="#{Atom::URI}">
+ <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
+</entry>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "updated", "entry") do
+<entry xmlns="#{Atom::URI}">
+ <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
+ <title>Example Entry</title>
+</entry>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "author", "entry") do
+<entry xmlns="#{Atom::URI}">
+ <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
+ <title>Example Entry</title>
+ <updated>2003-10-10T18:30:02Z</updated>
+</entry>
+EOA
+ end
+
+ assert_parse(<<-EOA, :nothing_raised) do
+<entry xmlns="#{Atom::URI}">
+ <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
+ <title>Example Entry</title>
+ <updated>2003-10-10T18:30:02Z</updated>
+ <author>
+ <name>A person</name>
+ </author>
+</entry>
+EOA
+ end
+ end
+
+ def test_entry
+ entry = RSS::Parser.parse(<<-EOA)
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <author>
+ <name>A person</name>
+ </author>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+</entry>
+EOA
+ assert_not_nil(entry)
+ assert_equal("Atom-Powered Robots Run Amok", entry.title.content)
+ assert_equal("http://example.org/2003/12/13/atom03", entry.link.href)
+ assert_equal("urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+ entry.id.content)
+ assert_equal(Time.parse("2003-12-13T18:30:02Z"), entry.updated.content)
+ assert_equal("Some text.", entry.summary.content)
+ end
+
+ def test_entry_author
+ assert_atom_person("author", method(:make_entry_document)) do |entry|
+ assert_equal(2, entry.authors.size)
+ entry.authors.last
+ end
+ end
+
+ def test_entry_category
+ assert_atom_category(method(:make_entry_document)) do |entry|
+ assert_equal(1, entry.categories.size)
+ entry.category
+ end
+ end
+
+ def test_entry_content_text
+ assert_atom_content(method(:make_entry_document)) do |entry|
+ entry.content
+ end
+ end
+
+ def test_entry_contributor
+ assert_atom_person("contributor", method(:make_entry_document)) do |entry|
+ assert_equal(1, entry.contributors.size)
+ entry.contributor
+ end
+ end
+
+ def test_entry_id
+ entry = RSS::Parser.parse(make_entry_document)
+ assert_equal(ENTRY_ID, entry.id.content)
+ end
+
+ def test_entry_link
+ assert_atom_link(method(:make_entry_document)) do |entry|
+ assert_equal(1, entry.links.size)
+ entry.link
+ end
+ end
+
+ def test_published
+ generator = method(:make_entry_document)
+ assert_atom_date_construct("published", generator) do |entry|
+ entry.published
+ end
+ end
+
+ def test_entry_rights
+ generator = method(:make_entry_document)
+ assert_atom_text_construct("rights", generator) do |entry|
+ entry.rights
+ end
+ end
+
+ def test_entry_source
+ generator = method(:make_entry_document_with_open_source)
+ assert_atom_source(generator) do |entry|
+ assert_not_nil(entry.source)
+ entry.source
+ end
+ end
+
+ def test_entry_summary
+ generator = method(:make_entry_document)
+ assert_atom_text_construct("summary", generator) do |entry|
+ entry.summary
+ end
+ end
+
+ def test_entry_title
+ entry = RSS::Parser.parse(make_entry_document)
+ assert_equal(ENTRY_TITLE, entry.title.content)
+ end
+
+ def test_entry_updated
+ entry = RSS::Parser.parse(make_entry_document)
+ assert_equal(Time.parse(ENTRY_UPDATED), entry.updated.content)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_parser_atom_feed.rb b/trunk/test/rss/test_parser_atom_feed.rb
new file mode 100644
index 0000000000..4358cc8898
--- /dev/null
+++ b/trunk/test/rss/test_parser_atom_feed.rb
@@ -0,0 +1,276 @@
+require "rss-testcase"
+
+require "rss/atom"
+
+module RSS
+ class TestParserAtomFeed < TestCase
+ def test_feed_validation
+ assert_ns("", Atom::URI) do
+ Parser.parse(<<-EOA)
+<feed/>
+EOA
+ end
+
+ assert_ns("", Atom::URI) do
+ Parser.parse(<<-EOA)
+<feed xmlns="hoge"/>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "id", "feed") do
+<feed xmlns="#{Atom::URI}"/>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "title", "feed") do
+<feed xmlns="#{Atom::URI}">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+</feed>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "updated", "feed") do
+<feed xmlns="#{Atom::URI}">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title>Example Feed</title>
+</feed>
+EOA
+ end
+
+ assert_parse(<<-EOA, :missing_tag, "author", "feed") do
+<feed xmlns="#{Atom::URI}">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title>Example Feed</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+</feed>
+EOA
+ end
+
+ assert_parse(<<-EOA, :nothing_raised) do
+<feed xmlns="#{Atom::URI}">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title>Example Feed</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>A person</name>
+ </author>
+</feed>
+EOA
+ end
+ end
+
+ def test_lang
+ feed = RSS::Parser.parse(<<-EOA)
+<feed xmlns="#{Atom::URI}" xml:lang="ja">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title xml:lang="en">Example Feed</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author xml:lang="en">
+ <name>A person</name>
+ </author>
+</feed>
+EOA
+
+ assert_equal("ja", feed.lang)
+ assert_equal("ja", feed.id.lang)
+ assert_equal("en", feed.title.lang)
+ assert_equal("ja", feed.updated.lang)
+ assert_equal("en", feed.author.lang)
+ assert_equal("en", feed.author.name.lang)
+ end
+
+ def test_base
+ feed = RSS::Parser.parse(<<-EOA)
+<feed xmlns="#{Atom::URI}" xml:base="http://example.com/">
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <title xml:lang="en">Example Feed</title>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <generator uri="generator">Generator</generator>
+ <link hreflang="ja" href="http://example.org/link1"/>
+ <link hreflang="en" href="link2"/>
+ <link hreflang="fr" xml:base="http://example.net/" href="link3"/>
+ <author>
+ <name>A person</name>
+ <uri>person</uri>
+ </author>
+</feed>
+EOA
+
+ assert_equal("http://example.com/", feed.base)
+ assert_equal("http://example.com/", feed.id.base)
+ assert_equal("http://example.com/", feed.title.base)
+ assert_equal("http://example.com/", feed.updated.base)
+ assert_equal("http://example.com/", feed.generator.base)
+ assert_equal("http://example.com/generator", feed.generator.uri)
+
+ assert_equal("http://example.com/", feed.links[0].base)
+ assert_equal("http://example.org/link1", feed.links[0].href)
+ assert_equal("http://example.com/", feed.links[1].base)
+ assert_equal("http://example.com/link2", feed.links[1].href)
+ assert_equal("http://example.net/", feed.links[2].base)
+ assert_equal("http://example.net/link3", feed.links[2].href)
+ assert_equal("http://example.com/person", feed.author.uri.content)
+ end
+
+ def test_feed_author
+ assert_atom_person("author", method(:make_feed)) do |feed|
+ assert_equal(2, feed.authors.size)
+ feed.authors[1]
+ end
+ end
+
+ def test_entry_author
+ generator = method(:make_feed_with_open_entry)
+ assert_atom_person("author", generator) do |feed|
+ assert_equal(1, feed.entries.size)
+ assert_equal(1, feed.entry.authors.size)
+ feed.entry.author
+ end
+ end
+
+ def test_feed_category
+ assert_atom_category(method(:make_feed)) do |feed|
+ assert_equal(1, feed.categories.size)
+ feed.category
+ end
+ end
+
+ def test_entry_category
+ assert_atom_category(method(:make_feed_with_open_entry)) do |feed|
+ assert_equal(1, feed.entries.size)
+ assert_equal(1, feed.entry.categories.size)
+ feed.entry.category
+ end
+ end
+
+ def test_entry_content
+ assert_atom_content(method(:make_feed_with_open_entry)) do |feed|
+ assert_equal(1, feed.entries.size)
+ feed.entry.content
+ end
+ end
+
+ def test_feed_contributor
+ assert_atom_person("contributor", method(:make_feed)) do |feed|
+ assert_equal(1, feed.contributors.size)
+ feed.contributor
+ end
+ end
+
+ def test_entry_contributor
+ generator = method(:make_feed_with_open_entry)
+ assert_atom_person("contributor", generator) do |feed|
+ assert_equal(1, feed.entries.size)
+ assert_equal(1, feed.entry.contributors.size)
+ feed.entry.contributor
+ end
+ end
+
+ def test_feed_generator
+ assert_atom_generator(method(:make_feed)) do |feed|
+ feed.generator
+ end
+ end
+
+ def test_feed_icon
+ assert_atom_icon(method(:make_feed)) do |feed|
+ feed.icon
+ end
+ end
+
+ def test_feed_id
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(FEED_ID, feed.id.content)
+ end
+
+ def test_entry_id
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(ENTRY_ID, feed.entry.id.content)
+ end
+
+ def test_feed_link
+ assert_atom_link(method(:make_feed)) do |feed|
+ assert_equal(1, feed.links.size)
+ feed.link
+ end
+ end
+
+ def test_entry_link
+ assert_atom_link(method(:make_feed_with_open_entry)) do |feed|
+ assert_equal(1, feed.entries.size)
+ assert_equal(1, feed.entry.links.size)
+ feed.entry.link
+ end
+ end
+
+ def test_feed_logo
+ assert_atom_logo(method(:make_feed)) do |feed|
+ feed.logo
+ end
+ end
+
+ def test_feed_rights
+ assert_atom_text_construct("rights", method(:make_feed)) do |feed|
+ feed.rights
+ end
+ end
+
+ def test_entry_rights
+ generator = method(:make_feed_with_open_entry)
+ assert_atom_text_construct("rights", generator) do |feed|
+ assert_equal(1, feed.entries.size)
+ feed.entry.rights
+ end
+ end
+
+ def test_entry_source
+ assert_atom_source(method(:make_feed_with_open_entry_source)) do |feed|
+ assert_equal(1, feed.entries.size)
+ assert_not_nil(feed.entry.source)
+ feed.entry.source
+ end
+ end
+
+ def test_feed_subtitle
+ assert_atom_text_construct("subtitle", method(:make_feed)) do |feed|
+ feed.subtitle
+ end
+ end
+
+ def test_feed_title
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(FEED_TITLE, feed.title.content)
+ end
+
+ def test_entry_title
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(ENTRY_TITLE, feed.entry.title.content)
+ end
+
+ def test_feed_updated
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(Time.parse(FEED_UPDATED), feed.updated.content)
+ end
+
+ def test_entry_updated
+ feed = RSS::Parser.parse(make_feed(''))
+ assert_equal(Time.parse(ENTRY_UPDATED), feed.entry.updated.content)
+ end
+
+ def test_entry_published
+ generator = method(:make_feed_with_open_entry)
+ assert_atom_date_construct("published", generator) do |feed|
+ assert_equal(1, feed.entries.size)
+ feed.entry.published
+ end
+ end
+
+ def test_entry_summary
+ generator = method(:make_feed_with_open_entry)
+ assert_atom_text_construct("summary", generator) do |feed|
+ assert_equal(1, feed.entries.size)
+ feed.entry.summary
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_0.9.rb b/trunk/test/rss/test_setup_maker_0.9.rb
new file mode 100644
index 0000000000..c20186cc8a
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_0.9.rb
@@ -0,0 +1,246 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMaker09 < TestCase
+
+ def test_setup_maker_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+ copyright = "foo"
+ managingEditor = "bar"
+ webMaster = "web master"
+ rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
+ docs = "http://foo.com/doc"
+ skipDays = [
+ "Sunday",
+ "Monday",
+ ]
+ skipHours = [
+ "0",
+ "13",
+ ]
+ pubDate = Time.now
+ lastBuildDate = Time.now
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ maker.channel.copyright = copyright
+ maker.channel.managingEditor = managingEditor
+ maker.channel.webMaster = webMaster
+ maker.channel.rating = rating
+ maker.channel.docs = docs
+ maker.channel.pubDate = pubDate
+ maker.channel.lastBuildDate = lastBuildDate
+
+ skipDays.each do |day|
+ maker.channel.skipDays.new_day do |new_day|
+ new_day.content = day
+ end
+ end
+ skipHours.each do |hour|
+ maker.channel.skipHours.new_hour do |new_hour|
+ new_hour.content = hour
+ end
+ end
+
+ setup_dummy_image(maker)
+ end
+
+ assert_not_set_error("maker.image", %w(title url)) do
+ RSS::Maker.make("0.91") do |maker|
+ rss.channel.setup_maker(maker)
+ end
+ end
+
+ new_rss = RSS::Maker.make("0.91") do |maker|
+ rss.channel.setup_maker(maker)
+ setup_dummy_image(maker)
+ end
+ channel = new_rss.channel
+
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(language, channel.language)
+ assert_equal(copyright, channel.copyright)
+ assert_equal(managingEditor, channel.managingEditor)
+ assert_equal(webMaster, channel.webMaster)
+ assert_equal(rating, channel.rating)
+ assert_equal(docs, channel.docs)
+ assert_equal(pubDate, channel.pubDate)
+ assert_equal(lastBuildDate, channel.lastBuildDate)
+
+ skipDays.each_with_index do |day, i|
+ assert_equal(day, channel.skipDays.days[i].content)
+ end
+ skipHours.each_with_index do |hour, i|
+ assert_equal(hour.to_i, channel.skipHours.hours[i].content)
+ end
+
+ assert(channel.items.empty?)
+ assert_nil(channel.textInput)
+ end
+
+ def test_setup_maker_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+
+ new_rss = RSS::Maker.make("0.91") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.image.setup_maker(maker)
+ end
+
+ image = new_rss.image
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+ assert_equal(width.to_i, image.width)
+ assert_equal(height.to_i, image.height)
+ assert_equal(description, image.description)
+ end
+
+ def test_setup_maker_textinput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+
+ new_rss = RSS::Maker.make("0.91") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.image.setup_maker(maker)
+ rss.textinput.setup_maker(maker)
+ end
+
+ textInput = new_rss.channel.textInput
+ assert_equal(title, textInput.title)
+ assert_equal(description, textInput.description)
+ assert_equal(name, textInput.name)
+ assert_equal(link, textInput.link)
+ end
+
+ def test_setup_maker_items(for_backward_compatibility=false)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+
+ item_size = 5
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ end
+ end
+
+ setup_dummy_image(maker)
+ end
+
+ new_rss = RSS::Maker.make("0.91") do |maker|
+ rss.channel.setup_maker(maker)
+
+ rss.items.each do |item|
+ if for_backward_compatibility
+ item.setup_maker(maker)
+ else
+ item.setup_maker(maker.items)
+ end
+ end
+
+ rss.image.setup_maker(maker)
+ end
+
+ assert_equal(item_size, new_rss.items.size)
+ new_rss.items.each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ end
+ end
+
+ def test_setup_maker_items_backward_compatibility
+ test_setup_maker_items(true)
+ end
+
+ def test_setup_maker
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ rss = RSS::Maker.make("0.91") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_image(maker)
+ end
+
+ new_rss = RSS::Maker.make("0.91") do |maker|
+ rss.setup_maker(maker)
+ end
+
+ assert_equal("0.91", new_rss.rss_version)
+ assert_equal(encoding, new_rss.encoding)
+ assert_equal(standalone, new_rss.standalone)
+
+ xss = rss.xml_stylesheets.first
+ assert_equal(1, rss.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_1.0.rb b/trunk/test/rss/test_setup_maker_1.0.rb
new file mode 100644
index 0000000000..0b960d91c8
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_1.0.rb
@@ -0,0 +1,550 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMaker10 < TestCase
+
+ def setup
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @dc_elems = {
+ :title => "hoge",
+ :description =>
+ " XML is placing increasingly heavy loads on
+ the existing technical infrastructure of the Internet.",
+ :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
+ :subject => "XML",
+ :publisher => "The O'Reilly Network",
+ :contributor => "hogehoge",
+ :type => "fugafuga",
+ :format => "hohoho",
+ :identifier => "fufufu",
+ :source => "barbar",
+ :language => "ja",
+ :relation => "cococo",
+ :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
+ :date => t,
+ }
+
+ @sy_elems = {
+ :updatePeriod => "hourly",
+ :updateFrequency => "2",
+ :updateBase => t,
+ }
+
+ @content_elems = {
+ :encoded => "<em>ATTENTION</em>",
+ }
+
+ @trackback_elems = {
+ :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
+ :about => [
+ "http://foo.com/trackback/tb.cgi?tb_id=20020923",
+ "http://foo.com/trackback/tb.cgi?tb_id=20021010",
+ ],
+ }
+
+ @taxo_topic_elems = [
+ {
+ :link => "http://meerkat.oreillynet.com/?c=cat23",
+ :title => "Data: XML",
+ :description => "A Meerkat channel",
+ },
+ {
+ :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
+ :title => "XML",
+ :subject => "XML",
+ :description => "DMOZ category",
+ :topics => [
+ "http://meerkat.oreillynet.com/?c=cat23",
+ "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
+ "http://dmoz.org/Computers/Programming/Internet/",
+ ]
+ },
+ ]
+ end
+
+ def test_setup_maker_channel
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.channel.about = about
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+
+ @dc_elems.each do |var, value|
+ maker.channel.__send__("dc_#{var}=", value)
+ end
+
+ @sy_elems.each do |var, value|
+ maker.channel.__send__("sy_#{var}=", value)
+ end
+
+ setup_dummy_item(maker)
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.items.each do |item|
+ item.setup_maker(maker)
+ end
+ end
+ channel = new_rss.channel
+
+ assert_equal(about, channel.about)
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(1, channel.items.Seq.lis.size)
+ assert_nil(channel.image)
+ assert_nil(channel.textinput)
+
+ @dc_elems.each do |var, value|
+ assert_equal(value, channel.__send__("dc_#{var}"))
+ end
+
+ @sy_elems.each do |var, value|
+ value = value.to_i if var == :updateFrequency
+ assert_equal(value, channel.__send__("sy_#{var}"))
+ end
+
+ end
+
+ def test_setup_maker_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+
+ @dc_elems.each do |var, value|
+ maker.image.__send__("dc_#{var}=", value)
+ end
+
+ setup_dummy_item(maker)
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.image.setup_maker(maker)
+ rss.items.each do |item|
+ item.setup_maker(maker)
+ end
+ end
+
+ image = new_rss.image
+ assert_equal(url, image.about)
+ assert_equal(url, new_rss.channel.image.resource)
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+
+ @dc_elems.each do |var, value|
+ assert_equal(image.__send__("dc_#{var}"), value)
+ end
+ end
+
+ def test_setup_maker_textinput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.link = link
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+
+ @dc_elems.each do |var, value|
+ maker.textinput.__send__("dc_#{var}=", value)
+ end
+
+ setup_dummy_item(maker)
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.textinput.setup_maker(maker)
+ rss.items.each do |item|
+ item.setup_maker(maker)
+ end
+ end
+
+ textinput = new_rss.textinput
+ assert_equal(link, textinput.about)
+ assert_equal(link, new_rss.channel.textinput.resource)
+ assert_equal(title, textinput.title)
+ assert_equal(name, textinput.name)
+ assert_equal(description, textinput.description)
+ assert_equal(link, textinput.link)
+
+ @dc_elems.each do |var, value|
+ assert_equal(textinput.__send__("dc_#{var}"), value)
+ end
+ end
+
+ def test_setup_maker_items(for_backward_compatibility=false)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+
+ item_size = 5
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+
+ @dc_elems.each do |var, value|
+ item.__send__("dc_#{var}=", value)
+ end
+
+ @content_elems.each do |var, value|
+ item.__send__("content_#{var}=", value)
+ end
+
+ item.trackback_ping = @trackback_elems[:ping]
+ @trackback_elems[:about].each do |value|
+ item.trackback_abouts.new_about do |new_about|
+ new_about.value = value
+ end
+ end
+ end
+ end
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.channel.setup_maker(maker)
+
+ rss.items.each do |item|
+ if for_backward_compatibility
+ item.setup_maker(maker)
+ else
+ item.setup_maker(maker.items)
+ end
+ end
+ end
+
+ assert_equal(item_size, new_rss.items.size)
+ new_rss.items.each_with_index do |item, i|
+ assert_equal("#{link}#{i}", item.about)
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+
+ @dc_elems.each do |var, value|
+ assert_equal(item.__send__("dc_#{var}"), value)
+ end
+
+ @content_elems.each do |var, value|
+ assert_equal(item.__send__("content_#{var}"), value)
+ end
+
+ assert_equal(@trackback_elems[:ping], item.trackback_ping)
+ assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
+ item.trackback_abouts.each_with_index do |about, j|
+ assert_equal(@trackback_elems[:about][j], about.value)
+ end
+ end
+ end
+
+ def test_setup_maker_items_sort
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+
+ item_size = 5
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ item = RSS::RDF::Item.new("#{link}#{i}")
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.dc_date = Time.now + i * 60
+ item.setup_maker(maker.items)
+ end
+ maker.items.do_sort = false
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.items.each_with_index do |item, i|
+ assert_equal("#{link}#{i}", item.about)
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ end
+
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ item = RSS::RDF::Item.new("#{link}#{i}")
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.dc_date = Time.now + i * 60
+ item.setup_maker(maker.items)
+ end
+ maker.items.do_sort = true
+ end
+ assert_equal(item_size, rss.items.size)
+ rss.items.reverse.each_with_index do |item, i|
+ assert_equal("#{link}#{i}", item.about)
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ end
+ end
+
+ def test_setup_maker_items_backward_compatibility
+ test_setup_maker_items(true)
+ end
+
+ def test_setup_maker
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.setup_maker(maker)
+ end
+
+ assert_equal("1.0", new_rss.rss_version)
+ assert_equal(encoding, new_rss.encoding)
+ assert_equal(standalone, new_rss.standalone)
+
+ xss = new_rss.xml_stylesheets.first
+ assert_equal(1, new_rss.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+ end
+
+ def test_setup_maker_full
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ channel_about = "http://hoge.com"
+ channel_title = "fugafuga"
+ channel_link = "http://hoge.com"
+ channel_description = "fugafugafugafuga"
+
+ image_title = "fugafuga"
+ image_url = "http://hoge.com/hoge.png"
+
+ textinput_title = "fugafuga"
+ textinput_description = "text hoge fuga"
+ textinput_name = "hoge"
+ textinput_link = "http://hoge.com"
+
+ item_title = "TITLE"
+ item_link = "http://hoge.com/"
+ item_description = "text hoge fuga"
+
+ item_size = 5
+
+ rss = RSS::Maker.make("1.0") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ maker.channel.about = channel_about
+ maker.channel.title = channel_title
+ maker.channel.link = channel_link
+ maker.channel.description = channel_description
+ @dc_elems.each do |var, value|
+ maker.channel.__send__("dc_#{var}=", value)
+ end
+ @sy_elems.each do |var, value|
+ maker.channel.__send__("sy_#{var}=", value)
+ end
+
+ maker.image.title = image_title
+ maker.image.url = image_url
+ @dc_elems.each do |var, value|
+ maker.image.__send__("dc_#{var}=", value)
+ end
+
+ maker.textinput.link = textinput_link
+ maker.textinput.title = textinput_title
+ maker.textinput.description = textinput_description
+ maker.textinput.name = textinput_name
+ @dc_elems.each do |var, value|
+ maker.textinput.__send__("dc_#{var}=", value)
+ end
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{item_title}#{i}"
+ item.link = "#{item_link}#{i}"
+ item.description = "#{item_description}#{i}"
+
+ @dc_elems.each do |var, value|
+ item.__send__("dc_#{var}=", value)
+ end
+
+ @content_elems.each do |var, value|
+ item.__send__("content_#{var}=", value)
+ end
+
+ item.trackback_ping = @trackback_elems[:ping]
+ @trackback_elems[:about].each do |value|
+ item.trackback_abouts.new_about do |new_about|
+ new_about.value = value
+ end
+ end
+ end
+ end
+
+ setup_taxo_topic(maker, @taxo_topic_elems)
+ end
+
+ new_rss = RSS::Maker.make("1.0") do |maker|
+ rss.setup_maker(maker)
+ end
+
+ assert_equal("1.0", new_rss.rss_version)
+ assert_equal(encoding, new_rss.encoding)
+ assert_equal(standalone, new_rss.standalone)
+
+ xss = new_rss.xml_stylesheets.first
+ assert_equal(1, new_rss.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+
+ channel = new_rss.channel
+ assert_equal(channel_about, channel.about)
+ assert_equal(channel_title, channel.title)
+ assert_equal(channel_link, channel.link)
+ assert_equal(channel_description, channel.description)
+ item_resources = []
+ item_size.times do |i|
+ item_resources << "#{item_link}#{i}"
+ end
+ assert_equal(item_resources, channel.items.resources)
+ assert_equal(image_url, channel.image.resource)
+ assert_equal(textinput_link, channel.textinput.resource)
+ @dc_elems.each do |var, value|
+ assert_equal(value, channel.__send__("dc_#{var}"))
+ end
+ @sy_elems.each do |var, value|
+ value = value.to_i if var == :updateFrequency
+ assert_equal(value, channel.__send__("sy_#{var}"))
+ end
+
+ image = new_rss.image
+ assert_equal(image_url, image.about)
+ assert_equal(image_url, new_rss.channel.image.resource)
+ assert_equal(image_title, image.title)
+ assert_equal(channel_link, image.link)
+ assert_equal(image_url, image.url)
+ @dc_elems.each do |var, value|
+ assert_equal(image.__send__("dc_#{var}"), value)
+ end
+
+ textinput = new_rss.textinput
+ assert_equal(textinput_link, textinput.about)
+ assert_equal(textinput_link, new_rss.channel.textinput.resource)
+ assert_equal(textinput_title, textinput.title)
+ assert_equal(textinput_name, textinput.name)
+ assert_equal(textinput_description, textinput.description)
+ assert_equal(textinput_link, textinput.link)
+ @dc_elems.each do |var, value|
+ assert_equal(textinput.__send__("dc_#{var}"), value)
+ end
+
+ assert_equal(item_size, new_rss.items.size)
+ new_rss.items.each_with_index do |item, i|
+ assert_equal("#{item_link}#{i}", item.about)
+ assert_equal("#{item_title}#{i}", item.title)
+ assert_equal("#{item_link}#{i}", item.link)
+ assert_equal("#{item_description}#{i}", item.description)
+
+ @dc_elems.each do |var, value|
+ assert_equal(item.__send__("dc_#{var}"), value)
+ end
+
+ @content_elems.each do |var, value|
+ assert_equal(item.__send__("content_#{var}"), value)
+ end
+
+ assert_equal(@trackback_elems[:ping], item.trackback_ping)
+ assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
+ item.trackback_abouts.each_with_index do |about, j|
+ assert_equal(@trackback_elems[:about][j], about.value)
+ end
+ end
+
+ assert_taxo_topic(@taxo_topic_elems, new_rss)
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_2.0.rb b/trunk/test/rss/test_setup_maker_2.0.rb
new file mode 100644
index 0000000000..8fb727de8d
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_2.0.rb
@@ -0,0 +1,308 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMaker20 < TestCase
+
+ def test_setup_maker_channel
+ title = "fugafuga"
+ link = "http://hoge.com"
+ description = "fugafugafugafuga"
+ language = "ja"
+ copyright = "foo"
+ managingEditor = "bar"
+ webMaster = "web master"
+ rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
+ docs = "http://foo.com/doc"
+ skipDays = [
+ "Sunday",
+ "Monday",
+ ]
+ skipHours = [
+ "0",
+ "13",
+ ]
+ pubDate = Time.now
+ lastBuildDate = Time.now
+ categories = [
+ "Nespapers",
+ "misc",
+ ]
+ generator = "RSS Maker"
+ ttl = "60"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ maker.channel.title = title
+ maker.channel.link = link
+ maker.channel.description = description
+ maker.channel.language = language
+ maker.channel.copyright = copyright
+ maker.channel.managingEditor = managingEditor
+ maker.channel.webMaster = webMaster
+ maker.channel.rating = rating
+ maker.channel.docs = docs
+ maker.channel.pubDate = pubDate
+ maker.channel.lastBuildDate = lastBuildDate
+
+ skipDays.each do |day|
+ maker.channel.skipDays.new_day do |new_day|
+ new_day.content = day
+ end
+ end
+ skipHours.each do |hour|
+ maker.channel.skipHours.new_hour do |new_hour|
+ new_hour.content = hour
+ end
+ end
+
+
+ categories.each do |category|
+ maker.channel.categories.new_category do |new_category|
+ new_category.content = category
+ end
+ end
+
+ maker.channel.generator = generator
+ maker.channel.ttl = ttl
+ end
+
+ new_rss = RSS::Maker.make("2.0") do |maker|
+ rss.channel.setup_maker(maker)
+ end
+ channel = new_rss.channel
+
+ assert_equal(title, channel.title)
+ assert_equal(link, channel.link)
+ assert_equal(description, channel.description)
+ assert_equal(language, channel.language)
+ assert_equal(copyright, channel.copyright)
+ assert_equal(managingEditor, channel.managingEditor)
+ assert_equal(webMaster, channel.webMaster)
+ assert_equal(rating, channel.rating)
+ assert_equal(docs, channel.docs)
+ assert_equal(pubDate, channel.pubDate)
+ assert_equal(lastBuildDate, channel.lastBuildDate)
+
+ skipDays.each_with_index do |day, i|
+ assert_equal(day, channel.skipDays.days[i].content)
+ end
+ skipHours.each_with_index do |hour, i|
+ assert_equal(hour.to_i, channel.skipHours.hours[i].content)
+ end
+
+
+ channel.categories.each_with_index do |category, i|
+ assert_equal(categories[i], category.content)
+ end
+
+ assert_equal(generator, channel.generator)
+ assert_equal(ttl.to_i, channel.ttl)
+
+
+ assert(channel.items.empty?)
+ assert_nil(channel.image)
+ assert_nil(channel.textInput)
+ end
+
+ def test_setup_maker_image
+ title = "fugafuga"
+ link = "http://hoge.com"
+ url = "http://hoge.com/hoge.png"
+ width = "144"
+ height = "400"
+ description = "an image"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+ maker.channel.link = link
+
+ maker.image.title = title
+ maker.image.url = url
+ maker.image.width = width
+ maker.image.height = height
+ maker.image.description = description
+ end
+
+ new_rss = RSS::Maker.make("2.0") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.image.setup_maker(maker)
+ end
+
+ image = new_rss.image
+ assert_equal(title, image.title)
+ assert_equal(link, image.link)
+ assert_equal(url, image.url)
+ assert_equal(width.to_i, image.width)
+ assert_equal(height.to_i, image.height)
+ assert_equal(description, image.description)
+ end
+
+ def test_setup_maker_textinput
+ title = "fugafuga"
+ description = "text hoge fuga"
+ name = "hoge"
+ link = "http://hoge.com"
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ maker.textinput.title = title
+ maker.textinput.description = description
+ maker.textinput.name = name
+ maker.textinput.link = link
+ end
+
+ new_rss = RSS::Maker.make("2.0") do |maker|
+ rss.channel.setup_maker(maker)
+ rss.textinput.setup_maker(maker)
+ end
+
+ textInput = new_rss.channel.textInput
+ assert_equal(title, textInput.title)
+ assert_equal(description, textInput.description)
+ assert_equal(name, textInput.name)
+ assert_equal(link, textInput.link)
+ end
+
+ def test_setup_maker_items(for_backward_compatibility=false)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ author = "oprah@oxygen.net"
+ comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
+ pubDate = Time.now
+
+ guid_isPermaLink = "true"
+ guid_content = "http://inessential.com/2002/09/01.php#a2"
+
+ enclosure_url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
+ enclosure_length = "12216320"
+ enclosure_type = "audio/mpeg"
+
+ source_url = "http://static.userland.com/tomalak/links2.xml"
+ source_content = "Tomalak's Realm"
+
+ category_domain = "http://www.fool.com/cusips"
+ category_content = "MSFT"
+
+ item_size = 5
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_dummy_channel(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.author = "#{author}#{i}"
+ item.comments = "#{comments}#{i}"
+ item.date = pubDate
+
+ item.guid.isPermaLink = guid_isPermaLink
+ item.guid.content = guid_content
+
+ item.enclosure.url = enclosure_url
+ item.enclosure.length = enclosure_length
+ item.enclosure.type = enclosure_type
+
+ item.source.url = source_url
+ item.source.content = source_content
+
+ category = item.categories.new_category
+ category.domain = category_domain
+ category.content = category_content
+ end
+ end
+ end
+
+ new_rss = RSS::Maker.make("2.0") do |maker|
+ rss.channel.setup_maker(maker)
+
+ rss.items.each do |item|
+ if for_backward_compatibility
+ item.setup_maker(maker)
+ else
+ item.setup_maker(maker.items)
+ end
+ end
+ end
+
+ assert_equal(item_size, new_rss.items.size)
+ new_rss.items.each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title)
+ assert_equal("#{link}#{i}", item.link)
+ assert_equal("#{description}#{i}", item.description)
+ assert_equal("#{author}#{i}", item.author)
+ assert_equal("#{comments}#{i}", item.comments)
+ assert_equal(pubDate, item.pubDate)
+
+ assert_equal(guid_isPermaLink == "true", item.guid.isPermaLink)
+ assert_equal(guid_content, item.guid.content)
+
+ assert_equal(enclosure_url, item.enclosure.url)
+ assert_equal(enclosure_length.to_i, item.enclosure.length)
+ assert_equal(enclosure_type, item.enclosure.type)
+
+ assert_equal(source_url, item.source.url)
+ assert_equal(source_content, item.source.content)
+
+ assert_equal(1, item.categories.size)
+ assert_equal(category_domain, item.category.domain)
+ assert_equal(category_content, item.category.content)
+ end
+
+ end
+
+ def test_setup_maker_items_backward_compatibility
+ test_setup_maker_items(true)
+ end
+
+ def test_setup_maker
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ rss = RSS::Maker.make("2.0") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel(maker)
+ end
+
+ new_rss = RSS::Maker.make("2.0") do |maker|
+ rss.setup_maker(maker)
+ end
+
+ assert_equal("2.0", new_rss.rss_version)
+ assert_equal(encoding, new_rss.encoding)
+ assert_equal(standalone, new_rss.standalone)
+
+ xss = rss.xml_stylesheets.first
+ assert_equal(1, rss.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+ end
+
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_atom_entry.rb b/trunk/test/rss/test_setup_maker_atom_entry.rb
new file mode 100644
index 0000000000..6f3df65f3f
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_atom_entry.rb
@@ -0,0 +1,409 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMakerAtomEntry < TestCase
+ def setup
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @dc_elems = {
+ :title => "hoge",
+ :description =>
+ " XML is placing increasingly heavy loads on
+ the existing technical infrastructure of the Internet.",
+ :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
+ :subject => "XML",
+ :publisher => "The O'Reilly Network",
+ :contributor => "hogehoge",
+ :type => "fugafuga",
+ :format => "hohoho",
+ :identifier => "fufufu",
+ :source => "barbar",
+ :language => "ja",
+ :relation => "cococo",
+ :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
+ :date => t,
+ }
+ end
+
+ def test_setup_maker_entry(with_dc=true)
+ authors = [
+ {
+ :name => "Bob",
+ :uri => "http://example.com/~bob/",
+ :email => "bob@example.com",
+ },
+ {
+ :name => "Alice",
+ :uri => "http://example.com/~alice/",
+ :email => "alice@example.com",
+ },
+ ]
+ categories = [
+ {
+ :term => "music",
+ :label => "Music",
+ },
+ {
+ :term => "book",
+ :scheme => "http://example.com/category/book/",
+ :label => "Book",
+ },
+ ]
+ contributors = [
+ {
+ :name => "Chris",
+ :email => "chris@example.com",
+ },
+ {
+ :name => "Eva",
+ :uri => "http://example.com/~eva/",
+ },
+ ]
+ id = "urn:uuid:8b105336-7e20-45fc-bb78-37fb3e1db25a"
+ link = "http://hoge.com"
+ published = Time.now - 60 * 3600
+ rights = "Copyrights (c) 2007 Alice and Bob"
+ description = "fugafugafugafuga"
+ title = "fugafuga"
+ updated = Time.now
+
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ maker.items.new_item do |item|
+ authors.each do |author_info|
+ item.authors.new_author do |author|
+ author_info.each do |key, value|
+ author.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ categories.each do |category_info|
+ item.categories.new_category do |category|
+ category_info.each do |key, value|
+ category.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ contributors.each do |contributor_info|
+ item.contributors.new_contributor do |contributor|
+ contributor_info.each do |key, value|
+ contributor.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ item.id = id
+ item.link = link
+ item.published = published
+ item.rights = rights
+ item.description = description
+ item.title = title
+ item.updated = updated
+
+ if with_dc
+ @dc_elems.each do |var, value|
+ if var == :date
+ item.new_dc_date(value)
+ else
+ item.__send__("dc_#{var}=", value)
+ end
+ end
+ end
+ end
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("atom:entry") do |maker|
+ feed.setup_maker(maker)
+ end
+ assert_not_nil(new_feed)
+
+ new_authors = new_feed.authors.collect do |author|
+ {
+ :name => author.name.content,
+ :uri => author.uri.content,
+ :email => author.email.content,
+ }
+ end
+ assert_equal(authors, new_authors)
+
+ new_categories = new_feed.categories.collect do |category|
+ {
+ :term => category.term,
+ :scheme => category.scheme,
+ :label => category.label,
+ }.reject {|key, value| value.nil?}
+ end
+ assert_equal(categories, new_categories)
+
+ new_contributors = new_feed.contributors.collect do |contributor|
+ info = {}
+ info[:name] = contributor.name.content
+ info[:uri] = contributor.uri.content if contributor.uri
+ info[:email] = contributor.email.content if contributor.email
+ info
+ end
+ assert_equal(contributors, new_contributors)
+
+ assert_equal(id, new_feed.id.content)
+ assert_equal(link, new_feed.link.href)
+ assert_equal(published, new_feed.published.content)
+ assert_equal(rights, new_feed.rights.content)
+ assert_equal(description, new_feed.summary.content)
+ assert_equal(title, new_feed.title.content)
+ assert_equal(updated, new_feed.updated.content)
+
+ if with_dc
+ @dc_elems.each do |var, value|
+ if var == :date
+ assert_equal([updated, value],
+ new_feed.dc_dates.collect {|date| date.value})
+ else
+ assert_equal(value, new_feed.__send__("dc_#{var}"))
+ end
+ end
+ end
+
+ assert_equal(1, new_feed.items.size)
+ end
+
+ def test_setup_maker_entry_without_dc
+ test_setup_maker_entry(false)
+ end
+
+ def test_setup_maker_items(for_backward_compatibility=false)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ updated = Time.now
+
+ item_size = 5
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.updated = updated + i * 60
+ end
+ end
+ end
+
+ new_feed = RSS::Maker.make("atom:entry") do |maker|
+ feed.items.each do |item|
+ if for_backward_compatibility
+ item.setup_maker(maker)
+ else
+ item.setup_maker(maker.items)
+ end
+ end
+
+ feed.items.clear
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(1, new_feed.items.size)
+ new_feed.items[0..1].each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title.content)
+ assert_equal("#{link}#{i}", item.link.href)
+ assert_equal("#{description}#{i}", item.summary.content)
+ assert_equal(updated + i * 60, item.updated.content)
+ end
+ end
+
+ def test_setup_maker_items_sort
+ title = "TITLE"
+ link = "http://hoge.com/"
+ summary = "text hoge fuga"
+ updated = Time.now
+
+ feed_size = 5
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ feed_size.times do |i|
+ entry_class = RSS::Atom::Entry
+ entry = entry_class.new
+ entry.title = entry_class::Title.new(:content => "#{title}#{i}")
+ entry.links << entry_class::Link.new(:href => "#{link}#{i}")
+ entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
+ entry.updated = entry_class::Updated.new(:content => updated + i * 60)
+ entry.setup_maker(maker.items)
+ end
+ maker.items.do_sort = false
+ end
+ assert_equal(1, feed.items.size)
+
+ assert_equal("#{title}0", feed.title.content)
+ assert_equal("#{link}0", feed.link.href)
+ assert_equal("#{summary}0", feed.summary.content)
+
+
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ feed_size.times do |i|
+ entry_class = RSS::Atom::Entry
+ entry = entry_class.new
+ entry.title = entry_class::Title.new(:content => "#{title}#{i}")
+ entry.links << entry_class::Link.new(:href => "#{link}#{i}")
+ entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
+ entry.updated = entry_class::Updated.new(:content => updated + i * 60)
+ entry.setup_maker(maker.items)
+ end
+ maker.items.do_sort = true
+ end
+ assert_equal(1, feed.items.size)
+
+ assert_equal("#{title}#{feed_size - 1}", feed.title.content)
+ assert_equal("#{link}#{feed_size - 1}", feed.link.href)
+ assert_equal("#{summary}#{feed_size - 1}", feed.summary.content)
+ end
+
+ def test_setup_maker_items_backward_compatibility
+ test_setup_maker_items(true)
+ end
+
+ def test_setup_maker
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("atom:entry") do |maker|
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
+ assert_equal(encoding, new_feed.encoding)
+ assert_equal(standalone, new_feed.standalone)
+
+ xss = new_feed.xml_stylesheets.first
+ assert_equal(1, new_feed.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+ end
+
+ def test_setup_maker_full
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ channel_about = "http://hoge.com"
+ channel_title = "fugafuga"
+ channel_link = "http://hoge.com"
+ channel_description = "fugafugafugafuga"
+ channel_author = "Bob"
+
+ image_url = "http://hoge.com/hoge.png"
+
+ item_title = "TITLE"
+ item_link = "http://hoge.com/"
+ item_description = "text hoge fuga"
+
+ entry_size = 5
+ feed = RSS::Maker.make("atom:entry") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ maker.channel.about = channel_about
+ maker.channel.title = channel_title
+ maker.channel.link = channel_link
+ maker.channel.description = channel_description
+ maker.channel.author = channel_author
+ @dc_elems.each do |var, value|
+ maker.channel.__send__("dc_#{var}=", value)
+ end
+
+ maker.image.url = image_url
+
+ entry_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{item_title}#{i}"
+ item.link = "#{item_link}#{i}"
+ item.description = "#{item_description}#{i}"
+
+ @dc_elems.each do |var, value|
+ item.__send__("dc_#{var}=", value)
+ end
+ end
+ end
+ end
+
+ new_feed = RSS::Maker.make("atom:entry") do |maker|
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
+ assert_equal(encoding, new_feed.encoding)
+ assert_equal(standalone, new_feed.standalone)
+
+ xss = new_feed.xml_stylesheets.first
+ assert_equal(1, new_feed.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+
+ assert_equal("#{item_title}0", new_feed.title.content)
+ assert_equal("#{item_link}0", new_feed.link.href)
+ assert_equal("#{item_description}0", new_feed.summary.content)
+ @dc_elems.each do |var, value|
+ assert_equal(value, new_feed.__send__("dc_#{var}"))
+ end
+ assert_equal(1, new_feed.items.size)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_atom_feed.rb b/trunk/test/rss/test_setup_maker_atom_feed.rb
new file mode 100644
index 0000000000..03d33dbb9c
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_atom_feed.rb
@@ -0,0 +1,445 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMakerAtomFeed < TestCase
+ def setup
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @dc_elems = {
+ :title => "hoge",
+ :description =>
+ " XML is placing increasingly heavy loads on
+ the existing technical infrastructure of the Internet.",
+ :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
+ :subject => "XML",
+ :publisher => "The O'Reilly Network",
+ :contributor => "hogehoge",
+ :type => "fugafuga",
+ :format => "hohoho",
+ :identifier => "fufufu",
+ :source => "barbar",
+ :language => "ja",
+ :relation => "cococo",
+ :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
+ :date => t,
+ }
+ end
+
+ def test_setup_maker_feed(with_dc=true)
+ authors = [
+ {
+ :name => "Bob",
+ :uri => "http://example.com/~bob/",
+ :email => "bob@example.com",
+ },
+ {
+ :name => "Alice",
+ :uri => "http://example.com/~alice/",
+ :email => "alice@example.com",
+ },
+ ]
+ categories = [
+ {
+ :term => "music",
+ :label => "Music",
+ },
+ {
+ :term => "book",
+ :scheme => "http://example.com/category/book/",
+ :label => "Book",
+ },
+ ]
+ contributors = [
+ {
+ :name => "Chris",
+ :email => "chris@example.com",
+ },
+ {
+ :name => "Eva",
+ :uri => "http://example.com/~eva/",
+ },
+ ]
+ generator = {
+ :uri => "http://example.com/generator/",
+ :version => "0.0.1",
+ :content => "Feed Generator",
+ }
+ icon = "http://example.com/icon.png"
+ about = "http://hoge.com"
+ title = "fugafuga"
+ link = "http://hoge.com"
+ logo = "http://example.com/logo.png"
+ rights = "Copyrights (c) 2007 Alice and Bob"
+ description = "fugafugafugafuga"
+ updated = Time.now
+
+ feed = RSS::Maker.make("atom") do |maker|
+ authors.each do |author_info|
+ maker.channel.authors.new_author do |author|
+ author_info.each do |key, value|
+ author.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ categories.each do |category_info|
+ maker.channel.categories.new_category do |category|
+ category_info.each do |key, value|
+ category.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ contributors.each do |contributor_info|
+ maker.channel.contributors.new_contributor do |contributor|
+ contributor_info.each do |key, value|
+ contributor.__send__("#{key}=", value)
+ end
+ end
+ end
+
+ generator.each do |key, value|
+ maker.channel.generator do |g|
+ g.__send__("#{key}=", value)
+ end
+ end
+
+ maker.channel.icon = icon
+
+ maker.channel.about = about
+ maker.channel.link = link
+ maker.channel.logo = logo
+ maker.channel.rights = rights
+ maker.channel.title = title
+ maker.channel.description = description
+ maker.channel.updated = updated
+
+ if with_dc
+ @dc_elems.each do |var, value|
+ if var == :date
+ maker.channel.new_dc_date(value)
+ else
+ maker.channel.__send__("dc_#{var}=", value)
+ end
+ end
+ end
+
+ setup_dummy_item_atom(maker)
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("atom") do |maker|
+ feed.setup_maker(maker)
+ end
+ assert_not_nil(new_feed)
+
+ new_authors = new_feed.authors.collect do |author|
+ {
+ :name => author.name.content,
+ :uri => author.uri.content,
+ :email => author.email.content,
+ }
+ end
+ assert_equal(authors, new_authors)
+
+ new_categories = new_feed.categories.collect do |category|
+ {
+ :term => category.term,
+ :scheme => category.scheme,
+ :label => category.label,
+ }.reject {|key, value| value.nil?}
+ end
+ assert_equal(categories, new_categories)
+
+ new_contributors = new_feed.contributors.collect do |contributor|
+ info = {}
+ info[:name] = contributor.name.content
+ info[:uri] = contributor.uri.content if contributor.uri
+ info[:email] = contributor.email.content if contributor.email
+ info
+ end
+ assert_equal(contributors, new_contributors)
+
+ new_generator = {
+ :uri => new_feed.generator.uri,
+ :version => new_feed.generator.version,
+ :content => new_feed.generator.content,
+ }
+ assert_equal(generator, new_generator)
+
+ assert_equal(icon, new_feed.icon.content)
+ assert_equal(about, new_feed.id.content)
+ assert_equal(link, new_feed.link.href)
+ assert_equal(logo, new_feed.logo.content)
+ assert_equal(rights, new_feed.rights.content)
+ assert_equal(description, new_feed.subtitle.content)
+ assert_equal(title, new_feed.title.content)
+ assert_equal(updated, new_feed.updated.content)
+
+ if with_dc
+ @dc_elems.each do |var, value|
+ if var == :date
+ assert_equal([updated, value],
+ new_feed.dc_dates.collect {|date| date.value})
+ else
+ assert_equal(value, new_feed.__send__("dc_#{var}"))
+ end
+ end
+ end
+
+ assert_equal(1, new_feed.items.size)
+ end
+
+ def test_setup_maker_feed_without_dc
+ test_setup_maker_feed(false)
+ end
+
+ def test_setup_maker_items(for_backward_compatibility=false)
+ title = "TITLE"
+ link = "http://hoge.com/"
+ description = "text hoge fuga"
+ updated = Time.now
+
+ item_size = 5
+ feed = RSS::Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ item_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{title}#{i}"
+ item.link = "#{link}#{i}"
+ item.description = "#{description}#{i}"
+ item.updated = updated + i * 60
+ end
+ end
+ end
+
+ new_feed = RSS::Maker.make("atom") do |maker|
+ feed.items.each do |item|
+ if for_backward_compatibility
+ item.setup_maker(maker)
+ else
+ item.setup_maker(maker.items)
+ end
+ end
+
+ feed.items.clear
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(item_size, new_feed.items.size)
+ new_feed.items.each_with_index do |item, i|
+ assert_equal("#{title}#{i}", item.title.content)
+ assert_equal("#{link}#{i}", item.link.href)
+ assert_equal("#{description}#{i}", item.summary.content)
+ assert_equal(updated + i * 60, item.updated.content)
+ end
+ end
+
+ def test_setup_maker_items_sort
+ title = "TITLE"
+ link = "http://hoge.com/"
+ summary = "text hoge fuga"
+ updated = Time.now
+
+ feed_size = 5
+ feed = RSS::Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ feed_size.times do |i|
+ entry_class = RSS::Atom::Feed::Entry
+ entry = entry_class.new
+ entry.title = entry_class::Title.new(:content => "#{title}#{i}")
+ entry.links << entry_class::Link.new(:href => "#{link}#{i}")
+ entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
+ entry.updated = entry_class::Updated.new(:content => updated + i * 60)
+ entry.setup_maker(maker.items)
+ end
+ maker.items.do_sort = false
+ end
+ assert_equal(feed_size, feed.entries.size)
+ feed.entries.each_with_index do |entry, i|
+ assert_equal("#{title}#{i}", entry.title.content)
+ assert_equal("#{link}#{i}", entry.link.href)
+ assert_equal("#{summary}#{i}", entry.summary.content)
+ end
+
+
+ feed = RSS::Maker.make("atom") do |maker|
+ setup_dummy_channel_atom(maker)
+
+ feed_size.times do |i|
+ entry_class = RSS::Atom::Feed::Entry
+ entry = entry_class.new
+ entry.title = entry_class::Title.new(:content => "#{title}#{i}")
+ entry.links << entry_class::Link.new(:href => "#{link}#{i}")
+ entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
+ entry.updated = entry_class::Updated.new(:content => updated + i * 60)
+ entry.setup_maker(maker.items)
+ end
+ maker.items.do_sort = true
+ end
+ assert_equal(feed_size, feed.entries.size)
+ feed.entries.reverse.each_with_index do |entry, i|
+ assert_equal("#{title}#{i}", entry.title.content)
+ assert_equal("#{link}#{i}", entry.link.href)
+ assert_equal("#{summary}#{i}", entry.summary.content)
+ end
+ end
+
+ def test_setup_maker_items_backward_compatibility
+ test_setup_maker_items(true)
+ end
+
+ def test_setup_maker
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ feed = RSS::Maker.make("atom") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ setup_dummy_channel_atom(maker)
+ setup_dummy_item_atom(maker)
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("atom") do |maker|
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
+ assert_equal(encoding, new_feed.encoding)
+ assert_equal(standalone, new_feed.standalone)
+
+ xss = new_feed.xml_stylesheets.first
+ assert_equal(1, new_feed.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+ end
+
+ def test_setup_maker_full
+ encoding = "EUC-JP"
+ standalone = true
+
+ href = 'a.xsl'
+ type = 'text/xsl'
+ title = 'sample'
+ media = 'printer'
+ charset = 'UTF-8'
+ alternate = 'yes'
+
+ channel_about = "http://hoge.com"
+ channel_title = "fugafuga"
+ channel_link = "http://hoge.com"
+ channel_description = "fugafugafugafuga"
+ channel_author = "Bob"
+
+ image_url = "http://hoge.com/hoge.png"
+
+ item_title = "TITLE"
+ item_link = "http://hoge.com/"
+ item_description = "text hoge fuga"
+
+ entry_size = 5
+ feed = RSS::Maker.make("atom") do |maker|
+ maker.encoding = encoding
+ maker.standalone = standalone
+
+ maker.xml_stylesheets.new_xml_stylesheet do |xss|
+ xss.href = href
+ xss.type = type
+ xss.title = title
+ xss.media = media
+ xss.charset = charset
+ xss.alternate = alternate
+ end
+
+ maker.channel.about = channel_about
+ maker.channel.title = channel_title
+ maker.channel.link = channel_link
+ maker.channel.description = channel_description
+ maker.channel.author = channel_author
+ @dc_elems.each do |var, value|
+ maker.channel.__send__("dc_#{var}=", value)
+ end
+
+ maker.image.url = image_url
+
+ entry_size.times do |i|
+ maker.items.new_item do |item|
+ item.title = "#{item_title}#{i}"
+ item.link = "#{item_link}#{i}"
+ item.description = "#{item_description}#{i}"
+
+ @dc_elems.each do |var, value|
+ item.__send__("dc_#{var}=", value)
+ end
+ end
+ end
+ end
+
+ new_feed = RSS::Maker.make("atom") do |maker|
+ feed.setup_maker(maker)
+ end
+
+ assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
+ assert_equal(encoding, new_feed.encoding)
+ assert_equal(standalone, new_feed.standalone)
+
+ xss = new_feed.xml_stylesheets.first
+ assert_equal(1, new_feed.xml_stylesheets.size)
+ assert_equal(href, xss.href)
+ assert_equal(type, xss.type)
+ assert_equal(title, xss.title)
+ assert_equal(media, xss.media)
+ assert_equal(charset, xss.charset)
+ assert_equal(alternate, xss.alternate)
+
+ assert_equal(channel_title, new_feed.title.content)
+ assert_equal(channel_link, new_feed.link.href)
+ assert_equal(channel_description, new_feed.subtitle.content)
+ assert_equal(channel_author, new_feed.author.name.content)
+ assert_equal(image_url, new_feed.logo.content)
+ @dc_elems.each do |var, value|
+ assert_equal(value, new_feed.__send__("dc_#{var}"))
+ end
+
+ assert_equal(entry_size, new_feed.entries.size)
+ new_feed.entries.each_with_index do |entry, i|
+ assert_equal("#{item_title}#{i}", entry.title.content)
+ assert_equal("#{item_link}#{i}", entry.link.href)
+ assert_equal("#{item_description}#{i}", entry.summary.content)
+
+ @dc_elems.each do |var, value|
+ assert_equal(value, entry.__send__("dc_#{var}"))
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_itunes.rb b/trunk/test/rss/test_setup_maker_itunes.rb
new file mode 100644
index 0000000000..1f0372d6e7
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_itunes.rb
@@ -0,0 +1,144 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMakerITunes < TestCase
+ def test_setup_maker_simple
+ author = "John Doe"
+ block = true
+ categories = ["Audio Blogs"]
+ image = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
+ duration = "4:05"
+ duration_components = [0, 4, 5]
+ explicit = true
+ keywords = ["salt", "pepper", "shaker", "exciting"]
+ new_feed_url = "http://newlocation.com/example.rss"
+ owner = {:name => "John Doe", :email => "john.doe@example.com"}
+ subtitle = "A show about everything"
+ summary = "All About Everything is a show about " +
+ "everything. Each week we dive into any " +
+ "subject known to man and talk about it " +
+ "as much as we can. Look for our Podcast " +
+ "in the iTunes Music Store"
+
+ feed = RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ channel = maker.channel
+ channel.itunes_author = author
+ channel.itunes_block = block
+ categories.each do |category|
+ channel.itunes_categories.new_category.text = category
+ end
+ channel.itunes_image = image
+ channel.itunes_explicit = explicit
+ channel.itunes_keywords = keywords
+ channel.itunes_owner.itunes_name = owner[:name]
+ channel.itunes_owner.itunes_email = owner[:email]
+ channel.itunes_subtitle = subtitle
+ channel.itunes_summary = summary
+
+ item = maker.items.last
+ item.itunes_author = author
+ item.itunes_block = block
+ item.itunes_duration = duration
+ item.itunes_explicit = explicit
+ item.itunes_keywords = keywords
+ item.itunes_subtitle = subtitle
+ item.itunes_summary = summary
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("rss2.0") do |maker|
+ feed.setup_maker(maker)
+ end
+ assert_not_nil(new_feed)
+
+ channel = new_feed.channel
+ item = new_feed.items.last
+
+ assert_equal(author, channel.itunes_author)
+ assert_equal(author, item.itunes_author)
+
+ assert_equal(block, channel.itunes_block?)
+ assert_equal(block, item.itunes_block?)
+
+ assert_equal(categories,
+ collect_itunes_categories(channel.itunes_categories))
+
+ assert_equal(image, channel.itunes_image.href)
+
+ assert_equal(duration_components,
+ [item.itunes_duration.hour,
+ item.itunes_duration.minute,
+ item.itunes_duration.second])
+
+ assert_equal(explicit, channel.itunes_explicit?)
+ assert_equal(explicit, item.itunes_explicit?)
+
+ assert_equal(keywords, channel.itunes_keywords)
+ assert_equal(keywords, item.itunes_keywords)
+
+ assert_equal(owner,
+ {
+ :name => channel.itunes_owner.itunes_name,
+ :email => channel.itunes_owner.itunes_email
+ })
+
+ assert_equal(subtitle, channel.itunes_subtitle)
+ assert_equal(subtitle, item.itunes_subtitle)
+
+ assert_equal(summary, channel.itunes_summary)
+ assert_equal(summary, item.itunes_summary)
+ end
+
+ def test_setup_maker_with_nested_categories
+ categories = [["Arts & Entertainment", "Games"],
+ ["Technology", "Computers"],
+ "Audio Blogs"]
+
+ feed = RSS::Maker.make("rss2.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ channel = maker.channel
+ categories.each do |category|
+ target = channel.itunes_categories
+ if category.is_a?(Array)
+ category.each do |sub_category|
+ target = target.new_category
+ target.text = sub_category
+ end
+ else
+ target.new_category.text = category
+ end
+ end
+ end
+ assert_not_nil(feed)
+
+ new_feed = RSS::Maker.make("rss2.0") do |maker|
+ feed.setup_maker(maker)
+ end
+ assert_not_nil(new_feed)
+
+ channel = new_feed.channel
+
+ assert_equal(categories,
+ collect_itunes_categories(channel.itunes_categories))
+ end
+
+ private
+ def collect_itunes_categories(categories)
+ categories.collect do |c|
+ rest = collect_itunes_categories(c.itunes_categories)
+ if rest.empty?
+ c.text
+ else
+ [c.text, *rest]
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_setup_maker_slash.rb b/trunk/test/rss/test_setup_maker_slash.rb
new file mode 100644
index 0000000000..07fa5bb342
--- /dev/null
+++ b/trunk/test/rss/test_setup_maker_slash.rb
@@ -0,0 +1,38 @@
+require "rss-testcase"
+
+require "rss/maker"
+
+module RSS
+ class TestSetupMakerSlash < TestCase
+ def test_setup_maker
+ elements = {
+ "section" => "articles",
+ "department" => "not-an-ocean-unless-there-are-lobsters",
+ "comments" => 177,
+ "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
+ }
+
+ rss = RSS::Maker.make("rss1.0") do |maker|
+ setup_dummy_channel(maker)
+ setup_dummy_item(maker)
+
+ item = maker.items.last
+ item.slash_section = elements["section"]
+ item.slash_department = elements["department"]
+ item.slash_comments = elements["comments"]
+ item.slash_hit_parade = elements["hit_parades"].join(",")
+ end
+ assert_not_nil(rss)
+
+ new_rss = RSS::Maker.make("rss1.0") do |maker|
+ rss.setup_maker(maker)
+ end
+ assert_not_nil(new_rss)
+
+ item = new_rss.items.last
+ assert_not_nil(item)
+
+ assert_slash_elements(elements, item)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_slash.rb b/trunk/test/rss/test_slash.rb
new file mode 100644
index 0000000000..aec0a868f5
--- /dev/null
+++ b/trunk/test/rss/test_slash.rb
@@ -0,0 +1,64 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/slash"
+
+module RSS
+ class TestSlash < TestCase
+ def setup
+ @elements = {
+ "section" => "articles",
+ "department" => "not-an-ocean-unless-there-are-lobsters",
+ "comments" => 177,
+ "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
+ }
+
+ slash_nodes = @elements.collect do |name, value|
+ if name == "hit_parades"
+ name = "hit_parade"
+ value = value.join(",")
+ end
+ "<slash:#{name}>#{value}</slash:#{name}>"
+ end.join("\n")
+
+ slash_ns = {"slash" => "http://purl.org/rss/1.0/modules/slash/"}
+ @source = make_RDF(<<-EOR, slash_ns)
+#{make_channel}
+#{make_image}
+#{make_item(slash_nodes)}
+#{make_textinput}
+EOR
+ end
+
+ def test_parser
+ rss = RSS::Parser.parse(@source)
+
+ assert_not_nil(rss)
+
+ item = rss.items[0]
+ assert_not_nil(item)
+
+ assert_slash_elements(item)
+ end
+
+ def test_to_s
+ rss = RSS::Parser.parse(@source)
+ rss = RSS::Parser.parse(rss.to_s)
+
+ assert_not_nil(rss)
+
+ item = rss.items[0]
+ assert_not_nil(item)
+
+ assert_slash_elements(item)
+ end
+
+ private
+ def assert_slash_elements(target)
+ super(@elements, target)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_syndication.rb b/trunk/test/rss/test_syndication.rb
new file mode 100644
index 0000000000..abd75e905e
--- /dev/null
+++ b/trunk/test/rss/test_syndication.rb
@@ -0,0 +1,125 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/syndication"
+
+module RSS
+ class TestSyndication < TestCase
+
+ def setup
+ @prefix = "sy"
+ @uri = "http://purl.org/rss/1.0/modules/syndication/"
+
+ @parents = %w(channel)
+
+ t = Time.iso8601("2000-01-01T12:00:05+00:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ @elems = {
+ :updatePeriod => "hourly",
+ :updateFrequency => "2",
+ :updateBase => t,
+ }
+
+ @sy_nodes = @elems.collect do |name, value|
+ "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
+ end.join("\n")
+
+ @rss_source = make_RDF(<<-EOR, {@prefix => @uri})
+#{make_channel(@sy_nodes)}
+#{make_image()}
+#{make_item()}
+#{make_textinput()}
+EOR
+
+ @rss = Parser.parse(@rss_source)
+ end
+
+ def test_parser
+
+ assert_nothing_raised do
+ Parser.parse(@rss_source)
+ end
+
+ @elems.each do |tag, value|
+ assert_too_much_tag(tag.to_s, "channel") do
+ Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
+#{make_channel(("<" + @prefix + ":" + tag.to_s + ">" +
+ CGI.escapeHTML(value.to_s) +
+ "</" + @prefix + ":" + tag.to_s + ">") * 2)}
+#{make_item}
+EOR
+ end
+ end
+
+ end
+
+ def test_accessor
+
+ t = Time.iso8601("2003-01-01T12:00:23+09:00")
+ class << t
+ alias_method(:to_s, :iso8601)
+ end
+
+ new_value = {
+ :updatePeriod => "daily",
+ :updateFrequency => "11",
+ :updateBase => t,
+ }
+
+ @elems.each do |name, value|
+ value = value.to_i if name == :updateFrequency
+ @parents.each do |parent|
+ assert_equal(value, @rss.__send__(parent).__send__("sy_#{name}"))
+ @rss.__send__(parent).__send__("sy_#{name}=", new_value[name])
+ new_val = new_value[name]
+ new_val = new_val.to_i if name == :updateFrequency
+ assert_equal(new_val, @rss.__send__(parent).__send__("sy_#{name}"))
+ end
+ end
+
+ %w(hourly daily weekly monthly yearly).each do |x|
+ @parents.each do |parent|
+ assert_nothing_raised do
+ @rss.__send__(parent).sy_updatePeriod = x
+ end
+ end
+ end
+
+ %w(-2 0.3 -0.4).each do |x|
+ @parents.each do |parent|
+ assert_not_available_value("sy:updateBase", x) do
+ @rss.__send__(parent).sy_updateBase = x
+ end
+ end
+ end
+
+ end
+
+ def test_to_s
+
+ @elems.each do |name, value|
+ excepted = "<#{@prefix}:#{name}>#{value}</#{@prefix}:#{name}>"
+ @parents.each do |parent|
+ assert_equal(excepted,
+ @rss.__send__(parent).__send__("sy_#{name}_element"))
+ end
+ end
+
+ REXML::Document.new(@rss_source).root.each_element do |parent|
+ if @parents.include?(parent.name)
+ parent.each_element do |elem|
+ if elem.namespace == @uri
+ assert_equal(elem.text, @elems[elem.name.intern].to_s)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_taxonomy.rb b/trunk/test/rss/test_taxonomy.rb
new file mode 100644
index 0000000000..5109f3d892
--- /dev/null
+++ b/trunk/test/rss/test_taxonomy.rb
@@ -0,0 +1,172 @@
+require "cgi"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/2.0"
+require "rss/taxonomy"
+
+module RSS
+ class TestTaxonomy < TestCase
+
+ def setup
+ @prefix = "taxo"
+ @uri = "http://purl.org/rss/1.0/modules/taxonomy/"
+ @dc_prefix = "dc"
+ @dc_uri = "http://purl.org/dc/elements/1.1/"
+
+ @ns = {
+ @prefix => @uri,
+ @dc_prefix => @dc_uri,
+ }
+
+ @topics_parents = %w(channel item)
+
+ @topics_lis = [
+ "http://meerkat.oreillynet.com/?c=cat23",
+ "http://meerkat.oreillynet.com/?c=47",
+ "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
+ ]
+
+ @topics_node = "<#{@prefix}:topics>\n"
+ @topics_node << " <rdf:Bag>\n"
+ @topics_lis.each do |value|
+ resource = CGI.escapeHTML(value)
+ @topics_node << " <rdf:li resource=\"#{resource}\"/>\n"
+ end
+ @topics_node << " </rdf:Bag>\n"
+ @topics_node << "</#{@prefix}:topics>"
+
+ @topic_topics_lis = \
+ [
+ "http://meerkat.oreillynet.com/?c=cat23",
+ "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
+ "http://dmoz.org/Computers/Programming/Internet/",
+ ]
+
+ @topic_contents = \
+ [
+ {
+ :link => "http://meerkat.oreillynet.com/?c=cat23",
+ :title => "Data: XML",
+ :description => "A Meerkat channel",
+ },
+ {
+ :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
+ :title => "XML",
+ :subject => "XML",
+ :description => "DMOZ category",
+ :topics => @topic_topics_lis,
+ }
+ ]
+
+ @topic_nodes = @topic_contents.collect do |info|
+ link = info[:link]
+ rv = "<#{@prefix}:topic rdf:about=\"#{link}\">\n"
+ info.each do |name, value|
+ case name
+ when :topics
+ rv << " <#{@prefix}:topics>\n"
+ rv << " <rdf:Bag>\n"
+ value.each do |li|
+ resource = CGI.escapeHTML(li)
+ rv << " <rdf:li resource=\"#{resource}\"/>\n"
+ end
+ rv << " </rdf:Bag>\n"
+ rv << " </#{@prefix}:topics>\n"
+ else
+ prefix = (name == :link ? @prefix : @dc_prefix)
+ rv << " <#{prefix}:#{name}>#{value}</#{prefix}:#{name}>\n"
+ end
+ end
+ rv << "</#{@prefix}:topic>"
+ end
+
+ @rss_source = make_RDF(<<-EOR, @ns)
+#{make_channel(@topics_node)}
+#{make_image()}
+#{make_item(@topics_node)}
+#{make_textinput()}
+#{@topic_nodes.join("\n")}
+EOR
+
+ @rss = Parser.parse(@rss_source)
+ end
+
+ def test_parser
+ assert_nothing_raised do
+ Parser.parse(@rss_source)
+ end
+
+ assert_too_much_tag("topics", "channel") do
+ Parser.parse(make_RDF(<<-EOR, @ns))
+#{make_channel(@topics_node * 2)}
+#{make_item()}
+EOR
+ end
+
+ assert_too_much_tag("topics", "item") do
+ Parser.parse(make_RDF(<<-EOR, @ns))
+#{make_channel()}
+#{make_item(@topics_node * 2)}
+EOR
+ end
+ end
+
+ def test_accessor
+ topics = @rss.channel.taxo_topics
+ assert_equal(@topics_lis.sort,
+ topics.Bag.lis.collect {|li| li.resource}.sort)
+ assert_equal(@topics_lis.sort, topics.resources.sort)
+
+ assert_equal(@rss.taxo_topics.first, @rss.taxo_topic)
+
+ @topic_contents.each_with_index do |info, i|
+ topic = @rss.taxo_topics[i]
+ info.each do |name, value|
+ case name
+ when :link
+ assert_equal(value, topic.about)
+ assert_equal(value, topic.taxo_link)
+ when :topics
+ assert_equal(value.sort, topic.taxo_topics.resources.sort)
+ else
+ assert_equal(value, topic.__send__("dc_#{name}"))
+ end
+ end
+ end
+ end
+
+ def test_to_s
+ @topics_parents.each do |parent|
+ meth = "taxo_topics_element"
+ assert_equal(@topics_node, @rss.__send__(parent).__send__(meth))
+ end
+
+ @topic_nodes.each_with_index do |node, i|
+ expected_xml = taxo_xmlns_container(node)
+ expected = REXML::Document.new(expected_xml).root.elements[1]
+ actual_xml = taxo_xmlns_container(@rss.taxo_topics[i].to_s(true, ""))
+ actual = REXML::Document.new(actual_xml).root.elements[1]
+ expected_elems = expected.reject {|x| x.is_a?(REXML::Text)}
+ actual_elems = actual.reject {|x| x.is_a?(REXML::Text)}
+ expected_elems.sort! {|x, y| x.name <=> y.name}
+ actual_elems.sort! {|x, y| x.name <=> y.name}
+ assert_equal(expected_elems.collect {|x| x.to_s},
+ actual_elems.collect {|x| x.to_s})
+ assert_equal(expected.attributes.sort, actual.attributes.sort)
+ end
+ end
+
+ private
+ def taxo_xmlns_container(content)
+ xmlns_container({
+ @prefix => @uri,
+ "dc" => "http://purl.org/dc/elements/1.1/",
+ "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ },
+ content)
+ end
+ end
+end
+
diff --git a/trunk/test/rss/test_to_s.rb b/trunk/test/rss/test_to_s.rb
new file mode 100644
index 0000000000..66739591ea
--- /dev/null
+++ b/trunk/test/rss/test_to_s.rb
@@ -0,0 +1,670 @@
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/maker"
+require "rss/1.0"
+require "rss/2.0"
+require "rss/content"
+require "rss/dublincore"
+require "rss/syndication"
+require "rss/trackback"
+
+module RSS
+ class TestToS < TestCase
+ def setup
+ @image_url = "http://example.com/foo.png"
+ @textinput_link = "http://example.com/search.cgi"
+ @item_links = [
+ "http://example.com/1",
+ "http://example.com/2",
+ ]
+
+ setup_xml_declaration_info
+ setup_xml_stylesheet_infos
+ setup_channel_info
+ setup_item_infos
+ setup_image_info
+ setup_textinput_info
+
+ setup_dublin_core_info
+ setup_syndication_info
+ setup_content_info
+ setup_trackback_info
+ end
+
+ def test_to_s_10
+ rss = RSS::Maker.make("1.0") do |maker|
+ setup_full(maker)
+ end
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel10(@channel_info, rss.channel)
+ assert_items10(@item_infos, rss.items)
+ rss.items.each do |item|
+ assert_trackback(@trackback_info, item)
+ end
+ assert_image10(@image_info, rss.image)
+ assert_textinput10(@textinput_info, rss.textinput)
+
+ rss = RSS::Parser.parse(rss.to_s)
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel10(@channel_info, rss.channel)
+ assert_items10(@item_infos, rss.items)
+ assert_image10(@image_info, rss.image)
+ assert_textinput10(@textinput_info, rss.textinput)
+ end
+
+ def test_to_s_09
+ rss = RSS::Maker.make("0.91") do |maker|
+ setup_full(maker)
+ end
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel09(@channel_info, rss.channel)
+ assert_items09(@item_infos, rss.items)
+ assert_image09(@image_info, rss.image)
+ assert_textinput09(@textinput_info, rss.textinput)
+
+ rss = RSS::Parser.parse(rss.to_s)
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel09(@channel_info, rss.channel)
+ assert_items09(@item_infos, rss.items)
+ assert_image09(@image_info, rss.image)
+ assert_textinput09(@textinput_info, rss.textinput)
+ end
+
+ def test_to_s_20
+ rss = RSS::Maker.make("2.0") do |maker|
+ setup_full(maker)
+ end
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel20(@channel_info, rss.channel)
+ assert_items20(@item_infos, rss.items)
+ assert_image20(@image_info, rss.image)
+ assert_textinput20(@textinput_info, rss.textinput)
+
+ rss = RSS::Parser.parse(rss.to_s)
+
+ assert_xml_declaration(@version, @encoding, @standalone, rss)
+ assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
+ assert_channel20(@channel_info, rss.channel)
+ assert_items20(@item_infos, rss.items)
+ assert_image20(@image_info, rss.image)
+ assert_textinput20(@textinput_info, rss.textinput)
+ end
+
+ private
+ def setup_xml_declaration_info
+ @version = "1.0"
+ @encoding = "UTF-8"
+ @standalone = false
+ end
+
+ def setup_xml_stylesheet_infos
+ @xs_infos = [
+ {
+ "href" => "XXX.xsl",
+ "type" => "text/xsl",
+ "title" => "XXX",
+ "media" => "print",
+ "alternate" => "no",
+ },
+ {
+ "href" => "YYY.css",
+ "type" => "text/css",
+ "title" => "YYY",
+ "media" => "all",
+ "alternate" => "no",
+ },
+ ]
+ end
+
+ def setup_channel_info
+ @channel_info = {
+ "about" => "http://example.com/index.rdf",
+ "title" => "Sample RSS",
+ "link" => "http://example.com/",
+ "description" => "Sample\n\n\n\n\nSite",
+ "language" => "en",
+ "copyright" => "FDL",
+ "managingEditor" => "foo@example.com",
+ "webMaster" => "webmaster@example.com",
+ "rating" => '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))',
+ "docs" => "http://backend.userland.com/rss091",
+ "skipDays" => [
+ "Monday",
+ "Friday",
+ ],
+ "skipHours" => [
+ "12",
+ "23",
+ ],
+ "date" => Time.now,
+ "lastBuildDate" => Time.now - 3600,
+ "generator" => "RSS Maker",
+ "ttl" => "60",
+ "cloud" => {
+ "domain" => "rpc.sys.com",
+ "port" => "80",
+ "path" => "/RPC2",
+ "registerProcedure" => "myCloud.rssPleaseNotify",
+ "protocol" => "xml-rpc",
+ },
+ "category" => {
+ "domain" => "http://example.com/misc/",
+ "content" => "misc",
+ },
+
+ "image" => {
+ "resource" => @image_url,
+ },
+
+ "textinput" => {
+ "resource" => @textinput_link,
+ },
+
+ "items" => @item_links.collect{|link| {"resource" => link}},
+ }
+ end
+
+ def setup_item_infos
+ @item_infos = [
+ {
+ "title" => "Sample item1",
+ "link" => @item_links[0],
+ "description" => "Sample description1",
+ "date" => Time.now - 3600,
+ "author" => "foo@example.com",
+ "comments" => "http://example.com/1/comments",
+ "guid" => {
+ "isPermaLink" => "true",
+ "content" => "http://example.com/1",
+ },
+ "enclosure" => {
+ "url" => "http://example.com/1.mp3",
+ "length" => "100",
+ "type" => "audio/mpeg",
+ },
+ "source" => {
+ "url" => "http:/example.com/",
+ "content" => "Sample site",
+ },
+ "category" => {
+ "domain" => "http://example.com/misc/",
+ "content" => "misc",
+ },
+ },
+
+ {
+ "title" => "Sample item2",
+ "link" => @item_links[1],
+ "description" => "Sample description2",
+ "date" => Time.now - 7200,
+ "author" => "foo@example.com",
+ "comments" => "http://example.com/2/comments",
+ "guid" => {
+ "isPermaLink" => "false",
+ "content" => "http://example.com/2",
+ },
+ "enclosure" => {
+ "url" => "http://example.com/2.mp3",
+ "length" => "200",
+ "type" => "audio/mpeg",
+ },
+ "source" => {
+ "url" => "http:/example.com/",
+ "content" => "Sample site",
+ },
+ "category" => {
+ "domain" => "http://example.com/misc/",
+ "content" => "misc",
+ },
+ },
+ ]
+ end
+
+ def setup_image_info
+ @image_info = {
+ "title" => "Sample image",
+ "url" => @image_url,
+ "width" => "88",
+ "height" => "31",
+ "description" => "Sample",
+ }
+ end
+
+ def setup_textinput_info
+ @textinput_info = {
+ "title" => "Sample textinput",
+ "description" => "Search",
+ "name" => "key",
+ "link" => @textinput_link,
+ }
+ end
+
+ def setup_dublin_core_info
+ @dc_info = {
+ "title" => "DC title",
+ "description" => "DC desc",
+ "creator" => "DC creator",
+ "subject" => "DC subject",
+ "publisher" => "DC publisher",
+ "contributor" => "DC contributor",
+ "type" => "DC type",
+ "format" => "DC format",
+ "identifier" => "DC identifier",
+ "source" => "DC source",
+ "language" => "ja",
+ "relation" => "DC relation",
+ "coverage" => "DC coverage",
+ "rights" => "DC rights",
+ "date" => Time.now - 60,
+ }
+ end
+
+ def setup_syndication_info
+ @sy_info = {
+ "updatePeriod" => "hourly",
+ "updateFrequency" => "2",
+ "updateBase" => Time.now - 3600,
+ }
+ end
+
+ def setup_content_info
+ @content_info = {
+ "encoded" => "<p>p</p>",
+ }
+ end
+
+ def setup_trackback_info
+ @trackback_info = {
+ "ping" => "http://example.com/tb.cgi?tb_id=XXX",
+ "abouts" => [
+ "http://example.net/tb.cgi?tb_id=YYY",
+ "http://example.org/tb.cgi?tb_id=ZZZ",
+ ]
+ }
+ end
+
+
+ def setup_full(maker)
+ setup_xml_declaration(maker)
+ setup_xml_stylesheets(maker)
+ setup_channel(maker)
+ setup_image(maker)
+ setup_items(maker)
+ setup_textinput(maker)
+ end
+
+ def setup_xml_declaration(maker)
+ %w(version encoding standalone).each do |name|
+ maker.__send__("#{name}=", instance_eval("@#{name}"))
+ end
+ end
+
+ def setup_xml_stylesheets(maker)
+ @xs_infos.each do |info|
+ xs = maker.xml_stylesheets.new_xml_stylesheet
+ info.each do |name, value|
+ xs.__send__("#{name}=", value)
+ end
+ end
+ end
+
+ def setup_channel(maker)
+ channel = maker.channel
+ info = @channel_info
+
+ %w(about title link description language copyright
+ managingEditor webMaster rating docs date
+ lastBuildDate generator ttl).each do |name|
+ channel.__send__("#{name}=", info[name])
+ end
+
+ skipDays = channel.skipDays
+ info["skipDays"].each do |day|
+ new_day = skipDays.new_day
+ new_day.content = day
+ end
+
+ skipHours = channel.skipHours
+ info["skipHours"].each do |hour|
+ new_hour = skipHours.new_hour
+ new_hour.content = hour
+ end
+
+ cloud = channel.cloud
+ %w(domain port path registerProcedure protocol).each do |name|
+ cloud.__send__("#{name}=", info["cloud"][name])
+ end
+
+ category = channel.categories.new_category
+ %w(domain content).each do |name|
+ category.__send__("#{name}=", info["category"][name])
+ end
+ end
+
+ def setup_image(maker)
+ image = maker.image
+ info = @image_info
+
+ %w(title url width height description).each do |name|
+ image.__send__("#{name}=", info[name])
+ end
+ end
+
+ def setup_items(maker)
+ items = maker.items
+
+ @item_infos.each do |info|
+ item = items.new_item
+ %w(title link description date author comments).each do |name|
+ item.__send__("#{name}=", info[name])
+ end
+
+ guid = item.guid
+ %w(isPermaLink content).each do |name|
+ guid.__send__("#{name}=", info["guid"][name])
+ end
+
+ enclosure = item.enclosure
+ %w(url length type).each do |name|
+ enclosure.__send__("#{name}=", info["enclosure"][name])
+ end
+
+ source = item.source
+ %w(url content).each do |name|
+ source.__send__("#{name}=", info["source"][name])
+ end
+
+ category = item.categories.new_category
+ %w(domain content).each do |name|
+ category.__send__("#{name}=", info["category"][name])
+ end
+
+ setup_trackback(item)
+ end
+ end
+
+ def setup_textinput(maker)
+ textinput = maker.textinput
+ info = @textinput_info
+
+ %w(title description name link).each do |name|
+ textinput.__send__("#{name}=", info[name])
+ end
+ end
+
+ def setup_content(target)
+ prefix = "content"
+ %w(encoded).each do |name|
+ target.__send__("#{prefix}_#{name}=", @content_info[name])
+ end
+ end
+
+ def setup_dublin_core(target)
+ prefix = "dc"
+ %w(title description creator subject publisher
+ contributor type format identifier source language
+ relation coverage rights).each do |name|
+ target.__send__("#{prefix}_#{name}=", @dc_info[name])
+ end
+ end
+
+ def setup_syndicate(target)
+ prefix = "sy"
+ %w(updatePeriod updateFrequency updateBase).each do |name|
+ target.__send__("#{prefix}_#{name}=", @sy_info[name])
+ end
+ end
+
+ def setup_trackback(target)
+ target.trackback_ping = @trackback_info["ping"]
+ @trackback_info["abouts"].each do |about|
+ new_about = target.trackback_abouts.new_about
+ new_about.value = about
+ end
+ end
+
+
+ def assert_channel10(attrs, channel)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+
+ names = %w(about title link description)
+ assert_attributes(attrs, names, channel)
+
+ %w(image items textinput).each do |name|
+ value = n_attrs[name]
+ if value
+ target = channel.__send__(name)
+ __send__("assert_channel10_#{name}", value, target)
+ end
+ end
+ end
+ end
+
+ def assert_channel10_image(attrs, image)
+ _wrap_assertion do
+ assert_attributes(attrs, %w(resource), image)
+ end
+ end
+
+ def assert_channel10_textinput(attrs, textinput)
+ _wrap_assertion do
+ assert_attributes(attrs, %w(resource), textinput)
+ end
+ end
+
+ def assert_channel10_items(attrs, items)
+ _wrap_assertion do
+ assert_equal(items.resources, items.Seq.lis.collect {|x| x.resource})
+ items.Seq.lis.each_with_index do |li, i|
+ assert_attributes(attrs[i], %w(resource), li)
+ end
+ end
+ end
+
+ def assert_image10(attrs, image)
+ _wrap_assertion do
+ names = %w(about title url link)
+ assert_attributes(attrs, names, image)
+ end
+ end
+
+ def assert_items10(attrs, items)
+ _wrap_assertion do
+ names = %w(about title link description)
+ items.each_with_index do |item, i|
+ assert_attributes(attrs[i], names, item)
+ end
+ end
+ end
+
+ def assert_textinput10(attrs, textinput)
+ _wrap_assertion do
+ names = %w(about title description name link)
+ assert_attributes(attrs, names, textinput)
+ end
+ end
+
+
+ def assert_channel09(attrs, channel)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+
+ names = %w(title description link language rating
+ copyright pubDate lastBuildDate docs
+ managingEditor webMaster)
+ assert_attributes(attrs, names, channel)
+
+ %w(skipHours skipDays).each do |name|
+ value = n_attrs[name]
+ if value
+ target = channel.__send__(name)
+ __send__("assert_channel09_#{name}", value, target)
+ end
+ end
+ end
+ end
+
+ def assert_channel09_skipDays(contents, skipDays)
+ _wrap_assertion do
+ days = skipDays.days
+ contents.each_with_index do |content, i|
+ assert_equal(content, days[i].content)
+ end
+ end
+ end
+
+ def assert_channel09_skipHours(contents, skipHours)
+ _wrap_assertion do
+ hours = skipHours.hours
+ contents.each_with_index do |content, i|
+ assert_equal(content.to_i, hours[i].content)
+ end
+ end
+ end
+
+ def assert_image09(attrs, image)
+ _wrap_assertion do
+ names = %w(url link title description)
+ names << ["width", :integer]
+ names << ["height", :integer]
+ assert_attributes(attrs, names, image)
+ end
+ end
+
+ def assert_items09(attrs, items)
+ _wrap_assertion do
+ names = %w(title link description)
+ items.each_with_index do |item, i|
+ assert_attributes(attrs[i], names, item)
+ end
+ end
+ end
+
+ def assert_textinput09(attrs, textinput)
+ _wrap_assertion do
+ names = %w(title description name link)
+ assert_attributes(attrs, names, textinput)
+ end
+ end
+
+
+ def assert_channel20(attrs, channel)
+ _wrap_assertion do
+ n_attrs = normalized_attrs(attrs)
+
+ names = %w(title link description language copyright
+ managingEditor webMaster pubDate
+ lastBuildDate generator docs rating)
+ names << ["ttl", :integer]
+ assert_attributes(attrs, names, channel)
+
+ %w(cloud categories skipHours skipDays).each do |name|
+ value = n_attrs[name]
+ if value
+ target = channel.__send__(name)
+ __send__("assert_channel20_#{name}", value, target)
+ end
+ end
+ end
+ end
+
+ def assert_channel20_skipDays(contents, skipDays)
+ assert_channel09_skipDays(contents, skipDays)
+ end
+
+ def assert_channel20_skipHours(contents, skipHours)
+ assert_channel09_skipHours(contents, skipHours)
+ end
+
+ def assert_channel20_cloud(attrs, cloud)
+ _wrap_assertion do
+ names = %w(domain path registerProcedure protocol)
+ names << ["port", :integer]
+ assert_attributes(attrs, names, cloud)
+ end
+ end
+
+ def assert_channel20_categories(attrs, categories)
+ _wrap_assertion do
+ names = %w(domain content)
+ categories.each_with_index do |category, i|
+ assert_attributes(attrs[i], names, category)
+ end
+ end
+ end
+
+ def assert_image20(attrs, image)
+ _wrap_assertion do
+ names = %w(url link title description)
+ names << ["width", :integer]
+ names << ["height", :integer]
+ assert_attributes(attrs, names, image)
+ end
+ end
+
+ def assert_items20(attrs, items)
+ _wrap_assertion do
+ names = %w(about title link description)
+ items.each_with_index do |item, i|
+ assert_attributes(attrs[i], names, item)
+
+ n_attrs = normalized_attrs(attrs[i])
+
+ %w(source enclosure categories guid).each do |name|
+ value = n_attrs[name]
+ if value
+ target = item.__send__(name)
+ __send__("assert_items20_#{name}", value, target)
+ end
+ end
+ end
+ end
+ end
+
+ def assert_items20_source(attrs, source)
+ _wrap_assertion do
+ assert_attributes(attrs, %w(url content), source)
+ end
+ end
+
+ def assert_items20_enclosure(attrs, enclosure)
+ _wrap_assertion do
+ names = ["url", ["length", :integer], "type"]
+ assert_attributes(attrs, names, enclosure)
+ end
+ end
+
+ def assert_items20_categories(attrs, categories)
+ _wrap_assertion do
+ assert_channel20_categories(attrs, categories)
+ end
+ end
+
+ def assert_items20_guid(attrs, guid)
+ _wrap_assertion do
+ names = [["isPermaLink", :boolean], ["content"]]
+ assert_attributes(attrs, names, guid)
+ end
+ end
+
+ def assert_textinput20(attrs, textinput)
+ _wrap_assertion do
+ names = %w(title description name link)
+ assert_attributes(attrs, names, textinput)
+ end
+ end
+ end
+end
diff --git a/trunk/test/rss/test_trackback.rb b/trunk/test/rss/test_trackback.rb
new file mode 100644
index 0000000000..26812d9010
--- /dev/null
+++ b/trunk/test/rss/test_trackback.rb
@@ -0,0 +1,135 @@
+require "cgi"
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/2.0"
+require "rss/trackback"
+
+module RSS
+ class TestTrackBack < TestCase
+
+ def setup
+ @prefix = "trackback"
+ @uri = "http://madskills.com/public/xml/rss/module/trackback/"
+
+ @parents = %w(item)
+
+ @elems = {
+ :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
+ :about => "http://foo.com/trackback/tb.cgi?tb_id=20020923",
+ }
+
+ @content_nodes = @elems.collect do |name, value|
+ "<#{@prefix}:#{name} rdf:resource=\"#{CGI.escapeHTML(value.to_s)}\"/>"
+ end.join("\n")
+
+ @content_nodes2 = @elems.collect do |name, value|
+ "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
+ end.join("\n")
+
+ @rss_source = make_RDF(<<-EOR, {@prefix => @uri})
+#{make_channel()}
+#{make_image()}
+#{make_item(@content_nodes)}
+#{make_textinput()}
+EOR
+
+ @rss = Parser.parse(@rss_source)
+
+ @rss20_source = make_rss20(nil, {@prefix => @uri}) do
+ make_channel20(nil) do
+ make_item20(@content_nodes2)
+ end
+ end
+
+ @rss20 = Parser.parse(@rss20_source, false)
+ end
+
+ def test_parser
+
+ assert_nothing_raised do
+ Parser.parse(@rss_source)
+ end
+
+ @elems.find_all{|k, v| k == :ping}.each do |tag, value|
+ assert_too_much_tag(tag.to_s, "item") do
+ Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
+#{make_channel()}
+#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" +
+ CGI.escapeHTML(value.to_s) +
+ "\"/>") * 2)}
+EOR
+ end
+ end
+
+ @elems.find_all{|k, v| k == :about}.each do |tag, value|
+ assert_missing_tag("trackback:ping", "item") do
+ Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
+#{make_channel()}
+#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" +
+ CGI.escapeHTML(value.to_s) +
+ "\"/>") * 2)}
+EOR
+ end
+
+ end
+
+ end
+
+ def test_accessor
+
+ new_value = {
+ :ping => "http://baz.com/trackback/tb.cgi?tb_id=20030808",
+ :about => "http://hoge.com/trackback/tb.cgi?tb_id=90030808",
+ }
+
+ @elems.each do |name, value|
+ @parents.each do |parent|
+ accessor = "#{RSS::TRACKBACK_PREFIX}_#{name}"
+ target = @rss.__send__(parent)
+ target20 = @rss20.channel.__send__(parent, -1)
+ assert_equal(value, target.__send__(accessor))
+ assert_equal(value, target20.__send__(accessor))
+ if name == :about
+ # abount is zero or more
+ target.__send__("#{accessor}=", 0, new_value[name].to_s)
+ target20.__send__("#{accessor}=", 0, new_value[name].to_s)
+ else
+ target.__send__("#{accessor}=", new_value[name].to_s)
+ target20.__send__("#{accessor}=", new_value[name].to_s)
+ end
+ assert_equal(new_value[name], target.__send__(accessor))
+ assert_equal(new_value[name], target20.__send__(accessor))
+ end
+ end
+
+ end
+
+ def test_to_s
+
+ @elems.each do |name, value|
+ excepted = %Q!<#{@prefix}:#{name} rdf:resource="#{CGI.escapeHTML(value)}"/>!
+ @parents.each do |parent|
+ meth = "#{RSS::TRACKBACK_PREFIX}_#{name}_element"
+ meth << "s" if name == :about
+ assert_equal(excepted, @rss.__send__(parent).__send__(meth))
+ end
+ end
+
+ REXML::Document.new(@rss_source).root.each_element do |parent|
+ if @parents.include?(parent.name)
+ parent.each_element do |elem|
+ if elem.namespace == @uri
+ assert_equal(elem.attributes["resource"], @elems[elem.name.intern])
+ end
+ end
+ end
+ end
+
+ end
+
+ end
+end
+
diff --git a/trunk/test/rss/test_version.rb b/trunk/test/rss/test_version.rb
new file mode 100644
index 0000000000..fefdb1e0f0
--- /dev/null
+++ b/trunk/test/rss/test_version.rb
@@ -0,0 +1,9 @@
+require "rss-testcase"
+
+module RSS
+ class TestVersion < TestCase
+ def test_version
+ assert_equal("0.2.5", ::RSS::VERSION)
+ end
+ end
+end
diff --git a/trunk/test/rss/test_xml-stylesheet.rb b/trunk/test/rss/test_xml-stylesheet.rb
new file mode 100644
index 0000000000..b946af1294
--- /dev/null
+++ b/trunk/test/rss/test_xml-stylesheet.rb
@@ -0,0 +1,108 @@
+require "rexml/document"
+
+require "rss-testcase"
+
+require "rss/1.0"
+require "rss/xml-stylesheet"
+
+module RSS
+ class TestXMLStyleSheet < TestCase
+
+ def test_accessor
+ [
+ {:href => "a.xsl", :type => "text/xsl"},
+ {:media => "print", :title => "FOO"},
+ {:charset => "UTF-8", :alternate => "yes"},
+ ].each do |attrs|
+ assert_xml_stylesheet_attrs(attrs, XMLStyleSheet.new(attrs))
+ end
+ end
+
+ def test_to_s
+ [
+ {:href => "a.xsl", :type => "text/xsl"},
+ {:type => "text/xsl"},
+ {:href => "a.xsl", :guess_type => "text/xsl"},
+ {:href => "a.css", :type => "text/css"},
+ {:href => "a.css", :type => "text/xsl",
+ :guess_type => "text/css"},
+ {:href => "a.xsl", :type => "text/xsl",
+ :title => "sample", :media => "printer",
+ :charset => "UTF-8", :alternate => "yes"},
+ {:href => "a.css", :guess_type => "text/css",
+ :alternate => "no"},
+ {:type => "text/xsl", :title => "sample",
+ :media => "printer", :charset => "UTF-8",
+ :alternate => "yes"},
+ ].each do |attrs|
+ target, contents = parse_pi(XMLStyleSheet.new(attrs).to_s)
+ assert_xml_stylesheet(target, attrs, XMLStyleSheet.new(contents))
+ end
+ end
+
+ def test_bad_alternate
+ %w(a ___ ??? BAD_ALTERNATE).each do |value|
+ xss = XMLStyleSheet.new
+ assert_raise(NotAvailableValueError) do
+ xss.alternate = value
+ end
+ xss.do_validate = false
+ assert_nothing_raised do
+ xss.alternate = value
+ end
+ assert_nil(xss.alternate)
+ end
+ end
+
+ def test_parse
+ [
+ [{:href => "a.xsl", :type => "text/xsl"},],
+ [{:media => "print", :title => "FOO"},],
+ [{:charset => "UTF-8", :alternate => "yes"},],
+ [{:href => "a.xsl", :type => "text/xsl"},
+ {:type => "text/xsl"},
+ {:href => "a.xsl", :guess_type => "text/xsl"},
+ {:href => "a.css", :type => "text/css"},
+ {:href => "a.css", :type => "text/xsl",
+ :guess_type => "text/css"},
+ {:href => "a.xsl", :type => "text/xsl",
+ :title => "sample", :media => "printer",
+ :charset => "UTF-8", :alternate => "yes"},
+ {:href => "a.css", :guess_type => "text/css",
+ :alternate => "no"},
+ {:type => "text/xsl", :title => "sample",
+ :media => "printer", :charset => "UTF-8",
+ :alternate => "yes"},],
+ ].each do |xsss|
+ doc = REXML::Document.new(make_sample_RDF)
+ root = doc.root
+ xsss.each do |xss|
+ content = xss.collect do |key, name|
+ %Q[#{key}="#{name}"]
+ end.join(" ")
+ pi = REXML::Instruction.new("xml-stylesheet", content)
+ root.previous_sibling = pi
+ end
+ rss = Parser.parse(doc.to_s)
+ have_href_xsss = xsss.find_all {|xss| xss.has_key?(:href)}
+ assert_equal(have_href_xsss.size, rss.xml_stylesheets.size)
+ rss.xml_stylesheets.each_with_index do |stylesheet, i|
+ target, = parse_pi(stylesheet.to_s)
+ assert_xml_stylesheet(target, have_href_xsss[i], stylesheet)
+ end
+ end
+ end
+
+ def parse_pi(pi)
+ /\A\s*<\?(\S+)([^(?:\?>)]+)\?>\s*\z/ =~ pi
+ target = $1
+ dummy = REXML::Document.new("<dummy #{$2}/>").root
+ contents = {}
+ dummy.attributes.each do |name, value|
+ contents[name] = value
+ end
+ [target, contents]
+ end
+
+ end
+end
diff --git a/trunk/test/ruby/allpairs.rb b/trunk/test/ruby/allpairs.rb
new file mode 100644
index 0000000000..393d0c3288
--- /dev/null
+++ b/trunk/test/ruby/allpairs.rb
@@ -0,0 +1,103 @@
+module AllPairs
+ module_function
+
+ def make_prime(v)
+ return 2 if v < 2
+ ary = [true] * (v*2)
+ 2.upto(Math.sqrt(ary.length).ceil) {|i|
+ return i if ary[i] && v <= i
+ (i*2).step(ary.length, i) {|j|
+ ary[j] = false
+ }
+ }
+ v.upto(ary.length-1) {|i|
+ return i if ary[i]
+ }
+ raise "[bug] prime not found greater than #{v}"
+ end
+
+ def make_basic_block(prime)
+ prime.times {|i|
+ prime.times {|j|
+ row = [i]
+ 0.upto(prime-1) {|m|
+ row << (i*m + j) % prime
+ }
+ yield row
+ }
+ }
+ end
+
+ def combine_block(tbl1, tbl2)
+ result = []
+ tbl2.each {|row|
+ result << row * tbl1.first.length
+ }
+ tbl1.each_with_index {|row, k|
+ next if k == 0
+ result << row.map {|i| [i] * tbl2.first.length }.flatten
+ }
+ result
+ end
+
+ def make_large_block(v, prime)
+ if prime <= v+1
+ make_basic_block(v) {|row|
+ yield row
+ }
+ else
+ tbl = []
+ make_basic_block(v) {|row|
+ tbl << row
+ }
+ tbls = [tbl]
+ while tbl.first.length ** 2 < prime
+ tbl = combine_block(tbl, tbl)
+ tbls << tbl
+ end
+ tbl1 = tbls.find {|t| prime <= t.first.length * tbl.first.length }
+ tbl = combine_block(tbl, tbl1)
+ tbl.each {|row|
+ yield row
+ }
+ end
+ end
+
+ def each_index(*vs)
+ n = vs.length
+ max_v = vs.max
+ prime = make_prime(max_v)
+ h = {}
+ make_large_block(max_v, n) {|row|
+ row = vs.zip(row).map {|v, i| i % v }
+ next if h[row]
+ h[row] = true
+ yield row
+ }
+ end
+
+ # generate all pairs test.
+ def each(*args)
+ args.map! {|a| a.to_a }
+ each_index(*args.map {|a| a.length}) {|is|
+ yield is.zip(args).map {|i, a| a[i] }
+ }
+ end
+
+ # generate all combination in cartesian product. (not all-pairs test)
+ def exhaustive_each(*args)
+ args = args.map {|a| a.to_a }
+ i = 0
+ while true
+ n = i
+ as = []
+ args.reverse_each {|a|
+ n, m = n.divmod(a.length)
+ as.unshift a[m]
+ }
+ break if 0 < n
+ yield as
+ i += 1
+ end
+ end
+end
diff --git a/trunk/test/ruby/beginmainend.rb b/trunk/test/ruby/beginmainend.rb
new file mode 100644
index 0000000000..6cdfb15ea6
--- /dev/null
+++ b/trunk/test/ruby/beginmainend.rb
@@ -0,0 +1,80 @@
+errout = ARGV.shift
+
+BEGIN {
+ puts "b1"
+ local_begin1 = "local_begin1"
+ $global_begin1 = "global_begin1"
+ ConstBegin1 = "ConstBegin1"
+}
+
+BEGIN {
+ puts "b2"
+
+ BEGIN {
+ puts "b2-1"
+ }
+}
+
+# for scope check
+#raise if defined?(local_begin1)
+raise unless defined?($global_begin1)
+raise unless defined?(::ConstBegin1)
+local_for_end2 = "e2"
+$global_for_end1 = "e1"
+
+puts "main"
+
+END {
+ puts local_for_end2 # e2
+}
+
+eval <<EOE
+ BEGIN {
+ puts "b3"
+
+ BEGIN {
+ puts "b3-1"
+ }
+ }
+
+ BEGIN {
+ puts "b4"
+ }
+
+ END {
+ puts "e3"
+ }
+
+ END {
+ puts "e4"
+
+ END {
+ puts "e4-1"
+
+ END {
+ puts "e4-1-1"
+ }
+ }
+
+ END {
+ puts "e4-2"
+ }
+ }
+EOE
+
+END {
+ exit
+ puts "should not be dumped"
+
+ END {
+ puts "not reached"
+ }
+}
+
+END {
+ puts $global_for_end1 # e1
+
+ END {
+ puts "e1-1"
+ }
+}
diff --git a/trunk/test/ruby/enc/test_big5.rb b/trunk/test/ruby/enc/test_big5.rb
new file mode 100644
index 0000000000..e8fe0270a8
--- /dev/null
+++ b/trunk/test/ruby/enc/test_big5.rb
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestBig5 < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("big5")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\xa1\xa1").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0xa1a1, s("\xa1\xa1").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\xa1\xa1"), 0xa1a1.chr("big5"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+ assert_match(r, s("\xa1\xa1\xa1\xa1"))
+ end
+
+ def test_left_adjust_char_head
+ assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_cp949.rb b/trunk/test/ruby/enc/test_cp949.rb
new file mode 100644
index 0000000000..e675c7b80c
--- /dev/null
+++ b/trunk/test/ruby/enc/test_cp949.rb
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestCP949 < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("cp949")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\xa1\xa1").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0xa1a1, s("\xa1\xa1").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\xa1\xa1"), 0xa1a1.chr("cp949"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+ assert_match(r, s("\xa1\xa1\xa1\xa1"))
+ end
+
+ def test_left_adjust_char_head
+ assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_euc_jp.rb b/trunk/test/ruby/enc/test_euc_jp.rb
new file mode 100644
index 0000000000..82abe2116d
--- /dev/null
+++ b/trunk/test/ruby/enc/test_euc_jp.rb
@@ -0,0 +1,20 @@
+# vim: set fileencoding=euc-jp
+
+require "test/unit"
+
+class TestEUC_JP < Test::Unit::TestCase
+ def test_mbc_case_fold
+ assert_match(/(£á)(a)\1\2/i, "£áa£áA")
+ assert_no_match(/(£á)(a)\1\2/i, "£áa£ÁA")
+ end
+
+ def test_property
+ assert_match(/¤¢{0}\p{Hiragana}{4}/, "¤Ò¤é¤¬¤Ê")
+ assert_no_match(/¤¢{0}\p{Hiragana}{4}/, "¥«¥¿¥«¥Ê")
+ assert_no_match(/¤¢{0}\p{Hiragana}{4}/, "´Á»ú´Á»ú")
+ assert_no_match(/¤¢{0}\p{Katakana}{4}/, "¤Ò¤é¤¬¤Ê")
+ assert_match(/¤¢{0}\p{Katakana}{4}/, "¥«¥¿¥«¥Ê")
+ assert_no_match(/¤¢{0}\p{Katakana}{4}/, "´Á»ú´Á»ú")
+ assert_raise(RegexpError) { Regexp.new('¤¢{0}\p{foobarbaz}') }
+ end
+end
diff --git a/trunk/test/ruby/enc/test_euc_kr.rb b/trunk/test/ruby/enc/test_euc_kr.rb
new file mode 100644
index 0000000000..087bc795f7
--- /dev/null
+++ b/trunk/test/ruby/enc/test_euc_kr.rb
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestEucKr < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("euc-kr")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\xa1\xa1").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0xa1a1, s("\xa1\xa1").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\xa1\xa1"), 0xa1a1.chr("euc-kr"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+ assert_match(r, s("\xa1\xa1\xa1\xa1"))
+ end
+
+ def test_left_adjust_char_head
+ assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_euc_tw.rb b/trunk/test/ruby/enc/test_euc_tw.rb
new file mode 100644
index 0000000000..f36d86b088
--- /dev/null
+++ b/trunk/test/ruby/enc/test_euc_tw.rb
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestEucTw < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("euc-tw")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\xa1\xa1").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0xa1a1, s("\xa1\xa1").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\xa1\xa1"), 0xa1a1.chr("euc-tw"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+ assert_match(r, s("\xa1\xa1\xa1\xa1"))
+ end
+
+ def test_left_adjust_char_head
+ assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_gb18030.rb b/trunk/test/ruby/enc/test_gb18030.rb
new file mode 100644
index 0000000000..a33a9eb28e
--- /dev/null
+++ b/trunk/test/ruby/enc/test_gb18030.rb
@@ -0,0 +1,125 @@
+require "test/unit"
+
+class TestGB18030 < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("gb18030")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\x81\x40").size)
+ assert_equal(1, s("\x81\x30\x81\x30").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0x8140, s("\x81\x40").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\x81\x40"), 0x8140.chr("gb18030"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\x81\x40)\\1"), "i")
+ assert_match(r, s("\x81\x40\x81\x40"))
+ end
+
+ def scheck(c, i)
+ assert_equal(s(c.reverse.take(c.size - i).join), s(c.reverse.join).chop)
+ end
+
+ def fcheck(c)
+ assert_raise(ArgumentError) { s(c.reverse.join).chop }
+ end
+
+ def test_left_adjust_char_head
+ # C1: 00-2f, 3a-3f, 7f, ff
+ # C2: 40-7e, 80
+ # C4: 30-39
+ # CM: 81-fe
+ c1 = "\x2f"
+ c2 = "\x40"
+ c4 = "\x30"
+ cm = "\x81"
+
+ # S_START-c1
+ # S_START-c2-S_one_C2-0
+ # S_START-c2-S_one_C2-c1
+ # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-c1
+ # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-cm-S_even_CM_one_CX-c1
+ # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-cm-S_even_CM_one_CX-cm-S_odd_CM_one_CX(rec)
+ # S_START-c4-S_one_C4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-c4-S_one_C4_odd_CMC4(rec)
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-cm-S_even_CM_odd_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-cm-S_even_CM_odd_CMC4-cm-S_odd_CM_odd_CMC4(rec)
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-cm-S_even_CM_even_CMC4-c1
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-cm-S_even_CM_even_CMC4-cm-S_odd_CM_even_CMC4(rec)
+ # S_START-c4-S_one_C4-cm-S_one_CMC4-cm-S_even_CM_one_CX(rec)
+ # S_START-cm-S_one_CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-c4-S_odd_C4CM(rec)
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-cm-S_odd_CM_even_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-cm-S_odd_CM_even_C4CM-cm-S_even_CM_even_C4CM(rec)
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-cm-S_odd_CM_odd_C4CM-c1
+ # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-cm-S_odd_CM_odd_C4CM-cm-S_even_CM_odd_C4CM(rec)
+ # S_START-cm-S_one_CM-cm-S_odd_CM_one_CX(rec)
+
+ scheck([c1], 1)
+ scheck([c2], 1)
+ scheck([c2, c1], 1)
+ scheck([c2, cm, c1], 2)
+ scheck([c2, cm, cm, c1], 1)
+ scheck([c2, cm, cm, cm], 2)
+ scheck([c4], 1)
+ scheck([c4, c1], 1)
+ scheck([c4, cm], 2)
+ fcheck([c4, cm, c1])
+ fcheck([c4, cm, c4, c1])
+ scheck([c4, cm, c4, cm], 4)
+ scheck([c4, cm, c4, cm, c1], 4)
+ scheck([c4, cm, c4, cm, c4], 4)
+ scheck([c4, cm, c4, cm, c4, c1], 4)
+ fcheck([c4, cm, c4, cm, c4, cm])
+ fcheck([c4, cm, c4, cm, c4, cm, c1])
+ fcheck([c4, cm, c4, cm, c4, cm, c4])
+ scheck([c4, cm, c4, cm, c4, cm, cm, c1], 4)
+ fcheck([c4, cm, c4, cm, c4, cm, cm, cm])
+ fcheck([c4, cm, c4, cm, c4, cm, cm, cm, c1])
+ scheck([c4, cm, c4, cm, c4, cm, cm, cm, cm], 4)
+ fcheck([c4, cm, c4, cm, cm, c1])
+ scheck([c4, cm, c4, cm, cm, cm], 4)
+ scheck([c4, cm, c4, cm, cm, cm, c1], 4)
+ fcheck([c4, cm, c4, cm, cm, cm, cm])
+ scheck([c4, cm, cm], 1)
+ scheck([cm], 1)
+ fcheck([cm, c1])
+ fcheck([cm, c4, c1])
+ scheck([cm, c4, cm], 3)
+ fcheck([cm, c4, cm, c1])
+ fcheck([cm, c4, cm, c4])
+ fcheck([cm, c4, cm, c4, c1])
+ fcheck([cm, c4, cm, c4, cm])
+ fcheck([cm, c4, cm, c4, cm, c1])
+ fcheck([cm, c4, cm, c4, cm, c4])
+ fcheck([cm, c4, cm, c4, cm, cm, c1])
+ fcheck([cm, c4, cm, c4, cm, cm, cm])
+ fcheck([cm, c4, cm, c4, cm, cm, cm, c1])
+ fcheck([cm, c4, cm, c4, cm, cm, cm, cm])
+ fcheck([cm, c4, cm, cm, c1])
+ fcheck([cm, c4, cm, cm, cm])
+ fcheck([cm, c4, cm, cm, cm, c1])
+ fcheck([cm, c4, cm, cm, cm, cm])
+ scheck([cm, cm], 2)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_gbk.rb b/trunk/test/ruby/enc/test_gbk.rb
new file mode 100644
index 0000000000..d6dc5d6d1b
--- /dev/null
+++ b/trunk/test/ruby/enc/test_gbk.rb
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestGBK < Test::Unit::TestCase
+ def s(s)
+ s.force_encoding("gbk")
+ end
+
+ def test_mbc_enc_len
+ assert_equal(1, s("\x81\x40").size)
+ end
+
+ def test_mbc_to_code
+ assert_equal(0x8140, s("\x81\x40").ord)
+ end
+
+ def test_code_to_mbc
+ assert_equal(s("\x81\x40"), 0x8140.chr("gbk"))
+ end
+
+ def test_mbc_case_fold
+ r = Regexp.new(s("(\x81\x40)\\1"), "i")
+ assert_match(r, s("\x81\x40\x81\x40"))
+ end
+
+ def test_left_adjust_char_head
+ assert_equal(s("\x81\x40"), s("\x81\x40\x81\x40").chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_iso_8859.rb b/trunk/test/ruby/enc/test_iso_8859.rb
new file mode 100644
index 0000000000..64cc7cd76d
--- /dev/null
+++ b/trunk/test/ruby/enc/test_iso_8859.rb
@@ -0,0 +1,163 @@
+require 'test/unit'
+
+class TestISO8859 < Test::Unit::TestCase
+ ASSERTS = %q(
+ assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+ assert_match(/^(\xdf)\1$/i, "ssss")
+ # assert_match(/^(\xdf)\1$/i, "\xdfss") # this must be bug...
+ assert_match(/^[\xdfz]+$/i, "sszzsszz")
+ assert_match(/^SS$/i, "\xdf")
+ assert_match(/^Ss$/i, "\xdf")
+ ((0xc0..0xde).to_a - [0xd7]).each do |c|
+ c1 = c.chr("ENCODING")
+ c2 = (c + 0x20).chr("ENCODING")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ assert_match(/^\xff$/i, "\xff")
+ )
+
+ def test_iso_8859_1
+ eval("# encoding: iso8859-1\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-1"))
+ end
+
+ def test_iso_8859_2
+ eval("# encoding: iso8859-2\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-2"))
+ end
+
+ def test_iso_8859_3
+ eval(%q(# encoding: iso8859-3
+ assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+ assert_match(/^(\xdf)\1$/i, "ssss")
+ assert_match(/^[\xdfz]+$/i, "sszzsszz")
+ assert_match(/^SS$/i, "\xdf")
+ assert_match(/^Ss$/i, "\xdf")
+ [0xa1, 0xa6, *(0xa9..0xac), 0xaf].each do |c|
+ c1 = c.chr("iso8859-3")
+ c2 = (c + 0x10).chr("iso8859-3")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ([*(0xc0..0xde)] - [0xc3, 0xd0, 0xd7]).each do |c|
+ c1 = c.chr("iso8859-3")
+ c2 = (c + 0x20).chr("iso8859-3")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ))
+ end
+
+ def test_iso_8859_4
+ eval("# encoding: iso8859-4\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-4"))
+ end
+
+ def test_iso_8859_5
+ eval(%q(# encoding: iso8859-5
+ (0xb0..0xcf).each do |c|
+ c1 = c.chr("iso8859-5")
+ c2 = (c + 0x20).chr("iso8859-5")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ((0xa1..0xaf).to_a - [0xad]).each do |c|
+ c1 = c.chr("iso8859-5")
+ c2 = (c + 0x50).chr("iso8859-5")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ))
+ end
+
+ def test_iso_8859_6
+ eval(%q(# encoding: iso8859-6
+ [0xa4, 0xac, 0xbb, 0xbf, *(0xc1..0xda), *(0xe0..0xf2)].each do |c|
+ c1 = c.chr("iso8859-6")
+ assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+ end
+ ))
+ end
+
+ def test_iso_8859_7
+ eval(%q(# encoding: iso8859-7
+ ((0xa0..0xfe).to_a - [0xae, 0xd2]).each do |c|
+ c1 = c.chr("iso8859-7")
+ assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+ end
+ ((0xc1..0xd9).to_a - [0xd2]).each do |c|
+ c1 = c.chr("iso8859-7")
+ c2 = (c + 0x20).chr("iso8859-7")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ))
+ end
+
+ def test_iso_8859_8
+ eval(%q(# encoding: iso8859-8
+ [0xa0, *(0xa2..0xbe), *(0xdf..0xfa), 0xfc, 0xfd].each do |c|
+ c1 = c.chr("iso8859-8")
+ assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+ end
+ ))
+ end
+
+ def test_iso_8859_9
+ eval(%q(# encoding: iso8859-9
+ assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+ assert_match(/^(\xdf)\1$/i, "ssss")
+ assert_match(/^[\xdfz]+$/i, "sszzsszz")
+ assert_match(/^SS$/i, "\xdf")
+ assert_match(/^Ss$/i, "\xdf")
+ ([*(0xc0..0xdc)] - [0xd7]).each do |c|
+ c1 = c.chr("iso8859-9")
+ c2 = (c + 0x20).chr("iso8859-9")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ ))
+ end
+
+ def test_iso_8859_10
+ eval("# encoding: iso8859-10\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-10"))
+ end
+
+ def test_iso_8859_11
+ eval(%q(# encoding: iso8859-11
+ [*(0xa0..0xda), *(0xdf..0xfb)].each do |c|
+ c1 = c.chr("iso8859-11")
+ assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+ end
+ ))
+ end
+
+ def test_iso_8859_13
+ eval("# encoding: iso8859-13\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-13"))
+ end
+
+ def test_iso_8859_14
+ eval("# encoding: iso8859-14\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-14"))
+ end
+
+ def test_iso_8859_15
+ eval("# encoding: iso8859-15\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-15"))
+ end
+
+ def test_iso_8859_16
+ eval("# encoding: iso8859-16\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-16"))
+ end
+end
+
diff --git a/trunk/test/ruby/enc/test_koi8.rb b/trunk/test/ruby/enc/test_koi8.rb
new file mode 100644
index 0000000000..ce2d8925ea
--- /dev/null
+++ b/trunk/test/ruby/enc/test_koi8.rb
@@ -0,0 +1,22 @@
+require "test/unit"
+
+class TestKOI8 < Test::Unit::TestCase
+ ASSERTS = %q(
+ (0xc0..0xdf).each do |c|
+ c1 = c.chr("ENCODING")
+ c2 = (c + 0x20).chr("ENCODING")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ )
+
+ def test_koi8_r
+ eval("# encoding: koi8-r\n" + ASSERTS.gsub("ENCODING", "koi8-r"))
+ end
+
+ def test_koi8_u
+ eval("# encoding: koi8-u\n" + ASSERTS.gsub("ENCODING", "koi8-u"))
+ end
+end
diff --git a/trunk/test/ruby/enc/test_shift_jis.rb b/trunk/test/ruby/enc/test_shift_jis.rb
new file mode 100644
index 0000000000..f81cb7801c
--- /dev/null
+++ b/trunk/test/ruby/enc/test_shift_jis.rb
@@ -0,0 +1,27 @@
+# vim: set fileencoding=shift_jis
+
+require "test/unit"
+
+class TestShiftJIS < Test::Unit::TestCase
+ def test_mbc_case_fold
+ assert_match(/(‚)(a)\1\2/i, "‚a‚A")
+ assert_no_match(/(‚)(a)\1\2/i, "‚a‚`A")
+ end
+
+ def test_property
+ assert_match(/‚ {0}\p{Hiragana}{4}/, "‚Ђ炪‚È")
+ assert_no_match(/‚ {0}\p{Hiragana}{4}/, "ƒJƒ^ƒJƒi")
+ assert_no_match(/‚ {0}\p{Hiragana}{4}/, "Š¿ŽšŠ¿Žš")
+ assert_no_match(/‚ {0}\p{Katakana}{4}/, "‚Ђ炪‚È")
+ assert_match(/‚ {0}\p{Katakana}{4}/, "ƒJƒ^ƒJƒi")
+ assert_no_match(/‚ {0}\p{Katakana}{4}/, "Š¿ŽšŠ¿Žš")
+ assert_raise(RegexpError) { Regexp.new('‚ {0}\p{foobarbaz}') }
+ end
+
+ def test_code_to_mbclen
+ s = "‚ ‚¢‚¤‚¦‚¨"
+ s << 0x82a9
+ assert_equal("‚ ‚¢‚¤‚¦‚¨‚©", s)
+ assert_raise(ArgumentError) { s << 0x82 }
+ end
+end
diff --git a/trunk/test/ruby/enc/test_utf16.rb b/trunk/test/ruby/enc/test_utf16.rb
new file mode 100644
index 0000000000..a7c735f436
--- /dev/null
+++ b/trunk/test/ruby/enc/test_utf16.rb
@@ -0,0 +1,358 @@
+require 'test/unit'
+
+class TestUTF16 < Test::Unit::TestCase
+ def encdump(str)
+ d = str.dump
+ if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
+ d
+ else
+ "#{d}.force_encoding(#{str.encoding.name.dump})"
+ end
+ end
+
+ def enccall(recv, meth, *args)
+ desc = ''
+ if String === recv
+ desc << encdump(recv)
+ else
+ desc << recv.inspect
+ end
+ desc << '.' << meth.to_s
+ if !args.empty?
+ desc << '('
+ args.each_with_index {|a, i|
+ desc << ',' if 0 < i
+ if String === a
+ desc << encdump(a)
+ else
+ desc << a.inspect
+ end
+ }
+ desc << ')'
+ end
+ result = nil
+ assert_nothing_raised(desc) {
+ result = recv.send(meth, *args)
+ }
+ result
+ end
+
+ def assert_str_equal(expected, actual, message=nil)
+ full_message = build_message(message, <<EOT)
+#{encdump expected} expected but not equal to
+#{encdump actual}.
+EOT
+ assert_block(full_message) { expected == actual }
+ end
+
+ # tests start
+
+ def test_utf16be_valid_encoding
+ [
+ "\x00\x00",
+ "\xd7\xff",
+ "\xd8\x00\xdc\x00",
+ "\xdb\xff\xdf\xff",
+ "\xe0\x00",
+ "\xff\xff",
+ ].each {|s|
+ s.force_encoding("utf-16be")
+ assert_equal(true, s.valid_encoding?, "#{encdump s}.valid_encoding?")
+ }
+ [
+ "\x00",
+ "\xd7",
+ "\xd8\x00",
+ "\xd8\x00\xd8\x00",
+ "\xdc\x00",
+ "\xdc\x00\xd8\x00",
+ "\xdc\x00\xdc\x00",
+ "\xe0",
+ "\xff",
+ ].each {|s|
+ s.force_encoding("utf-16be")
+ assert_equal(false, s.valid_encoding?, "#{encdump s}.valid_encoding?")
+ }
+ end
+
+ def test_utf16le_valid_encoding
+ [
+ "\x00\x00",
+ "\xff\xd7",
+ "\x00\xd8\x00\xdc",
+ "\xff\xdb\xff\xdf",
+ "\x00\xe0",
+ "\xff\xff",
+ ].each {|s|
+ s.force_encoding("utf-16le")
+ assert_equal(true, s.valid_encoding?, "#{encdump s}.valid_encoding?")
+ }
+ [
+ "\x00",
+ "\xd7",
+ "\x00\xd8",
+ "\x00\xd8\x00\xd8",
+ "\x00\xdc",
+ "\x00\xdc\x00\xd8",
+ "\x00\xdc\x00\xdc",
+ "\xe0",
+ "\xff",
+ ].each {|s|
+ s.force_encoding("utf-16le")
+ assert_equal(false, s.valid_encoding?, "#{encdump s}.valid_encoding?")
+ }
+ end
+
+ def test_strftime
+ s = "aa".force_encoding("utf-16be")
+ assert_raise(ArgumentError, "Time.now.strftime(#{encdump s})") { Time.now.strftime(s) }
+ end
+
+ def test_intern
+ s = "aaaa".force_encoding("utf-16be")
+ assert_equal(s.encoding, s.intern.to_s.encoding, "#{encdump s}.intern.to_s.encoding")
+ end
+
+ def test_sym_eq
+ s = "aa".force_encoding("utf-16le")
+ assert(s.intern != :aa, "#{encdump s}.intern != :aa")
+ end
+
+ def test_compatible
+ s1 = "aa".force_encoding("utf-16be")
+ s2 = "z".force_encoding("us-ascii")
+ assert_nil(Encoding.compatible?(s1, s2), "Encoding.compatible?(#{encdump s1}, #{encdump s2})")
+ end
+
+ def test_casecmp
+ s1 = "aa".force_encoding("utf-16be")
+ s2 = "AA"
+ assert_not_equal(0, s1.casecmp(s2), "#{encdump s1}.casecmp(#{encdump s2})")
+ end
+
+ def test_end_with
+ s1 = "ab".force_encoding("utf-16be")
+ s2 = "b".force_encoding("utf-16be")
+ assert_equal(false, s1.end_with?(s2), "#{encdump s1}.end_with?(#{encdump s2})")
+ end
+
+ def test_hex
+ assert_raise(EncodingCompatibilityError) {
+ "ff".encode("utf-16le").hex
+ }
+ assert_raise(EncodingCompatibilityError) {
+ "ff".encode("utf-16be").hex
+ }
+ end
+
+ def test_oct
+ assert_raise(EncodingCompatibilityError) {
+ "77".encode("utf-16le").oct
+ }
+ assert_raise(EncodingCompatibilityError) {
+ "77".encode("utf-16be").oct
+ }
+ end
+
+ def test_count
+ s1 = "aa".force_encoding("utf-16be")
+ s2 = "aa"
+ assert_raise(EncodingCompatibilityError, "#{encdump s1}.count(#{encdump s2})") {
+ s1.count(s2)
+ }
+ end
+
+ def test_plus
+ s1 = "a".force_encoding("us-ascii")
+ s2 = "aa".force_encoding("utf-16be")
+ assert_raise(EncodingCompatibilityError, "#{encdump s1} + #{encdump s2}") {
+ s1 + s2
+ }
+ end
+
+ def test_encoding_find
+ assert_raise(ArgumentError) {
+ Encoding.find("utf-8".force_encoding("utf-16be"))
+ }
+ end
+
+ def test_interpolation
+ s = "aa".force_encoding("utf-16be")
+ assert_raise(EncodingCompatibilityError, "\"a\#{#{encdump s}}\"") {
+ "a#{s}"
+ }
+ end
+
+ def test_slice!
+ enccall("aa".force_encoding("UTF-16BE"), :slice!, -1)
+ end
+
+ def test_plus_empty1
+ s1 = ""
+ s2 = "aa".force_encoding("utf-16be")
+ assert_nothing_raised("#{encdump s1} << #{encdump s2}") {
+ s1 + s2
+ }
+ end
+
+ def test_plus_empty2
+ s1 = "aa"
+ s2 = "".force_encoding("utf-16be")
+ assert_nothing_raised("#{encdump s1} << #{encdump s2}") {
+ s1 + s2
+ }
+ end
+
+ def test_plus_nonempty
+ s1 = "aa"
+ s2 = "bb".force_encoding("utf-16be")
+ assert_raise(EncodingCompatibilityError, "#{encdump s1} << #{encdump s2}") {
+ s1 + s2
+ }
+ end
+
+ def test_concat_empty1
+ s1 = ""
+ s2 = "aa".force_encoding("utf-16be")
+ assert_nothing_raised("#{encdump s1} << #{encdump s2}") {
+ s1 << s2
+ }
+ end
+
+ def test_concat_empty2
+ s1 = "aa"
+ s2 = "".force_encoding("utf-16be")
+ assert_nothing_raised("#{encdump s1} << #{encdump s2}") {
+ s1 << s2
+ }
+ end
+
+ def test_concat_nonempty
+ s1 = "aa"
+ s2 = "bb".force_encoding("utf-16be")
+ assert_raise(EncodingCompatibilityError, "#{encdump s1} << #{encdump s2}") {
+ s1 << s2
+ }
+ end
+
+ def test_chomp
+ s = "\1\n".force_encoding("utf-16be")
+ assert_equal(s, s.chomp, "#{encdump s}.chomp")
+ s = "\0\n".force_encoding("utf-16be")
+ assert_equal("", s.chomp, "#{encdump s}.chomp")
+ s = "\0\r\0\n".force_encoding("utf-16be")
+ assert_equal("", s.chomp, "#{encdump s}.chomp")
+ end
+
+ def test_succ
+ s = "\xff\xff".force_encoding("utf-16be")
+ assert(s.succ.valid_encoding?, "#{encdump s}.succ.valid_encoding?")
+
+ s = "\xdb\xff\xdf\xff".force_encoding("utf-16be")
+ assert(s.succ.valid_encoding?, "#{encdump s}.succ.valid_encoding?")
+ end
+
+ def test_regexp_union
+ enccall(Regexp, :union, "aa".force_encoding("utf-16be"), "bb".force_encoding("utf-16be"))
+ end
+
+ def test_empty_regexp
+ s = "".force_encoding("utf-16be")
+ assert_equal(Encoding.find("utf-16be"), Regexp.new(s).encoding,
+ "Regexp.new(#{encdump s}).encoding")
+ end
+
+ def test_regexp_match
+ assert_raise(ArgumentError) { Regexp.new("aa".force_encoding("utf-16be")) =~ "aa" }
+ end
+
+ def test_gsub
+ s = "abcd".force_encoding("utf-16be")
+ assert_nothing_raised {
+ s.gsub(Regexp.new(".".encode("utf-16be")), "xy")
+ }
+ s = "ab\0\ncd".force_encoding("utf-16be")
+ assert_raise(EncodingCompatibilityError) {
+ s.gsub(Regexp.new(".".encode("utf-16be")), "xy")
+ }
+ end
+
+ def test_split_awk
+ s = " ab cd ".encode("utf-16be")
+ r = s.split(" ".encode("utf-16be"))
+ assert_equal(2, r.length)
+ assert_str_equal("ab".encode("utf-16be"), r[0])
+ assert_str_equal("cd".encode("utf-16be"), r[1])
+ end
+
+ def test_count2
+ e = "abc".count("^b")
+ assert_equal(e, "abc".encode("utf-16be").count("^b".encode("utf-16be")))
+ assert_equal(e, "abc".encode("utf-16le").count("^b".encode("utf-16le")))
+ end
+
+ def test_header
+ assert_raise(ArgumentError) { eval("# encoding:utf-16le\nfoo") }
+ assert_raise(ArgumentError) { eval("# encoding:utf-16be\nfoo") }
+ end
+
+
+ def test_is_mbc_newline
+ sl = "f\0o\0o\0\n\0b\0a\0r\0\n\0b\0a\0z\0\n\0".force_encoding("utf-16le")
+ sb = "\0f\0o\0o\0\n\0b\0a\0r\0\n\0b\0a\0z\0\n".force_encoding("utf-16be")
+ al = sl.lines.to_a
+ ab = sb.lines.to_a
+ assert_equal("f\0o\0o\0\n\0".force_encoding("utf-16le"), al.shift)
+ assert_equal("b\0a\0r\0\n\0".force_encoding("utf-16le"), al.shift)
+ assert_equal("b\0a\0z\0\n\0".force_encoding("utf-16le"), al.shift)
+ assert_equal("\0f\0o\0o\0\n".force_encoding("utf-16be"), ab.shift)
+ assert_equal("\0b\0a\0r\0\n".force_encoding("utf-16be"), ab.shift)
+ assert_equal("\0b\0a\0z\0\n".force_encoding("utf-16be"), ab.shift)
+
+ sl = "f\0o\0o\0\n\0".force_encoding("utf-16le")
+ sb = "\0f\0o\0o\0\n".force_encoding("utf-16be")
+ sl2 = "f\0o\0o\0".force_encoding("utf-16le")
+ sb2 = "\0f\0o\0o".force_encoding("utf-16be")
+ assert_equal(sl2, sl.chomp)
+ assert_equal(sl2, sl.chomp.chomp)
+ assert_equal(sb2, sb.chomp)
+ assert_equal(sb2, sb.chomp.chomp)
+
+ sl = "f\0o\0o\0\n".force_encoding("utf-16le")
+ sb = "\0f\0o\0o\n".force_encoding("utf-16be")
+ assert_equal(sl, sl.chomp)
+ assert_equal(sb, sb.chomp)
+ end
+
+ def test_code_to_mbc
+ assert_equal("a\0".force_encoding("utf-16le"), "a".ord.chr("utf-16le"))
+ assert_equal("\0a".force_encoding("utf-16be"), "a".ord.chr("utf-16be"))
+ end
+
+ def utf8_to_utf16(s, e)
+ s.chars.map {|c| c.ord.chr(e) }.join
+ end
+
+ def test_mbc_case_fold
+ rl = Regexp.new(utf8_to_utf16("^(\u3042)(a)\\1\\2$", "utf-16le"), "i")
+ rb = Regexp.new(utf8_to_utf16("^(\u3042)(a)\\1\\2$", "utf-16be"), "i")
+ assert_equal(Encoding.find("utf-16le"), rl.encoding)
+ assert_equal(Encoding.find("utf-16be"), rb.encoding)
+ assert_match(rl, utf8_to_utf16("\u3042a\u3042a", "utf-16le"))
+ assert_match(rb, utf8_to_utf16("\u3042a\u3042a", "utf-16be"))
+ end
+
+ def test_surrogate_pair
+ sl = "\x42\xd8\xb7\xdf".force_encoding("utf-16le")
+ sb = "\xd8\x42\xdf\xb7".force_encoding("utf-16be")
+
+ assert_equal(1, sl.size)
+ assert_equal(1, sb.size)
+ assert_equal(0x20bb7, sl.ord)
+ assert_equal(0x20bb7, sb.ord)
+ assert_equal(sl, 0x20bb7.chr("utf-16le"))
+ assert_equal(sb, 0x20bb7.chr("utf-16be"))
+ assert_equal("", sl.chop)
+ assert_equal("", sb.chop)
+ end
+end
diff --git a/trunk/test/ruby/enc/test_utf32.rb b/trunk/test/ruby/enc/test_utf32.rb
new file mode 100644
index 0000000000..3d4a458512
--- /dev/null
+++ b/trunk/test/ruby/enc/test_utf32.rb
@@ -0,0 +1,93 @@
+require 'test/unit'
+
+class TestUTF32 < Test::Unit::TestCase
+ def encdump(str)
+ d = str.dump
+ if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
+ d
+ else
+ "#{d}.force_encoding(#{str.encoding.name.dump})"
+ end
+ end
+
+ def assert_str_equal(expected, actual, message=nil)
+ full_message = build_message(message, <<EOT)
+#{encdump expected} expected but not equal to
+#{encdump actual}.
+EOT
+ assert_block(full_message) { expected == actual }
+ end
+
+ def test_substr
+ assert_str_equal(
+ "abcdefgh".force_encoding("utf-32le"),
+ "abcdefgh".force_encoding("utf-32le")[0,3])
+ assert_str_equal(
+ "abcdefgh".force_encoding("utf-32be"),
+ "abcdefgh".force_encoding("utf-32be")[0,3])
+ end
+
+ def test_mbc_len
+ al = "abcdefghijkl".force_encoding("utf-32le").each_char.to_a
+ ab = "abcdefghijkl".force_encoding("utf-32be").each_char.to_a
+ assert_equal("abcd".force_encoding("utf-32le"), al.shift)
+ assert_equal("efgh".force_encoding("utf-32le"), al.shift)
+ assert_equal("ijkl".force_encoding("utf-32le"), al.shift)
+ assert_equal("abcd".force_encoding("utf-32be"), ab.shift)
+ assert_equal("efgh".force_encoding("utf-32be"), ab.shift)
+ assert_equal("ijkl".force_encoding("utf-32be"), ab.shift)
+ end
+
+ def ascii_to_utf16le(s)
+ s.unpack("C*").map {|x| [x,0,0,0] }.flatten.pack("C*").force_encoding("utf-32le")
+ end
+
+ def ascii_to_utf16be(s)
+ s.unpack("C*").map {|x| [0,0,0,x] }.flatten.pack("C*").force_encoding("utf-32be")
+ end
+
+ def test_mbc_newline
+ al = ascii_to_utf16le("foo\nbar\nbaz\n").lines.to_a
+ ab = ascii_to_utf16be("foo\nbar\nbaz\n").lines.to_a
+
+ assert_equal(ascii_to_utf16le("foo\n"), al.shift)
+ assert_equal(ascii_to_utf16le("bar\n"), al.shift)
+ assert_equal(ascii_to_utf16le("baz\n"), al.shift)
+ assert_equal(ascii_to_utf16be("foo\n"), ab.shift)
+ assert_equal(ascii_to_utf16be("bar\n"), ab.shift)
+ assert_equal(ascii_to_utf16be("baz\n"), ab.shift)
+
+ sl = "a\0".force_encoding("utf-32le")
+ sb = "a\0".force_encoding("utf-32be")
+ assert_equal(sl, sl.chomp)
+ assert_equal(sb, sb.chomp)
+ end
+
+ def test_mbc_to_code
+ sl = "a\0\0\0".force_encoding("utf-32le")
+ sb = "\0\0\0a".force_encoding("utf-32be")
+ assert_equal("a".ord, sl.ord)
+ assert_equal("a".ord, sb.ord)
+ end
+
+ def utf8_to_utf32(s, e)
+ s.chars.map {|c| c.ord.chr(e) }.join
+ end
+
+ def test_mbc_case_fold
+ rl = Regexp.new(utf8_to_utf32("^(\u3042)(a)\\1\\2$", "utf-32le"), "i")
+ rb = Regexp.new(utf8_to_utf32("^(\u3042)(a)\\1\\2$", "utf-32be"), "i")
+ assert_equal(Encoding.find("utf-32le"), rl.encoding)
+ assert_equal(Encoding.find("utf-32be"), rb.encoding)
+ assert_match(rl, utf8_to_utf32("\u3042a\u3042a", "utf-32le"))
+ assert_match(rb, utf8_to_utf32("\u3042a\u3042a", "utf-32be"))
+ end
+
+ def test_code_to_mbc
+ sl = "a\0\0\0".force_encoding("utf-32le")
+ sb = "\0\0\0a".force_encoding("utf-32be")
+ assert_equal(sl, "a".ord.chr("utf-32le"))
+ assert_equal(sb, "a".ord.chr("utf-32be"))
+ end
+end
+
diff --git a/trunk/test/ruby/enc/test_windows_1251.rb b/trunk/test/ruby/enc/test_windows_1251.rb
new file mode 100644
index 0000000000..6fbf3159a1
--- /dev/null
+++ b/trunk/test/ruby/enc/test_windows_1251.rb
@@ -0,0 +1,16 @@
+# encoding:windows-1251
+
+require "test/unit"
+
+class TestWindows1251 < Test::Unit::TestCase
+ def test_windows_1251
+ (0xc0..0xdf).each do |c|
+ c1 = c.chr("windows-1251")
+ c2 = (c + 0x20).chr("windows-1251")
+ assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+ assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+ assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+ assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+ end
+ end
+end
diff --git a/trunk/test/ruby/endblockwarn_rb b/trunk/test/ruby/endblockwarn_rb
new file mode 100644
index 0000000000..7b7f97f597
--- /dev/null
+++ b/trunk/test/ruby/endblockwarn_rb
@@ -0,0 +1,12 @@
+def end1
+ END {}
+end
+
+end1
+
+eval <<EOE
+ def end2
+ END {}
+ end
+EOE
+
diff --git a/trunk/test/ruby/envutil.rb b/trunk/test/ruby/envutil.rb
new file mode 100644
index 0000000000..4aba8a0bde
--- /dev/null
+++ b/trunk/test/ruby/envutil.rb
@@ -0,0 +1,176 @@
+require "open3"
+require "timeout"
+
+module EnvUtil
+ def rubybin
+ unless ENV["RUBYOPT"]
+
+ end
+ if ruby = ENV["RUBY"]
+ return ruby
+ end
+ ruby = "ruby"
+ rubyexe = ruby+".exe"
+ 3.times do
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if File.exist? rubyexe and File.executable? rubyexe
+ return File.expand_path(rubyexe)
+ end
+ ruby = File.join("..", ruby)
+ end
+ begin
+ require "rbconfig"
+ File.join(
+ RbConfig::CONFIG["bindir"],
+ RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
+ )
+ rescue LoadError
+ "ruby"
+ end
+ end
+ module_function :rubybin
+
+ LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
+ def rubyexec(*args)
+ ruby = EnvUtil.rubybin
+ c = "C"
+ env = {}
+ LANG_ENVS.each {|lc| env[lc], ENV[lc] = ENV[lc], c}
+ stdin = stdout = stderr = nil
+ Timeout.timeout(10) do
+ stdin, stdout, stderr = Open3.popen3(*([ruby] + args))
+ env.each_pair {|lc, v|
+ if v
+ ENV[lc] = v
+ else
+ ENV.delete(lc)
+ end
+ }
+ env = nil
+ yield(stdin, stdout, stderr)
+ end
+
+ ensure
+ env.each_pair {|lc, v|
+ if v
+ ENV[lc] = v
+ else
+ ENV.delete(lc)
+ end
+ } if env
+ stdin .close unless !stdin || stdin .closed?
+ stdout.close unless !stdout || stdout.closed?
+ stderr.close unless !stderr || stderr.closed?
+ end
+ module_function :rubyexec
+end
+
+module Test
+ module Unit
+ module Assertions
+ public
+ def assert_normal_exit(testsrc, message = '')
+ in_c, in_p = IO.pipe
+ out_p, out_c = IO.pipe
+ pid = spawn(EnvUtil.rubybin, '-W0', STDIN=>in_c, STDOUT=>out_c, STDERR=>out_c)
+ in_c.close
+ out_c.close
+ in_p.write testsrc
+ in_p.close
+ msg = out_p.read
+ out_p.close
+ Process.wait pid
+ status = $?
+ faildesc = nil
+ if status.signaled?
+ signo = status.termsig
+ signame = Signal.list.invert[signo]
+ sigdesc = "signal #{signo}"
+ if signame
+ sigdesc = "SIG#{signame} (#{sigdesc})"
+ end
+ if status.coredump?
+ sigdesc << " (core dumped)"
+ end
+ if msg.empty?
+ full_message = build_message(message, "pid ? killed by ?",
+ pid,
+ AssertionMessage::Literal.new(sigdesc))
+ else
+ msg << "\n" if /\n\z/ !~ msg
+ full_message = build_message(message, "pid ? killed by ?\n?",
+ pid,
+ AssertionMessage::Literal.new(sigdesc),
+ AssertionMessage::Literal.new(msg.gsub(/^/, '| ')))
+ end
+ end
+ assert_block(full_message) { !status.signaled? }
+ ensure
+ in_c.close if in_c && !in_c.closed?
+ in_p.close if in_p && !in_p.closed?
+ out_c.close if out_c && !out_c.closed?
+ out_p.close if out_p && !out_p.closed?
+ end
+
+ LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
+ def assert_in_out_err(args, test_stdin = "", test_stdout = "", test_stderr = "", message = nil)
+ in_c, in_p = IO.pipe
+ out_p, out_c = IO.pipe
+ err_p, err_c = IO.pipe
+ c = "C"
+ env = {}
+ LANG_ENVS.each {|lc| env[lc], ENV[lc] = ENV[lc], c}
+ pid = spawn(EnvUtil.rubybin, *args, STDIN=>in_c, STDOUT=>out_c, STDERR=>err_c)
+ in_c.close
+ out_c.close
+ err_c.close
+ in_p.write test_stdin
+ in_p.close
+ th_stdout = Thread.new { out_p.read }
+ th_stderr = Thread.new { err_p.read }
+ if th_stdout.join(10) && th_stderr.join(10)
+ stdout = th_stdout.value
+ stderr = th_stderr.value
+ else
+ flunk("timeout")
+ end
+ out_p.close
+ err_p.close
+ Process.wait pid
+ if block_given?
+ yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp })
+ else
+ if test_stdout.is_a?(Regexp)
+ assert_match(test_stdout, stdout, message)
+ else
+ assert_equal(test_stdout, stdout.lines.map {|l| l.chomp }, message)
+ end
+ if test_stderr.is_a?(Regexp)
+ assert_match(test_stderr, stderr, message)
+ else
+ assert_equal(test_stderr, stderr.lines.map {|l| l.chomp }, message)
+ end
+ end
+ ensure
+ env.each_pair {|lc, v|
+ if v
+ ENV[lc] = v
+ else
+ ENV.delete(lc)
+ end
+ } if env
+ in_c.close if in_c && !in_c.closed?
+ in_p.close if in_p && !in_p.closed?
+ out_c.close if out_c && !out_c.closed?
+ out_p.close if out_p && !out_p.closed?
+ err_c.close if err_c && !err_c.closed?
+ err_p.close if err_p && !err_p.closed?
+ (th_stdout.kill; th_stdout.join) if th_stdout
+ (th_stderr.kill; th_stderr.join) if th_stderr
+ end
+ end
+ end
+end
+
diff --git a/trunk/test/ruby/lbtest.rb b/trunk/test/ruby/lbtest.rb
new file mode 100644
index 0000000000..df7872dc76
--- /dev/null
+++ b/trunk/test/ruby/lbtest.rb
@@ -0,0 +1,48 @@
+require 'thread'
+
+class LocalBarrier
+ def initialize(n)
+ @wait = Queue.new
+ @done = Queue.new
+ @keeper = begin_keeper(n)
+ end
+
+ def sync
+ @done.push(true)
+ @wait.pop
+ end
+
+ def join
+ @keeper.join
+ end
+
+ private
+ def begin_keeper(n)
+ Thread.start do
+ n.times do
+ @done.pop
+ end
+ n.times do
+ @wait.push(true)
+ end
+ end
+ end
+end
+
+n = 10
+
+lb = LocalBarrier.new(n)
+
+(n - 1).times do |i|
+ Thread.start do
+ sleep((rand(n) + 1) / 10.0)
+ puts "#{i}: done"
+ lb.sync
+ puts "#{i}: cont"
+ end
+end
+
+lb.sync
+puts "#{n-1}: cone"
+
+puts "exit."
diff --git a/trunk/test/ruby/marshaltestlib.rb b/trunk/test/ruby/marshaltestlib.rb
new file mode 100644
index 0000000000..0a70380d44
--- /dev/null
+++ b/trunk/test/ruby/marshaltestlib.rb
@@ -0,0 +1,499 @@
+module MarshalTestLib
+ # include this module to a Test::Unit::TestCase and definde encode(o) and
+ # decode(s) methods. e.g.
+ #
+ # def encode(o)
+ # SOAPMarshal.dump(o)
+ # end
+ #
+ # def decode(s)
+ # SOAPMarshal.load(s)
+ # end
+
+ NegativeZero = (-1.0 / (1.0 / 0.0))
+
+ module Mod1; end
+ module Mod2; end
+
+ def marshaltest(o1)
+ str = encode(o1)
+ print str.dump, "\n" if $DEBUG
+ o2 = decode(str)
+ o2
+ end
+
+ def marshal_equal(o1, msg = nil)
+ msg = msg ? msg + "(#{ caller[0] })" : caller[0]
+ o2 = marshaltest(o1)
+ assert_equal(o1.class, o2.class, msg)
+ iv1 = o1.instance_variables.sort
+ iv2 = o2.instance_variables.sort
+ assert_equal(iv1, iv2)
+ val1 = iv1.map {|var| o1.instance_eval {eval var.to_s}}
+ val2 = iv1.map {|var| o2.instance_eval {eval var.to_s}}
+ assert_equal(val1, val2, msg)
+ if block_given?
+ assert_equal(yield(o1), yield(o2), msg)
+ else
+ assert_equal(o1, o2, msg)
+ end
+ end
+
+ class MyObject; def initialize(v) @v = v end; attr_reader :v; end
+ def test_object
+ o1 = Object.new
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_object_subclass
+ marshal_equal(MyObject.new(2)) {|o| o.v}
+ end
+
+ def test_object_extend
+ o1 = Object.new
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ def test_object_subclass_extend
+ o1 = MyObject.new(2)
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ class MyArray < Array
+ def initialize(v, *args)
+ super(args)
+ @v = v
+ end
+ end
+ def test_array
+ marshal_equal(5)
+ marshal_equal([1,2,3])
+ end
+
+ def test_array_subclass
+ marshal_equal(MyArray.new(0, 1, 2, 3))
+ end
+
+ def test_array_ivar
+ o1 = Array.new
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end
+ def test_exception
+ marshal_equal(Exception.new('foo')) {|o| o.message}
+ marshal_equal(assert_raise(NoMethodError) {no_such_method()}) {|o| o.message}
+ end
+
+ def test_exception_subclass
+ marshal_equal(MyException.new(20, "bar")) {|o| [o.message, o.v]}
+ end
+
+ def test_false
+ marshal_equal(false)
+ end
+
+ class MyHash < Hash; def initialize(v, *args) super(*args); @v = v; end end
+ def test_hash
+ marshal_equal({1=>2, 3=>4})
+ end
+
+ def test_hash_default
+ h = Hash.new(:default)
+ h[5] = 6
+ marshal_equal(h)
+ end
+
+ def test_hash_subclass
+ h = MyHash.new(7, 8)
+ h[4] = 5
+ marshal_equal(h)
+ end
+
+ def test_hash_default_proc
+ h = Hash.new {}
+ assert_raises(TypeError) { marshaltest(h) }
+ end
+
+ def test_hash_ivar
+ o1 = Hash.new
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_hash_extend
+ o1 = Hash.new
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ def test_hash_subclass_extend
+ o1 = MyHash.new(2)
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ def test_bignum
+ marshal_equal(-0x4000_0000_0000_0001)
+ marshal_equal(-0x4000_0001)
+ marshal_equal(0x4000_0000)
+ marshal_equal(0x4000_0000_0000_0000)
+ end
+
+ def test_fixnum
+ marshal_equal(-0x4000_0000)
+ marshal_equal(-0x3fff_ffff)
+ marshal_equal(-1)
+ marshal_equal(0)
+ marshal_equal(1)
+ marshal_equal(0x3fff_ffff)
+ end
+
+ def test_fixnum_ivar
+ o1 = 1
+ o1.instance_eval { @iv = 2 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ ensure
+ 1.instance_eval { remove_instance_variable("@iv") }
+ end
+
+ def test_fixnum_ivar_self
+ o1 = 1
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ ensure
+ 1.instance_eval { remove_instance_variable("@iv") }
+ end
+
+ def test_float
+ marshal_equal(-1.0)
+ marshal_equal(0.0)
+ marshal_equal(1.0)
+ end
+
+ def test_float_inf_nan
+ marshal_equal(1.0/0.0)
+ marshal_equal(-1.0/0.0)
+ marshal_equal(0.0/0.0) {|o| o.nan?}
+ marshal_equal(NegativeZero) {|o| 1.0/o}
+ end
+
+ def test_float_ivar
+ o1 = 1.23
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_float_ivar_self
+ o1 = 5.5
+ o1.instance_eval { @iv = o1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_float_extend
+ o1 = 0.0/0.0
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end
+ def test_range
+ marshal_equal(1..2)
+ marshal_equal(1...3)
+ end
+
+ def test_range_subclass
+ marshal_equal(MyRange.new(4,5,8, false))
+ end
+
+ class MyRegexp < Regexp; def initialize(v, *args) super(*args); @v = v; end end
+ def test_regexp
+ marshal_equal(/a/)
+ marshal_equal(/A/i)
+ marshal_equal(/A/mx)
+ end
+
+ def test_regexp_subclass
+ marshal_equal(MyRegexp.new(10, "a"))
+ end
+
+ class MyString < String; def initialize(v, *args) super(*args); @v = v; end end
+ def test_string
+ marshal_equal("abc")
+ end
+
+ def test_string_ivar
+ o1 = ""
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_string_subclass
+ marshal_equal(MyString.new(10, "a"))
+ end
+
+ def test_string_subclass_cycle
+ str = MyString.new(10, "b")
+ str.instance_eval { @v = str }
+ marshal_equal(str) { |o|
+ assert_equal(o.__id__, o.instance_eval { @v }.__id__)
+ o.instance_eval { @v }
+ }
+ end
+
+ def test_string_subclass_extend
+ o = "abc"
+ o.extend(Mod1)
+ str = MyString.new(o, "c")
+ marshal_equal(str) { |o|
+ assert(o.instance_eval { @v }).kind_of?(Mod1)
+ }
+ end
+
+ MyStruct = Struct.new("MyStruct", :a, :b)
+ if RUBY_VERSION < "1.8.0"
+ # Struct#== is not defined in ruby/1.6
+ class MyStruct
+ def ==(rhs)
+ return true if __id__ == rhs.__id__
+ return false unless rhs.is_a?(::Struct)
+ return false if self.class != rhs.class
+ members.each do |member|
+ return false if self.__send__(member) != rhs.__send__(member)
+ end
+ return true
+ end
+ end
+ end
+ class MySubStruct < MyStruct; def initialize(v, *args) super(*args); @v = v; end end
+ def test_struct
+ marshal_equal(MyStruct.new(1,2))
+ end
+
+ def test_struct_subclass
+ if RUBY_VERSION < "1.8.0"
+ # Substruct instance cannot be dumped in ruby/1.6
+ # ::Marshal.dump(MySubStruct.new(10, 1, 2)) #=> uninitialized struct
+ return false
+ end
+ marshal_equal(MySubStruct.new(10,1,2))
+ end
+
+ def test_struct_ivar
+ o1 = MyStruct.new
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_struct_subclass_extend
+ o1 = MyStruct.new
+ o1.extend(Mod1)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ o1.extend(Mod2)
+ marshal_equal(o1) { |o|
+ (class << self; self; end).ancestors
+ }
+ end
+
+ def test_symbol
+ marshal_equal(:a)
+ marshal_equal(:a?)
+ marshal_equal(:a!)
+ marshal_equal(:a=)
+ marshal_equal(:|)
+ marshal_equal(:^)
+ marshal_equal(:&)
+ marshal_equal(:<=>)
+ marshal_equal(:==)
+ marshal_equal(:===)
+ marshal_equal(:=~)
+ marshal_equal(:>)
+ marshal_equal(:>=)
+ marshal_equal(:<)
+ marshal_equal(:<=)
+ marshal_equal(:<<)
+ marshal_equal(:>>)
+ marshal_equal(:+)
+ marshal_equal(:-)
+ marshal_equal(:*)
+ marshal_equal(:/)
+ marshal_equal(:%)
+ marshal_equal(:**)
+ marshal_equal(:~)
+ marshal_equal(:+@)
+ marshal_equal(:-@)
+ marshal_equal(:[])
+ marshal_equal(:[]=)
+ marshal_equal(:`) #`
+ marshal_equal("a b".intern)
+ end
+
+ class MyTime < Time; def initialize(v, *args) super(*args); @v = v; end end
+ def test_time
+ # once there was a bug caused by usec overflow. try a little harder.
+ 10.times do
+ t = Time.now
+ marshal_equal(t, t.usec.to_s)
+ end
+ end
+
+ def test_time_subclass
+ marshal_equal(MyTime.new(10))
+ end
+
+ def test_time_ivar
+ o1 = Time.now
+ o1.instance_eval { @iv = 1 }
+ marshal_equal(o1) {|o| o.instance_eval { @iv }}
+ end
+
+ def test_time_in_array
+ t = Time.now
+ assert_equal([t,t], Marshal.load(Marshal.dump([t, t])), "[ruby-dev:34159]")
+ end
+
+ def test_true
+ marshal_equal(true)
+ end
+
+ def test_nil
+ marshal_equal(nil)
+ end
+
+ def test_share
+ o = [:share]
+ o1 = [o, o]
+ o2 = marshaltest(o1)
+ assert_same(o2.first, o2.last)
+ end
+
+ class CyclicRange < Range
+ def <=>(other); true; end
+ end
+ def test_range_cyclic
+ return unless CyclicRange.respond_to?(:allocate) # test for 1.8
+ o1 = CyclicRange.allocate
+ o1.instance_eval { initialize(o1, o1) }
+ o2 = marshaltest(o1)
+ assert_same(o2, o2.begin)
+ assert_same(o2, o2.end)
+ end
+
+ def test_singleton
+ o = Object.new
+ def o.m() end
+ assert_raises(TypeError) { marshaltest(o) }
+ o = Object.new
+ c = class << o
+ @v = 1
+ class C; self; end
+ end
+ assert_raises(TypeError) { marshaltest(o) }
+ assert_raises(TypeError) { marshaltest(c) }
+ assert_raises(TypeError) { marshaltest(ARGF) }
+ assert_raises(TypeError) { marshaltest(ENV) }
+ end
+
+ def test_extend
+ o = Object.new
+ o.extend Mod1
+ marshal_equal(o) { |obj| obj.kind_of? Mod1 }
+ o = Object.new
+ o.extend Mod1
+ o.extend Mod2
+ marshal_equal(o) {|obj| class << obj; ancestors end}
+ o = Object.new
+ o.extend Module.new
+ assert_raises(TypeError) { marshaltest(o) }
+ end
+
+ def test_extend_string
+ o = ""
+ o.extend Mod1
+ marshal_equal(o) { |obj| obj.kind_of? Mod1 }
+ o = ""
+ o.extend Mod1
+ o.extend Mod2
+ marshal_equal(o) {|obj| class << obj; ancestors end}
+ o = ""
+ o.extend Module.new
+ assert_raises(TypeError) { marshaltest(o) }
+ end
+
+ def test_anonymous
+ c = Class.new
+ assert_raises(TypeError) { marshaltest(c) }
+ o = c.new
+ assert_raises(TypeError) { marshaltest(o) }
+ m = Module.new
+ assert_raises(TypeError) { marshaltest(m) }
+ end
+
+ def test_string_empty
+ marshal_equal("")
+ end
+
+ def test_string_crlf
+ marshal_equal("\r\n")
+ end
+
+ def test_string_escape
+ marshal_equal("\0<;;>\1;;")
+ end
+
+ MyStruct2 = Struct.new(:a, :b)
+ if RUBY_VERSION < "1.8.0"
+ # Struct#== is not defined in ruby/1.6
+ class MyStruct2
+ def ==(rhs)
+ return true if __id__ == rhs.__id__
+ return false unless rhs.is_a?(::Struct)
+ return false if self.class != rhs.class
+ members.each do |member|
+ return false if self.__send__(member) != rhs.__send__(member)
+ end
+ return true
+ end
+ end
+ end
+ def test_struct_toplevel
+ o = MyStruct2.new(1,2)
+ marshal_equal(o)
+ end
+end
diff --git a/trunk/test/ruby/sentence.rb b/trunk/test/ruby/sentence.rb
new file mode 100644
index 0000000000..50f42d6885
--- /dev/null
+++ b/trunk/test/ruby/sentence.rb
@@ -0,0 +1,668 @@
+# == sentence library
+#
+# = Features
+#
+# * syntax based sentences generation
+# * sentence operations such as substitution.
+#
+# = Example
+#
+# Some arithmetic expressions using "+", "-", "*" and "/" are generated as follows.
+#
+# require 'sentence'
+# Sentence.each({
+# :exp => [["num"],
+# [:exp, "+", :exp],
+# [:exp, "-", :exp],
+# [:exp, "*", :exp],
+# [:exp, "/", :exp]]
+# }, :exp, 2) {|sent| p sent }
+# #=>
+# #<Sentence: "num">
+# #<Sentence: ("num") "+" ("num")>
+# #<Sentence: ("num") "+" (("num") "+" ("num"))>
+# #<Sentence: ("num") "+" (("num") "-" ("num"))>
+# #<Sentence: ("num") "+" (("num") "*" ("num"))>
+# #<Sentence: ("num") "+" (("num") "/" ("num"))>
+# #<Sentence: (("num") "+" ("num")) "+" ("num")>
+# ...
+#
+# Sentence.each takes 3 arguments.
+# The first argument is the syntax for the expressions.
+# The second argument, :exp, is a generating nonterminal.
+# The third argument, 2, limits derivation to restrict results finitely.
+#
+# Some arithmetic expressions including parenthesis can be generated as follows.
+#
+# syntax = {
+# :factor => [["n"],
+# ["(", :exp, ")"]],
+# :term => [[:factor],
+# [:term, "*", :factor],
+# [:term, "/", :factor]],
+# :exp => [[:term],
+# [:exp, "+", :term],
+# [:exp, "-", :term]]
+# }
+# Sentence.each(syntax, :exp, 2) {|sent| p sent }
+# #=>
+# #<Sentence: (("n"))>
+# #<Sentence: (("(" ((("n"))) ")"))>
+# #<Sentence: (("(" ((("(" ((("n"))) ")"))) ")"))>
+# #<Sentence: (("(" (((("n")) "*" ("n"))) ")"))>
+# #<Sentence: (("(" (((("n")) "/" ("n"))) ")"))>
+# #<Sentence: (("(" (((("n"))) "+" (("n"))) ")"))>
+# #<Sentence: (("(" (((("n"))) "-" (("n"))) ")"))>
+# #<Sentence: ((("n")) "*" ("n"))>
+# #<Sentence: ((("n")) "*" ("(" ((("n"))) ")"))>
+# ...
+#
+# Sentence#to_s can be used to concatenate strings
+# in a sentence:
+#
+# Sentence.each(syntax, :exp, 2) {|sent| p sent.to_s }
+# #=>
+# "n"
+# "(n)"
+# "((n))"
+# "(n*n)"
+# "(n/n)"
+# "(n+n)"
+# "(n-n)"
+# "n*n"
+# "n*(n)"
+# ...
+#
+
+# Sentence() instantiates a sentence object.
+#
+# Sentence("foo", "bar")
+# #=> #<Sentence: "foo" "bar">
+#
+# Sentence("foo", ["bar", "baz"])
+# #=> #<Sentence: "foo" ("bar" "baz")>
+#
+def Sentence(*ary)
+ Sentence.new(ary)
+end
+
+# Sentence class represents a tree with string leaves.
+#
+class Sentence
+ # _ary_ represents a tree.
+ # It should be a possibly nested array which contains strings.
+ #
+ # Note that _ary_ is not copied.
+ # Don't modify _ary_ after the sentence object is instantiated.
+ #
+ # Sentence.new(["a", "pen"])
+ # #<Sentence: "a" "pen">
+ #
+ # Sentence.new(["I", "have", ["a", "pen"]])
+ # #<Sentence: "I" "have" ("a" "pen")>
+ #
+ def initialize(ary)
+ @sent = ary
+ end
+
+ # returns a string which is concatenation of all strings.
+ # No separator is used.
+ #
+ # Sentence("2", "+", "3").to_s
+ # "2+3"
+ #
+ # Sentence("2", "+", ["3", "*", "5"]).to_s
+ # "2+3*5"
+ #
+ def to_s
+ @sent.join('')
+ end
+
+ # returns a string which is concatenation of all strings separated by _sep_.
+ # If _sep_ is not given, single space is used.
+ #
+ # Sentence("I", "have", ["a", "pen"]).join
+ # "I have a pen"
+ #
+ # Sentence("I", "have", ["a", "pen"]).join("/")
+ # "I/have/a/pen"
+ #
+ # Sentence("a", [], "b").join("/")
+ # "a/b"
+ #
+ def join(sep=' ')
+ @sent.flatten.join(sep)
+ end
+
+ # returns a tree as a nested array.
+ #
+ # Note that the result is not copied.
+ # Don't modify the result.
+ #
+ # Sentence(["foo", "bar"], "baz").to_a
+ # #=> [["foo", "bar"], "baz"]
+ #
+ def to_a
+ @sent
+ end
+
+ # returns <i>i</i>th element as a sentence or string.
+ #
+ # s = Sentence(["foo", "bar"], "baz")
+ # s #=> #<Sentence: ("foo" "bar") "baz">
+ # s[0] #=> #<Sentence: "foo" "bar">
+ # s[1] #=> "baz"
+ #
+ def [](i)
+ e = @sent[i]
+ e.respond_to?(:to_ary) ? Sentence.new(e) : e
+ end
+
+ # returns the number of top level elements.
+ #
+ # Sentence.new(%w[foo bar]).length
+ # #=> 2
+ #
+ # Sentence(%w[2 * 7], "+", %w[3 * 5]).length
+ # #=> 3
+ #
+ def length
+ @sent.length
+ end
+
+ # iterates over children.
+ #
+ # Sentence(%w[2 * 7], "+", %w[3 * 5]).each {|v| p v }
+ # #=>
+ # #<Sentence: "2" "*" "7">
+ # "+"
+ # #<Sentence: "3" "*" "5">
+ #
+ def each # :yield: element
+ @sent.each_index {|i|
+ yield self[i]
+ }
+ end
+ include Enumerable
+
+ def inspect
+ "#<#{self.class}: #{inner_inspect(@sent, '')}>"
+ end
+
+ # :stopdoc:
+ def inner_inspect(ary, r)
+ first = true
+ ary.each {|obj|
+ r << ' ' if !first
+ first = false
+ if obj.respond_to? :to_ary
+ r << '('
+ inner_inspect(obj, r)
+ r << ')'
+ else
+ r << obj.inspect
+ end
+ }
+ r
+ end
+ # :startdoc:
+
+ # returns new sentence object which
+ # _target_ is substituted by the block.
+ #
+ # Sentence#subst invokes <tt>_target_ === _string_</tt> for each
+ # string in the sentence.
+ # The strings which === returns true are substituted by the block.
+ # The block is invoked with the substituting string.
+ #
+ # Sentence.new(%w[2 + 3]).subst("+") { "*" }
+ # #<Sentence: "2" "*" "3">
+ #
+ # Sentence.new(%w[2 + 3]).subst(/\A\d+\z/) {|s| ((s.to_i)*2).to_s }
+ # #=> #<Sentence: "4" "+" "6">
+ #
+ def subst(target, &b) # :yield: string
+ Sentence.new(subst_rec(@sent, target, &b))
+ end
+
+ # :stopdoc:
+ def subst_rec(obj, target, &b)
+ if obj.respond_to? :to_ary
+ a = []
+ obj.each {|e| a << subst_rec(e, target, &b) }
+ a
+ elsif target === obj
+ yield obj
+ else
+ obj
+ end
+ end
+ # :startdoc:
+
+ # find a subsentence and return it.
+ # The block is invoked for each subsentence in preorder manner.
+ # The first subsentence which the block returns true is returned.
+ #
+ # Sentence(%w[2 * 7], "+", %w[3 * 5]).find_subtree {|s| s[1] == "*" }
+ # #=> #<Sentence: "2" "*" "7">
+ #
+ def find_subtree(&b) # :yield: sentence
+ find_subtree_rec(@sent, &b)
+ end
+
+ # :stopdoc:
+ def find_subtree_rec(obj, &b)
+ if obj.respond_to? :to_ary
+ s = Sentence.new(obj)
+ if b.call s
+ return s
+ else
+ obj.each {|e|
+ r = find_subtree_rec(e, &b)
+ return r if r
+ }
+ end
+ end
+ nil
+ end
+ # :startdoc:
+
+ # returns a new sentence object which expands according to the condition
+ # given by the block.
+ #
+ # The block is invoked for each subsentence.
+ # The subsentences which the block returns true are
+ # expanded into parent.
+ #
+ # s = Sentence(%w[2 * 7], "+", %w[3 * 5])
+ # #=> #<Sentence: ("2" "*" "7") "+" ("3" "*" "5")>
+ #
+ # s.expand { true }
+ # #=> #<Sentence: "2" "*" "7" "+" "3" "*" "5">
+ #
+ # s.expand {|s| s[0] == "3" }
+ # #=> #<Sentence: (("2" "*" "7") "+" "3" "*" "5")>
+ #
+ def expand(&b) # :yield: sentence
+ Sentence.new(expand_rec(@sent, &b))
+ end
+
+ # :stopdoc:
+ def expand_rec(obj, r=[], &b)
+ if obj.respond_to? :to_ary
+ obj.each {|o|
+ s = Sentence.new(o)
+ if b.call s
+ expand_rec(o, r, &b)
+ else
+ a = []
+ expand_rec(o, a, &b)
+ r << a
+ end
+ }
+ else
+ r << obj
+ end
+ r
+ end
+ # :startdoc:
+
+ # Sentence.each generates sentences
+ # by deriving the start symbol _sym_ using _syntax_.
+ # The derivation is restricted by an positive integer _limit_ to
+ # avoid infinite generation.
+ #
+ # Sentence.each yields the block with a generated sentence.
+ #
+ # Sentence.each({
+ # :exp => [["n"],
+ # [:exp, "+", :exp],
+ # [:exp, "*", :exp]]
+ # }, :exp, 1) {|sent| p sent }
+ # #=>
+ # #<Sentence: "n">
+ # #<Sentence: ("n") "+" ("n")>
+ # #<Sentence: ("n") "*" ("n")>
+ #
+ # Sentence.each({
+ # :exp => [["n"],
+ # [:exp, "+", :exp],
+ # [:exp, "*", :exp]]
+ # }, :exp, 2) {|sent| p sent }
+ # #=>
+ # #<Sentence: "n">
+ # #<Sentence: ("n") "+" ("n")>
+ # #<Sentence: ("n") "+" (("n") "+" ("n"))>
+ # #<Sentence: ("n") "+" (("n") "*" ("n"))>
+ # #<Sentence: (("n") "+" ("n")) "+" ("n")>
+ # #<Sentence: (("n") "*" ("n")) "+" ("n")>
+ # #<Sentence: ("n") "*" ("n")>
+ # #<Sentence: ("n") "*" (("n") "+" ("n"))>
+ # #<Sentence: ("n") "*" (("n") "*" ("n"))>
+ # #<Sentence: (("n") "+" ("n")) "*" ("n")>
+ # #<Sentence: (("n") "*" ("n")) "*" ("n")>
+ #
+ def Sentence.each(syntax, sym, limit)
+ Gen.new(syntax).each_tree(sym, limit) {|tree|
+ yield Sentence.new(tree)
+ }
+ end
+
+ # Sentence.expand_syntax returns an expanded syntax:
+ # * No rule derives to empty sequence
+ # * Underivable rule simplified
+ # * No channel rule
+ # * Symbols which has zero or one choices are not appered in rhs.
+ #
+ # Note that the rules which can derive empty and non-empty
+ # sequences are modified to derive only non-empty sequences.
+ #
+ # Sentence.expand_syntax({
+ # :underivable1 => [],
+ # :underivable2 => [[:underivable1]],
+ # :underivable3 => [[:underivable3]],
+ # :empty_only1 => [[]],
+ # :empty_only2 => [[:just_empty1, :just_empty1]],
+ # :empty_or_not => [[], ["foo"]],
+ # :empty_or_not_2 => [[:empty_or_not, :empty_or_not]],
+ # :empty_or_not_3 => [[:empty_or_not, :empty_or_not, :empty_or_not]],
+ # :empty_or_not_4 => [[:empty_or_not_2, :empty_or_not_2]],
+ # :channel1 => [[:channeled_data]],
+ # :channeled_data => [["a", "b"], ["c", "d"]],
+ # :single_choice => [["single", "choice"]],
+ # :single_choice_2 => [[:single_choice, :single_choice]],
+ # })
+ # #=>
+ # {
+ # :underivable1=>[], # underivable rules are simplified to [].
+ # :underivable2=>[],
+ # :underivable3=>[],
+ # :empty_only1=>[], # derivation to empty sequence are removed.
+ # :empty_only2=>[],
+ # :empty_or_not=>[["foo"]], # empty sequences are removed too.
+ # :empty_or_not_2=>[["foo"], ["foo", "foo"]],
+ # :empty_or_not_3=>[["foo"], ["foo", "foo"], ["foo", "foo", "foo"]],
+ # :empty_or_not_4=> [["foo"], ["foo", "foo"], [:empty_or_not_2, :empty_or_not_2]],
+ # :channel1=>[["a", "b"], ["c", "d"]], # channel rules are removed.
+ # :channeled_data=>[["a", "b"], ["c", "d"]],
+ # :single_choice=>[["single", "choice"]], # single choice rules are expanded.
+ # :single_choice_2=>[["single", "choice", "single", "choice"]],
+ # }
+ #
+ # Sentence.expand_syntax({
+ # :factor => [["n"],
+ # ["(", :exp, ")"]],
+ # :term => [[:factor],
+ # [:term, "*", :factor],
+ # [:term, "/", :factor]],
+ # :exp => [[:term],
+ # [:exp, "+", :term],
+ # [:exp, "-", :term]]
+ # })
+ # #=>
+ # {:exp=> [["n"],
+ # ["(", :exp, ")"],
+ # [:exp, "+", :term],
+ # [:exp, "-", :term],
+ # [:term, "*", :factor],
+ # [:term, "/", :factor]],
+ # :factor=> [["n"],
+ # ["(", :exp, ")"]],
+ # :term=> [["n"],
+ # ["(", :exp, ")"],
+ # [:term, "*", :factor],
+ # [:term, "/", :factor]]
+ # }
+ #
+ def Sentence.expand_syntax(syntax)
+ Sentence::Gen.expand_syntax(syntax)
+ end
+
+ # :stopdoc:
+ class Gen
+ def Gen.each_tree(syntax, sym, limit, &b)
+ Gen.new(syntax).each_tree(sym, limit, &b)
+ end
+
+ def Gen.each_string(syntax, sym, limit, &b)
+ Gen.new(syntax).each_string(sym, limit, &b)
+ end
+
+ def initialize(syntax)
+ @syntax = syntax
+ end
+
+ def self.expand_syntax(syntax)
+ syntax = simplify_underivable_rules(syntax)
+ syntax = simplify_emptyonly_rules(syntax)
+ syntax = make_rules_no_empseq(syntax)
+ syntax = expand_channel_rules(syntax)
+
+ syntax = expand_noalt_rules(syntax)
+ syntax = reorder_rules(syntax)
+ end
+
+ def self.simplify_underivable_rules(syntax)
+ deribable_syms = {}
+ changed = true
+ while changed
+ changed = false
+ syntax.each {|sym, rules|
+ next if deribable_syms[sym]
+ rules.each {|rhs|
+ if rhs.all? {|e| String === e || deribable_syms[e] }
+ deribable_syms[sym] = true
+ changed = true
+ break
+ end
+ }
+ }
+ end
+ result = {}
+ syntax.each {|sym, rules|
+ if deribable_syms[sym]
+ rules2 = []
+ rules.each {|rhs|
+ rules2 << rhs if rhs.all? {|e| String === e || deribable_syms[e] }
+ }
+ result[sym] = rules2.uniq
+ else
+ result[sym] = []
+ end
+ }
+ result
+ end
+
+ def self.simplify_emptyonly_rules(syntax)
+ justempty_syms = {}
+ changed = true
+ while changed
+ changed = false
+ syntax.each {|sym, rules|
+ next if justempty_syms[sym]
+ if !rules.empty? && rules.all? {|rhs| rhs.all? {|e| justempty_syms[e] } }
+ justempty_syms[sym] = true
+ changed = true
+ end
+ }
+ end
+ result = {}
+ syntax.each {|sym, rules|
+ result[sym] = rules.map {|rhs| rhs.reject {|e| justempty_syms[e] } }.uniq
+ }
+ result
+ end
+
+ def self.expand_emptyable_syms(rhs, emptyable_syms)
+ if rhs.empty?
+ yield []
+ else
+ first = rhs[0]
+ rest = rhs[1..-1]
+ if emptyable_syms[first]
+ expand_emptyable_syms(rest, emptyable_syms) {|rhs2|
+ yield [first] + rhs2
+ yield rhs2
+ }
+ else
+ expand_emptyable_syms(rest, emptyable_syms) {|rhs2|
+ yield [first] + rhs2
+ }
+ end
+ end
+ end
+
+ def self.make_rules_no_empseq(syntax)
+ emptyable_syms = {}
+ changed = true
+ while changed
+ changed = false
+ syntax.each {|sym, rules|
+ next if emptyable_syms[sym]
+ rules.each {|rhs|
+ if rhs.all? {|e| emptyable_syms[e] }
+ emptyable_syms[sym] = true
+ changed = true
+ break
+ end
+ }
+ }
+ end
+ result = {}
+ syntax.each {|sym, rules|
+ rules2 = []
+ rules.each {|rhs|
+ expand_emptyable_syms(rhs, emptyable_syms) {|rhs2|
+ next if rhs2.empty?
+ rules2 << rhs2
+ }
+ }
+ result[sym] = rules2.uniq
+ }
+ result
+ end
+
+ def self.expand_channel_rules(syntax)
+ channel_rules = {}
+ syntax.each {|sym, rules|
+ channel_rules[sym] = {sym=>true}
+ rules.each {|rhs|
+ if rhs.length == 1 && Symbol === rhs[0]
+ channel_rules[sym][rhs[0]] = true
+ end
+ }
+ }
+ changed = true
+ while changed
+ changed = false
+ channel_rules.each {|sym, set|
+ n1 = set.size
+ set.keys.each {|s|
+ set.update(channel_rules[s])
+ }
+ n2 = set.size
+ changed = true if n1 < n2
+ }
+ end
+ result = {}
+ syntax.each {|sym, rules|
+ rules2 = []
+ channel_rules[sym].each_key {|s|
+ syntax[s].each {|rhs|
+ unless rhs.length == 1 && Symbol === rhs[0]
+ rules2 << rhs
+ end
+ }
+ }
+ result[sym] = rules2.uniq
+ }
+ result
+ end
+
+ def self.expand_noalt_rules(syntax)
+ noalt_syms = {}
+ syntax.each {|sym, rules|
+ if rules.length == 1
+ noalt_syms[sym] = true
+ end
+ }
+ result = {}
+ syntax.each {|sym, rules|
+ rules2 = []
+ rules.each {|rhs|
+ rhs2 = []
+ rhs.each {|e|
+ if noalt_syms[e]
+ rhs2.concat syntax[e][0]
+ else
+ rhs2 << e
+ end
+ }
+ rules2 << rhs2
+ }
+ result[sym] = rules2.uniq
+ }
+ result
+ end
+
+ def self.reorder_rules(syntax)
+ result = {}
+ syntax.each {|sym, rules|
+ result[sym] = rules.sort_by {|rhs|
+ [rhs.find_all {|e| Symbol === e }.length, rhs.length]
+ }
+ }
+ result
+ end
+
+ def each_tree(sym, limit)
+ generate_from_sym(sym, limit) {|_, tree|
+ yield tree
+ }
+ nil
+ end
+
+ def each_string(sym, limit)
+ generate_from_sym(sym, limit) {|_, tree|
+ yield [tree].join('')
+ }
+ nil
+ end
+
+ def generate_from_sym(sym, limit, &b)
+ return if limit < 0
+ if String === sym
+ yield limit, sym
+ else
+ rules = @syntax[sym]
+ raise "undefined rule: #{sym}" if !rules
+ rules.each {|rhs|
+ if rhs.length == 1 || rules.length == 1
+ limit1 = limit
+ else
+ limit1 = limit-1
+ end
+ generate_from_rhs(rhs, limit1, &b)
+ }
+ end
+ nil
+ end
+
+ def generate_from_rhs(rhs, limit)
+ return if limit < 0
+ if rhs.empty?
+ yield limit, []
+ else
+ generate_from_sym(rhs[0], limit) {|limit1, child|
+ generate_from_rhs(rhs[1..-1], limit1) {|limit2, arr|
+ yield limit2, [child, *arr]
+ }
+ }
+ end
+ nil
+ end
+ end
+ # :startdoc:
+
+end
+
diff --git a/trunk/test/ruby/test_alias.rb b/trunk/test/ruby/test_alias.rb
new file mode 100644
index 0000000000..d72fe702af
--- /dev/null
+++ b/trunk/test/ruby/test_alias.rb
@@ -0,0 +1,64 @@
+require 'test/unit'
+
+class TestAlias < Test::Unit::TestCase
+ class Alias0
+ def foo
+ "foo"
+ end
+ end
+
+ class Alias1 < Alias0
+ alias bar foo
+
+ def foo
+ "foo+#{super}"
+ end
+ end
+
+ class Alias2 < Alias1
+ alias baz foo
+ undef foo
+ end
+
+ class Alias3 < Alias2
+ def foo
+ super
+ end
+
+ def bar
+ super
+ end
+
+ def quux
+ super
+ end
+ end
+
+ def test_alias
+ x = Alias2.new
+ assert_equal "foo", x.bar
+ assert_equal "foo+foo", x.baz
+ assert_equal "foo+foo", x.baz # test_check for cache
+
+ x = Alias3.new
+ assert_raise(NoMethodError) { x.foo }
+ assert_equal "foo", x.bar
+ assert_raise(NoMethodError) { x.quux }
+ end
+
+ class C
+ def m
+ $SAFE
+ end
+ end
+
+ def test_JVN_83768862
+ d = lambda {
+ $SAFE = 4
+ dclass = Class.new(C)
+ dclass.send(:alias_method, :mm, :m)
+ dclass.new
+ }.call
+ assert_raise(SecurityError) { d.mm }
+ end
+end
diff --git a/trunk/test/ruby/test_argf.rb b/trunk/test/ruby/test_argf.rb
new file mode 100644
index 0000000000..eb5556b98a
--- /dev/null
+++ b/trunk/test/ruby/test_argf.rb
@@ -0,0 +1,701 @@
+require 'test/unit'
+require 'timeout'
+require 'tmpdir'
+require 'tempfile'
+require_relative 'envutil'
+
+class TestArgf < Test::Unit::TestCase
+ def setup
+ @t1 = Tempfile.new("foo")
+ @t1.binmode
+ @t1.puts "1"
+ @t1.puts "2"
+ @t1.close
+ @t2 = Tempfile.new("bar")
+ @t2.binmode
+ @t2.puts "3"
+ @t2.puts "4"
+ @t2.close
+ @t3 = Tempfile.new("baz")
+ @t3.binmode
+ @t3.puts "5"
+ @t3.puts "6"
+ @t3.close
+ @tmps = [@t1, @t2, @t3]
+ end
+
+ def teardown
+ @tmps.each {|t|
+ bak = t.path + ".bak"
+ File.unlink bak if File.file? bak
+ }
+ end
+
+ def make_tempfile
+ t = Tempfile.new("foo")
+ t.puts "foo"
+ t.puts "bar"
+ t.puts "baz"
+ t.close
+ @tmps << t
+ t
+ end
+
+ def ruby(*args)
+ args = ['-e', '$>.write($<.read)'] if args.empty?
+ ruby = EnvUtil.rubybin
+ f = IO.popen([ruby] + args, 'r+')
+ yield(f)
+ ensure
+ f.close unless !f || f.closed?
+ end
+
+ def no_safe_rename
+ /cygwin|mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ end
+
+ def test_argf
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ a = ARGF
+ b = a.dup
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["1", 1, "1", 1]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["2", 2, "2", 2]
+ a.rewind
+ b.rewind
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["1", 1, "1", 3]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["2", 2, "2", 4]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["3", 3, "3", 5]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["4", 4, "4", 6]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["5", 5, "5", 7]
+ a.rewind
+ b.rewind
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["5", 5, "5", 8]
+ p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["6", 6, "6", 9]
+ SRC
+ a = f.read.split("\n")
+ assert_equal('["1", 1, "1", 1]', a.shift)
+ assert_equal('["2", 2, "2", 2]', a.shift)
+ assert_equal('["1", 1, "1", 3]', a.shift)
+ assert_equal('["2", 2, "2", 4]', a.shift)
+ assert_equal('["3", 3, "3", 5]', a.shift)
+ assert_equal('["4", 4, "4", 6]', a.shift)
+ assert_equal('["5", 5, "5", 7]', a.shift)
+ assert_equal('["5", 5, "5", 8]', a.shift)
+ assert_equal('["6", 6, "6", 9]', a.shift)
+
+ # is this test OK? [ruby-dev:34445]
+ end
+ end
+
+ def test_lineno
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ a = ARGF
+ a.gets; p $. #=> 1
+ a.gets; p $. #=> 2
+ a.gets; p $. #=> 3
+ a.rewind; p $. #=> 3
+ a.gets; p $. #=> 3
+ a.gets; p $. #=> 4
+ a.rewind; p $. #=> 4
+ a.gets; p $. #=> 3
+ a.lineno = 1000; p $. #=> 1000
+ a.gets; p $. #=> 1001
+ a.gets; p $. #=> 1002
+ $. = 2000
+ a.gets; p $. #=> 2001
+ a.gets; p $. #=> 2001
+ SRC
+ assert_equal("1,2,3,3,3,4,4,3,1000,1001,1002,2001,2001", f.read.chomp.gsub("\n", ","))
+ end
+ end
+
+ def test_lineno2
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ a = ARGF.dup
+ a.gets; p $. #=> 1
+ a.gets; p $. #=> 2
+ a.gets; p $. #=> 1
+ a.rewind; p $. #=> 1
+ a.gets; p $. #=> 1
+ a.gets; p $. #=> 2
+ a.gets; p $. #=> 1
+ a.lineno = 1000; p $. #=> 1
+ a.gets; p $. #=> 2
+ a.gets; p $. #=> 2
+ $. = 2000
+ a.gets; p $. #=> 2001
+ a.gets; p $. #=> 2000
+ SRC
+ assert_equal("1,2,1,1,1,2,1,1,2,2,2000,2000", f.read.chomp.gsub("\n", ","))
+ end
+ end
+
+ def test_inplace
+ assert_in_out_err(["-", @t1.path, @t2.path, @t3.path], <<-INPUT, [], [])
+ ARGF.inplace_mode = '.bak'
+ while line = ARGF.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ assert_equal("1.new\n2.new\n", File.read(@t1.path))
+ assert_equal("3.new\n4.new\n", File.read(@t2.path))
+ assert_equal("5.new\n6.new\n", File.read(@t3.path))
+ assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+ assert_equal("3\n4\n", File.read(@t2.path + ".bak"))
+ assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+ end
+
+ def test_inplace2
+ assert_in_out_err(["-", @t1.path, @t2.path, @t3.path], <<-INPUT, [], [])
+ ARGF.inplace_mode = '.bak'
+ puts ARGF.gets.chomp + '.new'
+ puts ARGF.gets.chomp + '.new'
+ p ARGF.inplace_mode
+ ARGF.inplace_mode = nil
+ puts ARGF.gets.chomp + '.new'
+ puts ARGF.gets.chomp + '.new'
+ p ARGF.inplace_mode
+ ARGF.inplace_mode = '.bak'
+ puts ARGF.gets.chomp + '.new'
+ p ARGF.inplace_mode
+ ARGF.inplace_mode = nil
+ puts ARGF.gets.chomp + '.new'
+ INPUT
+ assert_equal("1.new\n2.new\n\".bak\"\n3.new\n4.new\nnil\n", File.read(@t1.path))
+ assert_equal("3\n4\n", File.read(@t2.path))
+ assert_equal("5.new\n\".bak\"\n6.new\n", File.read(@t3.path))
+ assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+ assert_equal(false, File.file?(@t2.path + ".bak"))
+ assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+ end
+
+ def test_inplace3
+ assert_in_out_err(["-i.bak", "-", @t1.path, @t2.path, @t3.path], <<-INPUT, [], [])
+ puts ARGF.gets.chomp + '.new'
+ puts ARGF.gets.chomp + '.new'
+ p $-i
+ $-i = nil
+ puts ARGF.gets.chomp + '.new'
+ puts ARGF.gets.chomp + '.new'
+ p $-i
+ $-i = '.bak'
+ puts ARGF.gets.chomp + '.new'
+ p $-i
+ $-i = nil
+ puts ARGF.gets.chomp + '.new'
+ INPUT
+ assert_equal("1.new\n2.new\n\".bak\"\n3.new\n4.new\nnil\n", File.read(@t1.path))
+ assert_equal("3\n4\n", File.read(@t2.path))
+ assert_equal("5.new\n\".bak\"\n6.new\n", File.read(@t3.path))
+ assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+ assert_equal(false, File.file?(@t2.path + ".bak"))
+ assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+ end
+
+ def test_inplace_rename_impossible
+ t = make_tempfile
+
+ assert_in_out_err(["-", t.path], <<-INPUT) do |r, e|
+ ARGF.inplace_mode = '/\\\\'
+ while line = ARGF.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ if no_safe_rename
+ assert_equal([], e)
+ assert_equal([], r)
+ assert_equal("foo.new\nbar.new\nbaz.new\n", File.read(t.path))
+ else
+ assert_match(/Can't rename .* to .*: .*. skipping file/, e.first) #'
+ assert_equal([], r)
+ assert_equal("foo\nbar\nbaz\n", File.read(t.path))
+ end
+ end
+ end
+
+ def test_inplace_no_backup
+ t = make_tempfile
+
+ assert_in_out_err(["-", t.path], <<-INPUT) do |r, e|
+ ARGF.inplace_mode = ''
+ while line = ARGF.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ if no_safe_rename
+ assert_match(/Can't do inplace edit without backup/, e.join) #'
+ else
+ assert_equal([], e)
+ assert_equal([], r)
+ assert_equal("foo.new\nbar.new\nbaz.new\n", File.read(t.path))
+ end
+ end
+ end
+
+ def test_inplace_dup
+ t = make_tempfile
+
+ assert_in_out_err(["-", t.path], <<-INPUT, [], [])
+ ARGF.inplace_mode = '.bak'
+ f = ARGF.dup
+ while line = f.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ assert_equal("foo.new\nbar.new\nbaz.new\n", File.read(t.path))
+ end
+
+ def test_inplace_stdin
+ t = make_tempfile
+
+ assert_in_out_err(["-", "-"], <<-INPUT, [], /Can't do inplace edit for stdio; skipping/)
+ ARGF.inplace_mode = '.bak'
+ f = ARGF.dup
+ while line = f.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ end
+
+ def test_inplace_stdin2
+ t = make_tempfile
+
+ assert_in_out_err(["-"], <<-INPUT, [], /Can't do inplace edit for stdio/)
+ ARGF.inplace_mode = '.bak'
+ while line = ARGF.gets
+ puts line.chomp + '.new'
+ end
+ INPUT
+ end
+
+ def test_encoding
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ p ARGF.external_encoding.is_a?(Encoding)
+ p ARGF.internal_encoding.is_a?(Encoding)
+ ARGF.gets
+ p ARGF.external_encoding.is_a?(Encoding)
+ p ARGF.internal_encoding
+ SRC
+ assert_equal("true\ntrue\ntrue\nnil\n", f.read)
+ end
+ end
+
+ def test_tell
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ ARGF.binmode
+ loop do
+ p ARGF.tell
+ p ARGF.gets
+ end
+ rescue ArgumentError
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ [0, 2, 4, 2, 4, 2, 4].map {|i| i.to_s }.
+ zip((1..6).map {|i| '"' + i.to_s + '\n"' } + ["nil"]).flatten.
+ each do |x|
+ assert_equal(x, a.shift)
+ end
+ assert_equal('end', a.shift)
+ end
+ end
+
+ def test_seek
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ ARGF.seek(4)
+ p ARGF.gets #=> "3"
+ ARGF.seek(0, IO::SEEK_END)
+ p ARGF.gets #=> "5"
+ ARGF.seek(4)
+ p ARGF.gets #=> nil
+ begin
+ ARGF.seek(0)
+ rescue
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ assert_equal('"3\n"', a.shift)
+ assert_equal('"5\n"', a.shift)
+ assert_equal('nil', a.shift)
+ assert_equal('end', a.shift)
+ end
+ end
+
+ def test_set_pos
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ ARGF.pos = 4
+ p ARGF.gets #=> "3"
+ ARGF.pos = 4
+ p ARGF.gets #=> "5"
+ ARGF.pos = 4
+ p ARGF.gets #=> nil
+ begin
+ ARGF.pos = 4
+ rescue
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ assert_equal('"3\n"', a.shift)
+ assert_equal('"5\n"', a.shift)
+ assert_equal('nil', a.shift)
+ assert_equal('end', a.shift)
+ end
+ end
+
+ def test_rewind
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ ARGF.pos = 4
+ ARGF.rewind
+ p ARGF.gets #=> "1"
+ ARGF.pos = 4
+ p ARGF.gets #=> "3"
+ ARGF.pos = 4
+ p ARGF.gets #=> "5"
+ ARGF.pos = 4
+ p ARGF.gets #=> nil
+ begin
+ ARGF.rewind
+ rescue
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ assert_equal('"1\n"', a.shift)
+ assert_equal('"3\n"', a.shift)
+ assert_equal('"5\n"', a.shift)
+ assert_equal('nil', a.shift)
+ assert_equal('end', a.shift)
+ end
+ end
+
+ def test_fileno
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ p ARGF.fileno
+ ARGF.gets
+ ARGF.gets
+ p ARGF.fileno
+ ARGF.gets
+ ARGF.gets
+ p ARGF.fileno
+ ARGF.gets
+ ARGF.gets
+ p ARGF.fileno
+ ARGF.gets
+ begin
+ ARGF.fileno
+ rescue
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ fd1, fd2, fd3, fd4, tag = a
+ assert_match(/^\d+$/, fd1)
+ assert_match(/^\d+$/, fd2)
+ assert_match(/^\d+$/, fd3)
+ assert_match(/^\d+$/, fd4)
+ assert_equal('end', tag)
+ end
+ end
+
+ def test_to_io
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ 8.times do
+ p ARGF.to_io
+ ARGF.gets
+ end
+ SRC
+ a = f.read.split("\n")
+ f11, f12, f13, f21, f22, f31, f32, f4 = a
+ assert_equal(f11, f12)
+ assert_equal(f11, f13)
+ assert_equal(f21, f22)
+ assert_equal(f31, f32)
+ assert_match(/\(closed\)/, f4)
+ f4.sub!(/ \(closed\)/, "")
+ assert_equal(f31, f4)
+ end
+ end
+
+ def test_eof
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ 8.times do
+ p ARGF.eof?
+ ARGF.gets
+ end
+ rescue IOError
+ puts "end"
+ end
+ SRC
+ a = f.read.split("\n")
+ ((%w(true false) * 4).take(7) + %w(end)).each do |x|
+ assert_equal(x, a.shift)
+ end
+ end
+ end
+
+ def test_read
+ ruby('-e', "p ARGF.read(8)", @t1.path, @t2.path, @t3.path) do |f|
+ assert_equal("\"1\\n2\\n3\\n4\\n\"\n", f.read)
+ end
+ end
+
+ def test_read2
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = ""
+ ARGF.read(8, s)
+ p s
+ SRC
+ assert_equal("\"1\\n2\\n3\\n4\\n\"\n", f.read)
+ end
+ end
+
+ def test_read3
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ nil while ARGF.gets
+ p ARGF.read
+ p ARGF.read(0, "")
+ SRC
+ assert_equal("nil\n\"\"\n", f.read)
+ end
+ end
+
+ def test_readpartial
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = ""
+ begin
+ loop do
+ s << ARGF.readpartial(1)
+ t = ""; ARGF.readpartial(1, t); s << t
+ end
+ rescue EOFError
+ puts s
+ end
+ SRC
+ assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_readpartial2
+ ruby('-e', <<-SRC) do |f|
+ s = ""
+ begin
+ loop do
+ s << ARGF.readpartial(1)
+ t = ""; ARGF.readpartial(1, t); s << t
+ end
+ rescue EOFError
+ puts s
+ end
+ SRC
+ f.puts("foo")
+ f.puts("bar")
+ f.puts("baz")
+ f.close_write
+ assert_equal("foo\nbar\nbaz\n", f.read)
+ end
+ end
+
+ def test_getc
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = ""
+ while c = ARGF.getc
+ s << c
+ end
+ puts s
+ SRC
+ assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_getbyte
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = []
+ while c = ARGF.getbyte
+ s << c
+ end
+ p s
+ SRC
+ assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+ end
+ end
+
+ def test_readchar
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = ""
+ begin
+ while c = ARGF.readchar
+ s << c
+ end
+ rescue EOFError
+ puts s
+ end
+ SRC
+ assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_readbyte
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ s = []
+ while c = ARGF.readbyte
+ s << c
+ end
+ rescue EOFError
+ p s
+ end
+ SRC
+ assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+ end
+ end
+
+ def test_each_line
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = []
+ ARGF.each_line {|l| s << l }
+ p s
+ SRC
+ assert_equal("[\"1\\n\", \"2\\n\", \"3\\n\", \"4\\n\", \"5\\n\", \"6\\n\"]\n", f.read)
+ end
+ end
+
+ def test_each_line_paragraph
+ assert_in_out_err(['-e', 'ARGF.each_line("") {|para| p para}'], "a\n\nb\n",
+ ["\"a\\n\\n\"", "\"b\\n\""], [])
+ end
+
+ def test_each_byte
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = []
+ ARGF.each_byte {|c| s << c }
+ p s
+ SRC
+ assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+ end
+ end
+
+ def test_each_char
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ s = ""
+ ARGF.each_char {|c| s << c }
+ puts s
+ SRC
+ assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_filename
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ puts ARGF.filename.dump
+ end while ARGF.gets
+ puts ARGF.filename.dump
+ SRC
+ a = f.read.split("\n")
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ end
+ end
+
+ def test_filename2
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ puts $FILENAME.dump
+ end while ARGF.gets
+ puts $FILENAME.dump
+ SRC
+ a = f.read.split("\n")
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ end
+ end
+
+ def test_file
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ puts ARGF.file.path.dump
+ end while ARGF.gets
+ puts ARGF.file.path.dump
+ SRC
+ a = f.read.split("\n")
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t1.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t2.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ assert_equal(@t3.path.dump, a.shift)
+ end
+ end
+
+ def test_binmode
+ ruby('-e', "ARGF.binmode; STDOUT.binmode; puts ARGF.read", @t1.path, @t2.path, @t3.path) do |f|
+ f.binmode
+ assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_skip
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ begin
+ ARGF.skip
+ rescue
+ puts "cannot skip" # ???
+ end
+ puts ARGF.gets
+ ARGF.skip
+ puts ARGF.read
+ SRC
+ assert_equal("cannot skip\n1\n3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_close
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ ARGF.close
+ puts ARGF.read
+ SRC
+ assert_equal("3\n4\n5\n6\n", f.read)
+ end
+ end
+
+ def test_closed
+ ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ 3.times do
+ p ARGF.closed?
+ ARGF.gets
+ ARGF.gets
+ end
+ p ARGF.closed?
+ ARGF.gets
+ p ARGF.closed?
+ SRC
+ assert_equal("false\nfalse\nfalse\nfalse\ntrue\n", f.read)
+ end
+ end
+
+ def test_argv
+ ruby('-e', "p ARGF.argv; p $*", @t1.path, @t2.path, @t3.path) do |f|
+ assert_equal([@t1.path, @t2.path, @t3.path].inspect, f.gets.chomp)
+ assert_equal([@t1.path, @t2.path, @t3.path].inspect, f.gets.chomp)
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_array.rb b/trunk/test/ruby/test_array.rb
new file mode 100644
index 0000000000..234fb238a2
--- /dev/null
+++ b/trunk/test/ruby/test_array.rb
@@ -0,0 +1,1603 @@
+require 'test/unit'
+
+class TestArray < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ @cls = Array
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_0_literal
+ assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
+ assert_equal([1, 2, 1, 2], [1, 2] * 2)
+ assert_equal("1:2", [1, 2] * ":")
+
+ assert_equal([1, 2].hash, [1, 2].hash)
+
+ assert_equal([2,3], [1,2,3] & [2,3,4])
+ assert_equal([1,2,3,4], [1,2,3] | [2,3,4])
+ assert_equal([1,2,3] - [2,3], [1])
+
+ x = [0, 1, 2, 3, 4, 5]
+ assert_equal(2, x[2])
+ assert_equal([1, 2, 3], x[1..3])
+ assert_equal([1, 2, 3], x[1,3])
+
+ x[0, 2] = 10
+ assert(x[0] == 10 && x[1] == 2)
+
+ x[0, 0] = -1
+ assert(x[0] == -1 && x[1] == 10)
+
+ x[-1, 1] = 20
+ assert(x[-1] == 20 && x.pop == 20)
+ end
+
+ def test_array_andor_0
+ assert_equal([2], ([1,2,3]&[2,4,6]))
+ assert_equal([1,2,3,4,6], ([1,2,3]|[2,4,6]))
+ end
+
+ def test_compact_0
+ a = [nil, 1, nil, nil, 5, nil, nil]
+ assert_equal [1, 5], a.compact
+ assert_equal [nil, 1, nil, nil, 5, nil, nil], a
+ a.compact!
+ assert_equal [1, 5], a
+ end
+
+ def test_uniq_0
+ x = [1, 1, 4, 2, 5, 4, 5, 1, 2]
+ x.uniq!
+ assert_equal([1, 4, 2, 5], x)
+ end
+
+ def test_empty_0
+ assert_equal true, [].empty?
+ assert_equal false, [1].empty?
+ assert_equal false, [1, 1, 4, 2, 5, 4, 5, 1, 2].empty?
+ end
+
+ def test_sort_0
+ x = ["it", "came", "to", "pass", "that", "..."]
+ x = x.sort.join(" ")
+ assert_equal("... came it pass that to", x)
+ x = [2,5,3,1,7]
+ x.sort!{|a,b| a<=>b} # sort with condition
+ assert_equal([1,2,3,5,7], x)
+ x.sort!{|a,b| b-a} # reverse sort
+ assert_equal([7,5,3,2,1], x)
+ end
+
+ def test_split_0
+ x = "The Book of Mormon"
+ assert_equal(x.reverse, x.split(//).reverse!.join)
+ assert_equal(x.reverse, x.reverse!)
+ assert_equal("g:n:i:r:t:s: :e:t:y:b: :1", "1 byte string".split(//).reverse.join(":"))
+ x = "a b c d"
+ assert_equal(['a', 'b', 'c', 'd'], x.split)
+ assert_equal(['a', 'b', 'c', 'd'], x.split(' '))
+ end
+
+ def test_misc_0
+ assert(defined? "a".chomp)
+ assert_equal(["a", "b", "c"], "abc".scan(/./))
+ assert_equal([["1a"], ["2b"], ["3c"]], "1a2b3c".scan(/(\d.)/))
+ # non-greedy match
+ assert_equal([["a", "12"], ["b", "22"]], "a=12;b=22".scan(/(.*?)=(\d*);?/))
+
+ x = [1]
+ assert_equal('1:1:1:1:1', (x * 5).join(":"))
+ assert_equal('1', (x * 1).join(":"))
+ assert_equal('', (x * 0).join(":"))
+
+ *x = *(1..7).to_a
+ assert_equal(7, x.size)
+ assert_equal([1, 2, 3, 4, 5, 6, 7], x)
+
+ x = [1,2,3]
+ x[1,0] = x
+ assert_equal([1,1,2,3,2,3], x)
+
+ x = [1,2,3]
+ x[-1,0] = x
+ assert_equal([1,2,1,2,3,3], x)
+
+ x = [1,2,3]
+ x.concat(x)
+ assert_equal([1,2,3,1,2,3], x)
+
+ x = [1,2,3]
+ x.clear
+ assert_equal([], x)
+
+ x = [1,2,3]
+ y = x.dup
+ x << 4
+ y << 5
+ assert_equal([1,2,3,4], x)
+ assert_equal([1,2,3,5], y)
+ end
+
+ def test_beg_end_0
+ x = [1, 2, 3, 4, 5]
+
+ assert_equal(1, x.first)
+ assert_equal([1], x.first(1))
+ assert_equal([1, 2, 3], x.first(3))
+
+ assert_equal(5, x.last)
+ assert_equal([5], x.last(1))
+ assert_equal([3, 4, 5], x.last(3))
+
+ assert_equal(1, x.shift)
+ assert_equal([2, 3, 4], x.shift(3))
+ assert_equal([5], x)
+
+ assert_equal([2, 3, 4, 5], x.unshift(2, 3, 4))
+ assert_equal([1, 2, 3, 4, 5], x.unshift(1))
+ assert_equal([1, 2, 3, 4, 5], x)
+
+ assert_equal(5, x.pop)
+ assert_equal([3, 4], x.pop(2))
+ assert_equal([1, 2], x)
+
+ assert_equal([1, 2, 3, 4], x.push(3, 4))
+ assert_equal([1, 2, 3, 4, 5], x.push(5))
+ assert_equal([1, 2, 3, 4, 5], x)
+ end
+
+ def test_find_all_0
+ assert_respond_to([], :find_all)
+ assert_respond_to([], :select) # Alias
+ assert_equal([], [].find_all{ |obj| obj == "foo"})
+
+ x = ["foo", "bar", "baz", "baz", 1, 2, 3, 3, 4]
+ assert_equal(["baz","baz"], x.find_all{ |obj| obj == "baz" })
+ assert_equal([3,3], x.find_all{ |obj| obj == 3 })
+ end
+
+ def test_fill_0
+ assert_equal([-1, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1))
+ assert_equal([0, 1, 2, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 3))
+ assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3, 2))
+ assert_equal([0, 1, 2, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 3, 5))
+ assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2, 2))
+ assert_equal([0, 1, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 2, 5))
+ assert_equal([0, 1, 2, 3, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, -2, 1))
+ assert_equal([0, 1, 2, 3, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, -2, 3))
+ assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3..4))
+ assert_equal([0, 1, 2, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3...4))
+ assert_equal([0, 1, -1, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2..-2))
+ assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2...-2))
+ assert_equal([10, 11, 12, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill{|i| i+10})
+ assert_equal([0, 1, 2, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill(3){|i| i+10})
+ assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3, 2){|i| i+10})
+ assert_equal([0, 1, 2, 13, 14, 15, 16, 17], [0, 1, 2, 3, 4, 5].fill(3, 5){|i| i+10})
+ assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3..4){|i| i+10})
+ assert_equal([0, 1, 2, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(3...4){|i| i+10})
+ assert_equal([0, 1, 12, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(2..-2){|i| i+10})
+ assert_equal([0, 1, 12, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(2...-2){|i| i+10})
+ end
+
+ # From rubicon
+
+ def test_00_new
+ a = @cls.new()
+ assert_instance_of(@cls, a)
+ assert_equal(0, a.length)
+ assert_nil(a[0])
+ end
+
+ def test_01_square_brackets
+ a = @cls[ 5, 4, 3, 2, 1 ]
+ assert_instance_of(@cls, a)
+ assert_equal(5, a.length)
+ 5.times { |i| assert_equal(5-i, a[i]) }
+ assert_nil(a[6])
+ end
+
+ def test_AND # '&'
+ assert_equal(@cls[1, 3], @cls[ 1, 1, 3, 5 ] & @cls[ 1, 2, 3 ])
+ assert_equal(@cls[], @cls[ 1, 1, 3, 5 ] & @cls[ ])
+ assert_equal(@cls[], @cls[ ] & @cls[ 1, 2, 3 ])
+ assert_equal(@cls[], @cls[ 1, 2, 3 ] & @cls[ 4, 5, 6 ])
+ end
+
+ def test_MUL # '*'
+ assert_equal(@cls[], @cls[]*3)
+ assert_equal(@cls[1, 1, 1], @cls[1]*3)
+ assert_equal(@cls[1, 2, 1, 2, 1, 2], @cls[1, 2]*3)
+ assert_equal(@cls[], @cls[1, 2, 3] * 0)
+ assert_raise(ArgumentError) { @cls[1, 2]*(-3) }
+
+ assert_equal('1-2-3-4-5', @cls[1, 2, 3, 4, 5] * '-')
+ assert_equal('12345', @cls[1, 2, 3, 4, 5] * '')
+
+ end
+
+ def test_PLUS # '+'
+ assert_equal(@cls[], @cls[] + @cls[])
+ assert_equal(@cls[1], @cls[1] + @cls[])
+ assert_equal(@cls[1], @cls[] + @cls[1])
+ assert_equal(@cls[1, 1], @cls[1] + @cls[1])
+ assert_equal(@cls['cat', 'dog', 1, 2, 3], %w(cat dog) + (1..3).to_a)
+ end
+
+ def test_MINUS # '-'
+ assert_equal(@cls[], @cls[1] - @cls[1])
+ assert_equal(@cls[1], @cls[1, 2, 3, 4, 5] - @cls[2, 3, 4, 5])
+ # Ruby 1.8 feature change
+ #assert_equal(@cls[1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5])
+ assert_equal(@cls[1, 1, 1, 1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5])
+ a = @cls[]
+ 1000.times { a << 1 }
+ assert_equal(1000, a.length)
+ #assert_equal(@cls[1], a - @cls[2])
+ assert_equal(@cls[1] * 1000, a - @cls[2])
+ #assert_equal(@cls[1], @cls[1, 2, 1] - @cls[2])
+ assert_equal(@cls[1, 1], @cls[1, 2, 1] - @cls[2])
+ assert_equal(@cls[1, 2, 3], @cls[1, 2, 3] - @cls[4, 5, 6])
+ end
+
+ def test_LSHIFT # '<<'
+ a = @cls[]
+ a << 1
+ assert_equal(@cls[1], a)
+ a << 2 << 3
+ assert_equal(@cls[1, 2, 3], a)
+ a << nil << 'cat'
+ assert_equal(@cls[1, 2, 3, nil, 'cat'], a)
+ a << a
+ assert_equal(@cls[1, 2, 3, nil, 'cat', a], a)
+ end
+
+ def test_CMP # '<=>'
+ assert_equal(0, @cls[] <=> @cls[])
+ assert_equal(0, @cls[1] <=> @cls[1])
+ assert_equal(0, @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3, 'cat'])
+ assert_equal(-1, @cls[] <=> @cls[1])
+ assert_equal(1, @cls[1] <=> @cls[])
+ assert_equal(-1, @cls[1, 2, 3] <=> @cls[1, 2, 3, 'cat'])
+ assert_equal(1, @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3])
+ assert_equal(-1, @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3, 'dog'])
+ assert_equal(1, @cls[1, 2, 3, 'dog'] <=> @cls[1, 2, 3, 'cat'])
+ end
+
+ def test_EQUAL # '=='
+ assert(@cls[] == @cls[])
+ assert(@cls[1] == @cls[1])
+ assert(@cls[1, 1, 2, 2] == @cls[1, 1, 2, 2])
+ assert(@cls[1.0, 1.0, 2.0, 2.0] == @cls[1, 1, 2, 2])
+ end
+
+ def test_VERY_EQUAL # '==='
+ assert(@cls[] === @cls[])
+ assert(@cls[1] === @cls[1])
+ assert(@cls[1, 1, 2, 2] === @cls[1, 1, 2, 2])
+ assert(@cls[1.0, 1.0, 2.0, 2.0] === @cls[1, 1, 2, 2])
+ end
+
+ def test_AREF # '[]'
+ a = @cls[*(1..100).to_a]
+
+ assert_equal(1, a[0])
+ assert_equal(100, a[99])
+ assert_nil(a[100])
+ assert_equal(100, a[-1])
+ assert_equal(99, a[-2])
+ assert_equal(1, a[-100])
+ assert_nil(a[-101])
+ assert_nil(a[-101,0])
+ assert_nil(a[-101,1])
+ assert_nil(a[-101,-1])
+ assert_nil(a[10,-1])
+
+ assert_equal(@cls[1], a[0,1])
+ assert_equal(@cls[100], a[99,1])
+ assert_equal(@cls[], a[100,1])
+ assert_equal(@cls[100], a[99,100])
+ assert_equal(@cls[100], a[-1,1])
+ assert_equal(@cls[99], a[-2,1])
+ assert_equal(@cls[], a[-100,0])
+ assert_equal(@cls[1], a[-100,1])
+
+ assert_equal(@cls[10, 11, 12], a[9, 3])
+ assert_equal(@cls[10, 11, 12], a[-91, 3])
+
+ assert_equal(@cls[1], a[0..0])
+ assert_equal(@cls[100], a[99..99])
+ assert_equal(@cls[], a[100..100])
+ assert_equal(@cls[100], a[99..200])
+ assert_equal(@cls[100], a[-1..-1])
+ assert_equal(@cls[99], a[-2..-2])
+
+ assert_equal(@cls[10, 11, 12], a[9..11])
+ assert_equal(@cls[10, 11, 12], a[-91..-89])
+
+ assert_nil(a[10, -3])
+ # Ruby 1.8 feature change:
+ # Array#[size..x] returns [] instead of nil.
+ #assert_nil(a[10..7])
+ assert_equal [], a[10..7]
+
+ assert_raise(TypeError) {a['cat']}
+ end
+
+ def test_ASET # '[]='
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[0] = 0)
+ assert_equal(@cls[0] + @cls[*(1..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[10,10] = 0)
+ assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[-1] = 0)
+ assert_equal(@cls[*(0..98).to_a] + @cls[0], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[-10, 10] = 0)
+ assert_equal(@cls[*(0..89).to_a] + @cls[0], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[0,1000] = 0)
+ assert_equal(@cls[0] , a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a[10..19] = 0)
+ assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)
+
+ b = @cls[*%w( a b c )]
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[0,1] = b)
+ assert_equal(b + @cls[*(1..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[10,10] = b)
+ assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[-1, 1] = b)
+ assert_equal(@cls[*(0..98).to_a] + b, a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[-10, 10] = b)
+ assert_equal(@cls[*(0..89).to_a] + b, a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[0,1000] = b)
+ assert_equal(b , a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(b, a[10..19] = b)
+ assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)
+
+ # Ruby 1.8 feature change:
+ # assigning nil does not remove elements.
+=begin
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[0,1] = nil)
+ assert_equal(@cls[*(1..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[10,10] = nil)
+ assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[-1, 1] = nil)
+ assert_equal(@cls[*(0..98).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[-10, 10] = nil)
+ assert_equal(@cls[*(0..89).to_a], a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[0,1000] = nil)
+ assert_equal(@cls[] , a)
+
+ a = @cls[*(0..99).to_a]
+ assert_equal(nil, a[10..19] = nil)
+ assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)
+=end
+
+ a = @cls[1, 2, 3]
+ a[1, 0] = a
+ assert_equal([1, 1, 2, 3, 2, 3], a)
+
+ a = @cls[1, 2, 3]
+ a[-1, 0] = a
+ assert_equal([1, 2, 1, 2, 3, 3], a)
+ end
+
+ def test_assoc
+ a1 = @cls[*%w( cat feline )]
+ a2 = @cls[*%w( dog canine )]
+ a3 = @cls[*%w( mule asinine )]
+
+ a = @cls[ a1, a2, a3 ]
+
+ assert_equal(a1, a.assoc('cat'))
+ assert_equal(a3, a.assoc('mule'))
+ assert_equal(nil, a.assoc('asinine'))
+ assert_equal(nil, a.assoc('wombat'))
+ assert_equal(nil, a.assoc(1..2))
+ end
+
+ def test_at
+ a = @cls[*(0..99).to_a]
+ assert_equal(0, a.at(0))
+ assert_equal(10, a.at(10))
+ assert_equal(99, a.at(99))
+ assert_equal(nil, a.at(100))
+ assert_equal(99, a.at(-1))
+ assert_equal(0, a.at(-100))
+ assert_equal(nil, a.at(-101))
+ assert_raise(TypeError) { a.at('cat') }
+ end
+
+ def test_clear
+ a = @cls[1, 2, 3]
+ b = a.clear
+ assert_equal(@cls[], a)
+ assert_equal(@cls[], b)
+ assert_equal(a.__id__, b.__id__)
+ end
+
+ def test_clone
+ for taint in [ false, true ]
+ for untrust in [ false, true ]
+ for frozen in [ false, true ]
+ a = @cls[*(0..99).to_a]
+ a.taint if taint
+ a.untrust if untrust
+ a.freeze if frozen
+ b = a.clone
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert_equal(a.frozen?, b.frozen?)
+ assert_equal(a.untrusted?, b.untrusted?)
+ assert_equal(a.tainted?, b.tainted?)
+ end
+ end
+ end
+ end
+
+ def test_collect
+ a = @cls[ 1, 'cat', 1..1 ]
+ assert_equal([ Fixnum, String, Range], a.collect {|e| e.class} )
+ assert_equal([ 99, 99, 99], a.collect { 99 } )
+
+ assert_equal([], @cls[].collect { 99 })
+
+ # Ruby 1.9 feature change:
+ # Enumerable#collect without block returns an Enumerator.
+ #assert_equal([1, 2, 3], @cls[1, 2, 3].collect)
+ assert_kind_of Enumerator, @cls[1, 2, 3].collect
+ end
+
+ # also update map!
+ def test_collect!
+ a = @cls[ 1, 'cat', 1..1 ]
+ assert_equal([ Fixnum, String, Range], a.collect! {|e| e.class} )
+ assert_equal([ Fixnum, String, Range], a)
+
+ a = @cls[ 1, 'cat', 1..1 ]
+ assert_equal([ 99, 99, 99], a.collect! { 99 } )
+ assert_equal([ 99, 99, 99], a)
+
+ a = @cls[ ]
+ assert_equal([], a.collect! { 99 })
+ assert_equal([], a)
+ end
+
+ def test_compact
+ a = @cls[ 1, nil, nil, 2, 3, nil, 4 ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact)
+
+ a = @cls[ nil, 1, nil, 2, 3, nil, 4 ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact)
+
+ a = @cls[ 1, nil, nil, 2, 3, nil, 4, nil ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact)
+
+ a = @cls[ 1, 2, 3, 4 ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact)
+ end
+
+ def test_compact!
+ a = @cls[ 1, nil, nil, 2, 3, nil, 4 ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact!)
+ assert_equal(@cls[1, 2, 3, 4], a)
+
+ a = @cls[ nil, 1, nil, 2, 3, nil, 4 ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact!)
+ assert_equal(@cls[1, 2, 3, 4], a)
+
+ a = @cls[ 1, nil, nil, 2, 3, nil, 4, nil ]
+ assert_equal(@cls[1, 2, 3, 4], a.compact!)
+ assert_equal(@cls[1, 2, 3, 4], a)
+
+ a = @cls[ 1, 2, 3, 4 ]
+ assert_equal(nil, a.compact!)
+ assert_equal(@cls[1, 2, 3, 4], a)
+ end
+
+ def test_concat
+ assert_equal(@cls[1, 2, 3, 4], @cls[1, 2].concat(@cls[3, 4]))
+ assert_equal(@cls[1, 2, 3, 4], @cls[].concat(@cls[1, 2, 3, 4]))
+ assert_equal(@cls[1, 2, 3, 4], @cls[1, 2, 3, 4].concat(@cls[]))
+ assert_equal(@cls[], @cls[].concat(@cls[]))
+ assert_equal(@cls[@cls[1, 2], @cls[3, 4]], @cls[@cls[1, 2]].concat(@cls[@cls[3, 4]]))
+
+ a = @cls[1, 2, 3]
+ a.concat(a)
+ assert_equal([1, 2, 3, 1, 2, 3], a)
+ end
+
+ def test_count
+ a = @cls[1, 2, 3, 1, 2]
+ assert_equal(5, a.count)
+ assert_equal(2, a.count(1))
+ assert_equal(3, a.count {|x| x % 2 == 1 })
+ assert_equal(2, a.count(1) {|x| x % 2 == 1 })
+ assert_raise(ArgumentError) { a.count(0, 1) }
+ end
+
+ def test_delete
+ a = @cls[*('cab'..'cat').to_a]
+ assert_equal('cap', a.delete('cap'))
+ assert_equal(@cls[*('cab'..'cao').to_a] + @cls[*('caq'..'cat').to_a], a)
+
+ a = @cls[*('cab'..'cat').to_a]
+ assert_equal('cab', a.delete('cab'))
+ assert_equal(@cls[*('cac'..'cat').to_a], a)
+
+ a = @cls[*('cab'..'cat').to_a]
+ assert_equal('cat', a.delete('cat'))
+ assert_equal(@cls[*('cab'..'cas').to_a], a)
+
+ a = @cls[*('cab'..'cat').to_a]
+ assert_equal(nil, a.delete('cup'))
+ assert_equal(@cls[*('cab'..'cat').to_a], a)
+
+ a = @cls[*('cab'..'cat').to_a]
+ assert_equal(99, a.delete('cup') { 99 } )
+ assert_equal(@cls[*('cab'..'cat').to_a], a)
+ end
+
+ def test_delete_at
+ a = @cls[*(1..5).to_a]
+ assert_equal(3, a.delete_at(2))
+ assert_equal(@cls[1, 2, 4, 5], a)
+
+ a = @cls[*(1..5).to_a]
+ assert_equal(4, a.delete_at(-2))
+ assert_equal(@cls[1, 2, 3, 5], a)
+
+ a = @cls[*(1..5).to_a]
+ assert_equal(nil, a.delete_at(5))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[*(1..5).to_a]
+ assert_equal(nil, a.delete_at(-6))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+ end
+
+ # also reject!
+ def test_delete_if
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(a, a.delete_if { false })
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(a, a.delete_if { true })
+ assert_equal(@cls[], a)
+
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(a, a.delete_if { |i| i > 3 })
+ assert_equal(@cls[1, 2, 3], a)
+ end
+
+ def test_dup
+ for taint in [ false, true ]
+ for frozen in [ false, true ]
+ a = @cls[*(0..99).to_a]
+ a.taint if taint
+ a.freeze if frozen
+ b = a.dup
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert_equal(false, b.frozen?)
+ assert_equal(a.tainted?, b.tainted?)
+ end
+ end
+ end
+
+ def test_each
+ a = @cls[*%w( ant bat cat dog )]
+ i = 0
+ a.each { |e|
+ assert_equal(a[i], e)
+ i += 1
+ }
+ assert_equal(4, i)
+
+ a = @cls[]
+ i = 0
+ a.each { |e|
+ assert_equal(a[i], e)
+ i += 1
+ }
+ assert_equal(0, i)
+
+ assert_equal(a, a.each {})
+ end
+
+ def test_each_index
+ a = @cls[*%w( ant bat cat dog )]
+ i = 0
+ a.each_index { |ind|
+ assert_equal(i, ind)
+ i += 1
+ }
+ assert_equal(4, i)
+
+ a = @cls[]
+ i = 0
+ a.each_index { |ind|
+ assert_equal(i, ind)
+ i += 1
+ }
+ assert_equal(0, i)
+
+ assert_equal(a, a.each_index {})
+ end
+
+ def test_empty?
+ assert(@cls[].empty?)
+ assert(!@cls[1].empty?)
+ end
+
+ def test_eql?
+ assert(@cls[].eql?(@cls[]))
+ assert(@cls[1].eql?(@cls[1]))
+ assert(@cls[1, 1, 2, 2].eql?(@cls[1, 1, 2, 2]))
+ assert(!@cls[1.0, 1.0, 2.0, 2.0].eql?(@cls[1, 1, 2, 2]))
+ end
+
+ def test_fill
+ assert_equal(@cls[], @cls[].fill(99))
+ assert_equal(@cls[], @cls[].fill(99, 0))
+ assert_equal(@cls[99], @cls[].fill(99, 0, 1))
+ assert_equal(@cls[99], @cls[].fill(99, 0..0))
+
+ assert_equal(@cls[99], @cls[1].fill(99))
+ assert_equal(@cls[99], @cls[1].fill(99, 0))
+ assert_equal(@cls[99], @cls[1].fill(99, 0, 1))
+ assert_equal(@cls[99], @cls[1].fill(99, 0..0))
+
+ assert_equal(@cls[99, 99], @cls[1, 2].fill(99))
+ assert_equal(@cls[99, 99], @cls[1, 2].fill(99, 0))
+ assert_equal(@cls[99, 99], @cls[1, 2].fill(99, nil))
+ assert_equal(@cls[1, 99], @cls[1, 2].fill(99, 1, nil))
+ assert_equal(@cls[99, 2], @cls[1, 2].fill(99, 0, 1))
+ assert_equal(@cls[99, 2], @cls[1, 2].fill(99, 0..0))
+ end
+
+ def test_first
+ assert_equal(3, @cls[3, 4, 5].first)
+ assert_equal(nil, @cls[].first)
+ end
+
+ def test_flatten
+ a1 = @cls[ 1, 2, 3]
+ a2 = @cls[ 5, 6 ]
+ a3 = @cls[ 4, a2 ]
+ a4 = @cls[ a1, a3 ]
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten)
+ assert_equal(@cls[ a1, a3], a4)
+
+ a5 = @cls[ a1, @cls[], a3 ]
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten)
+ assert_equal(@cls[], @cls[].flatten)
+ assert_equal(@cls[],
+ @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)
+
+ assert_raise(TypeError, "[ruby-dev:31197]") { [[]].flatten("") }
+
+ a6 = @cls[[1, 2], 3]
+ a6.taint
+ a6.untrust
+ a7 = a6.flatten
+ assert_equal(true, a7.tainted?)
+ assert_equal(true, a7.untrusted?)
+ end
+
+ def test_flatten!
+ a1 = @cls[ 1, 2, 3]
+ a2 = @cls[ 5, 6 ]
+ a3 = @cls[ 4, a2 ]
+ a4 = @cls[ a1, a3 ]
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten!)
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a4)
+
+ a5 = @cls[ a1, @cls[], a3 ]
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten!)
+ assert_equal(@cls[1, 2, 3, 4, 5, 6], a5)
+
+ assert_equal(@cls[], @cls[].flatten)
+ assert_equal(@cls[],
+ @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)
+ end
+
+ def test_flatten_with_callcc
+ respond_to?(:callcc, true) or require 'continuation'
+ o = Object.new
+ def o.to_ary() callcc {|k| @cont = k; [1,2,3]} end
+ begin
+ assert_equal([10, 20, 1, 2, 3, 30, 1, 2, 3, 40], [10, 20, o, 30, o, 40].flatten)
+ rescue => e
+ else
+ o.instance_eval {@cont}.call
+ end
+ assert_instance_of(RuntimeError, e, '[ruby-dev:34798]')
+ assert_match(/reentered/, e.message, '[ruby-dev:34798]')
+ end
+
+ def test_hash
+ a1 = @cls[ 'cat', 'dog' ]
+ a2 = @cls[ 'cat', 'dog' ]
+ a3 = @cls[ 'dog', 'cat' ]
+ assert(a1.hash == a2.hash)
+ assert(a1.hash != a3.hash)
+ end
+
+ def test_include?
+ a = @cls[ 'cat', 99, /a/, @cls[ 1, 2, 3] ]
+ assert(a.include?('cat'))
+ assert(a.include?(99))
+ assert(a.include?(/a/))
+ assert(a.include?([1,2,3]))
+ assert(!a.include?('ca'))
+ assert(!a.include?([1,2]))
+ end
+
+ def test_index
+ a = @cls[ 'cat', 99, /a/, 99, @cls[ 1, 2, 3] ]
+ assert_equal(0, a.index('cat'))
+ assert_equal(1, a.index(99))
+ assert_equal(4, a.index([1,2,3]))
+ assert_nil(a.index('ca'))
+ assert_nil(a.index([1,2]))
+ end
+
+ def test_values_at
+ a = @cls[*('a'..'j').to_a]
+ assert_equal(@cls['a', 'c', 'e'], a.values_at(0, 2, 4))
+ assert_equal(@cls['j', 'h', 'f'], a.values_at(-1, -3, -5))
+ assert_equal(@cls['h', nil, 'a'], a.values_at(-3, 99, 0))
+ end
+
+ def test_join
+ $, = ""
+ a = @cls[]
+ assert_equal("", a.join)
+ assert_equal("", a.join(','))
+
+ $, = ""
+ a = @cls[1, 2]
+ assert_equal("12", a.join)
+ assert_equal("1,2", a.join(','))
+
+ $, = ""
+ a = @cls[1, 2, 3]
+ assert_equal("123", a.join)
+ assert_equal("1,2,3", a.join(','))
+
+ $, = ":"
+ a = @cls[1, 2, 3]
+ assert_equal("1:2:3", a.join)
+ assert_equal("1,2,3", a.join(','))
+
+ $, = ""
+ a = @cls[1, 2, 3]
+ a.taint
+ a.untrust
+ s = a.join
+ assert_equal(true, s.tainted?)
+ assert_equal(true, s.untrusted?)
+ end
+
+ def test_last
+ assert_equal(nil, @cls[].last)
+ assert_equal(1, @cls[1].last)
+ assert_equal(99, @cls[*(3..99).to_a].last)
+ end
+
+ def test_length
+ assert_equal(0, @cls[].length)
+ assert_equal(1, @cls[1].length)
+ assert_equal(2, @cls[1, nil].length)
+ assert_equal(2, @cls[nil, 1].length)
+ assert_equal(234, @cls[*(0..233).to_a].length)
+ end
+
+ # also update collect!
+ def test_map!
+ a = @cls[ 1, 'cat', 1..1 ]
+ assert_equal(@cls[ Fixnum, String, Range], a.map! {|e| e.class} )
+ assert_equal(@cls[ Fixnum, String, Range], a)
+
+ a = @cls[ 1, 'cat', 1..1 ]
+ assert_equal(@cls[ 99, 99, 99], a.map! { 99 } )
+ assert_equal(@cls[ 99, 99, 99], a)
+
+ a = @cls[ ]
+ assert_equal(@cls[], a.map! { 99 })
+ assert_equal(@cls[], a)
+ end
+
+ def test_pack
+ a = @cls[*%w( cat wombat x yy)]
+ assert_equal("catwomx yy ", a.pack("A3A3A3A3"))
+ assert_equal("cat", a.pack("A*"))
+ assert_equal("cwx yy ", a.pack("A3@1A3@2A3A3"))
+ assert_equal("catwomx\000\000yy\000", a.pack("a3a3a3a3"))
+ assert_equal("cat", a.pack("a*"))
+ assert_equal("ca", a.pack("a2"))
+ assert_equal("cat\000\000", a.pack("a5"))
+
+ assert_equal("\x61", @cls["01100001"].pack("B8"))
+ assert_equal("\x61", @cls["01100001"].pack("B*"))
+ assert_equal("\x61", @cls["0110000100110111"].pack("B8"))
+ assert_equal("\x61\x37", @cls["0110000100110111"].pack("B16"))
+ assert_equal("\x61\x37", @cls["01100001", "00110111"].pack("B8B8"))
+ assert_equal("\x60", @cls["01100001"].pack("B4"))
+ assert_equal("\x40", @cls["01100001"].pack("B2"))
+
+ assert_equal("\x86", @cls["01100001"].pack("b8"))
+ assert_equal("\x86", @cls["01100001"].pack("b*"))
+ assert_equal("\x86", @cls["0110000100110111"].pack("b8"))
+ assert_equal("\x86\xec", @cls["0110000100110111"].pack("b16"))
+ assert_equal("\x86\xec", @cls["01100001", "00110111"].pack("b8b8"))
+ assert_equal("\x06", @cls["01100001"].pack("b4"))
+ assert_equal("\x02", @cls["01100001"].pack("b2"))
+
+ assert_equal("ABC", @cls[ 65, 66, 67 ].pack("C3"))
+ assert_equal("\377BC", @cls[ -1, 66, 67 ].pack("C*"))
+ assert_equal("ABC", @cls[ 65, 66, 67 ].pack("c3"))
+ assert_equal("\377BC", @cls[ -1, 66, 67 ].pack("c*"))
+
+
+ assert_equal("AB\n\x10", @cls["4142", "0a", "12"].pack("H4H2H1"))
+ assert_equal("AB\n\x02", @cls["1424", "a0", "21"].pack("h4h2h1"))
+
+ assert_equal("abc=02def=\ncat=\n=01=\n",
+ @cls["abc\002def", "cat", "\001"].pack("M9M3M4"))
+
+ assert_equal("aGVsbG8K\n", @cls["hello\n"].pack("m"))
+ assert_equal(",:&5L;&\\*:&5L;&\\*\n", @cls["hello\nhello\n"].pack("u"))
+
+ assert_equal("\xc2\xa9B\xe2\x89\xa0", @cls[0xa9, 0x42, 0x2260].pack("U*"))
+
+
+ format = "c2x5CCxsdils_l_a6";
+ # Need the expression in here to force ary[5] to be numeric. This avoids
+ # test2 failing because ary2 goes str->numeric->str and ary does not.
+ ary = [1, -100, 127, 128, 32767, 987.654321098/100.0,
+ 12345, 123456, -32767, -123456, "abcdef"]
+ x = ary.pack(format)
+ ary2 = x.unpack(format)
+
+ assert_equal(ary.length, ary2.length)
+ assert_equal(ary.join(':'), ary2.join(':'))
+ assert_not_nil(x =~ /def/)
+
+=begin
+ skipping "Not tested:
+ D,d & double-precision float, native format\\
+ E & double-precision float, little-endian byte order\\
+ e & single-precision float, little-endian byte order\\
+ F,f & single-precision float, native format\\
+ G & double-precision float, network (big-endian) byte order\\
+ g & single-precision float, network (big-endian) byte order\\
+ I & unsigned integer\\
+ i & integer\\
+ L & unsigned long\\
+ l & long\\
+
+ N & long, network (big-endian) byte order\\
+ n & short, network (big-endian) byte-order\\
+ P & pointer to a structure (fixed-length string)\\
+ p & pointer to a null-terminated string\\
+ S & unsigned short\\
+ s & short\\
+ V & long, little-endian byte order\\
+ v & short, little-endian byte order\\
+ X & back up a byte\\
+ x & null byte\\
+ Z & ASCII string (null padded, count is width)\\
+"
+=end
+ end
+
+ def test_pop
+ a = @cls[ 'cat', 'dog' ]
+ assert_equal('dog', a.pop)
+ assert_equal(@cls['cat'], a)
+ assert_equal('cat', a.pop)
+ assert_equal(@cls[], a)
+ assert_nil(a.pop)
+ assert_equal(@cls[], a)
+ end
+
+ def test_push
+ a = @cls[1, 2, 3]
+ assert_equal(@cls[1, 2, 3, 4, 5], a.push(4, 5))
+ assert_equal(@cls[1, 2, 3, 4, 5, nil], a.push(nil))
+ # Ruby 1.8 feature:
+ # Array#push accepts any number of arguments.
+ #assert_raise(ArgumentError, "a.push()") { a.push() }
+ a.push
+ assert_equal @cls[1, 2, 3, 4, 5, nil], a
+ a.push 6, 7
+ assert_equal @cls[1, 2, 3, 4, 5, nil, 6, 7], a
+ end
+
+ def test_rassoc
+ a1 = @cls[*%w( cat feline )]
+ a2 = @cls[*%w( dog canine )]
+ a3 = @cls[*%w( mule asinine )]
+ a = @cls[ a1, a2, a3 ]
+
+ assert_equal(a1, a.rassoc('feline'))
+ assert_equal(a3, a.rassoc('asinine'))
+ assert_equal(nil, a.rassoc('dog'))
+ assert_equal(nil, a.rassoc('mule'))
+ assert_equal(nil, a.rassoc(1..2))
+ end
+
+ # also delete_if
+ def test_reject!
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(nil, a.reject! { false })
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(a, a.reject! { true })
+ assert_equal(@cls[], a)
+
+ a = @cls[ 1, 2, 3, 4, 5 ]
+ assert_equal(a, a.reject! { |i| i > 3 })
+ assert_equal(@cls[1, 2, 3], a)
+ end
+
+ def test_replace
+ a = @cls[ 1, 2, 3]
+ a_id = a.__id__
+ assert_equal(@cls[4, 5, 6], a.replace(@cls[4, 5, 6]))
+ assert_equal(@cls[4, 5, 6], a)
+ assert_equal(a_id, a.__id__)
+ assert_equal(@cls[], a.replace(@cls[]))
+ end
+
+ def test_reverse
+ a = @cls[*%w( dog cat bee ant )]
+ assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
+ assert_equal(@cls[*%w(dog cat bee ant)], a)
+ assert_equal(@cls[], @cls[].reverse)
+ end
+
+ def test_reverse!
+ a = @cls[*%w( dog cat bee ant )]
+ assert_equal(@cls[*%w(ant bee cat dog)], a.reverse!)
+ assert_equal(@cls[*%w(ant bee cat dog)], a)
+ # Ruby 1.8 feature change:
+ # Array#reverse always returns self.
+ #assert_nil(@cls[].reverse!)
+ assert_equal @cls[], @cls[].reverse!
+ end
+
+ def test_reverse_each
+ a = @cls[*%w( dog cat bee ant )]
+ i = a.length
+ a.reverse_each { |e|
+ i -= 1
+ assert_equal(a[i], e)
+ }
+ assert_equal(0, i)
+
+ a = @cls[]
+ i = 0
+ a.reverse_each { |e|
+ assert(false, "Never get here")
+ }
+ assert_equal(0, i)
+ end
+
+ def test_rindex
+ a = @cls[ 'cat', 99, /a/, 99, [ 1, 2, 3] ]
+ assert_equal(0, a.rindex('cat'))
+ assert_equal(3, a.rindex(99))
+ assert_equal(4, a.rindex([1,2,3]))
+ assert_nil(a.rindex('ca'))
+ assert_nil(a.rindex([1,2]))
+ end
+
+ def test_shift
+ a = @cls[ 'cat', 'dog' ]
+ assert_equal('cat', a.shift)
+ assert_equal(@cls['dog'], a)
+ assert_equal('dog', a.shift)
+ assert_equal(@cls[], a)
+ assert_nil(a.shift)
+ assert_equal(@cls[], a)
+ end
+
+ def test_size
+ assert_equal(0, @cls[].size)
+ assert_equal(1, @cls[1].size)
+ assert_equal(100, @cls[*(0..99).to_a].size)
+ end
+
+ def test_slice
+ a = @cls[*(1..100).to_a]
+
+ assert_equal(1, a.slice(0))
+ assert_equal(100, a.slice(99))
+ assert_nil(a.slice(100))
+ assert_equal(100, a.slice(-1))
+ assert_equal(99, a.slice(-2))
+ assert_equal(1, a.slice(-100))
+ assert_nil(a.slice(-101))
+
+ assert_equal(@cls[1], a.slice(0,1))
+ assert_equal(@cls[100], a.slice(99,1))
+ assert_equal(@cls[], a.slice(100,1))
+ assert_equal(@cls[100], a.slice(99,100))
+ assert_equal(@cls[100], a.slice(-1,1))
+ assert_equal(@cls[99], a.slice(-2,1))
+
+ assert_equal(@cls[10, 11, 12], a.slice(9, 3))
+ assert_equal(@cls[10, 11, 12], a.slice(-91, 3))
+
+ assert_nil(a.slice(-101, 2))
+
+ assert_equal(@cls[1], a.slice(0..0))
+ assert_equal(@cls[100], a.slice(99..99))
+ assert_equal(@cls[], a.slice(100..100))
+ assert_equal(@cls[100], a.slice(99..200))
+ assert_equal(@cls[100], a.slice(-1..-1))
+ assert_equal(@cls[99], a.slice(-2..-2))
+
+ assert_equal(@cls[10, 11, 12], a.slice(9..11))
+ assert_equal(@cls[10, 11, 12], a.slice(-91..-89))
+
+ assert_nil(a.slice(-101..-1))
+
+ assert_nil(a.slice(10, -3))
+ # Ruby 1.8 feature change:
+ # Array#slice[size..x] always returns [].
+ #assert_nil(a.slice(10..7))
+ assert_equal @cls[], a.slice(10..7)
+ end
+
+ def test_slice!
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(3, a.slice!(2))
+ assert_equal(@cls[1, 2, 4, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(4, a.slice!(-2))
+ assert_equal(@cls[1, 2, 3, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(@cls[3,4], a.slice!(2,2))
+ assert_equal(@cls[1, 2, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(@cls[4,5], a.slice!(-2,2))
+ assert_equal(@cls[1, 2, 3], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(@cls[3,4], a.slice!(2..3))
+ assert_equal(@cls[1, 2, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(nil, a.slice!(20))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(nil, a.slice!(-6))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(nil, a.slice!(-6..4))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+
+ a = @cls[1, 2, 3, 4, 5]
+ assert_equal(nil, a.slice!(-6,2))
+ assert_equal(@cls[1, 2, 3, 4, 5], a)
+ end
+
+ def test_sort
+ a = @cls[ 4, 1, 2, 3 ]
+ assert_equal(@cls[1, 2, 3, 4], a.sort)
+ assert_equal(@cls[4, 1, 2, 3], a)
+
+ assert_equal(@cls[4, 3, 2, 1], a.sort { |x, y| y <=> x} )
+ assert_equal(@cls[4, 1, 2, 3], a)
+
+ a.fill(1)
+ assert_equal(@cls[1, 1, 1, 1], a.sort)
+
+ assert_equal(@cls[], @cls[].sort)
+ end
+
+ def test_sort!
+ a = @cls[ 4, 1, 2, 3 ]
+ assert_equal(@cls[1, 2, 3, 4], a.sort!)
+ assert_equal(@cls[1, 2, 3, 4], a)
+
+ assert_equal(@cls[4, 3, 2, 1], a.sort! { |x, y| y <=> x} )
+ assert_equal(@cls[4, 3, 2, 1], a)
+
+ a.fill(1)
+ assert_equal(@cls[1, 1, 1, 1], a.sort!)
+
+ assert_equal(@cls[1], @cls[1].sort!)
+ assert_equal(@cls[], @cls[].sort!)
+ end
+
+ def test_sort_with_callcc
+ respond_to?(:callcc, true) or require 'continuation'
+ n = 1000
+ cont = nil
+ ary = (1..100).to_a
+ begin
+ ary.sort! {|a,b|
+ callcc {|k| cont = k} unless cont
+ assert_equal(100, ary.size, '[ruby-core:16679]')
+ a <=> b
+ }
+ rescue => e
+ end
+ n -= 1
+ cont.call if 0 < n
+ assert_instance_of(RuntimeError, e, '[ruby-core:16679]')
+ assert_match(/reentered/, e.message, '[ruby-core:16679]')
+ end
+
+ def test_sort_with_replace
+ xary = (1..100).to_a
+ 100.times do
+ ary = (1..100).to_a
+ ary.sort! {|a,b| ary.replace(xary); a <=> b}
+ GC.start
+ assert_equal(xary, ary, '[ruby-dev:34732]')
+ end
+ end
+
+ def test_to_a
+ a = @cls[ 1, 2, 3 ]
+ a_id = a.__id__
+ assert_equal(a, a.to_a)
+ assert_equal(a_id, a.to_a.__id__)
+ end
+
+ def test_to_ary
+ a = [ 1, 2, 3 ]
+ b = @cls[*a]
+
+ a_id = a.__id__
+ assert_equal(a, b.to_ary)
+ if (@cls == Array)
+ assert_equal(a_id, a.to_ary.__id__)
+ end
+ end
+
+ def test_to_s
+ $, = ""
+ a = @cls[]
+ assert_equal("[]", a.to_s)
+
+ $, = ""
+ a = @cls[1, 2]
+ assert_equal("[1, 2]", a.to_s)
+
+ $, = ""
+ a = @cls[1, 2, 3]
+ assert_equal("[1, 2, 3]", a.to_s)
+
+ $, = ":"
+ a = @cls[1, 2, 3]
+ assert_equal("[1, 2, 3]", a.to_s)
+
+ $, = ""
+ end
+
+ def test_uniq
+ a = @cls[ 1, 2, 3, 2, 1, 2, 3, 4, nil ]
+ b = a.dup
+ assert_equal(@cls[1, 2, 3, 4, nil], a.uniq)
+ assert_equal(b, a)
+
+ assert_equal(@cls[1, 2, 3], @cls[1, 2, 3].uniq)
+ end
+
+ def test_uniq!
+ a = @cls[ 1, 2, 3, 2, 1, 2, 3, 4, nil ]
+ assert_equal(@cls[1, 2, 3, 4, nil], a.uniq!)
+ assert_equal(@cls[1, 2, 3, 4, nil], a)
+
+ assert_nil(@cls[1, 2, 3].uniq!)
+ end
+
+ def test_unshift
+ a = @cls[]
+ assert_equal(@cls['cat'], a.unshift('cat'))
+ assert_equal(@cls['dog', 'cat'], a.unshift('dog'))
+ assert_equal(@cls[nil, 'dog', 'cat'], a.unshift(nil))
+ assert_equal(@cls[@cls[1,2], nil, 'dog', 'cat'], a.unshift(@cls[1, 2]))
+ end
+
+ def test_OR # '|'
+ assert_equal(@cls[], @cls[] | @cls[])
+ assert_equal(@cls[1], @cls[1] | @cls[])
+ assert_equal(@cls[1], @cls[] | @cls[1])
+ assert_equal(@cls[1], @cls[1] | @cls[1])
+
+ assert_equal(@cls[1,2], @cls[1] | @cls[2])
+ assert_equal(@cls[1,2], @cls[1, 1] | @cls[2, 2])
+ assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2])
+ end
+
+ def test_combination
+ assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
+ assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)
+ assert_equal(@cls[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], @cls[1,2,3,4].combination(2).to_a)
+ assert_equal(@cls[[1,2,3],[1,2,4],[1,3,4],[2,3,4]], @cls[1,2,3,4].combination(3).to_a)
+ assert_equal(@cls[[1,2,3,4]], @cls[1,2,3,4].combination(4).to_a)
+ assert_equal(@cls[], @cls[1,2,3,4].combination(5).to_a)
+ end
+
+ def test_product
+ assert_equal(@cls[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]],
+ @cls[1,2,3].product([4,5]))
+ assert_equal(@cls[[1,1],[1,2],[2,1],[2,2]], @cls[1,2].product([1,2]))
+
+ assert_equal(@cls[[1,3,5],[1,3,6],[1,4,5],[1,4,6],
+ [2,3,5],[2,3,6],[2,4,5],[2,4,6]],
+ @cls[1,2].product([3,4],[5,6]))
+ assert_equal(@cls[[1],[2]], @cls[1,2].product)
+ assert_equal(@cls[], @cls[1,2].product([]))
+ end
+
+ def test_permutation
+ a = @cls[1,2,3]
+ assert_equal(@cls[[]], a.permutation(0).to_a)
+ assert_equal(@cls[[1],[2],[3]], a.permutation(1).to_a.sort)
+ assert_equal(@cls[[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]],
+ a.permutation(2).to_a.sort)
+ assert_equal(@cls[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
+ a.permutation(3).sort.to_a)
+ assert_equal(@cls[], a.permutation(4).to_a)
+ assert_equal(@cls[], a.permutation(-1).to_a)
+ assert_equal("abcde".each_char.to_a.permutation(5).sort,
+ "edcba".each_char.to_a.permutation(5).sort)
+ assert_equal(@cls[].permutation(0).to_a, @cls[[]])
+
+ end
+
+ def test_take
+ assert_equal([1,2,3], [1,2,3,4,5,0].take(3))
+ assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) }
+ assert_equal([1,2], [1,2].take(1000000000), '[ruby-dev:34123]')
+ end
+
+ def test_take_while
+ assert_equal([1,2], [1,2,3,4,5,0].take_while {|i| i < 3 })
+ end
+
+ def test_drop
+ assert_equal([4,5,0], [1,2,3,4,5,0].drop(3))
+ assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].drop(-1) }
+ assert_equal([], [1,2].drop(1000000000), '[ruby-dev:34123]')
+ end
+
+ def test_drop_while
+ assert_equal([3,4,5,0], [1,2,3,4,5,0].drop_while {|i| i < 3 })
+ end
+
+ def test_modify_check
+ a = []
+ a.freeze
+ assert_raise(RuntimeError) { a.shift }
+ a = [1, 2]
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ a.shift
+ end.value
+ end
+ end
+
+ LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x|
+ begin
+ [].first(x)
+ rescue ArgumentError
+ true
+ rescue RangeError
+ false
+ end
+ end
+
+ def test_ary_new
+ assert_raise(ArgumentError) { [].to_enum.first(-1) }
+ assert_raise(ArgumentError) { [].to_enum.first(LONGP) }
+ end
+
+ def test_try_convert
+ assert_equal([1], Array.try_convert([1]))
+ assert_equal(nil, Array.try_convert("1"))
+ end
+
+ def test_initialize
+ assert_nothing_raised { [].instance_eval { initialize } }
+ assert_nothing_raised { Array.new { } }
+ assert_equal([1, 2, 3], Array.new([1, 2, 3]))
+ assert_raise(ArgumentError) { Array.new(-1, 1) }
+ assert_raise(ArgumentError) { Array.new(LONGP, 1) }
+ assert_equal([1, 1, 1], Array.new(3, 1))
+ assert_equal([1, 1, 1], Array.new(3) { 1 })
+ assert_equal([1, 1, 1], Array.new(3, 1) { 1 })
+ end
+
+ def test_aset
+ assert_raise(IndexError) { [0][-2] = 1 }
+ assert_raise(IndexError) { [0][LONGP] = 2 }
+ assert_raise(IndexError) { [0][(LONGP + 1) / 2 - 1] = 2 }
+ a = [0]
+ a[2] = 4
+ assert_equal([0, nil, 4], a)
+ assert_raise(ArgumentError) { [0][0, 0, 0] = 0 }
+ end
+
+ def test_first2
+ assert_equal([0], [0].first(2))
+ assert_raise(ArgumentError) { [0].first(-1) }
+ end
+
+ def test_shift2
+ assert_equal(0, ([0] * 16).shift)
+ # check
+ a = [0, 1, 2]
+ a[3] = 3
+ a.shift(2)
+ assert_equal([2, 3], a)
+ end
+
+ def test_unshift2
+ Struct.new(:a, :b, :c)
+ end
+
+ def test_aref
+ assert_raise(ArgumentError) { [][0, 0, 0] }
+ end
+
+ def test_fetch
+ assert_equal(1, [].fetch(0, 0) { 1 })
+ assert_equal(1, [0, 1].fetch(-1))
+ assert_raise(IndexError) { [0, 1].fetch(2) }
+ assert_raise(IndexError) { [0, 1].fetch(-3) }
+ assert_equal(2, [0, 1].fetch(2, 2))
+ end
+
+ def test_index2
+ a = [0, 1, 2]
+ assert_equal(a, a.index.to_a)
+ assert_equal(1, a.index {|x| x == 1 })
+ end
+
+ def test_rindex2
+ a = [0, 1, 2]
+ assert_equal([2, 1, 0], a.rindex.to_a)
+ assert_equal(1, a.rindex {|x| x == 1 })
+
+ a = [0, 1]
+ e = a.rindex
+ assert_equal(1, e.next)
+ a.clear
+ assert_raise(StopIteration) { e.next }
+
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:==) {|x| a.clear; false }
+ end
+ a = [nil, o]
+ assert_equal(nil, a.rindex(0))
+ end
+
+ def test_ary_to_ary
+ o = Object.new
+ def o.to_ary; [1, 2, 3]; end
+ a, b, c = o
+ assert_equal([1, 2, 3], [a, b, c])
+ end
+
+ def test_splice
+ a = [0]
+ assert_raise(IndexError) { a[-2, 0] = nil }
+ end
+
+ def test_insert
+ a = [0]
+ assert_equal([0], a.insert(1))
+ assert_equal([0, 1], a.insert(1, 1))
+ assert_raise(ArgumentError) { a.insert }
+ assert_equal([0, 1, 2], a.insert(-1, 2))
+ assert_equal([0, 1, 3, 2], a.insert(-2, 3))
+ end
+
+ def test_join2
+ a = []
+ a << a
+ assert_equal("[...]", a.join)
+ end
+
+ def test_to_a2
+ klass = Class.new(Array)
+ a = klass.new.to_a
+ assert_equal([], a)
+ assert_equal(Array, a.class)
+ end
+
+ def test_values_at2
+ a = [0, 1, 2, 3, 4, 5]
+ assert_equal([1, 2, 3], a.values_at(1..3))
+ assert_equal([], a.values_at(7..8))
+ assert_equal([nil], a.values_at(2**31-1))
+ end
+
+ def test_select
+ assert_equal([0, 2], [0, 1, 2, 3].select {|x| x % 2 == 0 })
+ end
+
+ def test_delete2
+ a = [0] * 1024 + [1] + [0] * 1024
+ a.delete(0)
+ assert_equal([1], a)
+ end
+
+ def test_reject
+ assert_equal([1, 3], [0, 1, 2, 3].reject {|x| x % 2 == 0 })
+ end
+
+ def test_zip
+ assert_equal([[1, :a, "a"], [2, :b, "b"], [3, nil, "c"]],
+ [1, 2, 3].zip([:a, :b], ["a", "b", "c", "d"]))
+ a = []
+ [1, 2, 3].zip([:a, :b], ["a", "b", "c", "d"]) {|x| a << x }
+ assert_equal([[1, :a, "a"], [2, :b, "b"], [3, nil, "c"]], a)
+ end
+
+ def test_transpose
+ assert_equal([[1, :a], [2, :b], [3, :c]],
+ [[1, 2, 3], [:a, :b, :c]].transpose)
+ assert_raise(IndexError) { [[1, 2, 3], [:a, :b]].transpose }
+ end
+
+ def test_clear2
+ assert_equal([], ([0] * 1024).clear)
+ end
+
+ def test_fill2
+ assert_raise(ArgumentError) { [].fill(0, 1, LONGP) }
+ end
+
+ def test_times
+ assert_raise(ArgumentError) { [0, 0, 0, 0] * ((LONGP + 1) / 4) }
+ end
+
+ def test_equal
+ o = Object.new
+ def o.to_ary; end
+ def o.==(x); :foo; end
+ assert(:foo, [0, 1, 2] == o)
+ assert([0, 1, 2] != [0, 1, 3])
+ end
+
+ def test_hash2
+ a = []
+ a << a
+ b = []
+ b << b
+ assert_equal(a.hash, b.hash)
+ end
+
+ def test_flatten2
+ a = []
+ a << a
+ assert_raise(ArgumentError) { a.flatten }
+ end
+
+ def test_shuffle
+ 100.times do
+ assert_equal([0, 1, 2], [2, 1, 0].shuffle.sort)
+ end
+ end
+
+ def test_sample
+ 100.times do
+ assert([0, 1, 2].include?([2, 1, 0].sample))
+ samples = [2, 1, 0].sample(2)
+ samples.each{|sample|
+ assert([0, 1, 2].include?(sample))
+ }
+ end
+ end
+
+ def test_cycle
+ a = []
+ [0, 1, 2].cycle do |i|
+ a << i
+ break if a.size == 10
+ end
+ assert_equal([0, 1, 2, 0, 1, 2, 0, 1, 2, 0], a)
+
+ a = [0, 1, 2]
+ assert_nil(a.cycle { a.clear })
+
+ a = []
+ [0, 1, 2].cycle(3) {|i| a << i }
+ assert_equal([0, 1, 2, 0, 1, 2, 0, 1, 2], a)
+ end
+
+ def test_reverse_each2
+ a = [0, 1, 2, 3, 4, 5]
+ r = []
+ a.reverse_each do |x|
+ r << x
+ a.pop
+ a.pop
+ end
+ assert_equal([5, 3, 1], r)
+ end
+
+ def test_combination2
+ assert_raise(RangeError) do
+ (0..100).to_a.combination(50) {}
+ end
+ end
+
+ def test_product2
+ a = (0..100).to_a
+ assert_raise(RangeError) do
+ a.product(a, a, a, a, a, a, a, a, a, a) {}
+ end
+ end
+
+ class Array2 < Array
+ end
+
+ def test_array_subclass
+ assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]")
+ end
+
+ def test_inspect
+ a = @cls[1, 2, 3]
+ a.taint
+ a.untrust
+ s = a.inspect
+ assert_equal(true, s.tainted?)
+ assert_equal(true, s.untrusted?)
+ end
+end
diff --git a/trunk/test/ruby/test_assignment.rb b/trunk/test/ruby/test_assignment.rb
new file mode 100644
index 0000000000..b82cee81d1
--- /dev/null
+++ b/trunk/test/ruby/test_assignment.rb
@@ -0,0 +1,687 @@
+require 'test/unit'
+
+class TestAssignment < Test::Unit::TestCase
+ def test_assign
+ a=[]; a[0] ||= "bar";
+ assert_equal("bar", a[0])
+ h={}; h["foo"] ||= "bar";
+ assert_equal("bar", h["foo"])
+
+ aa = 5
+ aa ||= 25
+ assert_equal(5, aa)
+ bb ||= 25
+ assert_equal(25, bb)
+ cc &&=33
+ assert_nil(cc)
+ cc = 5
+ cc &&=44
+ assert_equal(44, cc)
+
+ a = nil; assert_nil(a)
+ a = 1; assert_equal(1, a)
+ a = []; assert_equal([], a)
+ a = [1]; assert_equal([1], a)
+ a = [nil]; assert_equal([nil], a)
+ a = [[]]; assert_equal([[]], a)
+ a = [1,2]; assert_equal([1,2], a)
+ a = [*[]]; assert_equal([], a)
+ a = [*[1]]; assert_equal([1], a)
+ a = [*[1,2]]; assert_equal([1,2], a)
+
+ a = *[]; assert_equal([], a)
+ a = *[1]; assert_equal([1], a)
+ a = *[nil]; assert_equal([nil], a)
+ a = *[[]]; assert_equal([[]], a)
+ a = *[1,2]; assert_equal([1,2], a)
+ a = *[*[]]; assert_equal([], a)
+ a = *[*[1]]; assert_equal([1], a)
+ a = *[*[1,2]]; assert_equal([1,2], a)
+
+ *a = nil; assert_equal([nil], a)
+ *a = 1; assert_equal([1], a)
+ *a = []; assert_equal([], a)
+ *a = [1]; assert_equal([1], a)
+ *a = [nil]; assert_equal([nil], a)
+ *a = [[]]; assert_equal([[]], a)
+ *a = [1,2]; assert_equal([1,2], a)
+ *a = [*[]]; assert_equal([], a)
+ *a = [*[1]]; assert_equal([1], a)
+ *a = [*[1,2]]; assert_equal([1,2], a)
+
+ *a = *[]; assert_equal([], a)
+ *a = *[1]; assert_equal([1], a)
+ *a = *[nil]; assert_equal([nil], a)
+ *a = *[[]]; assert_equal([[]], a)
+ *a = *[1,2]; assert_equal([1,2], a)
+ *a = *[*[]]; assert_equal([], a)
+ *a = *[*[1]]; assert_equal([1], a)
+ *a = *[*[1,2]]; assert_equal([1,2], a)
+
+ a,b,*c = nil; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = 1; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = []; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = [1]; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = [nil]; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = [[]]; assert_equal([[],nil,[]], [a,b,c])
+ a,b,*c = [1,2]; assert_equal([1,2,[]], [a,b,c])
+ a,b,*c = [*[]]; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = [*[1]]; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = [*[1,2]]; assert_equal([1,2,[]], [a,b,c])
+
+ a,b,*c = *[]; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = *[1]; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = *[nil]; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = *[[]]; assert_equal([[],nil,[]], [a,b,c])
+ a,b,*c = *[1,2]; assert_equal([1,2,[]], [a,b,c])
+ a,b,*c = *[*[]]; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = *[*[1]]; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = *[*[1,2]]; assert_equal([1,2,[]], [a,b,c])
+ end
+
+ def test_yield
+ def f; yield(nil); end; f {|a| assert_nil(a)}; undef f
+ def f; yield(1); end; f {|a| assert_equal(1, a)}; undef f
+ def f; yield([]); end; f {|a| assert_equal([], a)}; undef f
+ def f; yield([1]); end; f {|a| assert_equal([1], a)}; undef f
+ def f; yield([nil]); end; f {|a| assert_equal([nil], a)}; undef f
+ def f; yield([[]]); end; f {|a| assert_equal([[]], a)}; undef f
+ def f; yield([*[]]); end; f {|a| assert_equal([], a)}; undef f
+ def f; yield([*[1]]); end; f {|a| assert_equal([1], a)}; undef f
+ def f; yield([*[1,2]]); end; f {|a| assert_equal([1,2], a)}; undef f
+
+ def f; yield(*[1]); end; f {|a| assert_equal(1, a)}; undef f
+ def f; yield(*[nil]); end; f {|a| assert_equal(nil, a)}; undef f
+ def f; yield(*[[]]); end; f {|a| assert_equal([], a)}; undef f
+ def f; yield(*[*[1]]); end; f {|a| assert_equal(1, a)}; undef f
+
+ def f; yield; end; f {|*a| assert_equal([], a)}; undef f
+ def f; yield(nil); end; f {|*a| assert_equal([nil], a)}; undef f
+ def f; yield(1); end; f {|*a| assert_equal([1], a)}; undef f
+ def f; yield([]); end; f {|*a| assert_equal([[]], a)}; undef f
+ def f; yield([1]); end; f {|*a| assert_equal([[1]], a)}; undef f
+ def f; yield([nil]); end; f {|*a| assert_equal([[nil]], a)}; undef f
+ def f; yield([[]]); end; f {|*a| assert_equal([[[]]], a)}; undef f
+ def f; yield([1,2]); end; f {|*a| assert_equal([[1,2]], a)}; undef f
+ def f; yield([*[]]); end; f {|*a| assert_equal([[]], a)}; undef f
+ def f; yield([*[1]]); end; f {|*a| assert_equal([[1]], a)}; undef f
+ def f; yield([*[1,2]]); end; f {|*a| assert_equal([[1,2]], a)}; undef f
+
+ def f; yield(*[]); end; f {|*a| assert_equal([], a)}; undef f
+ def f; yield(*[1]); end; f {|*a| assert_equal([1], a)}; undef f
+ def f; yield(*[nil]); end; f {|*a| assert_equal([nil], a)}; undef f
+ def f; yield(*[[]]); end; f {|*a| assert_equal([[]], a)}; undef f
+ def f; yield(*[*[]]); end; f {|*a| assert_equal([], a)}; undef f
+ def f; yield(*[*[1]]); end; f {|*a| assert_equal([1], a)}; undef f
+ def f; yield(*[*[1,2]]); end; f {|*a| assert_equal([1,2], a)}; undef f
+
+ def f; yield; end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(nil); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(1); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
+ def f; yield([]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield([1]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
+ def f; yield([nil]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield([[]]); end; f {|a,b,*c| assert_equal([[],nil,[]], [a,b,c])}; undef f
+ def f; yield([*[]]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield([*[1]]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
+ def f; yield([*[1,2]]); end; f {|a,b,*c| assert_equal([1,2,[]], [a,b,c])}; undef f
+
+ def f; yield(*[]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[1]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[nil]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[[]]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[*[]]); end; f {|a,b,*c| assert_equal([nil,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[*[1]]); end; f {|a,b,*c| assert_equal([1,nil,[]], [a,b,c])}; undef f
+ def f; yield(*[*[1,2]]); end; f {|a,b,*c| assert_equal([1,2,[]], [a,b,c])}; undef f
+ end
+
+ def test_return
+ def r; return; end; a = r(); assert_nil(a); undef r
+ def r; return nil; end; a = r(); assert_nil(a); undef r
+ def r; return 1; end; a = r(); assert_equal(1, a); undef r
+ def r; return []; end; a = r(); assert_equal([], a); undef r
+ def r; return [1]; end; a = r(); assert_equal([1], a); undef r
+ def r; return [nil]; end; a = r(); assert_equal([nil], a); undef r
+ def r; return [[]]; end; a = r(); assert_equal([[]], a); undef r
+ def r; return [*[]]; end; a = r(); assert_equal([], a); undef r
+ def r; return [*[1]]; end; a = r(); assert_equal([1], a); undef r
+ def r; return [*[1,2]]; end; a = r(); assert_equal([1,2], a); undef r
+
+ def r; return *[]; end; a = r(); assert_equal([], a); undef r
+ def r; return *[1]; end; a = r(); assert_equal([1], a); undef r
+ def r; return *[nil]; end; a = r(); assert_equal([nil], a); undef r
+ def r; return *[[]]; end; a = r(); assert_equal([[]], a); undef r
+ def r; return *[*[]]; end; a = r(); assert_equal([], a); undef r
+ def r; return *[*[1]]; end; a = r(); assert_equal([1], a); undef r
+ def r; return *[*[1,2]]; end; a = r(); assert_equal([1,2], a); undef r
+
+ def r; return *[[]]; end; a = *r(); assert_equal([[]], a); undef r
+ def r; return *[*[1,2]]; end; a = *r(); assert_equal([1,2], a); undef r
+
+ def r; return; end; *a = r(); assert_equal([nil], a); undef r
+ def r; return nil; end; *a = r(); assert_equal([nil], a); undef r
+ def r; return 1; end; *a = r(); assert_equal([1], a); undef r
+ def r; return []; end; *a = r(); assert_equal([], a); undef r
+ def r; return [1]; end; *a = r(); assert_equal([1], a); undef r
+ def r; return [nil]; end; *a = r(); assert_equal([nil], a); undef r
+ def r; return [[]]; end; *a = r(); assert_equal([[]], a); undef r
+ def r; return [1,2]; end; *a = r(); assert_equal([1,2], a); undef r
+ def r; return [*[]]; end; *a = r(); assert_equal([], a); undef r
+ def r; return [*[1]]; end; *a = r(); assert_equal([1], a); undef r
+ def r; return [*[1,2]]; end; *a = r(); assert_equal([1,2], a); undef r
+
+ def r; return *[]; end; *a = r(); assert_equal([], a); undef r
+ def r; return *[1]; end; *a = r(); assert_equal([1], a); undef r
+ def r; return *[nil]; end; *a = r(); assert_equal([nil], a); undef r
+ def r; return *[[]]; end; *a = r(); assert_equal([[]], a); undef r
+ def r; return *[1,2]; end; *a = r(); assert_equal([1,2], a); undef r
+ def r; return *[*[]]; end; *a = r(); assert_equal([], a); undef r
+ def r; return *[*[1]]; end; *a = r(); assert_equal([1], a); undef r
+ def r; return *[*[1,2]]; end; *a = r(); assert_equal([1,2], a); undef r
+
+ def r; return *[[]]; end; *a = *r(); assert_equal([[]], a); undef r
+ def r; return *[1,2]; end; *a = *r(); assert_equal([1,2], a); undef r
+ def r; return *[*[1,2]]; end; *a = *r(); assert_equal([1,2], a); undef r
+
+ def r; return; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return nil; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return 1; end; a,b,*c = r(); assert_equal([1,nil,[]], [a,b,c]); undef r
+ def r; return []; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return [1]; end; a,b,*c = r(); assert_equal([1,nil,[]], [a,b,c]); undef r
+ def r; return [nil]; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return [[]]; end; a,b,*c = r(); assert_equal([[],nil,[]], [a,b,c]); undef r
+ def r; return [1,2]; end; a,b,*c = r(); assert_equal([1,2,[]], [a,b,c]); undef r
+ def r; return [*[]]; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return [*[1]]; end; a,b,*c = r(); assert_equal([1,nil,[]], [a,b,c]); undef r
+ def r; return [*[1,2]]; end; a,b,*c = r(); assert_equal([1,2,[]], [a,b,c]); undef r
+
+ def r; return *[]; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return *[1]; end; a,b,*c = r(); assert_equal([1,nil,[]], [a,b,c]); undef r
+ def r; return *[nil]; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return *[[]]; end; a,b,*c = r(); assert_equal([[],nil,[]], [a,b,c]); undef r
+ def r; return *[1,2]; end; a,b,*c = r(); assert_equal([1,2,[]], [a,b,c]); undef r
+ def r; return *[*[]]; end; a,b,*c = r(); assert_equal([nil,nil,[]], [a,b,c]); undef r
+ def r; return *[*[1]]; end; a,b,*c = r(); assert_equal([1,nil,[]], [a,b,c]); undef r
+ def r; return *[*[1,2]]; end; a,b,*c = r(); assert_equal([1,2,[]], [a,b,c]); undef r
+
+ def r; return 1, *[]; end; a,b = r(); assert_equal([1,nil], [a,b]); undef r
+ def r; return 1,2,*[1]; end; a,b = r(); assert_equal([1,2], [a,b]); undef r
+ def r; return 1,2,3,*[1,2]; end; a,b = r(); assert_equal([1,2], [a,b]); undef r
+ end
+
+ def test_lambda
+ f = lambda {|r,| assert_equal([], r)}
+ f.call([], *[])
+
+ f = lambda {|r,*l| assert_equal([], r); assert_equal([1], l)}
+ f.call([], *[1])
+
+ f = lambda{|x| x}
+ assert_equal(42, f.call(42))
+ assert_equal([42], f.call([42]))
+ assert_equal([[42]], f.call([[42]]))
+ assert_equal([42,55], f.call([42,55]))
+
+ f = lambda{|x,| x}
+ assert_equal(42, f.call(42))
+ assert_equal([42], f.call([42]))
+ assert_equal([[42]], f.call([[42]]))
+ assert_equal([42,55], f.call([42,55]))
+
+ f = lambda{|*x| x}
+ assert_equal([42], f.call(42))
+ assert_equal([[42]], f.call([42]))
+ assert_equal([[[42]]], f.call([[42]]))
+ assert_equal([[42,55]], f.call([42,55]))
+ assert_equal([42,55], f.call(42,55))
+ end
+
+ def test_multi
+ a,=*[1]
+ assert_equal(1, a)
+ a,=*[[1]]
+ assert_equal([1], a)
+ a,=*[[[1]]]
+ assert_equal([[1]], a)
+
+ x, (y, z) = 1, 2, 3
+ assert_equal([1,2,nil], [x,y,z])
+ x, (y, z) = 1, [2,3]
+ assert_equal([1,2,3], [x,y,z])
+ x, (y, z) = 1, [2]
+ assert_equal([1,2,nil], [x,y,z])
+ end
+
+ def test_break
+ a = loop do break; end; assert_nil(a)
+ a = loop do break nil; end; assert_nil(a)
+ a = loop do break 1; end; assert_equal(1, a)
+ a = loop do break []; end; assert_equal([], a)
+ a = loop do break [1]; end; assert_equal([1], a)
+ a = loop do break [nil]; end; assert_equal([nil], a)
+ a = loop do break [[]]; end; assert_equal([[]], a)
+ a = loop do break [*[]]; end; assert_equal([], a)
+ a = loop do break [*[1]]; end; assert_equal([1], a)
+ a = loop do break [*[1,2]]; end; assert_equal([1,2], a)
+
+ a = loop do break *[]; end; assert_equal([], a)
+ a = loop do break *[1]; end; assert_equal([1], a)
+ a = loop do break *[nil]; end; assert_equal([nil], a)
+ a = loop do break *[[]]; end; assert_equal([[]], a)
+ a = loop do break *[*[]]; end; assert_equal([], a)
+ a = loop do break *[*[1]]; end; assert_equal([1], a)
+ a = loop do break *[*[1,2]]; end; assert_equal([1,2], a)
+
+ *a = loop do break; end; assert_equal([nil], a)
+ *a = loop do break nil; end; assert_equal([nil], a)
+ *a = loop do break 1; end; assert_equal([1], a)
+ *a = loop do break []; end; assert_equal([], a)
+ *a = loop do break [1]; end; assert_equal([1], a)
+ *a = loop do break [nil]; end; assert_equal([nil], a)
+ *a = loop do break [[]]; end; assert_equal([[]], a)
+ *a = loop do break [1,2]; end; assert_equal([1,2], a)
+ *a = loop do break [*[]]; end; assert_equal([], a)
+ *a = loop do break [*[1]]; end; assert_equal([1], a)
+ *a = loop do break [*[1,2]]; end; assert_equal([1,2], a)
+
+ *a = loop do break *[]; end; assert_equal([], a)
+ *a = loop do break *[1]; end; assert_equal([1], a)
+ *a = loop do break *[nil]; end; assert_equal([nil], a)
+ *a = loop do break *[[]]; end; assert_equal([[]], a)
+ *a = loop do break *[1,2]; end; assert_equal([1,2], a)
+ *a = loop do break *[*[]]; end; assert_equal([], a)
+ *a = loop do break *[*[1]]; end; assert_equal([1], a)
+ *a = loop do break *[*[1,2]]; end; assert_equal([1,2], a)
+
+ *a = *loop do break *[[]]; end; assert_equal([[]], a)
+ *a = *loop do break *[1,2]; end; assert_equal([1,2], a)
+ *a = *loop do break *[*[1,2]]; end; assert_equal([1,2], a)
+
+ a,b,*c = loop do break; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break nil; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break 1; end; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = loop do break []; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break [1]; end; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = loop do break [nil]; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break [[]]; end; assert_equal([[],nil,[]], [a,b,c])
+ a,b,*c = loop do break [1,2]; end; assert_equal([1,2,[]], [a,b,c])
+ a,b,*c = loop do break [*[]]; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break [*[1]]; end; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = loop do break [*[1,2]]; end; assert_equal([1,2,[]], [a,b,c])
+
+ a,b,*c = loop do break *[]; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break *[1]; end; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = loop do break *[nil]; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break *[[]]; end; assert_equal([[],nil,[]], [a,b,c])
+ a,b,*c = loop do break *[1,2]; end; assert_equal([1,2,[]], [a,b,c])
+ a,b,*c = loop do break *[*[]]; end; assert_equal([nil,nil,[]], [a,b,c])
+ a,b,*c = loop do break *[*[1]]; end; assert_equal([1,nil,[]], [a,b,c])
+ a,b,*c = loop do break *[*[1,2]]; end; assert_equal([1,2,[]], [a,b,c])
+ end
+
+ def test_next
+ def r(val); a = yield(); assert_equal(val, a); end
+ r(nil){next}
+ r(nil){next nil}
+ r(1){next 1}
+ r([]){next []}
+ r([1]){next [1]}
+ r([nil]){next [nil]}
+ r([[]]){next [[]]}
+ r([]){next [*[]]}
+ r([1]){next [*[1]]}
+ r([1,2]){next [*[1,2]]}
+
+ r([]){next *[]}
+ r([1]){next *[1]}
+ r([nil]){next *[nil]}
+ r([[]]){next *[[]]}
+ r([]){next *[*[]]}
+ r([1]){next *[*[1]]}
+ r([1,2]){next *[*[1,2]]}
+ undef r
+
+ def r(val); *a = yield(); assert_equal(val, a); end
+ r([nil]){next}
+ r([nil]){next nil}
+ r([1]){next 1}
+ r([]){next []}
+ r([1]){next [1]}
+ r([nil]){next [nil]}
+ r([[]]){next [[]]}
+ r([1,2]){next [1,2]}
+ r([]){next [*[]]}
+ r([1]){next [*[1]]}
+ r([1,2]){next [*[1,2]]}
+ undef r
+
+ def r(val); *a = *yield(); assert_equal(val, a); end
+ r([[]]){next *[[]]}
+ r([1,2]){next *[1,2]}
+ r([1,2]){next *[*[1,2]]}
+ undef r
+
+ def r(val); a,b,*c = yield(); assert_equal(val, [a,b,c]); end
+ r([nil,nil,[]]){next}
+ r([nil,nil,[]]){next nil}
+ r([1,nil,[]]){next 1}
+ r([nil,nil,[]]){next []}
+ r([1,nil,[]]){next [1]}
+ r([nil,nil,[]]){next [nil]}
+ r([[],nil,[]]){next [[]]}
+ r([1,2,[]]){next [1,2]}
+ r([nil,nil,[]]){next [*[]]}
+ r([1,nil,[]]){next [*[1]]}
+ r([1,2,[]]){next [*[1,2]]}
+ undef r
+
+ def r(val); a,b,*c = *yield(); assert_equal(val, [a,b,c]); end
+ r([[],nil,[]]){next *[[]]}
+ r([1,2,[]]){next *[1,2]}
+ r([1,2,[]]){next *[*[1,2]]}
+ undef r
+ end
+
+ def test_massign
+ a = nil
+ assert(defined?(a))
+ assert_nil(a)
+
+ # multiple asignment
+ a, b = 1, 2
+ assert_equal 1, a
+ assert_equal 2, b
+
+ a, b, c = 1, 2, 3
+ assert_equal 1, a
+ assert_equal 2, b
+ assert_equal 3, c
+
+ a = 1
+ b = 2
+ a, b = b, a
+ assert_equal 2, a
+ assert_equal 1, b
+
+ a, = 1, 2
+ assert_equal 1, a
+
+ a, = 1, 2, 3
+ assert_equal 1, a
+
+ a, * = 1, 2, 3
+ assert_equal 1, a
+
+ a, *b = 1, 2, 3
+ assert_equal 1, a
+ assert_equal [2, 3], b
+
+ # not supported yet
+ #a, *b, c = 1, 2, 3, 4
+ #assert_equal 1, a
+ #assert_equal [2,3], b
+ #assert_equal 4, c
+
+ a = 1, 2
+ assert_equal [1, 2], a
+
+ a = [1, 2], [3, 4]
+ assert_equal [[1,2], [3,4]], a
+
+ a, (b, c), d = 1, [2, 3], 4
+ assert_equal 1, a
+ assert_equal 2, b
+ assert_equal 3, c
+ assert_equal 4, d
+
+ *a = 1, 2, 3
+ assert_equal([1, 2, 3], a)
+
+ *a = 4
+ assert_equal([4], a)
+
+ *a = nil
+ assert_equal([nil], a)
+
+ a, b = 1
+ assert_equal 1, a
+ assert_nil b
+
+ a, b = [1, 2]
+ assert_equal 1, a
+ assert_equal 2, b
+ end
+
+ def test_nested_massign
+ (a, b), c = [[1, 2], 3]; assert_equal [1,2,3], [a,b,c]
+ a, (b, c) = [[1, 2], 3]; assert_equal [[1,2], 3, nil], [a,b,c]
+ a, (b, c) = [1, [2, 3]]; assert_equal [1,2,3], [a,b,c]
+ (a, b), *c = [[1, 2], 3]; assert_equal [1,2,[3]], [a,b,c]
+ (a,b),c,(d,e) = [[1,2],3,[4,5]]; assert_equal [1,2,3,4,5],[a,b,c,d,e]
+ (a,*b),c,(d,e,*) = [[1,2],3,[4,5]]; assert_equal [1,[2],3,4,5],[a,b,c,d,e]
+ (a,b),c,(d,*e) = [[1,2,3],4,[5,6,7,8]]; assert_equal [1,2,4,5,[6,7,8]],[a,b,c,d,e]
+ (a,(b1,b2)),c,(d,e) = [[1,2],3,[4,5]]; assert_equal [1,2,nil,3,4,5],[a,b1,b2,c,d,e]
+ (a,(b1,b2)),c,(d,e) = [[1,[21,22]],3,[4,5]]; assert_equal [1,21,22,3,4,5],[a,b1,b2,c,d,e]
+ end
+
+ class MyObj
+ def to_ary
+ [[1,2],[3,4]]
+ end
+ end
+
+ def test_to_ary_splat
+ a, b = MyObj.new
+ assert_equal [[1,2],[3,4]], [a,b]
+ end
+
+ A = 1
+ B = 2
+ X, Y = A, B
+ class Base
+ A = 3
+ B = 4
+ end
+
+ def test_const_massign
+ assert_equal [1,2], [X,Y]
+ a, b = Base::A, Base::B
+ assert_equal [3,4], [a,b]
+ end
+end
+
+require_relative 'sentence'
+class TestAssignmentGen < Test::Unit::TestCase
+ Syntax = {
+ :exp => [["0"],
+ ["nil"],
+ ["false"],
+ ["[]"],
+ ["[",:exps,"]"]],
+ :exps => [[:exp],
+ [:exp,",",:exps]],
+ :arg => [[:exp]],
+ :mrhs => [[:args,",",:arg],
+ [:args,",","*",:arg],
+ ["*",:arg]],
+ :args => [[:arg],
+ ["*",:arg],
+ [:args,",",:arg],
+ [:args,",","*",:arg]],
+ :mlhs => [[:mlhs_basic],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_inner => [[:mlhs_basic],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_basic => [[:mlhs_head],
+ [:mlhs_head,:mlhs_item],
+ [:mlhs_head,"*",:mlhs_node],
+ [:mlhs_head,"*",:mlhs_node,",",:mlhs_post],
+ [:mlhs_head,"*"],
+ [:mlhs_head,"*",",", :mlhs_post],
+ [ "*",:mlhs_node],
+ [ "*",:mlhs_node,",",:mlhs_post],
+ [ "*"],
+ [ "*",",", :mlhs_post]],
+ :mlhs_head => [[:mlhs_item,","],
+ [:mlhs_head,:mlhs_item,","]],
+ :mlhs_post => [[:mlhs_item],
+ [:mlhs_post,",",:mlhs_item]],
+ :mlhs_item => [[:mlhs_node],
+ ["(",:mlhs_inner,")"]],
+ :mlhs_node => [["var"]],
+ :xassign => [["var"," = ",:exp],
+ ["var"," = ",:mrhs],
+ [:mlhs," = ",:exp],
+ [:mlhs," = ",:mrhs]],
+ }
+
+ def rename_var(obj)
+ vars = []
+ r = obj.subst('var') {
+ var = "v#{vars.length}"
+ vars << var
+ var
+ }
+ return r, vars
+ end
+
+ def expand_except_paren(obj)
+ return obj if obj.respond_to? :to_str
+ obj.expand {|s|
+ !(s[0] == '(' && s[-1] == ')') &&
+ !(s[0] == '[' && s[-1] == ']')
+ }
+ end
+
+ def extract_single_element(ary)
+ raise "not a single element array: #{ary.inspect}" if ary.length != 1
+ ary[0]
+ end
+
+ def emu_assign_ary(lhs, rv, h)
+ rv = rv.respond_to?(:to_ary) ? rv : [rv]
+ rv = rv.dup
+ a = [[]]
+ lhs.each {|e|
+ if e == ','
+ a << []
+ else
+ a.last << e
+ end
+ }
+ a.pop if a.last == []
+ pre = []
+ star = post = nil
+ a.each {|e|
+ if post
+ post << e
+ elsif e[0] == '*'
+ star = e
+ post = []
+ else
+ pre << e
+ end
+ }
+ pre.map! {|e| extract_single_element(e) }
+ if star
+ if star == ['*']
+ star = nil
+ else
+ star = extract_single_element(star[1..-1])
+ end
+ end
+ post.map! {|e| extract_single_element(e) } if post
+
+ until pre.empty?
+ emu_assign_single(pre.shift, rv.shift, h)
+ end
+
+ if post
+ if rv.length < post.length
+ until post.empty?
+ emu_assign_single(post.shift, rv.shift, h)
+ end
+ else
+ until post.empty?
+ emu_assign_single(post.pop, rv.pop, h)
+ end
+ end
+ end
+
+ if star
+ emu_assign_single(star, rv, h)
+ end
+ end
+
+ def emu_assign_single(lhs, rv, h={})
+ if lhs.respond_to? :to_str
+ if /\A[a-z0-9]+\z/ =~ lhs
+ h[lhs] = rv
+ else
+ raise "unexpected lhs string: #{lhs.inspect}"
+ end
+ elsif Sentence === lhs
+ if lhs[0] == '(' && lhs[-1] == ')'
+ emu_assign_ary(lhs[1...-1], rv, h)
+ elsif lhs.length == 1 && String === lhs[0] && /\A[a-z0-9]+\z/ =~ lhs[0]
+ h[lhs[0]] = rv
+ else
+ raise "unexpected lhs sentence: #{lhs.inspect}"
+ end
+ else
+ raise "unexpected lhs: #{lhs.inspect}"
+ end
+ h
+ end
+
+ def emu_assign(assign)
+ lhs = expand_except_paren(assign[0])
+ rhs = expand_except_paren(assign[2])
+ lopen = Sentence === lhs && lhs[-1] != ')' && lhs.any? {|e| e == '*' || e == ',' }
+ ropen = Sentence === rhs && rhs[-1] != ']' && rhs.any? {|e| e == '*' || e == ',' }
+ lhs = Sentence.new(['(']+lhs.to_a+[')']) if lopen
+ begin
+ rv = eval((ropen ? ["[",assign[2],"]"] : assign[2]).join(''))
+ rescue Exception
+ rv = $!.message
+ end
+ emu_assign_single(lhs, rv)
+ end
+
+ def do_assign(assign, vars)
+ assign = assign.to_s
+ code1 = "#{assign}; [#{vars.join(",")}]"
+ assign.gsub!(/\bv\d+\b/, "o.a")
+ code2 = "o=[];class << o; self end.send(:define_method,:a=){|v|self << v};#{assign};o"
+ begin
+ vals1 = eval(code1)
+ rescue Exception
+ return {:ex=>$!.message}
+ end
+ begin
+ vals2 = eval(code2)
+ rescue Exception
+ return {:ex=>$!.message}
+ end
+ assert_equal(vals1, vals2, code1)
+ vals = vals1
+ h = {}
+ [vars, vals].transpose.each {|k,v| h[k] = v }
+ h
+ end
+
+ def check(assign)
+ assign, vars = rename_var(assign)
+ sent = assign.to_s
+ bruby = do_assign(assign, vars).to_a.sort
+ bemu = emu_assign(assign).to_a.sort
+ assert_equal(bemu, bruby, sent)
+ end
+
+ def test_assignment
+ syntax = Sentence.expand_syntax(Syntax)
+ Sentence.each(syntax, :xassign, 4) {|assign|
+ check(assign)
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_basicinstructions.rb b/trunk/test/ruby/test_basicinstructions.rb
new file mode 100644
index 0000000000..6ac93e037a
--- /dev/null
+++ b/trunk/test/ruby/test_basicinstructions.rb
@@ -0,0 +1,628 @@
+require 'test/unit'
+
+ConstTest = 3
+class Class
+ alias _remove_const remove_const
+ public :_remove_const
+end
+
+class TestBasicInstructions < Test::Unit::TestCase
+
+ def test_immediates
+ assert_equal((1==1), true)
+ assert_equal((1==2), false)
+ assert_equal [][0], nil
+ assert_equal "sym".intern, :sym
+ assert_equal "sym".intern, :"sym"
+ assert_equal 1234 + 0, 1234
+ assert_equal 1234, 1_2_3_4
+ assert_equal 41, 0b0101001
+ assert_equal 420, 0644
+ assert_equal 18, 0x12
+ assert_equal 123456789012345678901234567890 + 0,
+ 123456789012345678901234567890
+ assert_equal 1.234 + 0.0, 1.234
+ end
+
+ def test_self
+ assert_equal self, self
+ assert_equal false, (self == false) # Qfalse==0 in C
+ assert_equal false, (self == nil)
+ assert_equal false, (self == 0)
+ end
+
+ def test_string
+ expected = "str" + "ing"
+ assert_equal expected, 'string'
+ assert_equal expected, "string"
+ assert_equal expected, %q(string)
+ assert_equal expected, %Q(string)
+ assert_equal expected, %(string)
+ end
+
+ def test_dstring
+ assert_equal "2", "#{1+1}"
+ s = "OK"
+ assert_equal "OK", "#{s}"
+ assert_equal "OKx", "#{s}x"
+ assert_equal "xOK", "x#{s}"
+ assert_equal "xOKx", "x#{s}x"
+ end
+
+ def test_dsym
+ assert_equal :a3c, :"a#{1+2}c"
+ s = "sym"
+ assert_equal :sym, :"#{s}"
+ assert_equal :sym, :"#{"#{"#{s}"}"}"
+ end
+
+ def test_xstr
+ assert_equal 'hoge', `echo hoge`.chomp
+ assert_equal '3', `echo #{1 + 2}`.chomp
+ hoge = 'huga'
+ assert_equal 'huga', `echo #{hoge}`.chomp
+ end
+
+ def test_regexp
+ assert_equal /test/, /test/
+ assert_equal 'test', /test/.source
+ assert_equal 'TEST', /TEST/.source
+ assert_equal true, !!(/test/ =~ 'test')
+ assert_equal false, !!(/test/ =~ 'does not match')
+
+ re = /test/
+ assert_equal re, re
+ assert_equal 'test', re.source
+ assert_equal true, !!(re =~ 'test')
+ assert_equal false, !!(re =~ 'does not match')
+
+ assert_equal /x#{1+1}x/, /x#{1+1}x/
+ s = "OK"
+ assert_equal /x#{s}x/, /x#{s}x/
+ assert_equal true, !!(/x#{s}x/ =~ "xOKx")
+ assert_equal false, !!(/x#{s}x/ =~ "does not match")
+
+ s = "OK"
+ prev = nil
+ 3.times do
+ assert_equal prev.object_id, (prev ||= /#{s}/o).object_id if prev
+ end
+ end
+
+ def test_array
+ assert_equal [], []
+ assert_equal 0, [].size
+ assert_equal [1, 2, 3], [1, 2, 3]
+ assert_equal [3, 7, 11], [1+2, 3+4, 5+6]
+ assert_equal [[1], [2], [3]], [[1], [2], [3]]
+
+ a = [1, 2, 3]
+ assert_equal 1, a[0]
+ assert_equal 2, a[1]
+ assert_equal 3, a[2]
+ assert_nil a[3]
+
+ a = %w( a b c )
+ assert_equal 'a', a[0]
+ assert_equal 'b', a[1]
+ assert_equal 'c', a[2]
+ assert_nil a[3]
+ end
+
+ def test_hash
+ assert_equal({}, {})
+ assert_equal({1=>2}, {1=>2})
+ assert_equal({1=>2, 3=>4}, {1=>2, 3=>4})
+ assert_equal({1=>2, 3=>4}, {3=>4, 1=>2})
+ # assert_equal({1=>2, 3=>4}, {1,2, 3,4}) # 1.9 doesn't support
+ assert_equal({"key"=>"val"}, {"key"=>"val"})
+ end
+
+ def test_range
+ assert_equal((1..3), (1..3))
+ assert_equal((1...3), (1...3))
+ assert_not_equal((1...3), (1..3))
+ assert_not_equal((1..3), (1...3))
+ assert_equal((1..3), (1..2+1))
+ assert_equal((1...3), (1...2+1))
+ assert_equal(('a'..'z'), ('a'..'z'))
+ end
+
+ def test_not
+ assert_equal true, !nil
+ assert_equal true, !false
+ assert_equal false, !true
+ assert_equal false, !3
+ assert_equal false, !(1+1)
+
+ assert_equal false, !!nil
+ assert_equal false, !!false
+ assert_equal true, !!true
+ assert_equal true, !!3
+ assert_equal true, !!(1+1)
+
+ assert_equal true, (not nil)
+ assert_equal true, (not false)
+ assert_equal false, (not true)
+ assert_equal false, (not 3)
+ assert_equal false, (not (1 + 1))
+
+ assert_equal false, (not not nil)
+ assert_equal false, (not not false)
+ assert_equal true, (not not true)
+ assert_equal true, (not not 3)
+ assert_equal true, (not not (1+1))
+ end
+
+ def test_local_variable
+ a = 7
+ assert_equal 7, a
+ assert_equal a, a
+ b = 17
+ assert_equal 7, a
+ assert_equal 17, b
+ assert_equal a, a
+ assert_equal b, b
+ assert_not_equal a, b
+ assert_not_equal b, a
+ a = b
+ assert_equal 17, a
+ assert_equal 17, b
+ assert_equal a, a
+ assert_equal b, b
+ assert_equal a, b
+ assert_equal b, a
+ c = 28
+ assert_equal 17, a
+ assert_equal 17, b
+ assert_equal 28, c
+ assert_equal a, a
+ assert_equal b, b
+ assert_equal a, b
+ assert_equal c, c
+ assert_not_equal a, c
+ assert_not_equal b, c
+ a = b = c
+ assert_equal 28, a
+ assert_equal 28, b
+ assert_equal 28, c
+ assert_equal a, a
+ assert_equal b, b
+ assert_equal a, b
+ assert_equal b, a
+ assert_equal a, c
+ assert_equal c, a
+ assert_equal b, c
+ assert_equal c, b
+
+ a = 1
+ b = 2
+ c = 3
+ set_lvar_in_another_method
+ assert_equal 1, a
+ assert_equal 2, b
+ assert_equal 3, c
+ end
+
+ def set_lvar_in_another_method
+ assert_raise(NameError) { a }
+ assert_raise(NameError) { b }
+ assert_raise(NameError) { c }
+ a = "NOT OK"
+ b = "NOT OK"
+ c = "NOT OK"
+ end
+
+ class Const
+ $Const = self
+ C = 'Const::C'
+ def self.c() C end
+ def c() C end
+
+ class A
+ C = 'Const::A::C'
+ def self.c() C end
+ def c() C end
+ CC = 'Const::A::CC'
+ def self.cc() CC end
+ def cc() CC end
+
+ class B
+ C = 'Const::A::B::C'
+ def self.c() C end
+ def c() C end
+ def self.cc() CC end
+ def cc() CC end
+ end
+ end
+
+ class AA < A
+ def self.cc() CC end
+ def cc() CC end
+ end
+
+ class AAA < AA
+ def self.cc() CC end
+ def cc() CC end
+ end
+ end
+ C = 0
+
+ def test_const_path
+ do_test_const_path
+ do_test_const_path
+ do_test_const_path
+ end
+
+ def do_test_const_path
+ assert_equal 0, C
+ assert_equal 0, C
+ assert_equal 3, ::ConstTest
+ assert_equal 3, ::ConstTest
+ assert_equal $Const, Const
+
+ assert_equal 'Const::C', Const::C
+ assert_equal 'Const::C', Const::C
+ assert_equal 'Const::A::C', Const::A::C
+ assert_equal 'Const::A::C', Const::A::C
+ assert_equal 'Const::A::B::C', Const::A::B::C
+ assert_equal 'Const::A::B::C', Const::A::B::C
+
+ Const::A::B._remove_const :C
+ assert_equal 'Const::C', Const::C
+ assert_equal 'Const::A::C', Const::A::C
+ assert_raise(NameError) { Const::A::B::C }
+
+ Const::A._remove_const :C
+ assert_equal 'Const::C', Const::C
+ assert_raise(NameError) { Const::A::C }
+ assert_raise(NameError) { Const::A::B::C }
+
+ Const._remove_const :C
+ assert_raise(NameError) { Const::C }
+ assert_raise(NameError) { Const::A::C }
+ assert_raise(NameError) { Const::A::B::C }
+
+ Const::A.const_set :C, 'Const::A::C'
+ assert_raise(NameError) { Const::C }
+ assert_equal 'Const::A::C', Const::A::C
+ assert_raise(NameError) { Const::A::B::C }
+
+ Const::A::B.const_set :C, 'Const::A::B::C'
+ assert_raise(NameError) { Const::C }
+ assert_equal 'Const::A::C', Const::A::C
+ assert_equal 'Const::A::B::C', Const::A::B::C
+
+ Const.const_set :C, 'Const::C'
+ assert_equal 'Const::C', Const::C
+ assert_equal 'Const::A::C', Const::A::C
+ assert_equal 'Const::A::B::C', Const::A::B::C
+ end
+
+ def test_const_cref
+ do_test_const_cref
+ do_test_const_cref
+ do_test_const_cref
+ end
+
+ def do_test_const_cref
+ assert_equal 'Const::C', Const.new.c
+ assert_equal 'Const::A::C', Const::A.new.c
+ assert_equal 'Const::A::B::C', Const::A::B.new.c
+
+ assert_equal 'Const::C', Const.c
+ assert_equal 'Const::A::C', Const::A.c
+ assert_equal 'Const::A::B::C', Const::A::B.c
+
+ Const::A::B._remove_const :C
+ assert_equal 'Const::C', Const.c
+ assert_equal 'Const::A::C', Const::A.c
+ assert_equal 'Const::A::C', Const::A::B.c
+ assert_equal 'Const::C', Const.new.c
+ assert_equal 'Const::A::C', Const::A.new.c
+ assert_equal 'Const::A::C', Const::A::B.new.c
+
+ Const::A._remove_const :C
+ assert_equal 'Const::C', Const.c
+ assert_equal 'Const::C', Const::A.c
+ assert_equal 'Const::C', Const::A::B.c
+ assert_equal 'Const::C', Const.new.c
+ assert_equal 'Const::C', Const::A.new.c
+ assert_equal 'Const::C', Const::A::B.new.c
+
+ Const::A::B.const_set :C, 'Const::A::B::C'
+ assert_equal 'Const::C', Const.c
+ assert_equal 'Const::C', Const::A.c
+ assert_equal 'Const::A::B::C', Const::A::B.c
+ assert_equal 'Const::C', Const.new.c
+ assert_equal 'Const::C', Const::A.new.c
+ assert_equal 'Const::A::B::C', Const::A::B.new.c
+
+ Const::A.const_set :C, 'Const::A::C'
+ assert_equal 'Const::C', Const.c
+ assert_equal 'Const::A::C', Const::A.c
+ assert_equal 'Const::A::B::C', Const::A::B.c
+ assert_equal 'Const::C', Const.new.c
+ assert_equal 'Const::A::C', Const::A.new.c
+ assert_equal 'Const::A::B::C', Const::A::B.new.c
+ ensure
+ # reset
+ Const.const_set :C, 'Const::C' unless Const.const_defined?(:C)
+ Const::A.const_set :C, 'Const::A::C' unless Const::A.const_defined?(:C)
+ Const::A::B.const_set :C, 'Const::A::B::C' unless Const::A::B.const_defined?(:C)
+ end
+
+ def test_const_inherit
+ do_test_const_inherit
+ do_test_const_inherit
+ do_test_const_inherit
+ end
+
+ def do_test_const_inherit
+ assert_equal 'Const::A::CC', Const::A.cc
+ assert_equal 'Const::A::CC', Const::AA.cc
+ assert_equal 'Const::A::CC', Const::AAA.cc
+ assert_equal 'Const::A::CC', Const::A.new.cc
+ assert_equal 'Const::A::CC', Const::AA.new.cc
+ assert_equal 'Const::A::CC', Const::AAA.new.cc
+
+ Const::AA.const_set :CC, 'Const::AA::CC'
+ assert_equal 'Const::A::CC', Const::A.cc
+ assert_equal 'Const::AA::CC', Const::AA.cc
+ assert_equal 'Const::AA::CC', Const::AAA.cc
+ assert_equal 'Const::A::CC', Const::A.new.cc
+ assert_equal 'Const::AA::CC', Const::AA.new.cc
+ assert_equal 'Const::AA::CC', Const::AAA.new.cc
+
+ Const::AAA.const_set :CC, 'Const::AAA::CC'
+ assert_equal 'Const::A::CC', Const::A.cc
+ assert_equal 'Const::AA::CC', Const::AA.cc
+ assert_equal 'Const::AAA::CC', Const::AAA.cc
+ assert_equal 'Const::A::CC', Const::A.new.cc
+ assert_equal 'Const::AA::CC', Const::AA.new.cc
+ assert_equal 'Const::AAA::CC', Const::AAA.new.cc
+
+ Const::AA._remove_const :CC
+ assert_equal 'Const::A::CC', Const::A.cc
+ assert_equal 'Const::A::CC', Const::AA.cc
+ assert_equal 'Const::AAA::CC', Const::AAA.cc
+ assert_equal 'Const::A::CC', Const::A.new.cc
+ assert_equal 'Const::A::CC', Const::AA.new.cc
+ assert_equal 'Const::AAA::CC', Const::AAA.new.cc
+
+ Const::AAA._remove_const :CC
+ assert_equal 'Const::A::CC', Const::A.cc
+ assert_equal 'Const::A::CC', Const::AA.cc
+ assert_equal 'Const::A::CC', Const::AAA.cc
+ assert_equal 'Const::A::CC', Const::A.new.cc
+ assert_equal 'Const::A::CC', Const::AA.new.cc
+ assert_equal 'Const::A::CC', Const::AAA.new.cc
+ end
+
+ def test_global_variable
+ $gvar1 = 1
+ assert_equal 1, $gvar1
+ $gvar1 = 2
+ assert_equal 2, $gvar1
+ $gvar2 = 77
+ assert_equal 2, $gvar1
+ assert_equal 77, $gvar2
+ $gvar2 = $gvar1
+ assert_equal 2, $gvar1
+ assert_equal 2, $gvar2
+ $gvar1 = 1
+ assert_equal 1, $gvar1
+ assert_equal 2, $gvar2
+ set_gvar_in_another_method
+ assert_equal "OK1", $gvar1
+ assert_equal "OK2", $gvar2
+ end
+
+ def set_gvar_in_another_method
+ assert_equal 1, $gvar1
+ assert_equal 2, $gvar2
+ $gvar1 = "OK1"
+ $gvar2 = "OK2"
+ end
+
+ class CVarA
+ @@cv = 'CVarA@@cv'
+ def self.cv() @@cv end
+ def self.cv=(v) @@cv = v end
+ class << self
+ def cv2() @@cv end
+ end
+ def cv() @@cv end
+ def cv=(v) @@cv = v end
+ end
+
+ class CVarB < CVarA
+ def self.cvB() @@cv end
+ def self.cvB=(v) @@cv = v end
+ class << self
+ def cvB2() @@cv end
+ end
+ def cvB() @@cv end
+ def cvB=(v) @@cv = v end
+ end
+
+ def test_class_variable
+ assert_equal 'CVarA@@cv', CVarA.cv
+ assert_equal 'CVarA@@cv', CVarA.cv2
+ assert_equal 'CVarA@@cv', CVarA.new.cv
+ CVarA.cv = 'singleton'
+ assert_equal 'singleton', CVarA.cv
+ assert_equal 'singleton', CVarA.cv2
+ assert_equal 'singleton', CVarA.new.cv
+ CVarA.new.cv = 'instance'
+ assert_equal 'instance', CVarA.cv
+ assert_equal 'instance', CVarA.cv2
+ assert_equal 'instance', CVarA.new.cv
+
+ CVarA.cv = 'CVarA@@cv'
+ CVarB.cv = 'B/singleton'
+ assert_equal 'B/singleton', CVarB.cv
+ assert_equal 'B/singleton', CVarB.cv2
+ assert_equal 'B/singleton', CVarB.new.cv
+ assert_equal 'B/singleton', CVarA.cv
+ assert_equal 'B/singleton', CVarA.cv2
+ assert_equal 'B/singleton', CVarA.new.cv
+ CVarB.new.cv = 'B/instance'
+ assert_equal 'B/instance', CVarB.cv
+ assert_equal 'B/instance', CVarB.cv2
+ assert_equal 'B/instance', CVarB.new.cv
+ assert_equal 'B/instance', CVarA.cv
+ assert_equal 'B/instance', CVarA.cv2
+ assert_equal 'B/instance', CVarA.new.cv
+
+ CVarA.cv = 'CVarA@@cv'
+ assert_equal('CVarA@@cv', CVarB.cvB)
+ assert_equal('CVarA@@cv', CVarB.cvB2)
+ assert_equal('CVarA@@cv', CVarB.new.cvB)
+ CVarB.cvB = 'B/singleton'
+ assert_equal 'B/singleton', CVarB.cvB
+ assert_equal 'B/singleton', CVarB.cvB2
+ assert_equal 'B/singleton', CVarB.new.cvB
+ assert_equal 'B/singleton', CVarA.cv
+ assert_equal 'B/singleton', CVarA.cv2
+ assert_equal 'B/singleton', CVarA.new.cv
+ CVarB.new.cvB = 'B/instance'
+ assert_equal 'B/instance', CVarB.cvB
+ assert_equal 'B/instance', CVarB.cvB2
+ assert_equal 'B/instance', CVarB.new.cvB
+ assert_equal 'B/instance', CVarA.cv
+ assert_equal 'B/instance', CVarA.cv2
+ assert_equal 'B/instance', CVarA.new.cv
+
+ CVarA.cv = 'CVarA@@cv'
+ CVarB.cvB = 'CVarB@@cv'
+ end
+
+ class OP
+ attr_accessor :x
+ end
+
+ def test_opassign
+ x = nil
+ x ||= 1
+ assert_equal 1, x
+ x &&= 2
+ assert_equal 2, x
+ x ||= 3
+ assert_equal 2, x
+ x &&= 4
+ assert_equal 4, x
+
+ y = OP.new
+ y.x = nil
+ y.x ||= 1
+ assert_equal 1, y.x
+ y.x &&= 2
+ assert_equal 2, y.x
+ y.x ||= 3
+ assert_equal 2, y.x
+ y.x &&= 4
+ assert_equal 4, y.x
+
+ z = OP.new
+ z.x = y
+ z.x.x = nil
+ z.x.x ||= 1
+ assert_equal 1, z.x.x
+ z.x.x &&= 2
+ assert_equal 2, z.x.x
+ z.x.x ||= 3
+ assert_equal 2, z.x.x
+ z.x.x &&= 4
+ assert_equal 4, z.x.x
+
+ a = []
+ a[0] = nil
+ a[0] ||= 1
+ assert_equal 1, a[0]
+ a[0] &&= 2
+ assert_equal 2, a[0]
+ a[0] ||= 3
+ assert_equal 2, a[0]
+ a[0] &&= 4
+ assert_equal 4, a[0]
+ end
+
+ def test_backref
+ /re/ =~ 'not match'
+ assert_nil $~
+ assert_nil $`
+ assert_nil $&
+ assert_nil $'
+ assert_nil $+
+ assert_nil $1
+ assert_nil $2
+ assert_nil $3
+ assert_nil $4
+ assert_nil $5
+ assert_nil $6
+ assert_nil $7
+ assert_nil $8
+ assert_nil $9
+
+ /(a)(b)(c)(d)(e)(f)(g)(h)(i)/ =~ 'xabcdefghiy'
+ assert_not_nil $~
+ assert_instance_of MatchData, $~
+ assert_equal 'abcdefghi', $~[0]
+ assert_equal 'a', $~[1]
+ assert_equal 'b', $~[2]
+ assert_equal 'c', $~[3]
+ assert_equal 'd', $~[4]
+ assert_equal 'e', $~[5]
+ assert_equal 'f', $~[6]
+ assert_equal 'g', $~[7]
+ assert_equal 'h', $~[8]
+ assert_equal 'i', $~[9]
+ assert_equal 'x', $`
+ assert_equal 'abcdefghi', $&
+ assert_equal 'y', $'
+ assert_equal 'i', $+
+ assert_equal 'a', $1
+ assert_equal 'b', $2
+ assert_equal 'c', $3
+ assert_equal 'd', $4
+ assert_equal 'e', $5
+ assert_equal 'f', $6
+ assert_equal 'g', $7
+ assert_equal 'h', $8
+ assert_equal 'i', $9
+
+ /re/ =~ 'not match'
+ assert_nil $~
+ assert_nil $`
+ assert_nil $&
+ assert_nil $'
+ assert_nil $+
+ assert_nil $1
+ assert_nil $2
+ assert_nil $3
+ assert_nil $4
+ assert_nil $5
+ assert_nil $6
+ assert_nil $7
+ assert_nil $8
+ assert_nil $9
+ end
+
+ def test_array_splat
+ a = []
+ assert_equal [], [*a]
+ assert_equal [1], [1, *a]
+ a = [2]
+ assert_equal [2], [*a]
+ assert_equal [1, 2], [1, *a]
+ a = [2, 3]
+ assert_equal [2, 3], [*a]
+ assert_equal [1, 2, 3], [1, *a]
+
+ a = nil
+ assert_equal [], [*a]
+ assert_equal [1], [1, *a]
+ end
+
+end
diff --git a/trunk/test/ruby/test_beginendblock.rb b/trunk/test/ruby/test_beginendblock.rb
new file mode 100644
index 0000000000..594596698b
--- /dev/null
+++ b/trunk/test/ruby/test_beginendblock.rb
@@ -0,0 +1,101 @@
+require 'test/unit'
+require 'tempfile'
+require_relative 'envutil'
+
+class TestBeginEndBlock < Test::Unit::TestCase
+ DIR = File.dirname(File.expand_path(__FILE__))
+
+ def q(content)
+ "\"#{content}\""
+ end
+
+ def test_beginendblock
+ ruby = EnvUtil.rubybin
+ target = File.join(DIR, 'beginmainend.rb')
+ result = IO.popen([ruby, target]){|io|io.read}
+ assert_equal(%w(b1 b2-1 b2 main b3-1 b3 b4 e1 e4 e3 e2 e4-2 e4-1 e1-1 e4-1-1), result.split)
+
+ input = Tempfile.new(self.class.name)
+ inputpath = input.path
+ input.close
+ result = IO.popen([ruby, "-n", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read}
+ assert_equal(%w(:begin), result.split)
+ result = IO.popen([ruby, "-p", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read}
+ assert_equal(%w(:begin), result.split)
+ input.open
+ input.puts "foo\nbar"
+ input.close
+ result = IO.popen([ruby, "-n", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read}
+ assert_equal(%w(:begin :end), result.split)
+ result = IO.popen([ruby, "-p", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read}
+ assert_equal(%w(:begin foo bar :end), result.split)
+ end
+
+ def test_begininmethod
+ assert_raises(SyntaxError) do
+ eval("def foo; BEGIN {}; end")
+ end
+
+ assert_raises(SyntaxError) do
+ eval('eval("def foo; BEGIN {}; end")')
+ end
+ end
+
+ def test_endblockwarn
+ ruby = EnvUtil.rubybin
+ # Use Tempfile to create temporary file path.
+ launcher = Tempfile.new(self.class.name)
+ errout = Tempfile.new(self.class.name)
+
+ launcher << <<EOF
+errout = ARGV.shift
+STDERR.reopen(File.open(errout, "w"))
+STDERR.sync = true
+Dir.chdir(#{q(DIR)})
+system("#{ruby}", "endblockwarn_rb")
+EOF
+ launcher.close
+ launcherpath = launcher.path
+ errout.close
+ erroutpath = errout.path
+ system(ruby, launcherpath, erroutpath)
+ expected = <<EOW
+endblockwarn_rb:2: warning: END in method; use at_exit
+(eval):2: warning: END in method; use at_exit
+EOW
+ assert_equal(expected, File.read(erroutpath))
+ # expecting Tempfile to unlink launcher and errout file.
+ end
+
+ def test_raise_in_at_exit
+ ruby = EnvUtil.rubybin
+ out = IO.popen([ruby, '-e', 'STDERR.reopen(STDOUT)',
+ '-e', 'at_exit{raise %[SomethingBad]}',
+ '-e', 'raise %[SomethingElse]']) {|f|
+ f.read
+ }
+ assert_match /SomethingBad/, out, "[ruby-core:9675]"
+ assert_match /SomethingElse/, out, "[ruby-core:9675]"
+ end
+
+ def test_should_propagate_exit_code
+ ruby = EnvUtil.rubybin
+ assert_equal false, system(ruby, '-e', 'at_exit{exit 2}')
+ assert_equal 2, $?.exitstatus
+ assert_nil $?.termsig
+ end
+
+ def test_should_propagate_signaled
+ ruby = EnvUtil.rubybin
+ out = IO.popen(
+ [ruby,
+ '-e', 'STDERR.reopen(STDOUT)',
+ '-e', 'at_exit{Process.kill(:INT, $$); loop{}}']) {|f|
+ f.read
+ }
+ assert_match /Interrupt$/, out
+ Process.kill(0, 0) rescue return # check if signal works
+ assert_nil $?.exitstatus
+ assert_equal Signal.list["INT"], $?.termsig
+ end
+end
diff --git a/trunk/test/ruby/test_bignum.rb b/trunk/test/ruby/test_bignum.rb
new file mode 100644
index 0000000000..f6e9e65544
--- /dev/null
+++ b/trunk/test/ruby/test_bignum.rb
@@ -0,0 +1,390 @@
+require 'test/unit'
+
+class TestBignum < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def fact(n)
+ return 1 if n == 0
+ f = 1
+ while n>0
+ f *= n
+ n -= 1
+ end
+ return f
+ end
+
+ def test_bignum
+ $x = fact(40)
+ assert_equal($x, $x)
+ assert_equal($x, fact(40))
+ assert($x < $x+2)
+ assert($x > $x-2)
+ assert_equal(815915283247897734345611269596115894272000000000, $x)
+ assert_not_equal(815915283247897734345611269596115894272000000001, $x)
+ assert_equal(815915283247897734345611269596115894272000000001, $x+1)
+ assert_equal(335367096786357081410764800000, $x/fact(20))
+ $x = -$x
+ assert_equal(-815915283247897734345611269596115894272000000000, $x)
+ assert_equal(2-(2**32), -(2**32-2))
+ assert_equal(2**32 - 5, (2**32-3)-2)
+
+ for i in 1000..1014
+ assert_equal(2 ** i, 1 << i)
+ end
+
+ n1 = 1 << 1000
+ for i in 1000..1014
+ assert_equal(n1, 1 << i)
+ n1 *= 2
+ end
+
+ n2=n1
+ for i in 1..10
+ n1 = n1 / 2
+ n2 = n2 >> 1
+ assert_equal(n1, n2)
+ end
+
+ for i in 4000..4096
+ n1 = 1 << i;
+ assert_equal(n1-1, (n1**2-1) / (n1+1))
+ end
+ end
+
+ def test_calc
+ b = 10**80
+ a = b * 9 + 7
+ assert_equal(7, a.modulo(b))
+ assert_equal(-b + 7, a.modulo(-b))
+ assert_equal(b + -7, (-a).modulo(b))
+ assert_equal(-7, (-a).modulo(-b))
+ assert_equal(7, a.remainder(b))
+ assert_equal(7, a.remainder(-b))
+ assert_equal(-7, (-a).remainder(b))
+ assert_equal(-7, (-a).remainder(-b))
+
+ assert_equal(10000000000000000000100000000000000000000, 10**40+10**20)
+ assert_equal(100000000000000000000, 10**40/10**20)
+
+ a = 677330545177305025495135714080
+ b = 14269972710765292560
+ assert_equal(0, a % b)
+ assert_equal(0, -a % b)
+ end
+
+ def shift_test(a)
+ b = a / (2 ** 32)
+ c = a >> 32
+ assert_equal(b, c)
+
+ b = a * (2 ** 32)
+ c = a << 32
+ assert_equal(b, c)
+ end
+
+ def test_shift
+ shift_test(-4518325415524767873)
+ shift_test(-0xfffffffffffffffff)
+ end
+
+ def test_to_s
+ assert_equal("fvvvvvvvvvvvv" ,18446744073709551615.to_s(32), "[ruby-core:10686]")
+ assert_equal("g000000000000" ,18446744073709551616.to_s(32), "[ruby-core:10686]")
+ assert_equal("3w5e11264sgsf" ,18446744073709551615.to_s(36), "[ruby-core:10686]")
+ assert_equal("3w5e11264sgsg" ,18446744073709551616.to_s(36), "[ruby-core:10686]")
+ assert_equal("nd075ib45k86f" ,18446744073709551615.to_s(31), "[ruby-core:10686]")
+ assert_equal("nd075ib45k86g" ,18446744073709551616.to_s(31), "[ruby-core:10686]")
+ assert_equal("1777777777777777777777" ,18446744073709551615.to_s(8))
+ assert_equal("-1777777777777777777777" ,-18446744073709551615.to_s(8))
+ end
+
+
+ T_ZERO = (2**32).coerce(0).first
+ T_ONE = (2**32).coerce(1).first
+ T_MONE = (2**32).coerce(-1).first
+ T31 = 2**31 # 2147483648
+ T31P = T31 - 1 # 2147483647
+ T32 = 2**32 # 4294967296
+ T32P = T32 - 1 # 4294967295
+ T64 = 2**64 # 18446744073709551616
+ T64P = T64 - 1 # 18446744073709551615
+
+ def test_big_2comp
+ assert_equal("-4294967296", (~T32P).to_s)
+ assert_equal("..f00000000", "%x" % -T32)
+ end
+
+ def test_int2inum
+ assert_equal([T31P], [T31P].pack("I").unpack("I"))
+ assert_equal([T31P], [T31P].pack("i").unpack("i"))
+ end
+
+ def test_quad_pack
+ assert_equal([ 1], [ 1].pack("q").unpack("q"))
+ assert_equal([- 1], [- 1].pack("q").unpack("q"))
+ assert_equal([ T31P], [ T31P].pack("q").unpack("q"))
+ assert_equal([-T31P], [-T31P].pack("q").unpack("q"))
+ assert_equal([ T64P], [ T64P].pack("Q").unpack("Q"))
+ assert_equal([ 0], [ T64 ].pack("Q").unpack("Q"))
+ end
+
+ def test_str_to_inum
+ assert_equal(1, " +1".to_i)
+ assert_equal(-1, " -1".to_i)
+ assert_equal(0, "++1".to_i)
+ assert_equal(73, "111".oct)
+ assert_equal(273, "0x111".oct)
+ assert_equal(7, "0b111".oct)
+ assert_equal(73, "0o111".oct)
+ assert_equal(111, "0d111".oct)
+ assert_equal(73, "0111".oct)
+ assert_equal(111, Integer("111"))
+ assert_equal(13, "111".to_i(3))
+ assert_raise(ArgumentError) { "111".to_i(37) }
+ assert_equal(1333, "111".to_i(36))
+ assert_equal(1057, "111".to_i(32))
+ assert_equal(0, "00a".to_i)
+ assert_equal(1, Integer("1 "))
+ assert_raise(ArgumentError) { Integer("1_") }
+ assert_raise(ArgumentError) { Integer("1__") }
+ assert_raise(ArgumentError) { Integer("1_0 x") }
+ assert_equal(T31P, "1111111111111111111111111111111".to_i(2))
+ assert_equal(0_2, '0_2'.to_i)
+ assert_equal(00_2, '00_2'.to_i)
+ assert_equal(00_02, '00_02'.to_i)
+ end
+
+ def test_to_s2
+ assert_raise(ArgumentError) { T31P.to_s(37) }
+ assert_equal("9" * 32768, (10**32768-1).to_s)
+ assert_raise(RangeError) { Process.wait(1, T64P) }
+ assert_equal("0", T_ZERO.to_s)
+ assert_equal("1", T_ONE.to_s)
+ end
+
+ def test_to_f
+ assert_nothing_raised { T31P.to_f.to_i }
+ assert_raise(FloatDomainError) { (1024**1024).to_f.to_i }
+ end
+
+ def test_cmp
+ assert(T31P > 1)
+ assert(T31P < 2147483648.0)
+ assert(T31P < T64P)
+ assert(T64P > T31P)
+ assert_raise(ArgumentError) { T31P < "foo" }
+ end
+
+ def test_eq
+ assert(T31P != 1)
+ assert(T31P == 2147483647.0)
+ assert(T31P != "foo")
+ end
+
+ def test_eql
+ assert(T31P.eql?(T31P))
+ end
+
+ def test_convert
+ assert_equal([255], [T_MONE].pack("C").unpack("C"))
+ assert_equal([0], [T32].pack("C").unpack("C"))
+ assert_raise(RangeError) { 0.to_s(T32) }
+ assert_raise(Errno::EINVAL) do
+ begin Process.wait(0, T32P); rescue Errno::ECHILD; end
+ begin Process.wait(0, T64P); rescue Errno::ECHILD; end
+ end
+ assert_raise(RangeError) do
+ begin Process.wait(0, T32); rescue Errno::ECHILD; end
+ begin Process.wait(0, T64); rescue Errno::ECHILD; end
+ end
+ assert_raise(RangeError) do
+ begin Process.wait(0, -T32P); rescue Errno::ECHILD; end
+ begin Process.wait(0, -T64P); rescue Errno::ECHILD; end
+ end
+ end
+
+ def test_sub
+ assert_equal(-T31, T32 - (T32 + T31))
+ end
+
+ def test_plus
+ assert_equal(T32.to_f, T32P + 1.0)
+ assert_raise(TypeError) { T32 + "foo" }
+ end
+
+ def test_minus
+ assert_equal(T32P.to_f, T32 - 1.0)
+ assert_raise(TypeError) { T32 - "foo" }
+ end
+
+ def test_mul
+ assert_equal(T32.to_f, T32 * 1.0)
+ assert_raise(TypeError) { T32 * "foo" }
+ end
+
+ def test_divrem
+ assert_equal(0, T32 / T64)
+ end
+
+ def test_div
+ assert_equal(T32.to_f, T32 / 1.0)
+ assert_raise(TypeError) { T32 / "foo" }
+ assert_equal(0x20000000, 0x40000001.div(2.0), "[ruby-dev:34553]")
+ end
+
+ def test_idiv
+ assert_equal(715827882, 1073741824.div(Rational(3,2)), ' [ruby-dev:34066]')
+ end
+
+ def test_modulo
+ assert_raise(TypeError) { T32 % "foo" }
+ end
+
+ def test_remainder
+ assert_equal(0, T32.remainder(1))
+ assert_raise(TypeError) { T32.remainder("foo") }
+ end
+
+ def test_divmod
+ assert_equal([T32, 0], T32.divmod(1))
+ assert_equal([2, 0], T32.divmod(T31))
+ assert_raise(TypeError) { T32.divmod("foo") }
+ end
+
+ def test_quo
+ assert_equal(T32.to_f, T32.quo(1))
+ assert_equal(T32.to_f, T32.quo(1.0))
+ assert_equal(T32.to_f, T32.quo(T_ONE))
+
+ assert_raise(TypeError) { T32.quo("foo") }
+
+ assert_equal(1024**1024, (1024**1024).quo(1))
+ assert_equal(1024**1024, (1024**1024).quo(1.0))
+ assert_equal(1024**1024*2, (1024**1024*2).quo(1))
+ inf = 1 / 0.0; nan = inf / inf
+
+ assert((1024**1024*2).quo(nan).nan?)
+ end
+
+ def test_pow
+ assert_equal(1.0, T32 ** 0.0)
+ assert_equal(1.0 / T32, T32 ** -1)
+ assert((T32 ** T32).infinite?)
+ assert((T32 ** (2**30-1)).infinite?)
+
+ ### rational changes the behavior of Bignum#**
+ #assert_raise(TypeError) { T32**"foo" }
+ assert_raise(TypeError, ArgumentError) { T32**"foo" }
+ end
+
+ def test_and
+ assert_equal(0, T32 & 1)
+ assert_equal(-T32, (-T32) & (-T31))
+ assert_equal(0, T32 & T64)
+ end
+
+ def test_or
+ assert_equal(T32 + 1, T32 | 1)
+ assert_equal(T32 + T31, T32 | T31)
+ assert_equal(-T31, (-T32) | (-T31))
+ assert_equal(T64 + T32, T32 | T64)
+ end
+
+ def test_xor
+ assert_equal(T32 + 1, T32 ^ 1)
+ assert_equal(T32 + T31, T32 ^ T31)
+ assert_equal(T31, (-T32) ^ (-T31))
+ assert_equal(T64 + T32, T32 ^ T64)
+ end
+
+ def test_shift2
+ assert_equal(2**33, (2**32) << 1)
+ assert_equal(2**31, (2**32) << -1)
+ assert_equal(2**33, (2**32) << 1.0)
+ assert_equal(2**31, (2**32) << -1.0)
+ assert_equal(2**33, (2**32) << T_ONE)
+ assert_equal(2**31, (2**32) << T_MONE)
+ assert_equal(2**31, (2**32) >> 1)
+ assert_equal(2**33, (2**32) >> -1)
+ assert_equal(2**31, (2**32) >> 1.0)
+ assert_equal(2**33, (2**32) >> -1.0)
+ assert_equal(2**31, (2**32) >> T_ONE)
+ assert_equal(2**33, (2**32) >> T_MONE)
+ assert_equal( 0, (2**32) >> (2**32))
+ assert_equal(-1, -(2**32) >> (2**32))
+ assert_equal( 0, (2**32) >> 128)
+ assert_equal(-1, -(2**32) >> 128)
+ assert_equal( 0, (2**31) >> 32)
+ assert_equal(-1, -(2**31) >> 32)
+ end
+
+ def test_aref
+ assert_equal(0, (2**32)[0])
+ assert_equal(0, (2**32)[2**32])
+ assert_equal(0, (2**32)[-(2**32)])
+ assert_equal(0, (2**32)[T_ZERO])
+ assert_equal(0, (-(2**64))[0])
+ assert_equal(1, (-2**256)[256])
+ end
+
+ def test_hash
+ assert_nothing_raised { T31P.hash }
+ end
+
+ def test_coerce
+ assert_equal([T64P, T31P], T31P.coerce(T64P))
+ assert_raise(TypeError) { T31P.coerce(nil) }
+ end
+
+ def test_abs
+ assert_equal(T31P, (-T31P).abs)
+ end
+
+ def test_size
+ assert(T31P.size.is_a?(Integer))
+ end
+
+ def test_odd
+ assert_equal(true, (2**32+1).odd?)
+ assert_equal(false, (2**32).odd?)
+ end
+
+ def test_even
+ assert_equal(false, (2**32+1).even?)
+ assert_equal(true, (2**32).even?)
+ end
+
+ def interrupt
+ time = Time.now
+ start_flag = false
+ end_flag = false
+ thread = Thread.new do
+ start_flag = true
+ yield
+ end_flag = true
+ end
+ sleep 1
+ thread.raise
+ thread.join rescue nil
+ start_flag && !end_flag && Time.now - time < 10
+ end
+
+ def test_interrupt
+ assert(interrupt { (65536 ** 65536).to_s })
+ end
+
+ def test_too_big_to_s
+ if (big = 2**31-1).is_a?(Fixnum)
+ return
+ end
+ e = assert_raise(RangeError) {(1 << big).to_s}
+ assert_match(/too big to convert/, e.message)
+ end
+end
diff --git a/trunk/test/ruby/test_call.rb b/trunk/test/ruby/test_call.rb
new file mode 100644
index 0000000000..da7ee93c73
--- /dev/null
+++ b/trunk/test/ruby/test_call.rb
@@ -0,0 +1,19 @@
+require 'test/unit'
+
+class TestCall < Test::Unit::TestCase
+ def aaa(a, b=100, *rest)
+ res = [a, b]
+ res += rest if rest
+ return res
+ end
+
+ def test_call
+ assert_raises(ArgumentError) {aaa()}
+ assert_raises(ArgumentError) {aaa}
+
+ assert_equal([1, 100], aaa(1))
+ assert_equal([1, 2], aaa(1, 2))
+ assert_equal([1, 2, 3, 4], aaa(1, 2, 3, 4))
+ assert_equal([1, 2, 3, 4], aaa(1, *[2, 3, 4]))
+ end
+end
diff --git a/trunk/test/ruby/test_case.rb b/trunk/test/ruby/test_case.rb
new file mode 100644
index 0000000000..41a22038a0
--- /dev/null
+++ b/trunk/test/ruby/test_case.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+
+class TestCase < Test::Unit::TestCase
+ def test_case
+ case 5
+ when 1, 2, 3, 4, 6, 7, 8
+ assert(false)
+ when 5
+ assert(true)
+ end
+
+ case 5
+ when 5
+ assert(true)
+ when 1..10
+ assert(false)
+ end
+
+ case 5
+ when 1..10
+ assert(true)
+ else
+ assert(false)
+ end
+
+ case 5
+ when 5
+ assert(true)
+ else
+ assert(false)
+ end
+
+ case "foobar"
+ when /^f.*r$/
+ assert(true)
+ else
+ assert(false)
+ end
+
+ case
+ when true
+ assert(true)
+ when false, nil
+ assert(false)
+ else
+ assert(false)
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_class.rb b/trunk/test/ruby/test_class.rb
new file mode 100644
index 0000000000..93a19e86e9
--- /dev/null
+++ b/trunk/test/ruby/test_class.rb
@@ -0,0 +1,147 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestClass < Test::Unit::TestCase
+ # ------------------
+ # Various test classes
+ # ------------------
+
+ class ClassOne
+ attr :num_args
+ @@subs = []
+ def initialize(*args)
+ @num_args = args.size
+ @args = args
+ end
+ def [](n)
+ @args[n]
+ end
+ def ClassOne.inherited(klass)
+ @@subs.push klass
+ end
+ def subs
+ @@subs
+ end
+ end
+
+ class ClassTwo < ClassOne
+ end
+
+ class ClassThree < ClassOne
+ end
+
+ class ClassFour < ClassThree
+ end
+
+ # ------------------
+ # Start of tests
+ # ------------------
+
+ def test_s_inherited
+ assert_equal([ClassTwo, ClassThree, ClassFour], ClassOne.new.subs)
+ end
+
+ def test_s_new
+ c = Class.new
+ assert_same(Class, c.class)
+ assert_same(Object, c.superclass)
+
+ c = Class.new(Fixnum)
+ assert_same(Class, c.class)
+ assert_same(Fixnum, c.superclass)
+ end
+
+ def test_00_new_basic
+ a = ClassOne.new
+ assert_equal(ClassOne, a.class)
+ assert_equal(0, a.num_args)
+
+ a = ClassOne.new(1, 2, 3)
+ assert_equal(3, a.num_args)
+ assert_equal(1, a[0])
+ end
+
+ def test_01_new_inherited
+ a = ClassTwo.new
+ assert_equal(ClassTwo, a.class)
+ assert_equal(0, a.num_args)
+
+ a = ClassTwo.new(1, 2, 3)
+ assert_equal(3, a.num_args)
+ assert_equal(1, a[0])
+ end
+
+ def test_superclass
+ assert_equal(ClassOne, ClassTwo.superclass)
+ assert_equal(Object, ClassTwo.superclass.superclass)
+ assert_equal(BasicObject, ClassTwo.superclass.superclass.superclass)
+ end
+
+ def test_class_cmp
+ assert_raise(TypeError) { Class.new <= 1 }
+ assert_raise(TypeError) { Class.new >= 1 }
+ assert_nil(Class.new <=> 1)
+ end
+
+ def test_class_initialize
+ assert_raise(TypeError) do
+ Class.new.instance_eval { initialize }
+ end
+ end
+
+ def test_instanciate_singleton_class
+ c = class << Object.new; self; end
+ assert_raise(TypeError) { c.new }
+ end
+
+ def test_superclass_of_basicobject
+ assert_equal(nil, BasicObject.superclass)
+ end
+
+ def test_module_function
+ c = Class.new
+ assert_raise(TypeError) do
+ Module.instance_method(:module_function).bind(c).call(:foo)
+ end
+ end
+
+ def test_check_inheritable
+ assert_raise(TypeError) { Class.new(Object.new) }
+
+ o = Object.new
+ c = class << o; self; end
+ assert_raise(TypeError) { Class.new(c) }
+
+ assert_nothing_raised { Class.new(Class) } # is it OK?
+ assert_raise(TypeError) { eval("class Foo < Class; end") }
+ end
+
+ def test_initialize_copy
+ c = Class.new
+ assert_raise(TypeError) { c.instance_eval { initialize_copy(1) } }
+
+ o = Object.new
+ c = class << o; self; end
+ assert_raise(TypeError) { c.dup }
+ end
+
+ def test_singleton_class
+ assert_raise(TypeError) { 1.extend(Module.new) }
+ assert_raise(TypeError) { :foo.extend(Module.new) }
+
+ assert_in_out_err([], <<-INPUT, %w(:foo :foo true true), [])
+ module Foo; def foo; :foo; end; end
+ false.extend(Foo)
+ true.extend(Foo)
+ p false.foo
+ p true.foo
+ p FalseClass.include?(Foo)
+ p TrueClass.include?(Foo)
+ INPUT
+ end
+
+ def test_uninitialized
+ assert_raise(TypeError) { Class.allocate.new }
+ assert_raise(TypeError) { Class.allocate.superclass }
+ end
+end
diff --git a/trunk/test/ruby/test_clone.rb b/trunk/test/ruby/test_clone.rb
new file mode 100644
index 0000000000..43c0cffa1d
--- /dev/null
+++ b/trunk/test/ruby/test_clone.rb
@@ -0,0 +1,28 @@
+require 'test/unit'
+
+class TestClone < Test::Unit::TestCase
+ module M001; end
+ module M002; end
+ module M003; include M002; end
+ module M002; include M001; end
+ module M003; include M002; end
+
+ def test_clone
+ foo = Object.new
+ def foo.test
+ "test"
+ end
+ bar = foo.clone
+ def bar.test2
+ "test2"
+ end
+
+ assert_equal("test2", bar.test2)
+ assert_equal("test", bar.test)
+ assert_equal("test", foo.test)
+
+ assert_raises(NoMethodError) {foo.test2}
+
+ assert_equal([M003, M002, M001], M003.ancestors)
+ end
+end
diff --git a/trunk/test/ruby/test_comparable.rb b/trunk/test/ruby/test_comparable.rb
new file mode 100644
index 0000000000..e558b190f0
--- /dev/null
+++ b/trunk/test/ruby/test_comparable.rb
@@ -0,0 +1,66 @@
+require 'test/unit'
+
+class TestComparable < Test::Unit::TestCase
+ def setup
+ @o = Object.new
+ @o.extend(Comparable)
+ end
+
+ def test_equal
+ def @o.<=>(x); 0; end
+ assert_equal(true, @o == nil)
+ def @o.<=>(x); 1; end
+ assert_equal(false, @o == nil)
+ def @o.<=>(x); raise; end
+ assert_equal(false, @o == nil)
+ end
+
+ def test_gt
+ def @o.<=>(x); 1; end
+ assert_equal(true, @o > nil)
+ def @o.<=>(x); 0; end
+ assert_equal(false, @o > nil)
+ def @o.<=>(x); -1; end
+ assert_equal(false, @o > nil)
+ end
+
+ def test_ge
+ def @o.<=>(x); 1; end
+ assert_equal(true, @o >= nil)
+ def @o.<=>(x); 0; end
+ assert_equal(true, @o >= nil)
+ def @o.<=>(x); -1; end
+ assert_equal(false, @o >= nil)
+ end
+
+ def test_lt
+ def @o.<=>(x); 1; end
+ assert_equal(false, @o < nil)
+ def @o.<=>(x); 0; end
+ assert_equal(false, @o < nil)
+ def @o.<=>(x); -1; end
+ assert_equal(true, @o < nil)
+ end
+
+ def test_le
+ def @o.<=>(x); 1; end
+ assert_equal(false, @o <= nil)
+ def @o.<=>(x); 0; end
+ assert_equal(true, @o <= nil)
+ def @o.<=>(x); -1; end
+ assert_equal(true, @o <= nil)
+ end
+
+ def test_between
+ def @o.<=>(x); 0 <=> x end
+ assert_equal(false, @o.between?(1, 2))
+ assert_equal(false, @o.between?(-2, -1))
+ assert_equal(true, @o.between?(-1, 1))
+ assert_equal(true, @o.between?(0, 0))
+ end
+
+ def test_err
+ assert_raise(ArgumentError) { 1.0 < nil }
+ assert_raise(ArgumentError) { 1.0 < Object.new }
+ end
+end
diff --git a/trunk/test/ruby/test_complex.rb b/trunk/test/ruby/test_complex.rb
new file mode 100644
index 0000000000..b661864519
--- /dev/null
+++ b/trunk/test/ruby/test_complex.rb
@@ -0,0 +1,1147 @@
+require 'test/unit'
+
+class ComplexSub < Complex; end
+
+class Complex_Test < Test::Unit::TestCase
+
+ def test_compsub
+ c = ComplexSub.__send__(:new, 1)
+ cc = ComplexSub.__send__(:convert, 1)
+ if defined?(ComplexSub::Unify)
+ assert_instance_of(Fixnum, c)
+ assert_instance_of(Fixnum, cc)
+ else
+ assert_instance_of(ComplexSub, c)
+ assert_instance_of(ComplexSub, cc)
+
+ c2 = c + 1
+ assert_instance_of(ComplexSub, c2)
+ c2 = c - 1
+ assert_instance_of(ComplexSub, c2)
+
+ c3 = c - c2
+ assert_instance_of(ComplexSub, c3)
+
+ s = Marshal.dump(c)
+ c5 = Marshal.load(s)
+ assert_equal(c, c5)
+ assert_instance_of(ComplexSub, c5)
+ end
+
+ end
+
+ def test_eql_p
+ c = Complex(0)
+ c2 = Complex(0)
+ c3 = Complex(1)
+
+ assert_equal(true, c.eql?(c2))
+ assert_equal(false, c.eql?(c3))
+
+ if defined?(Complex::Unify)
+ assert_equal(true, c.eql?(0))
+ else
+ assert_equal(false, c.eql?(0))
+ end
+ end
+
+ def test_hash
+ assert_instance_of(Fixnum, Complex(1,2).hash)
+
+ h = {}
+ h[Complex(0)] = 0
+ h[Complex(0,1)] = 1
+ h[Complex(1,0)] = 2
+ h[Complex(1,1)] = 3
+
+ assert_equal(4, h.size)
+ assert_equal(2, h[Complex(1,0)])
+
+ h[Complex(0,0)] = 9
+ assert_equal(4, h.size)
+ end
+
+ def test_freeze
+ c = Complex(1)
+ c.freeze
+ unless defined?(Complex::Unify)
+ assert_equal(true, c.frozen?)
+ end
+ assert_instance_of(String, c.to_s)
+ end
+
+ def test_new_bang # no unify
+ assert_instance_of(Complex, Complex.__send__(:new!, 2,0))
+ assert_equal([2,0], Complex.__send__(:new!, 2,0).
+ instance_eval{[real, image]})
+ assert_equal([2,4], Complex.__send__(:new!, 2,4).
+ instance_eval{[real, image]})
+ assert_equal([-2,4], Complex.__send__(:new!, -2,4).
+ instance_eval{[real, image]})
+ assert_equal([2,-4], Complex.__send__(:new!, 2,-4).
+ instance_eval{[real, image]})
+ assert_equal([-2,-4], Complex.__send__(:new!, -2,-4).
+ instance_eval{[real, image]})
+
+ assert_equal([2,0], Complex.__send__(:new!, Complex(2)).
+ instance_eval{[real, image]})
+ assert_equal([2,3], Complex.__send__(:new!, Complex(2), Complex(3)).
+ instance_eval{[real, image]})
+ assert_equal([2,3], Complex.__send__(:new!, 2, Complex(3)).
+ instance_eval{[real, image]})
+
+ assert_equal([1.1,0], Complex.__send__(:new!, 1.1).
+ instance_eval{[real, image]})
+ assert_equal([-1.1,0], Complex.__send__(:new!, -1.1).
+ instance_eval{[real, image]})
+ assert_equal([1,0], Complex.__send__(:new!, '1').
+ instance_eval{[real, image]})
+ assert_equal([0,0], Complex.__send__(:new!, nil).
+ instance_eval{[real, image]})
+ end
+
+ def test_new
+ if defined?(Complex::Unify)
+ assert_instance_of(Fixnum, Complex.__send__(:new, 2,0))
+ else
+ assert_instance_of(Complex, Complex.__send__(:new, 2,0))
+ assert_equal([2,0], Complex.__send__(:new, 2,0). instance_eval{[real, image]})
+ end
+ assert_equal([2,4], Complex.__send__(:new, 2,4).instance_eval{[real, image]})
+ assert_equal([-2,4], Complex.__send__(:new, -2,4).instance_eval{[real, image]})
+ assert_equal([2,-4], Complex.__send__(:new, 2,-4).instance_eval{[real, image]})
+ assert_equal([-2,-4], Complex.__send__(:new, -2,-4).instance_eval{[real, image]})
+
+ assert_raise(ArgumentError){Complex.__send__(:new, Complex(1,2),2)}
+ assert_raise(ArgumentError){Complex.__send__(:new, 2,Complex(1,2))}
+ assert_raise(ArgumentError){Complex.__send__(:new, Complex(1,2),Complex(1,2))}
+
+ assert_raise(ArgumentError){Complex.__send__(:new, '1')}
+ assert_raise(ArgumentError){Complex.__send__(:new, nil)}
+=begin
+ assert_raise(ArgumentError){Complex.__send__(:new, Complex(1))}
+=end
+ end
+
+ def test_conv
+ c = Complex(0,0)
+ assert_equal(Complex.__send__(:new, 0,0), c)
+
+ c = Complex(2**32, 2**32)
+ assert_equal(Complex.__send__(:new, 2**32,2**32), c)
+ assert_equal([2**32,2**32], [c.real,c.image])
+
+ c = Complex(-2**32, 2**32)
+ assert_equal(Complex.__send__(:new, -2**32,2**32), c)
+ assert_equal([-2**32,2**32], [c.real,c.image])
+
+ c = Complex(2**32, -2**32)
+ assert_equal(Complex.__send__(:new, 2**32,-2**32), c)
+ assert_equal([2**32,-2**32], [c.real,c.image])
+
+ c = Complex(-2**32, -2**32)
+ assert_equal(Complex.__send__(:new, -2**32,-2**32), c)
+ assert_equal([-2**32,-2**32], [c.real,c.image])
+
+ c = Complex(Complex(1),0)
+ assert_equal(Complex.__send__(:new, 1,0), c)
+
+ c = Complex(0,Complex(1))
+ assert_equal(Complex.__send__(:new, 0,1), c)
+
+ c = 5.re
+ assert_equal(Complex.__send__(:new, 5,0), c)
+
+ c = Complex(1,2).re
+ assert_equal(Complex.__send__(:new, 1,2), c)
+
+ c = 5.im
+ assert_equal(Complex.__send__(:new, 0,5), c)
+
+ c = Complex(2,0).im
+ assert_equal(Complex.__send__(:new, 0,2), c)
+ assert_raise(ArgumentError){Complex(1,2).im}
+
+ c = Complex::I
+ assert_equal(Complex.__send__(:new, 0,1), c)
+
+ assert_equal(Complex.__send__(:new, 1),Complex(1))
+ assert_equal(Complex.__send__(:new, 1),Complex('1'))
+ assert_raise(ArgumentError){Complex(nil)}
+ end
+
+ def test_attr
+ c = Complex(4)
+
+ assert_equal(4, c.real)
+ assert_equal(0, c.image)
+
+ c = Complex(4,5)
+
+ assert_equal(4, c.real)
+ assert_equal(5, c.image)
+
+ c = Complex(-0.0,-0.0)
+
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.image.to_s)
+
+ c = Complex.__send__(:new, 4)
+
+ assert_equal(4, c.real)
+ assert_equal(0, c.image)
+ assert_equal(c.imag, c.image)
+
+ c = Complex.__send__(:new, 4,5)
+
+ assert_equal(4, c.real)
+ assert_equal(5, c.image)
+ assert_equal(c.imag, c.image)
+
+ c = Complex.__send__(:new, -0.0,-0.0)
+
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.image.to_s)
+ assert_equal(c.imag.to_s, c.image.to_s)
+
+ c = Complex.__send__(:new!, 4)
+
+ assert_equal(4, c.real)
+ assert_equal(c.imag, c.image)
+ assert_equal(0, c.image)
+
+ c = Complex.__send__(:new!, 4,5)
+
+ assert_equal(4, c.real)
+ assert_equal(5, c.image)
+ assert_equal(c.imag, c.image)
+
+ c = Complex.__send__(:new!, -0.0,-0.0)
+
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.image.to_s)
+ assert_equal(c.imag.to_s, c.image.to_s)
+ end
+
+ def test_attr2
+ c = Complex(1)
+
+ if defined?(Complex::Unify)
+ assert_equal(true, c.scalar?)
+=begin
+ assert_equal(true, c.finite?)
+ assert_equal(false, c.infinite?)
+ assert_equal(false, c.nan?)
+ assert_equal(true, c.integer?)
+ assert_equal(false, c.float?)
+ assert_equal(true, c.rational?)
+ assert_equal(true, c.real?)
+ assert_equal(false, c.complex?)
+ assert_equal(true, c.exact?)
+ assert_equal(false, c.inexact?)
+=end
+ else
+ assert_equal(false, c.scalar?)
+=begin
+ assert_equal(true, c.finite?)
+ assert_equal(false, c.infinite?)
+ assert_equal(false, c.nan?)
+ assert_equal(false, c.integer?)
+ assert_equal(false, c.float?)
+ assert_equal(false, c.rational?)
+ assert_equal(false, c.real?)
+ assert_equal(true, c.complex?)
+ assert_equal(true, c.exact?)
+ assert_equal(false, c.inexact?)
+=end
+ end
+
+=begin
+ assert_equal(0, Complex(0).sign)
+ assert_equal(1, Complex(2).sign)
+ assert_equal(-1, Complex(-2).sign)
+=end
+
+ assert_equal(true, Complex(0).zero?)
+ assert_equal(true, Complex(0,0).zero?)
+ assert_equal(false, Complex(1,0).zero?)
+ assert_equal(false, Complex(0,1).zero?)
+ assert_equal(false, Complex(1,1).zero?)
+
+ assert_equal(nil, Complex(0).nonzero?)
+ assert_equal(nil, Complex(0,0).nonzero?)
+ assert_equal(Complex(1,0), Complex(1,0).nonzero?)
+ assert_equal(Complex(0,1), Complex(0,1).nonzero?)
+ assert_equal(Complex(1,1), Complex(1,1).nonzero?)
+ end
+
+ def test_uplus
+ assert_equal(Complex(1), +Complex(1))
+ assert_equal(Complex(-1), +Complex(-1))
+ assert_equal(Complex(1,1), +Complex(1,1))
+ assert_equal(Complex(-1,1), +Complex(-1,1))
+ assert_equal(Complex(1,-1), +Complex(1,-1))
+ assert_equal(Complex(-1,-1), +Complex(-1,-1))
+ end
+
+ def test_negate
+ assert_equal(Complex(-1), -Complex(1))
+ assert_equal(Complex(1), -Complex(-1))
+ assert_equal(Complex(-1,-1), -Complex(1,1))
+ assert_equal(Complex(1,-1), -Complex(-1,1))
+ assert_equal(Complex(-1,1), -Complex(1,-1))
+ assert_equal(Complex(1,1), -Complex(-1,-1))
+
+=begin
+ assert_equal(0, Complex(0).negate)
+ assert_equal(-2, Complex(2).negate)
+ assert_equal(2, Complex(-2).negate)
+=end
+ end
+
+ def test_add
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ assert_equal(Complex(3,5), c + c2)
+
+ assert_equal(Complex(3,2), c + 2)
+ assert_equal(Complex(3.0,2), c + 2.0)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(3,1),Rational(2)), c + Rational(2))
+ assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3))
+ end
+ end
+
+ def test_sub
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ assert_equal(Complex(-1,-1), c - c2)
+
+ assert_equal(Complex(-1,2), c - 2)
+ assert_equal(Complex(-1.0,2), c - 2.0)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(-1,1),Rational(2)), c - Rational(2))
+ assert_equal(Complex(Rational(1,3),Rational(2)), c - Rational(2,3))
+ end
+ end
+
+ def test_mul
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ assert_equal(Complex(-4,7), c * c2)
+
+ assert_equal(Complex(2,4), c * 2)
+ assert_equal(Complex(2.0,4.0), c * 2.0)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(2,1),Rational(4)), c * Rational(2))
+ assert_equal(Complex(Rational(2,3),Rational(4,3)), c * Rational(2,3))
+ end
+
+ end
+
+ def test_div
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(8,13),Rational(1,13)), c / c2)
+ else
+ r = c / c2
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+ end
+
+ c = Complex(1.0,2.0)
+ c2 = Complex(2.0,3.0)
+
+ r = c / c2
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(1,2),1), c / 2)
+ else
+ assert_equal(Complex(0.5,1.0), c / 2)
+ end
+ assert_equal(Complex(0.5,1.0), c / 2.0)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
+ assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
+ end
+ end
+
+ def test_quo
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(8,13),Rational(1,13)), c.quo(c2))
+ else
+ r = c.quo(c2)
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+ end
+
+ c = Complex(1.0,2.0)
+ c2 = Complex(2.0,3.0)
+
+ r = c.quo(c2)
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(1,2),1), c.quo(2))
+ else
+ assert_equal(Complex(0.5,1.0), c.quo(2))
+ end
+ assert_equal(Complex(0.5,1.0), c.quo(2.0))
+
+ if defined?(Rational)
+ assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
+ assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
+ end
+ end
+
+ def test_fdiv
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ r = c.fdiv(c2)
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+
+ c = Complex(1.0,2.0)
+ c2 = Complex(2.0,3.0)
+
+ r = c.fdiv(c2)
+ assert_in_delta(0.615, r.real, 0.001)
+ assert_in_delta(0.076, r.image, 0.001)
+
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ assert_equal(Complex(0.5,1.0), c.fdiv(2))
+ assert_equal(Complex(0.5,1.0), c.fdiv(2.0))
+ end
+
+ def test_expt
+ c = Complex(1,2)
+ c2 = Complex(2,3)
+
+ r = c ** c2
+ assert_in_delta(-0.015, r.real, 0.001)
+ assert_in_delta(-0.179, r.image, 0.001)
+
+ assert_equal(Complex(-3,4), c ** 2)
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Complex(Rational(-3,25),Rational(-4,25)), c ** -2)
+ else
+ r = c ** -2
+ assert_in_delta(-0.12, r.real, 0.001)
+ assert_in_delta(-0.16, r.image, 0.001)
+ end
+ r = c ** 2.0
+ assert_in_delta(-3.0, r.real, 0.001)
+ assert_in_delta(4.0, r.image, 0.001)
+
+ r = c ** -2.0
+ assert_in_delta(-0.12, r.real, 0.001)
+ assert_in_delta(-0.16, r.image, 0.001)
+
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Complex(-3,4), c ** Rational(2))
+#=begin
+ assert_equal(Complex(Rational(-3,25),Rational(-4,25)),
+ c ** Rational(-2)) # why failed?
+#=end
+
+ r = c ** Rational(2,3)
+ assert_in_delta(1.264, r.real, 0.001)
+ assert_in_delta(1.150, r.image, 0.001)
+
+ r = c ** Rational(-2,3)
+ assert_in_delta(0.432, r.real, 0.001)
+ assert_in_delta(-0.393, r.image, 0.001)
+ end
+ end
+
+ def test_cmp
+ assert_raise(NoMethodError){1 <=> Complex(1,1)}
+ assert_raise(NoMethodError){Complex(1,1) <=> 1}
+ assert_raise(NoMethodError){Complex(1,1) <=> Complex(1,1)}
+ end
+
+ def test_equal
+ assert(Complex(1,0) == Complex(1))
+ assert(Complex(1,0) == Complex.__send__(:new, 1))
+ assert(Complex(1,0) == Complex.__send__(:new, 1,0))
+ assert(Complex(1,0) == Complex.__send__(:new!, 1))
+ assert(Complex(1,0) == Complex.__send__(:new!, 1,0))
+
+ assert(Complex(-1,0) == Complex(-1))
+ assert(Complex(-1,0) == Complex.__send__(:new, -1))
+ assert(Complex(-1,0) == Complex.__send__(:new, -1,0))
+ assert(Complex(-1,0) == Complex.__send__(:new!, -1))
+ assert(Complex(-1,0) == Complex.__send__(:new!, -1,0))
+
+ assert_equal(false, Complex(2,1) == Complex(1))
+ assert_equal(true, Complex(2,1) != Complex(1))
+ assert_equal(false, Complex(1) == nil)
+ assert_equal(false, Complex(1) == '')
+ end
+
+ def test_math
+ c = Complex(1,2)
+
+ assert_in_delta(2.236, c.abs, 0.001)
+ assert_equal(5, c.abs2)
+
+ assert_equal(c.abs, Math.sqrt(c * c.conj))
+ assert_equal(c.abs, Math.sqrt(c.real**2 + c.image**2))
+ assert_equal(c.abs2, c * c.conj)
+ assert_equal(c.abs2, c.real**2 + c.image**2)
+
+ assert_in_delta(1.107, c.arg, 0.001)
+ assert_in_delta(1.107, c.angle, 0.001)
+
+ r = c.polar
+ assert_in_delta(2.236, r[0], 0.001)
+ assert_in_delta(1.107, r[1], 0.001)
+ assert_equal(Complex(1,-2), c.conjugate)
+ assert_equal(Complex(1,-2), c.conj)
+# assert_equal(Complex(1,-2), ~c)
+# assert_equal(5, c * ~c)
+
+ assert_equal(Complex(1,2), c.numerator)
+ assert_equal(1, c.denominator)
+ end
+
+ def test_to_s
+ c = Complex(1,2)
+
+ assert_instance_of(String, c.to_s)
+ assert_equal('1+2i', c.to_s)
+
+ assert_equal('0+2i', Complex(0,2).to_s)
+ assert_equal('0-2i', Complex(0,-2).to_s)
+ assert_equal('1+2i', Complex(1,2).to_s)
+ assert_equal('-1+2i', Complex(-1,2).to_s)
+ assert_equal('-1-2i', Complex(-1,-2).to_s)
+ assert_equal('1-2i', Complex(1,-2).to_s)
+ assert_equal('-1-2i', Complex(-1,-2).to_s)
+
+ assert_equal('0+2.0i', Complex(0,2.0).to_s)
+ assert_equal('0-2.0i', Complex(0,-2.0).to_s)
+ assert_equal('1.0+2.0i', Complex(1.0,2.0).to_s)
+ assert_equal('-1.0+2.0i', Complex(-1.0,2.0).to_s)
+ assert_equal('-1.0-2.0i', Complex(-1.0,-2.0).to_s)
+ assert_equal('1.0-2.0i', Complex(1.0,-2.0).to_s)
+ assert_equal('-1.0-2.0i', Complex(-1.0,-2.0).to_s)
+
+ if defined?(Rational) && !defined?(Complex::Unify) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal('0+2/1i', Complex(0,Rational(2)).to_s)
+ assert_equal('0-2/1i', Complex(0,Rational(-2)).to_s)
+ assert_equal('1+2/1i', Complex(1,Rational(2)).to_s)
+ assert_equal('-1+2/1i', Complex(-1,Rational(2)).to_s)
+ assert_equal('-1-2/1i', Complex(-1,Rational(-2)).to_s)
+ assert_equal('1-2/1i', Complex(1,Rational(-2)).to_s)
+ assert_equal('-1-2/1i', Complex(-1,Rational(-2)).to_s)
+
+ assert_equal('0+2/3i', Complex(0,Rational(2,3)).to_s)
+ assert_equal('0-2/3i', Complex(0,Rational(-2,3)).to_s)
+ assert_equal('1+2/3i', Complex(1,Rational(2,3)).to_s)
+ assert_equal('-1+2/3i', Complex(-1,Rational(2,3)).to_s)
+ assert_equal('-1-2/3i', Complex(-1,Rational(-2,3)).to_s)
+ assert_equal('1-2/3i', Complex(1,Rational(-2,3)).to_s)
+ assert_equal('-1-2/3i', Complex(-1,Rational(-2,3)).to_s)
+ end
+ end
+
+ def test_inspect
+ c = Complex(1,2)
+
+ assert_instance_of(String, c.inspect)
+ assert_equal('(1+2i)', c.inspect)
+ end
+
+ def test_marshal
+ c = Complex(1,2)
+
+ s = Marshal.dump(c)
+ c2 = Marshal.load(s)
+ assert_equal(c, c2)
+ assert_instance_of(Complex, c2)
+
+ if defined?(Rational)
+ c = Complex(Rational(1,2),Rational(2,3))
+
+ s = Marshal.dump(c)
+ c2 = Marshal.load(s)
+ assert_equal(c, c2)
+ assert_instance_of(Complex, c2)
+ end
+ end
+
+ def test_parse
+ assert_equal(Complex(0), ''.to_c)
+ assert_equal(Complex(0), ' '.to_c)
+ assert_equal(Complex(5), '5'.to_c)
+ assert_equal(Complex(-5), '-5'.to_c)
+ assert_equal(Complex(5,3), '5+3i'.to_c)
+ assert_equal(Complex(-5,3), '-5+3i'.to_c)
+ assert_equal(Complex(5,-3), '5-3i'.to_c)
+ assert_equal(Complex(-5,-3), '-5-3i'.to_c)
+ assert_equal(Complex(0,3), '3i'.to_c)
+ assert_equal(Complex(0,-3), '-3i'.to_c)
+ assert_equal(Complex(5,1), '5+i'.to_c)
+ assert_equal(Complex(0,1), 'i'.to_c)
+ assert_equal(Complex(0,1), '+i'.to_c)
+ assert_equal(Complex(0,-1), '-i'.to_c)
+
+ assert_equal(Complex(5,3), '5+3I'.to_c)
+ assert_equal(Complex(5,3), '5+3j'.to_c)
+ assert_equal(Complex(5,3), '5+3J'.to_c)
+ assert_equal(Complex(0,3), '3I'.to_c)
+ assert_equal(Complex(0,3), '3j'.to_c)
+ assert_equal(Complex(0,3), '3J'.to_c)
+ assert_equal(Complex(0,1), 'I'.to_c)
+ assert_equal(Complex(0,1), 'J'.to_c)
+
+ assert_equal(Complex(5.0), '5.0'.to_c)
+ assert_equal(Complex(-5.0), '-5.0'.to_c)
+ assert_equal(Complex(5.0,3.0), '5.0+3.0i'.to_c)
+ assert_equal(Complex(-5.0,3.0), '-5.0+3.0i'.to_c)
+ assert_equal(Complex(5.0,-3.0), '5.0-3.0i'.to_c)
+ assert_equal(Complex(-5.0,-3.0), '-5.0-3.0i'.to_c)
+ assert_equal(Complex(0.0,3.0), '3.0i'.to_c)
+ assert_equal(Complex(0.0,-3.0), '-3.0i'.to_c)
+
+ assert_equal(Complex(5.0), '5e0'.to_c)
+ assert_equal(Complex(-5.0), '-5e0'.to_c)
+ assert_equal(Complex(5.0,3.0), '5e0+3e0i'.to_c)
+ assert_equal(Complex(-5.0,3.0), '-5e0+3e0i'.to_c)
+ assert_equal(Complex(5.0,-3.0), '5e0-3e0i'.to_c)
+ assert_equal(Complex(-5.0,-3.0), '-5e0-3e0i'.to_c)
+ assert_equal(Complex(0.0,3.0), '3e0i'.to_c)
+ assert_equal(Complex(0.0,-3.0), '-3e0i'.to_c)
+
+ assert_equal(Complex.polar(10,10), '10@10'.to_c)
+ assert_equal(Complex.polar(-10,-10), '-10@-10'.to_c)
+ assert_equal(Complex.polar(10.5,10.5), '10.5@10.5'.to_c)
+ assert_equal(Complex.polar(-10.5,-10.5), '-10.5@-10.5'.to_c)
+
+ assert_equal(Complex(5), Complex('5'))
+ assert_equal(Complex(-5), Complex('-5'))
+ assert_equal(Complex(5,3), Complex('5+3i'))
+ assert_equal(Complex(-5,3), Complex('-5+3i'))
+ assert_equal(Complex(5,-3), Complex('5-3i'))
+ assert_equal(Complex(-5,-3), Complex('-5-3i'))
+ assert_equal(Complex(0,3), Complex('3i'))
+ assert_equal(Complex(0,-3), Complex('-3i'))
+ assert_equal(Complex(5,1), Complex('5+i'))
+ assert_equal(Complex(0,1), Complex('i'))
+ assert_equal(Complex(0,1), Complex('+i'))
+ assert_equal(Complex(0,-1), Complex('-i'))
+
+ assert_equal(Complex(5,3), Complex('5+3I'))
+ assert_equal(Complex(5,3), Complex('5+3j'))
+ assert_equal(Complex(5,3), Complex('5+3J'))
+ assert_equal(Complex(0,3), Complex('3I'))
+ assert_equal(Complex(0,3), Complex('3j'))
+ assert_equal(Complex(0,3), Complex('3J'))
+ assert_equal(Complex(0,1), Complex('I'))
+ assert_equal(Complex(0,1), Complex('J'))
+
+ assert_equal(Complex(5.0), Complex('5.0'))
+ assert_equal(Complex(-5.0), Complex('-5.0'))
+ assert_equal(Complex(5.0,3.0), Complex('5.0+3.0i'))
+ assert_equal(Complex(-5.0,3.0), Complex('-5.0+3.0i'))
+ assert_equal(Complex(5.0,-3.0), Complex('5.0-3.0i'))
+ assert_equal(Complex(-5.0,-3.0), Complex('-5.0-3.0i'))
+ assert_equal(Complex(0.0,3.0), Complex('3.0i'))
+ assert_equal(Complex(0.0,-3.0), Complex('-3.0i'))
+
+ assert_equal(Complex(5.0), Complex('5e0'))
+ assert_equal(Complex(-5.0), Complex('-5e0'))
+ assert_equal(Complex(5.0,3.0), Complex('5e0+3e0i'))
+ assert_equal(Complex(-5.0,3.0), Complex('-5e0+3e0i'))
+ assert_equal(Complex(5.0,-3.0), Complex('5e0-3e0i'))
+ assert_equal(Complex(-5.0,-3.0), Complex('-5e0-3e0i'))
+ assert_equal(Complex(0.0,3.0), Complex('3e0i'))
+ assert_equal(Complex(0.0,-3.0), Complex('-3e0i'))
+
+ assert_equal(Complex.polar(10,10), Complex('10@10'))
+ assert_equal(Complex.polar(-10,-10), Complex('-10@-10'))
+ assert_equal(Complex.polar(10.5,10.5), Complex('10.5@10.5'))
+ assert_equal(Complex.polar(-10.5,-10.5), Complex('-10.5@-10.5'))
+
+ assert_equal(Complex(0), '_'.to_c)
+ assert_equal(Complex(0), '_5'.to_c)
+ assert_equal(Complex(5), '5_'.to_c)
+ assert_equal(Complex(5), '5x'.to_c)
+ assert_equal(Complex(5), '5+_3i'.to_c)
+ assert_equal(Complex(5), '5+3_i'.to_c)
+ assert_equal(Complex(5,3), '5+3i_'.to_c)
+ assert_equal(Complex(5,3), '5+3ix'.to_c)
+ assert_raise(ArgumentError){ Complex('')}
+ assert_raise(ArgumentError){ Complex('_')}
+ assert_raise(ArgumentError){ Complex('_5')}
+ assert_raise(ArgumentError){ Complex('5_')}
+ assert_raise(ArgumentError){ Complex('5x')}
+ assert_raise(ArgumentError){ Complex('5+_3i')}
+ assert_raise(ArgumentError){ Complex('5+3_i')}
+ assert_raise(ArgumentError){ Complex('5+3i_')}
+ assert_raise(ArgumentError){ Complex('5+3ix')}
+
+ if defined?(Rational) && defined?(''.to_r)
+ assert_equal(Complex(Rational(1,5)), '1/5'.to_c)
+ assert_equal(Complex(Rational(-1,5)), '-1/5'.to_c)
+ assert_equal(Complex(Rational(1,5),3), '1/5+3i'.to_c)
+ assert_equal(Complex(Rational(1,5),-3), '1/5-3i'.to_c)
+ assert_equal(Complex(Rational(-1,5),3), '-1/5+3i'.to_c)
+ assert_equal(Complex(Rational(-1,5),-3), '-1/5-3i'.to_c)
+ assert_equal(Complex(Rational(1,5),Rational(3,2)), '1/5+3/2i'.to_c)
+ assert_equal(Complex(Rational(1,5),Rational(-3,2)), '1/5-3/2i'.to_c)
+ assert_equal(Complex(Rational(-1,5),Rational(3,2)), '-1/5+3/2i'.to_c)
+ assert_equal(Complex(Rational(-1,5),Rational(-3,2)), '-1/5-3/2i'.to_c)
+ assert_equal(Complex(Rational(1,5),Rational(3,2)), '1/5+3/2i'.to_c)
+ assert_equal(Complex(Rational(1,5),Rational(-3,2)), '1/5-3/2i'.to_c)
+ assert_equal(Complex(Rational(-1,5),Rational(3,2)), '-1/5+3/2i'.to_c)
+ assert_equal(Complex(Rational(-1,5),Rational(-3,2)), '-1/5-3/2i'.to_c)
+ assert_equal(Complex.polar(Rational(1,5),Rational(3,2)), Complex('1/5@3/2'))
+ assert_equal(Complex.polar(Rational(-1,5),Rational(-3,2)), Complex('-1/5@-3/2'))
+ end
+
+ end
+
+ def test_respond
+ c = Complex(1,1)
+ assert_equal(false, c.respond_to?(:<))
+ assert_equal(false, c.respond_to?(:<=))
+ assert_equal(false, c.respond_to?(:<=>))
+ assert_equal(false, c.respond_to?(:>))
+ assert_equal(false, c.respond_to?(:>=))
+ assert_equal(false, c.respond_to?(:between?))
+# assert_equal(false, c.respond_to?(:div)) # ?
+ assert_equal(false, c.respond_to?(:divmod))
+ assert_equal(false, c.respond_to?(:floor))
+ assert_equal(false, c.respond_to?(:ceil))
+ assert_equal(false, c.respond_to?(:modulo))
+ assert_equal(false, c.respond_to?(:round))
+ assert_equal(false, c.respond_to?(:step))
+ assert_equal(false, c.respond_to?(:tunrcate))
+
+ assert_equal(false, c.respond_to?(:positive?))
+ assert_equal(false, c.respond_to?(:negative?))
+# assert_equal(false, c.respond_to?(:sign))
+
+ assert_equal(false, c.respond_to?(:quotient))
+ assert_equal(false, c.respond_to?(:quot))
+ assert_equal(false, c.respond_to?(:quotrem))
+
+ assert_equal(false, c.respond_to?(:gcd))
+ assert_equal(false, c.respond_to?(:lcm))
+ assert_equal(false, c.respond_to?(:gcdlcm))
+ end
+
+ def test_to_i
+ assert_equal(3, Complex(3).to_i)
+ assert_equal(3, Integer(Complex(3)))
+ assert_raise(RangeError){Complex(3,2).to_i}
+ assert_raise(RangeError){Integer(Complex(3,2))}
+ end
+
+ def test_to_f
+ assert_equal(3.0, Complex(3).to_f)
+ assert_equal(3.0, Float(Complex(3)))
+ assert_raise(RangeError){Complex(3,2).to_f}
+ assert_raise(RangeError){Float(Complex(3,2))}
+ end
+
+ def test_to_r
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Rational(3), Complex(3).to_r)
+ assert_equal(Rational(3), Rational(Complex(3)))
+ assert_raise(RangeError){Complex(3,2).to_r}
+ assert_raise(RangeError){Rational(Complex(3,2))}
+ end
+ end
+
+ def test_to_c
+ c = nil.to_c
+ assert_equal([0,0] , [c.real, c.image])
+
+ c = 0.to_c
+ assert_equal([0,0] , [c.real, c.image])
+
+ c = 1.to_c
+ assert_equal([1,0] , [c.real, c.image])
+
+ c = 1.1.to_c
+ assert_equal([1.1, 0], [c.real, c.image])
+
+ if defined?(Rational)
+ c = Rational(1,2).to_c
+ assert_equal([Rational(1,2), 0], [c.real, c.image])
+ end
+
+ c = Complex(1,2).to_c
+ assert_equal([1, 2], [c.real, c.image])
+ end
+
+ def test_prec
+ assert_equal(nil, Complex < Precision)
+ end
+
+ def test_supp
+ assert_equal(true, 1.scalar?)
+ assert_equal(true, 1.1.scalar?)
+
+ assert_equal(1, 1.real)
+ assert_equal(0, 1.image)
+ assert_equal(0, 1.imag)
+
+ assert_equal(1.1, 1.1.real)
+ assert_equal(0, 1.1.image)
+ assert_equal(0, 1.1.imag)
+
+ assert_equal(0, 1.arg)
+ assert_equal(0, 1.angle)
+
+ assert_equal(0, 1.0.arg)
+ assert_equal(0, 1.0.angle)
+
+ assert_equal(Math::PI, -1.arg)
+ assert_equal(Math::PI, -1.angle)
+
+ assert_equal(Math::PI, -1.0.arg)
+ assert_equal(Math::PI, -1.0.angle)
+
+ assert_equal([1,0], 1.polar)
+ assert_equal([1, Math::PI], -1.polar)
+
+ assert_equal([1.0,0], 1.0.polar)
+ assert_equal([1.0, Math::PI], -1.0.polar)
+
+ assert_equal(1, 1.conjugate)
+ assert_equal(-1, -1.conjugate)
+ assert_equal(1, 1.conj)
+ assert_equal(-1, -1.conj)
+
+ assert_equal(1.1, 1.1.conjugate)
+ assert_equal(-1.1, -1.1.conjugate)
+ assert_equal(1.1, 1.1.conj)
+ assert_equal(-1.1, -1.1.conj)
+
+ assert_equal(1, 1.numerator)
+ assert_equal(9, 9.numerator)
+ assert_equal(1, 1.denominator)
+ assert_equal(1, 9.denominator)
+
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(1.0, 1.0.numerator)
+ assert_equal(9.0, 9.0.numerator)
+ assert_equal(1.0, 1.0.denominator)
+ assert_equal(1.0, 9.0.denominator)
+ end
+
+=begin
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Rational(1,9), 9.reciprocal)
+ assert_equal(Rational(1,9), 9.0.reciprocal)
+ assert_equal(Rational(1,9), 9.inverse)
+ assert_equal(Rational(1,9), 9.0.inverse)
+ end
+=end
+
+ if defined?(Rational)
+ assert_equal(Rational(1,2), 1.quo(2))
+ assert_equal(Rational(5000000000), 10000000000.quo(2))
+ assert_equal(0.5, 1.0.quo(2))
+ assert_equal(Rational(1,4), Rational(1,2).quo(2))
+ assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
+ else
+ assert_equal(0.5, 1.quo(2))
+ assert_equal(5000000000.0, 10000000000.quo(2))
+ assert_equal(0.5, 1.0.quo(2))
+ assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
+ end
+
+=begin
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Rational(1,2), 1.rdiv(2))
+ assert_equal(Rational(5000000000), 10000000000.rdiv(2))
+ assert_equal(Rational(1,2), 1.0.rdiv(2))
+ assert_equal(Rational(1,4), Rational(1,2).rdiv(2))
+ assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
+ end
+=end
+
+ assert_equal(0.5, 1.fdiv(2))
+ assert_equal(5000000000.0, 10000000000.fdiv(2))
+ assert_equal(0.5, 1.0.fdiv(2))
+ if defined?(Rational)
+ assert_equal(0.25, Rational(1,2).fdiv(2))
+ end
+ assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
+
+ unless $".grep(/(\A|\/)complex/).empty?
+ assert_equal(Complex(0,2), Math.sqrt(-4.0))
+# assert_equal(true, Math.sqrt(-4.0).inexact?)
+ assert_equal(Complex(0,2), Math.sqrt(-4))
+# assert_equal(true, Math.sqrt(-4).exact?)
+ if defined?(Rational)
+ assert_equal(Complex(0,2), Math.sqrt(Rational(-4)))
+# assert_equal(true, Math.sqrt(Rational(-4)).exact?)
+ end
+
+ assert_equal(Complex(0,3), Math.sqrt(-9.0))
+# assert_equal(true, Math.sqrt(-9.0).inexact?)
+ assert_equal(Complex(0,3), Math.sqrt(-9))
+# assert_equal(true, Math.sqrt(-9).exact?)
+ if defined?(Rational)
+ assert_equal(Complex(0,3), Math.sqrt(Rational(-9)))
+# assert_equal(true, Math.sqrt(Rational(-9)).exact?)
+ end
+
+ c = Math.sqrt(Complex(1, 2))
+ assert_in_delta(1.272, c.real, 0.001)
+ assert_in_delta(0.786, c.image, 0.001)
+
+ c = Math.sqrt(-9)
+ assert_in_delta(0.0, c.real, 0.001)
+ assert_in_delta(3.0, c.image, 0.001)
+
+ c = Math.exp(Complex(1, 2))
+ assert_in_delta(-1.131, c.real, 0.001)
+ assert_in_delta(2.471, c.image, 0.001)
+
+ c = Math.sin(Complex(1, 2))
+ assert_in_delta(3.165, c.real, 0.001)
+ assert_in_delta(1.959, c.image, 0.001)
+
+ c = Math.cos(Complex(1, 2))
+ assert_in_delta(2.032, c.real, 0.001)
+ assert_in_delta(-3.051, c.image, 0.001)
+
+ c = Math.tan(Complex(1, 2))
+ assert_in_delta(0.033, c.real, 0.001)
+ assert_in_delta(1.014, c.image, 0.001)
+
+ c = Math.sinh(Complex(1, 2))
+ assert_in_delta(-0.489, c.real, 0.001)
+ assert_in_delta(1.403, c.image, 0.001)
+
+ c = Math.cosh(Complex(1, 2))
+ assert_in_delta(-0.642, c.real, 0.001)
+ assert_in_delta(1.068, c.image, 0.001)
+
+ c = Math.tanh(Complex(1, 2))
+ assert_in_delta(1.166, c.real, 0.001)
+ assert_in_delta(-0.243, c.image, 0.001)
+
+ c = Math.log(Complex(1, 2))
+ assert_in_delta(0.804, c.real, 0.001)
+ assert_in_delta(1.107, c.image, 0.001)
+
+ c = Math.log(Complex(1, 2), Math::E)
+ assert_in_delta(0.804, c.real, 0.001)
+ assert_in_delta(1.107, c.image, 0.001)
+
+ c = Math.log(-1)
+ assert_in_delta(0.0, c.real, 0.001)
+ assert_in_delta(Math::PI, c.image, 0.001)
+
+ c = Math.log(8, 2)
+ assert_in_delta(3.0, c.real, 0.001)
+ assert_in_delta(0.0, c.image, 0.001)
+
+ c = Math.log(-8, -2)
+ assert_in_delta(1.092, c.real, 0.001)
+ assert_in_delta(-0.420, c.image, 0.001)
+
+ c = Math.log10(Complex(1, 2))
+ assert_in_delta(0.349, c.real, 0.001)
+ assert_in_delta(0.480, c.image, 0.001)
+
+ c = Math.asin(Complex(1, 2))
+ assert_in_delta(0.427, c.real, 0.001)
+ assert_in_delta(1.528, c.image, 0.001)
+
+ c = Math.acos(Complex(1, 2))
+ assert_in_delta(1.143, c.real, 0.001)
+ assert_in_delta(-1.528, c.image, 0.001)
+
+ c = Math.atan(Complex(1, 2))
+ assert_in_delta(1.338, c.real, 0.001)
+ assert_in_delta(0.402, c.image, 0.001)
+
+ c = Math.atan2(Complex(1, 2), 1)
+ assert_in_delta(1.338, c.real, 0.001)
+ assert_in_delta(0.402, c.image, 0.001)
+
+ c = Math.asinh(Complex(1, 2))
+ assert_in_delta(1.469, c.real, 0.001)
+ assert_in_delta(1.063, c.image, 0.001)
+
+ c = Math.acosh(Complex(1, 2))
+ assert_in_delta(1.528, c.real, 0.001)
+ assert_in_delta(1.143, c.image, 0.001)
+
+ c = Math.atanh(Complex(1, 2))
+ assert_in_delta(0.173, c.real, 0.001)
+ assert_in_delta(1.178, c.image, 0.001)
+ end
+
+ end
+
+=begin
+ def test_canonicalize
+ f = defined?(Complex::Unify)
+ Complex.const_set(:Unify, true) unless f
+
+ assert_same(1, Complex.instance_eval { new(1, 0) })
+ assert_not_same(1.0, Complex.instance_eval { new(1.0, 0) })
+ assert_equal(Complex(1.0, 0), Complex.instance_eval { new(1.0, 0) })
+
+ Complex.instance_eval { remove_const(:Unify) } unless f
+ end
+
+ def test_polar
+ c = Complex.polar(2, 2)
+ assert_in_delta(2*Math.cos(2), c.real , 0.001)
+ assert_in_delta(2*Math.sin(2), c.image, 0.001)
+
+ c = Complex.polar(1, Complex(0, 1))
+ assert_in_delta(1/Math::E, c.real , 0.001)
+ assert_in_delta( 0, c.image, 0.001)
+ end
+
+ def test_generic?
+ assert_equal(true, Complex.generic?(1))
+ assert_equal(true, Complex.generic?(2**100))
+ assert_equal(true, Complex.generic?(Rational(1, 2)))
+ assert_equal(true, Complex.generic?(1.0))
+ assert_equal(false, Complex.generic?(Complex(1, 1)))
+ end
+
+ def test_new_bang2
+ o = Object.new
+ def o.to_i; 1; end
+ assert_equal(Complex(1, 1), Complex.instance_eval { new!(o, o) })
+ end
+
+ def test_denominator
+ f = defined?(Complex::Unify)
+ unify_val = f && Complex::Unify
+ Complex.instance_eval { remove_const(:Unify) } if f
+
+ dummy_rational = Class.new(Rational)
+ o1 = dummy_rational.instance_eval { new(1, 1) }
+ o2 = dummy_rational.instance_eval { new(1, 1) }
+ d1 = d2 = nil
+ class << o1; self; end.instance_eval { define_method(:denominator) { d1 } rescue nil }
+ class << o2; self; end.instance_eval { define_method(:denominator) { d2 } rescue nil }
+ # o1.denominator returns d1 and o1.denominator returns d2
+
+ c = Complex(o1, o2)
+
+ d1 = d2 = 0
+ assert_equal(0, c.denominator)
+
+ d1 = d2 = -1
+ assert_equal(1, c.denominator)
+
+ d1 = d2 = 256
+ assert_equal(256, c.denominator)
+
+ d1, d2 = 512, 256
+ assert_equal(512, c.denominator)
+
+ d1, d2 = 256, 512
+ assert_equal(512, c.denominator)
+
+ d1, d2 = -(2**100), -(3**100)
+ assert_equal(6**100, c.denominator)
+
+ d1, d2 = 1, 2**100
+ assert_equal(2**100, c.denominator)
+
+ Complex.const_set(:Unify, unify_val) if f
+ end
+
+ def test_abs
+ b = 2**100
+ def b.*(x); self; end rescue nil
+ def b.+(x); -1; end rescue nil
+ assert_equal(Complex(0, 1), Complex(b, 1).abs)
+
+ def b.+(x); Complex(0, 1); end rescue nil
+ c = Complex(b, 1).abs
+ assert_in_delta(1/Math.sqrt(2), c.real , 0.001)
+ assert_in_delta(1/Math.sqrt(2), c.image, 0.001)
+
+ def b.+(x); Complex(0, -1); end rescue nil
+ c = Complex(b, 1).abs
+ assert_in_delta( 1/Math.sqrt(2), c.real , 0.001)
+ assert_in_delta(-1/Math.sqrt(2), c.image, 0.001)
+
+ inf = 1.0/0.0
+ nan = inf/inf
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Complex(1, nan).abs }
+ end
+
+ def test_coerce
+ c = Complex(6, 3)
+ assert_equal(Complex(42, 0), c.coerce(42).first)
+ assert_raise(TypeError) { c.coerce(Object.new) }
+
+ o = Object.new
+ def o.coerce(x); [x.real, x.image]; end
+ assert_equal(9, c + o)
+ assert_equal(3, c - o)
+ assert_equal(18, c * o)
+ assert_equal(2, c / o)
+ assert_equal(216, c ** o)
+ end
+
+ def test_add2
+ assert_equal(Complex(2**100, 1), Complex(0, 1) + 2**100)
+ end
+
+ def test_mul2
+ assert_equal(Complex(0.0, 0.0), Complex(1.0, 1.0) * 0)
+ assert_equal(Complex(0, 0), Complex(0, 0) * (2**100))
+ end
+
+ def test_expt2
+ assert_equal(Complex(1, 0), Complex(2, 2) ** 0)
+ assert_equal(Complex(0, -1), Complex(0, 1) ** (2**100-1))
+ assert_equal(Complex(1, 0), Complex(1, 0) ** Rational(1, 2**100))
+ end
+=end
+
+ def test_fixed_bug
+ if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ assert_equal(Complex(1), 1 ** Complex(1))
+ end
+ assert_equal('-1.0-0.0i', Complex(-1.0, -0.0).to_s)
+ end
+
+ def test_known_bug
+ end
+
+end
diff --git a/trunk/test/ruby/test_condition.rb b/trunk/test/ruby/test_condition.rb
new file mode 100644
index 0000000000..ba2e0688f3
--- /dev/null
+++ b/trunk/test/ruby/test_condition.rb
@@ -0,0 +1,16 @@
+require 'test/unit'
+
+class TestCondition < Test::Unit::TestCase
+
+ # [should] first test to see if we can run the tests.
+
+ def test_condition
+ $x = '0';
+
+ $x == $x && assert(true)
+ $x != $x && assert(false)
+ $x == $x || assert(false)
+ $x != $x || assert(true)
+
+ end
+end
diff --git a/trunk/test/ruby/test_const.rb b/trunk/test/ruby/test_const.rb
new file mode 100644
index 0000000000..3708a5a0ca
--- /dev/null
+++ b/trunk/test/ruby/test_const.rb
@@ -0,0 +1,48 @@
+require 'test/unit'
+
+class TestConst < Test::Unit::TestCase
+ TEST1 = 1
+ TEST2 = 2
+
+ module Const
+ TEST3 = 3
+ TEST4 = 4
+ end
+
+ module Const2
+ TEST3 = 6
+ TEST4 = 8
+ end
+
+ def test_const
+ assert defined?(TEST1)
+ assert_equal 1, TEST1
+ assert defined?(TEST2)
+ assert_equal 2, TEST2
+
+ self.class.class_eval {
+ include Const
+ }
+ assert defined?(TEST1)
+ assert_equal 1, TEST1
+ assert defined?(TEST2)
+ assert_equal 2, TEST2
+ assert defined?(TEST3)
+ assert_equal 3, TEST3
+ assert defined?(TEST4)
+ assert_equal 4, TEST4
+
+ self.class.class_eval {
+ include Const2
+ }
+ STDERR.print "intentionally redefines TEST3, TEST4\n" if $VERBOSE
+ assert defined?(TEST1)
+ assert_equal 1, TEST1
+ assert defined?(TEST2)
+ assert_equal 2, TEST2
+ assert defined?(TEST3)
+ assert_equal 6, TEST3
+ assert defined?(TEST4)
+ assert_equal 8, TEST4
+ end
+end
diff --git a/trunk/test/ruby/test_continuation.rb b/trunk/test/ruby/test_continuation.rb
new file mode 100644
index 0000000000..c719db8c35
--- /dev/null
+++ b/trunk/test/ruby/test_continuation.rb
@@ -0,0 +1,81 @@
+require 'test/unit'
+require 'continuation'
+require 'fiber'
+require_relative 'envutil'
+
+class TestContinuation < Test::Unit::TestCase
+ def test_create
+ assert_equal(:ok, callcc{:ok})
+ assert_equal(:ok, callcc{|c| c.call :ok})
+ end
+
+ def test_call
+ assert_equal(:ok, callcc{|c| c.call :ok})
+
+ ary = []
+ ary << callcc{|c|
+ @cont = c
+ :a
+ }
+ @cont.call :b if ary.length < 3
+ assert_equal([:a, :b, :b], ary)
+ end
+
+ def test_check_localvars
+ vv = 0
+ @v = 0
+ @ary = []
+ [1, 2, 3].each{|i|
+ callcc {|k| @k = k}
+ @v += 1
+ vv += 1
+ }
+ @ary << [vv, @v]
+ @k.call if @v < 10
+ assert_equal((3..10).map{|e| [e, e]}, @ary)
+ end
+
+ def test_error
+ cont = callcc{|c| c}
+ assert_raise(RuntimeError){
+ Thread.new{cont.call}.join
+ }
+ assert_raise(LocalJumpError){
+ callcc
+ }
+ assert_raise(RuntimeError){
+ c = nil
+ Fiber.new do
+ callcc {|c2| c = c2 }
+ end.resume
+ c.call
+ }
+ end
+
+ def test_ary_flatten
+ assert_normal_exit %q{
+ require 'continuation'
+ n = 0
+ o = Object.new
+ def o.to_ary() callcc {|k| $k = k; [1,2,3]} end
+ [10,20,o,30,o,40].flatten.inspect
+ n += 1
+ $k.call if n < 100
+ }, '[ruby-dev:34798]'
+ end
+
+ def test_marshal_dump
+ assert_normal_exit %q{
+ require 'continuation'
+ n = 0
+ o = Object.new
+ def o.marshal_dump() callcc {|k| $k = k }; "fofof" end
+ a = [1,2,3,o,4,5,6]
+ Marshal.dump(a).inspect
+ n += 1
+ $k.call if n < 100
+ }, '[ruby-dev:34802]'
+ end
+
+end
+
diff --git a/trunk/test/ruby/test_defined.rb b/trunk/test/ruby/test_defined.rb
new file mode 100644
index 0000000000..bfcd7fb667
--- /dev/null
+++ b/trunk/test/ruby/test_defined.rb
@@ -0,0 +1,81 @@
+require 'test/unit'
+
+class TestDefined < Test::Unit::TestCase
+ class Foo
+ def foo
+ p :foo
+ end
+ protected :foo
+ def bar(f)
+ yield(defined?(self.foo))
+ yield(defined?(f.foo))
+ end
+ def baz(f)
+ end
+ end
+
+ def defined_test
+ return !defined?(yield)
+ end
+
+ def test_defined
+ $x = nil
+
+ assert(defined?($x)) # global variable
+ assert_equal('global-variable', defined?($x))# returns description
+
+ assert_nil(defined?(foo)) # undefined
+ foo=5
+ assert(defined?(foo)) # local variable
+
+ assert(defined?(Array)) # constant
+ assert(defined?(::Array)) # toplevel constant
+ assert(defined?(File::Constants)) # nested constant
+ assert(defined?(Object.new)) # method
+ assert(!defined?(Object.print)) # private method
+ assert(defined?(1 == 2)) # operator expression
+
+ f = Foo.new
+ assert_nil(defined?(f.foo)) # protected method
+ f.bar(f) { |v| assert(v) }
+ assert_nil(defined?(f.quux)) # undefined method
+ assert_nil(defined?(f.baz(x))) # undefined argument
+ x = 0
+ assert(defined?(f.baz(x)))
+ assert_nil(defined?(f.quux(x)))
+ assert(defined?(print(x)))
+ assert_nil(defined?(quux(x)))
+
+ assert(defined_test) # not iterator
+ assert(!defined_test{}) # called as iterator
+
+ /a/ =~ ''
+ assert_equal nil, defined?($&)
+ assert_equal nil, defined?($`)
+ assert_equal nil, defined?($')
+ assert_equal nil, defined?($+)
+ assert_equal nil, defined?($1)
+ assert_equal nil, defined?($2)
+ /a/ =~ 'a'
+ assert_equal 'global-variable', defined?($&)
+ assert_equal 'global-variable', defined?($`)
+ assert_equal 'global-variable', defined?($')
+ assert_equal nil, defined?($+)
+ assert_equal nil, defined?($1)
+ assert_equal nil, defined?($2)
+ /(a)/ =~ 'a'
+ assert_equal 'global-variable', defined?($&)
+ assert_equal 'global-variable', defined?($`)
+ assert_equal 'global-variable', defined?($')
+ assert_equal 'global-variable', defined?($+)
+ assert_equal 'global-variable', defined?($1)
+ assert_equal nil, defined?($2)
+ /(a)b/ =~ 'ab'
+ assert_equal 'global-variable', defined?($&)
+ assert_equal 'global-variable', defined?($`)
+ assert_equal 'global-variable', defined?($')
+ assert_equal 'global-variable', defined?($+)
+ assert_equal 'global-variable', defined?($1)
+ assert_equal nil, defined?($2)
+ end
+end
diff --git a/trunk/test/ruby/test_dir.rb b/trunk/test/ruby/test_dir.rb
new file mode 100644
index 0000000000..0ea28f55d8
--- /dev/null
+++ b/trunk/test/ruby/test_dir.rb
@@ -0,0 +1,170 @@
+require 'test/unit'
+
+require 'tmpdir'
+require 'fileutils'
+require 'pathname'
+
+class TestDir < Test::Unit::TestCase
+
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ @root = Pathname.new(Dir.mktmpdir('__test_dir__')).realpath.to_s
+ @nodir = File.join(@root, "dummy")
+ for i in ?a..?z
+ if i.ord % 2 == 0
+ FileUtils.touch(File.join(@root, i))
+ else
+ FileUtils.mkdir(File.join(@root, i))
+ end
+ end
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ FileUtils.remove_entry_secure @root if File.directory?(@root)
+ end
+
+ def test_seek
+ dir = Dir.open(@root)
+ begin
+ cache = []
+ loop do
+ pos = dir.tell
+ break unless name = dir.read
+ cache << [pos, name]
+ end
+ for x,y in cache.sort_by {|z| z[0] % 3 } # shuffle
+ dir.seek(x)
+ assert_equal(y, dir.read)
+ end
+ ensure
+ dir.close
+ end
+ end
+
+ def test_JVN_13947696
+ b = lambda {
+ d = Dir.open('.')
+ $SAFE = 4
+ d.close
+ }
+ assert_raise(SecurityError) { b.call }
+ end
+
+ def test_nodir
+ assert_raise(Errno::ENOENT) { Dir.open(@nodir) }
+ end
+
+ def test_inspect
+ d = Dir.open(@root)
+ assert_match(/^#<Dir:#{ Regexp.quote(@root) }>$/, d.inspect)
+ assert_match(/^#<Dir:.*>$/, Dir.allocate.inspect)
+ ensure
+ d.close
+ end
+
+ def test_path
+ d = Dir.open(@root)
+ assert_equal(@root, d.path)
+ assert_nil(Dir.allocate.path)
+ ensure
+ d.close
+ end
+
+ def test_set_pos
+ d = Dir.open(@root)
+ loop do
+ i = d.pos
+ break unless x = d.read
+ d.pos = i
+ assert_equal(x, d.read)
+ end
+ ensure
+ d.close
+ end
+
+ def test_rewind
+ d = Dir.open(@root)
+ a = (0..5).map { d.read }
+ d.rewind
+ b = (0..5).map { d.read }
+ assert_equal(a, b)
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ d.rewind
+ end.join
+ end
+ ensure
+ d.close
+ end
+
+ def test_chdir
+ @pwd = Dir.pwd
+ @env_home = ENV["HOME"]
+ @env_logdir = ENV["LOGDIR"]
+ ENV.delete("HOME")
+ ENV.delete("LOGDIR")
+
+ assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) }
+ assert_raise(ArgumentError) { Dir.chdir }
+ ENV["HOME"] = @pwd
+ Dir.chdir do
+ assert_equal(@pwd, Dir.pwd)
+ Dir.chdir(@root)
+ assert_equal(@root, Dir.pwd)
+ end
+
+ ensure
+ begin
+ Dir.chdir(@pwd)
+ rescue
+ abort("cannot return the original directory: #{ @pwd }")
+ end
+ if @env_home
+ ENV["HOME"] = @env_home
+ else
+ ENV.delete("HOME")
+ end
+ if @env_logdir
+ ENV["LOGDIR"] = @env_logdir
+ else
+ ENV.delete("LOGDIR")
+ end
+ end
+
+ def test_chroot_nodir
+ assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM
+ ) { Dir.chroot(File.join(@nodir, "")) }
+ end
+
+ def test_close
+ d = Dir.open(@root)
+ d.close
+ assert_raise(IOError) { d.read }
+ end
+
+ def test_glob
+ assert_equal((%w(. ..) + (?a..?z).to_a).map{|f| File.join(@root, f) },
+ Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH).sort)
+ assert_equal([@root] + (?a..?z).map {|f| File.join(@root, f) }.sort,
+ Dir.glob([@root, File.join(@root, "*")]).sort)
+ assert_equal([@root] + (?a..?z).map {|f| File.join(@root, f) }.sort,
+ Dir.glob(@root + "\0\0\0" + File.join(@root, "*")).sort)
+
+ assert_equal((?a..?z).step(2).map {|f| File.join(File.join(@root, f), "") }.sort,
+ Dir.glob(File.join(@root, "*/")).sort)
+
+ FileUtils.touch(File.join(@root, "{}"))
+ assert_equal(%w({} a).map{|f| File.join(@root, f) },
+ Dir.glob(File.join(@root, '{\{\},a}')))
+ assert_equal([], Dir.glob(File.join(@root, '[')))
+ assert_equal([], Dir.glob(File.join(@root, '[a-\\')))
+ end
+
+ def test_foreach
+ assert_equal(Dir.foreach(@root).to_a.sort, %w(. ..) + (?a..?z).to_a)
+ end
+
+end
diff --git a/trunk/test/ruby/test_econv.rb b/trunk/test/ruby/test_econv.rb
new file mode 100644
index 0000000000..32ac4ca935
--- /dev/null
+++ b/trunk/test/ruby/test_econv.rb
@@ -0,0 +1,524 @@
+require 'test/unit'
+
+class TestEncodingConverter < Test::Unit::TestCase
+ def check_ec(edst, esrc, eres, dst, src, ec, off, len, flags=0)
+ res = ec.primitive_convert(src, dst, off, len, flags)
+ assert_equal([edst.dup.force_encoding("ASCII-8BIT"),
+ esrc.dup.force_encoding("ASCII-8BIT"),
+ eres],
+ [dst.dup.force_encoding("ASCII-8BIT"),
+ src.dup.force_encoding("ASCII-8BIT"),
+ res])
+ end
+
+ def assert_econv(converted, eres, obuf_bytesize, ec, consumed, rest, flags=0)
+ ec = Encoding::Converter.new(*ec) if Array === ec
+ i = consumed + rest
+ o = ""
+ ret = ec.primitive_convert(i, o, 0, obuf_bytesize, flags)
+ assert_equal([converted, eres, rest],
+ [o, ret, i])
+ end
+
+ def assert_errinfo(e_res, e_enc1, e_enc2, e_error_bytes, e_readagain_bytes, e_partial_input, ec)
+ assert_equal([e_res, e_enc1, e_enc2,
+ e_error_bytes && e_error_bytes.dup.force_encoding("ASCII-8BIT"),
+ e_readagain_bytes && e_readagain_bytes.dup.force_encoding("ASCII-8BIT"),
+ e_partial_input],
+ ec.primitive_errinfo)
+ end
+
+ def test_new
+ assert_kind_of(Encoding::Converter, Encoding::Converter.new("UTF-8", "EUC-JP"))
+ assert_kind_of(Encoding::Converter, Encoding::Converter.new(Encoding::UTF_8, Encoding::EUC_JP))
+ end
+
+ def test_new_fail
+ name1 = "encoding-which-is-not-exist-1"
+ name2 = "encoding-which-is-not-exist-2"
+
+ assert_raise(Encoding::NoConverter) {
+ Encoding::Converter.new(name1, name2)
+ }
+
+ encoding_list = Encoding.list.map {|e| e.name }
+ assert(!encoding_list.include?(name1))
+ assert(!encoding_list.include?(name2))
+ end
+
+ def test_get_encoding
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ assert_equal(Encoding::UTF_8, ec.source_encoding)
+ assert_equal(Encoding::EUC_JP, ec.destination_encoding)
+ end
+
+ def test_result_encoding
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ dst = "".force_encoding("ASCII-8BIT")
+ assert_equal(Encoding::ASCII_8BIT, dst.encoding)
+ ec.primitive_convert("\u{3042}", dst, nil, 10)
+ assert_equal(Encoding::EUC_JP, dst.encoding)
+ end
+
+ def test_output_region
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ ec.primitive_convert(src="a", dst="b", nil, 1, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("ba", dst)
+ ec.primitive_convert(src="a", dst="b", 0, 1, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("a", dst)
+ ec.primitive_convert(src="a", dst="b", 1, 1, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("ba", dst)
+ assert_raise(ArgumentError) {
+ ec.primitive_convert(src="a", dst="b", 2, 1, Encoding::Converter::PARTIAL_INPUT)
+ }
+ assert_raise(ArgumentError) {
+ ec.primitive_convert(src="a", dst="b", -1, 1, Encoding::Converter::PARTIAL_INPUT)
+ }
+ assert_raise(ArgumentError) {
+ ec.primitive_convert(src="a", dst="b", 1, -1, Encoding::Converter::PARTIAL_INPUT)
+ }
+ end
+
+ def test_partial_input
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ ret = ec.primitive_convert(src="", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal(:source_buffer_empty, ret)
+ ret = ec.primitive_convert(src="", dst="", nil, 10)
+ assert_equal(:finished, ret)
+ end
+
+ def test_accumulate_dst1
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ a = ["", "abc\u{3042}def", ec, nil, 1]
+ check_ec("a", "c\u{3042}def", :destination_buffer_full, *a)
+ check_ec("ab", "\u{3042}def", :destination_buffer_full, *a)
+ check_ec("abc", "def", :destination_buffer_full, *a)
+ check_ec("abc\xA4", "def", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2", "ef", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2d", "f", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2de", "", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2def", "", :finished, *a)
+ end
+
+ def test_accumulate_dst2
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ a = ["", "abc\u{3042}def", ec, nil, 2]
+ check_ec("ab", "\u{3042}def", :destination_buffer_full, *a)
+ check_ec("abc\xA4", "def", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2d", "f", :destination_buffer_full, *a)
+ check_ec("abc\xA4\xA2def", "", :finished, *a)
+ end
+
+ def test_eucjp_to_utf8
+ assert_econv("", :finished, 100, ["UTF-8", "EUC-JP"], "", "")
+ assert_econv("a", :finished, 100, ["UTF-8", "EUC-JP"], "a", "")
+ end
+
+ def test_iso2022jp
+ assert_econv("", :finished, 100, ["Shift_JIS", "ISO-2022-JP"], "", "")
+ end
+
+ def test_iso2022jp_encode
+ ec = Encoding::Converter.new("EUC-JP", "ISO-2022-JP")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "a"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "\xA2"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "\xA4"; check_ec("a\e$B\"$", "", :source_buffer_empty, *a)
+ src << "\xA1"; check_ec("a\e$B\"$", "", :source_buffer_empty, *a)
+ src << "\xA2"; check_ec("a\e$B\"$!\"", "", :source_buffer_empty, *a)
+ src << "b"; check_ec("a\e$B\"$!\"\e(Bb", "", :source_buffer_empty, *a)
+ src << "\xA2\xA6"; check_ec("a\e$B\"$!\"\e(Bb\e$B\"&", "", :source_buffer_empty, *a)
+ a[-1] = 0; check_ec("a\e$B\"$!\"\e(Bb\e$B\"&\e(B", "", :finished, *a)
+ end
+
+ def test_iso2022jp_decode
+ ec = Encoding::Converter.new("ISO-2022-JP", "EUC-JP")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "a"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "\e"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "$"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "B"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "\x21"; check_ec("a", "", :source_buffer_empty, *a)
+ src << "\x22"; check_ec("a\xA1\xA2", "", :source_buffer_empty, *a)
+ src << "\n"; check_ec("a\xA1\xA2", "", :invalid_byte_sequence, *a)
+ src << "\x23"; check_ec("a\xA1\xA2", "", :source_buffer_empty, *a)
+ src << "\x24"; check_ec("a\xA1\xA2\xA3\xA4", "", :source_buffer_empty, *a)
+ src << "\e"; check_ec("a\xA1\xA2\xA3\xA4", "", :source_buffer_empty, *a)
+ src << "("; check_ec("a\xA1\xA2\xA3\xA4", "", :source_buffer_empty, *a)
+ src << "B"; check_ec("a\xA1\xA2\xA3\xA4", "", :source_buffer_empty, *a)
+ src << "c"; check_ec("a\xA1\xA2\xA3\xA4c", "", :source_buffer_empty, *a)
+ src << "\n"; check_ec("a\xA1\xA2\xA3\xA4c\n","", :source_buffer_empty, *a)
+ end
+
+ def test_invalid
+ assert_econv("", :invalid_byte_sequence, 100, ["UTF-8", "EUC-JP"], "\x80", "")
+ assert_econv("a", :invalid_byte_sequence, 100, ["UTF-8", "EUC-JP"], "a\x80", "")
+ assert_econv("a", :invalid_byte_sequence, 100, ["UTF-8", "EUC-JP"], "a\x80", "\x80")
+ assert_econv("abc", :invalid_byte_sequence, 100, ["UTF-8", "EUC-JP"], "abc\xFF", "def")
+ assert_econv("abc", :invalid_byte_sequence, 100, ["Shift_JIS", "EUC-JP"], "abc\xFF", "def")
+ assert_econv("abc", :invalid_byte_sequence, 100, ["ISO-2022-JP", "EUC-JP"], "abc\xFF", "def")
+ end
+
+ def test_invalid2
+ ec = Encoding::Converter.new("Shift_JIS", "EUC-JP")
+ a = ["", "abc\xFFdef", ec, nil, 1]
+ check_ec("a", "c\xFFdef", :destination_buffer_full, *a)
+ check_ec("ab", "\xFFdef", :destination_buffer_full, *a)
+ check_ec("abc", "def", :invalid_byte_sequence, *a)
+ check_ec("abcd", "f", :destination_buffer_full, *a)
+ check_ec("abcde", "", :destination_buffer_full, *a)
+ check_ec("abcdef", "", :finished, *a)
+ end
+
+ def test_invalid3
+ ec = Encoding::Converter.new("Shift_JIS", "EUC-JP")
+ a = ["", "abc\xFFdef", ec, nil, 10]
+ check_ec("abc", "def", :invalid_byte_sequence, *a)
+ check_ec("abcdef", "", :finished, *a)
+ end
+
+ def test_invalid4
+ ec = Encoding::Converter.new("Shift_JIS", "EUC-JP")
+ a = ["", "abc\xFFdef", ec, nil, 10, Encoding::Converter::OUTPUT_FOLLOWED_BY_INPUT]
+ check_ec("a", "bc\xFFdef", :output_followed_by_input, *a)
+ check_ec("ab", "c\xFFdef", :output_followed_by_input, *a)
+ check_ec("abc", "\xFFdef", :output_followed_by_input, *a)
+ check_ec("abc", "def", :invalid_byte_sequence, *a)
+ check_ec("abcd", "ef", :output_followed_by_input, *a)
+ check_ec("abcde", "f", :output_followed_by_input, *a)
+ check_ec("abcdef", "", :output_followed_by_input, *a)
+ check_ec("abcdef", "", :finished, *a)
+ end
+
+ def test_invalid_utf16le
+ ec = Encoding::Converter.new("UTF-16LE", "UTF-8")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "A"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x01"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x02"; check_ec("A", "", :invalid_byte_sequence, *a)
+ src << "\x03"; check_ec("A\u{0201}", "", :source_buffer_empty, *a)
+ src << "\x04"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A\u{0201}\u{0403}", "", :invalid_byte_sequence, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xdc"; check_ec("A\u{0201}\u{0403}\u{10000}", "", :source_buffer_empty, *a)
+ end
+
+ def test_invalid_utf16be
+ ec = Encoding::Converter.new("UTF-16BE", "UTF-8")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "A"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x02"; check_ec("A", "", :invalid_byte_sequence, *a)
+ src << "\x01"; check_ec("A\u{0201}", "", :source_buffer_empty, *a)
+ src << "\x04"; check_ec("A\u{0201}", "", :source_buffer_empty, *a)
+ src << "\x03"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xd8"; check_ec("A\u{0201}\u{0403}", "", :invalid_byte_sequence, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\xdc"; check_ec("A\u{0201}\u{0403}", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A\u{0201}\u{0403}\u{10000}", "", :source_buffer_empty, *a)
+ end
+
+ def test_invalid_utf32be
+ ec = Encoding::Converter.new("UTF-32BE", "UTF-8")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "A"; check_ec("A", "", :source_buffer_empty, *a)
+
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\xdc"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :invalid_byte_sequence, *a)
+
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "B"; check_ec("AB", "", :source_buffer_empty, *a)
+
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "C"; check_ec("ABC", "", :source_buffer_empty, *a)
+ end
+
+ def test_invalid_utf32le
+ ec = Encoding::Converter.new("UTF-32LE", "UTF-8")
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "A"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\xdc"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :invalid_byte_sequence, *a)
+
+ src << "B"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("A", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+
+ src << "C"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("AB", "", :source_buffer_empty, *a)
+ src << "\x00"; check_ec("ABC", "", :source_buffer_empty, *a)
+ end
+
+ def test_errors
+ ec = Encoding::Converter.new("UTF-16BE", "EUC-JP")
+ a = ["", "\xFF\xFE\x00A\xDC\x00\x00B", ec, nil, 10]
+ check_ec("", "\x00A\xDC\x00\x00B", :undefined_conversion, *a)
+ check_ec("A", "\x00B", :invalid_byte_sequence, *a) # \xDC\x00 is invalid as UTF-16BE
+ check_ec("AB", "", :finished, *a)
+ end
+
+ def test_errors2
+ ec = Encoding::Converter.new("UTF-16BE", "EUC-JP")
+ a = ["", "\xFF\xFE\x00A\xDC\x00\x00B", ec, nil, 10, Encoding::Converter::OUTPUT_FOLLOWED_BY_INPUT]
+ check_ec("", "\x00A\xDC\x00\x00B", :undefined_conversion, *a)
+ check_ec("A", "\xDC\x00\x00B", :output_followed_by_input, *a)
+ check_ec("A", "\x00B", :invalid_byte_sequence, *a)
+ check_ec("AB", "", :output_followed_by_input, *a)
+ check_ec("AB", "", :finished, *a)
+ end
+
+ def test_universal_newline
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::UNIVERSAL_NEWLINE_DECODER)
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "abc\r\ndef"; check_ec("abc\ndef", "", :source_buffer_empty, *a)
+ src << "ghi\njkl"; check_ec("abc\ndefghi\njkl", "", :source_buffer_empty, *a)
+ src << "mno\rpqr"; check_ec("abc\ndefghi\njklmno\npqr", "", :source_buffer_empty, *a)
+ src << "stu\r"; check_ec("abc\ndefghi\njklmno\npqrstu\n", "", :source_buffer_empty, *a)
+ src << "\nvwx"; check_ec("abc\ndefghi\njklmno\npqrstu\nvwx", "", :source_buffer_empty, *a)
+ src << "\nyz"; check_ec("abc\ndefghi\njklmno\npqrstu\nvwx\nyz", "", :source_buffer_empty, *a)
+ end
+
+ def test_universal_newline2
+ ec = Encoding::Converter.new("", "", Encoding::Converter::UNIVERSAL_NEWLINE_DECODER)
+ a = ["", src="", ec, nil, 50, Encoding::Converter::PARTIAL_INPUT]
+ src << "abc\r\ndef"; check_ec("abc\ndef", "", :source_buffer_empty, *a)
+ src << "ghi\njkl"; check_ec("abc\ndefghi\njkl", "", :source_buffer_empty, *a)
+ src << "mno\rpqr"; check_ec("abc\ndefghi\njklmno\npqr", "", :source_buffer_empty, *a)
+ src << "stu\r"; check_ec("abc\ndefghi\njklmno\npqrstu\n", "", :source_buffer_empty, *a)
+ src << "\nvwx"; check_ec("abc\ndefghi\njklmno\npqrstu\nvwx", "", :source_buffer_empty, *a)
+ src << "\nyz"; check_ec("abc\ndefghi\njklmno\npqrstu\nvwx\nyz", "", :source_buffer_empty, *a)
+ end
+
+ def test_crlf_newline
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::CRLF_NEWLINE_ENCODER)
+ assert_econv("abc\r\ndef", :finished, 50, ec, "abc\ndef", "")
+ end
+
+ def test_crlf_newline2
+ ec = Encoding::Converter.new("", "", Encoding::Converter::CRLF_NEWLINE_ENCODER)
+ assert_econv("abc\r\ndef", :finished, 50, ec, "abc\ndef", "")
+ end
+
+ def test_cr_newline
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::CR_NEWLINE_ENCODER)
+ assert_econv("abc\rdef", :finished, 50, ec, "abc\ndef", "")
+ end
+
+ def test_cr_newline2
+ ec = Encoding::Converter.new("", "", Encoding::Converter::CR_NEWLINE_ENCODER)
+ assert_econv("abc\rdef", :finished, 50, ec, "abc\ndef", "")
+ end
+
+ def test_output_followed_by_input
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP")
+ a = ["", "abc\u{3042}def", ec, nil, 100, Encoding::Converter::OUTPUT_FOLLOWED_BY_INPUT]
+ check_ec("a", "bc\u{3042}def", :output_followed_by_input, *a)
+ check_ec("ab", "c\u{3042}def", :output_followed_by_input, *a)
+ check_ec("abc", "\u{3042}def", :output_followed_by_input, *a)
+ check_ec("abc\xA4\xA2", "def", :output_followed_by_input, *a)
+ check_ec("abc\xA4\xA2d", "ef", :output_followed_by_input, *a)
+ check_ec("abc\xA4\xA2de", "f", :output_followed_by_input, *a)
+ check_ec("abc\xA4\xA2def", "", :output_followed_by_input, *a)
+ check_ec("abc\xA4\xA2def", "", :finished, *a)
+ end
+
+ def test_errinfo_invalid_euc_jp
+ ec = Encoding::Converter.new("EUC-JP", "Shift_JIS")
+ ec.primitive_convert(src="\xff", dst="", nil, 10)
+ assert_errinfo(:invalid_byte_sequence, "EUC-JP", "UTF-8", "\xFF", "", nil, ec)
+ end
+
+ def test_errinfo_undefined_hiragana
+ ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
+ ec.primitive_convert(src="\xa4\xa2", dst="", nil, 10)
+ assert_errinfo(:undefined_conversion, "UTF-8", "ISO-8859-1", "\xE3\x81\x82", "", nil, ec)
+ end
+
+ def test_errinfo_invalid_partial_character
+ ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
+ ec.primitive_convert(src="\xa4", dst="", nil, 10)
+ assert_errinfo(:invalid_byte_sequence, "EUC-JP", "UTF-8", "\xA4", "", nil, ec)
+ end
+
+ def test_errinfo_valid_partial_character
+ ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
+ ec.primitive_convert(src="\xa4", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_errinfo(:source_buffer_empty, nil, nil, nil, nil, :partial_input, ec)
+ end
+
+ def test_errinfo_invalid_utf16be
+ ec = Encoding::Converter.new("UTF-16BE", "UTF-8")
+ ec.primitive_convert(src="\xd8\x00\x00@", dst="", nil, 10)
+ assert_errinfo(:invalid_byte_sequence, "UTF-16BE", "UTF-8", "\xD8\x00", "\x00", nil, ec)
+ assert_equal("@", src)
+ end
+
+ def test_errinfo_invalid_utf16le
+ ec = Encoding::Converter.new("UTF-16LE", "UTF-8")
+ ec.primitive_convert(src="\x00\xd8@\x00", dst="", nil, 10)
+ assert_errinfo(:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "@\x00", nil, ec)
+ assert_equal("", src)
+ end
+
+ def test_output_iso2022jp
+ ec = Encoding::Converter.new("EUC-JP", "ISO-2022-JP")
+ ec.primitive_convert(src="\xa1\xa1", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!".force_encoding("ISO-2022-JP"), dst)
+ assert_equal(true, ec.primitive_insert_output("???"))
+ ec.primitive_convert("", dst, nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!\e(B???".force_encoding("ISO-2022-JP"), dst)
+ ec.primitive_convert(src="\xa1\xa2", dst, nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!\e(B???\e$B!\"".force_encoding("ISO-2022-JP"), dst)
+
+ assert_equal(true, ec.primitive_insert_output("\xA1\xA1".force_encoding("EUC-JP")))
+ ec.primitive_convert("", dst, nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!\e(B???\e$B!\"!!".force_encoding("ISO-2022-JP"), dst)
+
+ ec.primitive_convert(src="\xa1\xa3", dst, nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!\e(B???\e$B!\"!!!\#".force_encoding("ISO-2022-JP"), dst)
+
+ assert_equal(true, ec.primitive_insert_output("\u3042"))
+ ec.primitive_convert("", dst, nil, 10, Encoding::Converter::PARTIAL_INPUT)
+ assert_equal("\e$B!!\e(B???\e$B!\"!!!\#$\"".force_encoding("ISO-2022-JP"), dst)
+
+ assert_raise(Encoding::ConversionUndefined) {
+ ec.primitive_insert_output("\uFFFD")
+ }
+
+ assert_equal("\e$B!!\e(B???\e$B!\"!!!\#$\"".force_encoding("ISO-2022-JP"), dst)
+
+ ec.primitive_convert("", dst, nil, 10)
+ assert_equal("\e$B!!\e(B???\e$B!\"!!!\#$\"\e(B".force_encoding("ISO-2022-JP"), dst)
+ end
+
+ def test_exc_invalid
+ err = assert_raise(Encoding::InvalidByteSequence) {
+ "abc\xa4def".encode("ISO-8859-1", "EUC-JP")
+ }
+ assert_equal("EUC-JP", err.source_encoding)
+ assert_equal("UTF-8", err.destination_encoding)
+ assert_equal("\xA4".force_encoding("ASCII-8BIT"), err.error_bytes)
+ end
+
+ def test_exc_undef
+ err = assert_raise(Encoding::ConversionUndefined) {
+ "abc\xa4\xa2def".encode("ISO-8859-1", "EUC-JP")
+ }
+ assert_equal("UTF-8", err.source_encoding)
+ assert_equal("ISO-8859-1", err.destination_encoding)
+ assert_equal("\u{3042}", err.error_char)
+ end
+
+ def test_putback
+ ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
+ ret = ec.primitive_convert(src="abc\xa1def", dst="", nil, 10)
+ assert_equal(:invalid_byte_sequence, ret)
+ assert_equal(["abc", "ef"], [dst, src])
+ src = ec.primitive_putback(nil) + src
+ assert_equal(["abc", "def"], [dst, src])
+ ret = ec.primitive_convert(src, dst, nil, 10)
+ assert_equal(:finished, ret)
+ assert_equal(["abcdef", ""], [dst, src])
+ end
+
+ def test_invalid_replace
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::INVALID_REPLACE)
+ ret = ec.primitive_convert(src="abc\x80def", dst="", nil, 100)
+ assert_equal(:finished, ret)
+ assert_equal("", src)
+ assert_equal("abc?def", dst)
+ end
+
+ def test_invalid_ignore
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::INVALID_IGNORE)
+ ret = ec.primitive_convert(src="abc\x80def", dst="", nil, 100)
+ assert_equal(:finished, ret)
+ assert_equal("", src)
+ assert_equal("abcdef", dst)
+ end
+
+ def test_undef_replace
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::UNDEF_REPLACE)
+ ret = ec.primitive_convert(src="abc\u{fffd}def", dst="", nil, 100)
+ assert_equal(:finished, ret)
+ assert_equal("", src)
+ assert_equal("abc?def", dst)
+ end
+
+ def test_undef_ignore
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", Encoding::Converter::UNDEF_IGNORE)
+ ret = ec.primitive_convert(src="abc\u{fffd}def", dst="", nil, 100)
+ assert_equal(:finished, ret)
+ assert_equal("", src)
+ assert_equal("abcdef", dst)
+ end
+
+ def test_noconv
+ ec = Encoding::Converter.new("", "")
+ assert_equal(nil, ec.source_encoding)
+ assert_equal(nil, ec.destination_encoding)
+ assert_equal([:source_buffer_empty, nil, nil, nil, nil, nil], ec.primitive_errinfo)
+ a = ["", "abcdefg", ec, nil, 2]
+ check_ec("ab", "cdefg", :destination_buffer_full, *a)
+ check_ec("abcd", "efg", :destination_buffer_full, *a)
+ check_ec("abcdef", "g", :destination_buffer_full, *a)
+ check_ec("abcdefg", "", :finished, *a)
+ end
+
+ def test_noconv_partial
+ ec = Encoding::Converter.new("", "")
+ a = ["", "abcdefg", ec, nil, 2, Encoding::Converter::PARTIAL_INPUT]
+ check_ec("ab", "cdefg", :destination_buffer_full, *a)
+ check_ec("abcd", "efg", :destination_buffer_full, *a)
+ check_ec("abcdef", "g", :destination_buffer_full, *a)
+ check_ec("abcdefg", "", :source_buffer_empty, *a)
+ end
+
+ def test_noconv_output_followed_by_input
+ ec = Encoding::Converter.new("", "")
+ a = ["", "abcdefg", ec, nil, 2, Encoding::Converter::OUTPUT_FOLLOWED_BY_INPUT]
+ check_ec("a", "bcdefg", :output_followed_by_input, *a)
+ check_ec("ab", "cdefg", :output_followed_by_input, *a)
+ check_ec("abc", "defg", :output_followed_by_input, *a)
+ check_ec("abcd", "efg", :output_followed_by_input, *a)
+ check_ec("abcde", "fg", :output_followed_by_input, *a)
+ check_ec("abcdef", "g", :output_followed_by_input, *a)
+ check_ec("abcdefg", "", :output_followed_by_input, *a)
+ check_ec("abcdefg", "", :finished, *a)
+ end
+
+ def test_noconv_insert_output
+ ec = Encoding::Converter.new("", "")
+ ec.primitive_insert_output("xyz")
+ ret = ec.primitive_convert(src="abc", dst="", nil, 20)
+ assert_equal(:finished, ret)
+ assert_equal(["xyzabc", ""], [dst, src])
+ end
+end
diff --git a/trunk/test/ruby/test_encoding.rb b/trunk/test/ruby/test_encoding.rb
new file mode 100644
index 0000000000..24000796fa
--- /dev/null
+++ b/trunk/test/ruby/test_encoding.rb
@@ -0,0 +1,54 @@
+require 'test/unit'
+
+class TestEncoding < Test::Unit::TestCase
+
+ # Test basic encoding methods: list, find, name
+ def test_encoding
+ encodings = Encoding.list
+ assert_equal(encodings.empty?, false)
+
+ encodings.each do |e|
+ assert_equal(e, Encoding.find(e.name))
+ assert_equal(e, Encoding.find(e.name.upcase))
+ assert_equal(e, Encoding.find(e.name.capitalize))
+ assert_equal(e, Encoding.find(e.name.downcase))
+ end
+ end
+
+ # Test that Encoding objects can't be copied
+ # And that they can be compared by object_id
+ def test_singleton
+ encodings = Encoding.list
+ encodings.each do |e|
+ assert_raise(TypeError) { e.dup }
+ assert_raise(TypeError) { e.clone }
+ assert_equal(e.object_id, Marshal.load(Marshal.dump(e)).object_id)
+ end
+ end
+
+ def test_find
+ assert_raise(ArgumentError) { Encoding.find("foobarbazqux") }
+ end
+
+ def test_dummy_p
+ assert_equal(true, Encoding::ISO_2022_JP.dummy?)
+ assert_equal(false, Encoding::UTF_8.dummy?)
+ end
+
+ def test_name_list
+ assert_instance_of(Array, Encoding.name_list)
+ Encoding.name_list.each do |x|
+ assert_instance_of(String, x)
+ end
+ end
+
+ def test_aliases
+ assert_instance_of(Hash, Encoding.aliases)
+ Encoding.aliases.each do |k, v|
+ assert(Encoding.name_list.include?(k))
+ assert(Encoding.name_list.include?(v))
+ assert_instance_of(String, k)
+ assert_instance_of(String, v)
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_enum.rb b/trunk/test/ruby/test_enum.rb
new file mode 100644
index 0000000000..a739982963
--- /dev/null
+++ b/trunk/test/ruby/test_enum.rb
@@ -0,0 +1,259 @@
+require 'test/unit'
+require 'continuation'
+
+class TestEnumerable < Test::Unit::TestCase
+ def setup
+ @obj = Object.new
+ class << @obj
+ include Enumerable
+ def each
+ yield 1
+ yield 2
+ yield 3
+ yield 1
+ yield 2
+ end
+ end
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_grep
+ assert_equal([1, 2, 1, 2], @obj.grep(1..2))
+ a = []
+ @obj.grep(2) {|x| a << x }
+ assert_equal([2, 2], a)
+ end
+
+ def test_count
+ assert_equal(5, @obj.count)
+ assert_equal(2, @obj.count(1))
+ assert_equal(3, @obj.count {|x| x % 2 == 1 })
+ assert_equal(2, @obj.count(1) {|x| x % 2 == 1 })
+ assert_raise(ArgumentError) { @obj.count(0, 1) }
+ end
+
+ def test_find
+ assert_equal(2, @obj.find {|x| x % 2 == 0 })
+ assert_equal(nil, @obj.find {|x| false })
+ assert_equal(:foo, @obj.find(proc { :foo }) {|x| false })
+ end
+
+ def test_find_index
+ assert_equal(1, @obj.find_index(2))
+ assert_equal(1, @obj.find_index {|x| x % 2 == 0 })
+ assert_equal(nil, @obj.find_index {|x| false })
+ assert_raise(ArgumentError) { @obj.find_index(0, 1) }
+ end
+
+ def test_find_all
+ assert_equal([1, 3, 1], @obj.find_all {|x| x % 2 == 1 })
+ end
+
+ def test_reject
+ assert_equal([2, 3, 2], @obj.reject {|x| x < 2 })
+ end
+
+ def test_to_a
+ assert_equal([1, 2, 3, 1, 2], @obj.to_a)
+ end
+
+ def test_inject
+ assert_equal(12, @obj.inject {|z, x| z * x })
+ assert_equal(48, @obj.inject {|z, x| z * 2 + x })
+ assert_equal(12, @obj.inject(:*))
+ assert_equal(24, @obj.inject(2) {|z, x| z * x })
+ assert_equal(24, @obj.inject(2, :*) {|z, x| z * x })
+ end
+
+ def test_partition
+ assert_equal([[1, 3, 1], [2, 2]], @obj.partition {|x| x % 2 == 1 })
+ end
+
+ def test_group_by
+ h = { 1 => [1, 1], 2 => [2, 2], 3 => [3] }
+ assert_equal(h, @obj.group_by {|x| x })
+ end
+
+ def test_first
+ assert_equal(1, @obj.first)
+ assert_equal([1, 2, 3], @obj.first(3))
+ end
+
+ def test_sort
+ assert_equal([1, 1, 2, 2, 3], @obj.sort)
+ end
+
+ def test_sort_by
+ assert_equal([3, 2, 2, 1, 1], @obj.sort_by {|x| -x })
+ end
+
+ def test_all
+ assert_equal(true, @obj.all? {|x| x <= 3 })
+ assert_equal(false, @obj.all? {|x| x < 3 })
+ assert_equal(true, @obj.all?)
+ assert_equal(false, [true, true, false].all?)
+ end
+
+ def test_any
+ assert_equal(true, @obj.any? {|x| x >= 3 })
+ assert_equal(false, @obj.any? {|x| x > 3 })
+ assert_equal(true, @obj.any?)
+ assert_equal(false, [false, false, false].any?)
+ end
+
+ def test_one
+ assert(@obj.one? {|x| x == 3 })
+ assert(!(@obj.one? {|x| x == 1 }))
+ assert(!(@obj.one? {|x| x == 4 }))
+ assert(%w{ant bear cat}.one? {|word| word.length == 4})
+ assert(!(%w{ant bear cat}.one? {|word| word.length > 4}))
+ assert(!(%w{ant bear cat}.one? {|word| word.length < 4}))
+ assert(!([ nil, true, 99 ].one?))
+ assert([ nil, true, false ].one?)
+ end
+
+ def test_none
+ assert(@obj.none? {|x| x == 4 })
+ assert(!(@obj.none? {|x| x == 1 }))
+ assert(!(@obj.none? {|x| x == 3 }))
+ assert(%w{ant bear cat}.none? {|word| word.length == 5})
+ assert(!(%w{ant bear cat}.none? {|word| word.length >= 4}))
+ assert([].none?)
+ assert([nil].none?)
+ assert([nil,false].none?)
+ end
+
+ def test_min
+ assert_equal(1, @obj.min)
+ assert_equal(3, @obj.min {|a,b| b <=> a })
+ a = %w(albatross dog horse)
+ assert_equal("albatross", a.min)
+ assert_equal("dog", a.min {|a,b| a.length <=> b.length })
+ assert_equal(1, [3,2,1].min)
+ end
+
+ def test_max
+ assert_equal(3, @obj.max)
+ assert_equal(1, @obj.max {|a,b| b <=> a })
+ a = %w(albatross dog horse)
+ assert_equal("horse", a.max)
+ assert_equal("albatross", a.max {|a,b| a.length <=> b.length })
+ assert_equal(1, [3,2,1].max{|a,b| b <=> a })
+ end
+
+ def test_minmax
+ assert_equal([1, 3], @obj.minmax)
+ assert_equal([3, 1], @obj.minmax {|a,b| b <=> a })
+ a = %w(albatross dog horse)
+ assert_equal(["albatross", "horse"], a.minmax)
+ assert_equal(["dog", "albatross"], a.minmax {|a,b| a.length <=> b.length })
+ assert_equal([1, 3], [2,3,1].minmax)
+ assert_equal([3, 1], [2,3,1].minmax {|a,b| b <=> a })
+ end
+
+ def test_min_by
+ assert_equal(3, @obj.min_by {|x| -x })
+ a = %w(albatross dog horse)
+ assert_equal("dog", a.min_by {|x| x.length })
+ assert_equal(3, [2,3,1].min_by {|x| -x })
+ end
+
+ def test_max_by
+ assert_equal(1, @obj.max_by {|x| -x })
+ a = %w(albatross dog horse)
+ assert_equal("albatross", a.max_by {|x| x.length })
+ assert_equal(1, [2,3,1].max_by {|x| -x })
+ end
+
+ def test_minmax_by
+ assert_equal([3, 1], @obj.minmax_by {|x| -x })
+ a = %w(albatross dog horse)
+ assert_equal(["dog", "albatross"], a.minmax_by {|x| x.length })
+ assert_equal([3, 1], [2,3,1].minmax_by {|x| -x })
+ end
+
+ def test_member
+ assert(@obj.member?(1))
+ assert(!(@obj.member?(4)))
+ assert([1,2,3].member?(1))
+ assert(!([1,2,3].member?(4)))
+ end
+
+ def test_each_with_index
+ a = []
+ @obj.each_with_index {|x, i| a << [x, i] }
+ assert_equal([[1,0],[2,1],[3,2],[1,3],[2,4]], a)
+
+ hash = Hash.new
+ %w(cat dog wombat).each_with_index do |item, index|
+ hash[item] = index
+ end
+ assert_equal({"cat"=>0, "wombat"=>2, "dog"=>1}, hash)
+ end
+
+ def test_zip
+ assert_equal([[1,1],[2,2],[3,3],[1,1],[2,2]], @obj.zip(@obj))
+ a = []
+ @obj.zip([:a, :b, :c]) {|x,y| a << [x, y] }
+ assert_equal([[1,:a],[2,:b],[3,:c],[1,nil],[2,nil]], a)
+ end
+
+ def test_take
+ assert_equal([1,2,3], @obj.take(3))
+ end
+
+ def test_take_while
+ assert_equal([1,2], @obj.take_while {|x| x <= 2})
+ end
+
+ def test_drop
+ assert_equal([3,1,2], @obj.drop(2))
+ end
+
+ def test_drop_while
+ assert_equal([3,1,2], @obj.drop_while {|x| x <= 2})
+ end
+
+ def test_cycle
+ assert_equal([1,2,3,1,2,1,2,3,1,2], @obj.cycle.take(10))
+ end
+
+ def test_callcc
+ assert_raise(RuntimeError) do
+ c = nil
+ @obj.sort_by {|x| callcc {|c2| c ||= c2 }; x }
+ c.call
+ end
+
+ assert_raise(RuntimeError) do
+ c = nil
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:<=>) do |x|
+ callcc {|c2| c ||= c2 }
+ 0
+ end
+ end
+ [o, o].sort_by {|x| x }
+ c.call
+ end
+
+ assert_raise(RuntimeError) do
+ c = nil
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:<=>) do |x|
+ callcc {|c2| c ||= c2 }
+ 0
+ end
+ end
+ [o, o, o].sort_by {|x| x }
+ c.call
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_enumerator.rb b/trunk/test/ruby/test_enumerator.rb
new file mode 100644
index 0000000000..d1e75208f8
--- /dev/null
+++ b/trunk/test/ruby/test_enumerator.rb
@@ -0,0 +1,125 @@
+require 'test/unit'
+
+class TestEnumerator < Test::Unit::TestCase
+ def setup
+ @obj = Object.new
+ class << @obj
+ include Enumerable
+ def foo(*a)
+ a.each {|x| yield x }
+ end
+ end
+ end
+
+ def enum_test obj
+ i = 0
+ obj.map{|e|
+ e
+ }.sort
+ end
+
+ def test_iterators
+ assert_equal [0, 1, 2], enum_test(3.times)
+ assert_equal [:x, :y, :z], enum_test([:x, :y, :z].each)
+ assert_equal [[:x, 1], [:y, 2]], enum_test({:x=>1, :y=>2})
+ end
+
+ ## Enumerator as Iterator
+
+ def test_next
+ e = 3.times
+ 3.times{|i|
+ assert_equal i, e.next
+ }
+ assert_raise(StopIteration){e.next}
+ end
+
+ def test_loop
+ e = 3.times
+ i = 0
+ loop{
+ assert_equal(i, e.next)
+ i += 1
+ }
+ end
+
+ def test_nested_itaration
+ def (o = Object.new).each
+ yield :ok1
+ yield [:ok2, :x].each.next
+ end
+ e = o.to_enum
+ assert_equal :ok1, e.next
+ assert_equal :ok2, e.next
+ assert_raise(StopIteration){e.next}
+ end
+
+
+ def test_initialize
+ assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a)
+ assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a)
+ assert_raise(ArgumentError) { Enumerator.new }
+ end
+
+ def test_initialize_copy
+ assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).dup.to_a)
+ e = @obj.to_enum(:foo, 1, 2, 3)
+ assert_nothing_raised { assert_equal(1, e.next) }
+ assert_raise(TypeError) { e.dup }
+ end
+
+ def test_gc
+ assert_nothing_raised do
+ 1.times do
+ foo = [1,2,3].to_enum
+ GC.start
+ end
+ GC.start
+ end
+ end
+
+ def test_slice
+ assert_equal([[1,2,3],[4,5,6],[7,8,9],[10]], (1..10).each_slice(3).to_a)
+ end
+
+ def test_cons
+ a = [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [7,8,9], [8,9,10]]
+ assert_equal(a, (1..10).each_cons(3).to_a)
+ end
+
+ def test_with_index
+ assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
+ end
+
+ def test_with_memo
+ r = 1..10
+ return unless r.each.respond_to? :with_memo
+ assert_equal([55, 3628800], (1..10).each.with_memo([0,1]) {|i, memo|
+ memo[0] += i
+ memo[1] *= i
+ })
+
+ a = [2,5,2,1,5,3,4,2,1,0]
+ a.delete_if.with_memo({}) {|i, seen|
+ if seen.key?(i)
+ true
+ else
+ seen[i] = true
+ false
+ end
+ }
+ assert_equal([2, 5, 1, 3, 4, 0], a)
+ end
+
+ def test_next_rewind
+ e = @obj.to_enum(:foo, 1, 2, 3)
+ assert_equal(1, e.next)
+ assert_equal(2, e.next)
+ e.rewind
+ assert_equal(1, e.next)
+ assert_equal(2, e.next)
+ assert_equal(3, e.next)
+ assert_raise(StopIteration) { e.next }
+ end
+end
+
diff --git a/trunk/test/ruby/test_env.rb b/trunk/test/ruby/test_env.rb
new file mode 100644
index 0000000000..28f0e87b59
--- /dev/null
+++ b/trunk/test/ruby/test_env.rb
@@ -0,0 +1,350 @@
+require 'test/unit'
+
+class TestEnv < Test::Unit::TestCase
+ IGNORE_CASE = /djgpp|bccwin|mswin|mingw/ =~ RUBY_PLATFORM
+ PATH_ENV = /human68k/ =~ RUBY_PLATFORM ? "path" : "PATH"
+
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ @backup = ENV.to_hash
+ ENV.delete('test')
+ ENV.delete('TEST')
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ ENV.clear
+ @backup.each {|k, v| ENV[k] = v }
+ end
+
+ def test_bracket
+ assert_nil(ENV['test'])
+ assert_nil(ENV['TEST'])
+ ENV['test'] = 'foo'
+ assert_equal('foo', ENV['test'])
+ if IGNORE_CASE
+ assert_equal('foo', ENV['TEST'])
+ else
+ assert_nil(ENV['TEST'])
+ end
+ ENV['TEST'] = 'bar'
+ assert_equal('bar', ENV['TEST'])
+ if IGNORE_CASE
+ assert_equal('bar', ENV['test'])
+ else
+ assert_equal('foo', ENV['test'])
+ end
+
+ assert_raises(TypeError) {
+ tmp = ENV[1]
+ }
+ assert_raises(TypeError) {
+ ENV[1] = 'foo'
+ }
+ assert_raises(TypeError) {
+ ENV['test'] = 0
+ }
+ end
+
+ def test_has_value
+ val = 'a'
+ val.succ! while ENV.has_value?(val) && ENV.has_value?(val.upcase)
+ ENV['test'] = val[0...-1]
+
+ assert_equal(false, ENV.has_value?(val))
+ assert_equal(false, ENV.has_value?(val.upcase))
+ ENV['test'] = val
+ assert_equal(true, ENV.has_value?(val))
+ assert_equal(false, ENV.has_value?(val.upcase))
+ ENV['test'] = val.upcase
+ assert_equal(false, ENV.has_value?(val))
+ assert_equal(true, ENV.has_value?(val.upcase))
+ end
+
+ def test_key
+ val = 'a'
+ val.succ! while ENV.has_value?(val) && ENV.has_value?(val.upcase)
+ ENV['test'] = val[0...-1]
+
+ assert_nil(ENV.key(val))
+ assert_nil(ENV.key(val.upcase))
+ ENV['test'] = val
+ if IGNORE_CASE
+ assert_equal('TEST', ENV.key(val).upcase)
+ else
+ assert_equal('test', ENV.key(val))
+ end
+ assert_nil(ENV.key(val.upcase))
+ ENV['test'] = val.upcase
+ assert_nil(ENV.key(val))
+ if IGNORE_CASE
+ assert_equal('TEST', ENV.key(val.upcase).upcase)
+ else
+ assert_equal('test', ENV.key(val.upcase))
+ end
+ end
+
+ def test_delete
+ assert_raise(ArgumentError) { ENV.delete("foo\0bar") }
+ assert_nil(ENV.delete("TEST"))
+ assert_nothing_raised { ENV.delete(PATH_ENV) }
+ end
+
+ def test_getenv
+ assert_raise(ArgumentError) { ENV["foo\0bar"] }
+ ENV[PATH_ENV] = ""
+ assert_equal("", ENV[PATH_ENV])
+ end
+
+ def test_fetch
+ ENV["test"] = "foo"
+ assert_equal("foo", ENV.fetch("test"))
+ ENV.delete("test")
+ assert_raise(KeyError) { ENV.fetch("test") }
+ assert_equal("foo", ENV.fetch("test", "foo"))
+ assert_equal("bar", ENV.fetch("test") { "bar" })
+ assert_equal("bar", ENV.fetch("test", "foo") { "bar" })
+ assert_raise(ArgumentError) { ENV.fetch("foo\0bar") }
+ assert_nothing_raised { ENV.fetch(PATH_ENV, "foo") }
+ ENV[PATH_ENV] = ""
+ assert_equal("", ENV.fetch(PATH_ENV))
+ end
+
+ def test_aset
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ ENV["test"] = "foo"
+ end.join
+ end
+ assert_raise(TypeError) { ENV["test"] = nil }
+ assert_raise(ArgumentError) { ENV["foo\0bar"] = "test" }
+ assert_raise(ArgumentError) { ENV["test"] = "foo\0bar" }
+ ENV[PATH_ENV] = "/tmp/".taint
+ assert_equal("/tmp/", ENV[PATH_ENV])
+ end
+
+ def test_keys
+ a = nil
+ assert_block { a = ENV.keys }
+ assert_kind_of(Array, a)
+ a.each {|k| assert_kind_of(String, k) }
+ end
+
+ def test_each_key
+ ENV.each_key {|k| assert_kind_of(String, k) }
+ end
+
+ def test_values
+ a = nil
+ assert_block { a = ENV.values }
+ assert_kind_of(Array, a)
+ a.each {|k| assert_kind_of(String, k) }
+ end
+
+ def test_each_value
+ ENV.each_value {|k| assert_kind_of(String, k) }
+ end
+
+ def test_each_pair
+ ENV.each_pair do |k, v|
+ assert_kind_of(String, k)
+ assert_kind_of(String, v)
+ end
+ end
+
+ def test_reject_bang
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.reject! {|k, v| IGNORE_CASE ? k.upcase == "TEST" : k == "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ assert_equal(h1, h2)
+
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.delete_if {|k, v| IGNORE_CASE ? k.upcase == "TEST" : k == "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ assert_equal(h1, h2)
+ end
+
+ def test_values_at
+ ENV["test"] = "foo"
+ assert_equal(["foo", "foo"], ENV.values_at("test", "test"))
+ end
+
+ def test_select
+ ENV["test"] = "foo"
+ h = ENV.select {|k| IGNORE_CASE ? k.upcase == "TEST" : k == "test" }
+ assert_equal(1, h.size)
+ k = h.keys.first
+ v = h.values.first
+ if IGNORE_CASE
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ end
+
+ def test_clear
+ ENV.clear
+ assert_equal(0, ENV.size)
+ end
+
+ def test_to_s
+ assert_equal("ENV", ENV.to_s)
+ end
+
+ def test_inspect
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ s = ENV.inspect
+ if IGNORE_CASE
+ s = s.upcase
+ assert(s == '{"FOO"=>"BAR", "BAZ"=>"QUX"}' || s == '{"BAZ"=>"QUX", "FOO"=>"BAR"}')
+ else
+ assert(s == '{"foo"=>"bar", "baz"=>"qux"}' || s == '{"baz"=>"qux", "foo"=>"bar"}')
+ end
+ end
+
+ def test_to_a
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ a = ENV.to_a
+ assert_equal(2, a.size)
+ if IGNORE_CASE
+ a = a.map {|x| x.map {|y| y.upcase } }
+ assert(a == [%w(FOO BAR), %w(BAZ QUX)] || a == [%w(BAZ QUX), %w(FOO BAR)])
+ else
+ assert(a == [%w(foo bar), %w(baz qux)] || a == [%w(baz qux), %w(foo bar)])
+ end
+ end
+
+ def test_rehash
+ assert_nil(ENV.rehash)
+ end
+
+ def test_size
+ s = ENV.size
+ ENV["test"] = "foo"
+ assert_equal(s + 1, ENV.size)
+ end
+
+ def test_empty_p
+ ENV.clear
+ assert(ENV.empty?)
+ ENV["test"] = "foo"
+ assert(!ENV.empty?)
+ end
+
+ def test_has_key
+ assert(!ENV.has_key?("test"))
+ ENV["test"] = "foo"
+ assert(ENV.has_key?("test"))
+ assert_raise(ArgumentError) { ENV.has_key?("foo\0bar") }
+ end
+
+ def test_assoc
+ assert_nil(ENV.assoc("test"))
+ ENV["test"] = "foo"
+ k, v = ENV.assoc("test")
+ if IGNORE_CASE
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ assert_raise(ArgumentError) { ENV.assoc("foo\0bar") }
+ end
+
+ def test_has_value2
+ ENV.clear
+ assert(!ENV.has_value?("foo"))
+ ENV["test"] = "foo"
+ assert(ENV.has_value?("foo"))
+ end
+
+ def test_rassoc
+ ENV.clear
+ assert_nil(ENV.rassoc("foo"))
+ ENV["foo"] = "bar"
+ ENV["test"] = "foo"
+ ENV["baz"] = "qux"
+ k, v = ENV.rassoc("foo")
+ if IGNORE_CASE
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ end
+
+ def test_to_hash
+ h = {}
+ ENV.each {|k, v| h[k] = v }
+ assert_equal(h, ENV.to_hash)
+ end
+
+ def test_reject
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ h2 = ENV.reject {|k, v| IGNORE_CASE ? k.upcase == "TEST" : k == "test" }
+ assert_equal(h1, h2)
+ end
+
+ def check(as, bs)
+ if IGNORE_CASE
+ as = as.map {|xs| xs.map {|x| x.upcase } }
+ bs = bs.map {|xs| xs.map {|x| x.upcase } }
+ end
+ assert_equal(as.sort, bs.sort)
+ end
+
+ def test_shift
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ a = ENV.shift
+ b = ENV.shift
+ check([a, b], [%w(foo bar), %w(baz qux)])
+ assert_nil(ENV.shift)
+ end
+
+ def test_invert
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ check(ENV.invert.to_a, [%w(bar foo), %w(qux baz)])
+ end
+
+ def test_replace
+ ENV["foo"] = "xxx"
+ ENV.replace({"foo"=>"bar", "baz"=>"qux"})
+ check(ENV.to_hash.to_a, [%w(foo bar), %w(baz qux)])
+ end
+
+ def test_update
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV.update({"baz"=>"quux","a"=>"b"})
+ check(ENV.to_hash.to_a, [%w(foo bar), %w(baz quux), %w(a b)])
+
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| v1 ? k + "_" + v1 + "_" + v2 : v2 }
+ check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
+ end
+end
diff --git a/trunk/test/ruby/test_eval.rb b/trunk/test/ruby/test_eval.rb
new file mode 100644
index 0000000000..23d34a5f81
--- /dev/null
+++ b/trunk/test/ruby/test_eval.rb
@@ -0,0 +1,394 @@
+require 'test/unit'
+
+class TestEval < Test::Unit::TestCase
+
+ @ivar = 12
+ @@cvar = 13
+ $gvar__eval = 14
+ Const = 15
+
+ def test_eval_basic
+ assert_equal nil, eval("nil")
+ assert_equal true, eval("true")
+ assert_equal false, eval("false")
+ assert_equal self, eval("self")
+ assert_equal 1, eval("1")
+ assert_equal :sym, eval(":sym")
+
+ assert_equal 11, eval("11")
+ @ivar = 12
+ assert_equal 12, eval("@ivar")
+ assert_equal 13, eval("@@cvar")
+ assert_equal 14, eval("$gvar__eval")
+ assert_equal 15, eval("Const")
+
+ assert_equal 16, eval("7 + 9")
+ assert_equal 17, eval("17.to_i")
+ assert_equal "18", eval(%q("18"))
+ assert_equal "19", eval(%q("1#{9}"))
+
+ 1.times {
+ assert_equal 12, eval("@ivar")
+ assert_equal 13, eval("@@cvar")
+ assert_equal 14, eval("$gvar__eval")
+ assert_equal 15, eval("Const")
+ }
+ end
+
+ def test_eval_binding_basic
+ assert_equal nil, eval("nil", binding())
+ assert_equal true, eval("true", binding())
+ assert_equal false, eval("false", binding())
+ assert_equal self, eval("self", binding())
+ assert_equal 1, eval("1", binding())
+ assert_equal :sym, eval(":sym", binding())
+
+ assert_equal 11, eval("11", binding())
+ @ivar = 12
+ assert_equal 12, eval("@ivar", binding())
+ assert_equal 13, eval("@@cvar", binding())
+ assert_equal 14, eval("$gvar__eval", binding())
+ assert_equal 15, eval("Const", binding())
+
+ assert_equal 16, eval("7 + 9", binding())
+ assert_equal 17, eval("17.to_i", binding())
+ assert_equal "18", eval(%q("18"), binding())
+ assert_equal "19", eval(%q("1#{9}"), binding())
+
+ 1.times {
+ assert_equal 12, eval("@ivar")
+ assert_equal 13, eval("@@cvar")
+ assert_equal 14, eval("$gvar__eval")
+ assert_equal 15, eval("Const")
+ }
+ end
+
+ def test_module_eval_string_basic
+ c = self.class
+ assert_equal nil, c.module_eval("nil")
+ assert_equal true, c.module_eval("true")
+ assert_equal false, c.module_eval("false")
+ assert_equal c, c.module_eval("self")
+ assert_equal :sym, c.module_eval(":sym")
+ assert_equal 11, c.module_eval("11")
+ @ivar = 12
+ assert_equal 12, c.module_eval("@ivar")
+ assert_equal 13, c.module_eval("@@cvar")
+ assert_equal 14, c.module_eval("$gvar__eval")
+ assert_equal 15, c.module_eval("Const")
+ assert_equal 16, c.module_eval("7 + 9")
+ assert_equal 17, c.module_eval("17.to_i")
+ assert_equal "18", c.module_eval(%q("18"))
+ assert_equal "19", c.module_eval(%q("1#{9}"))
+
+ @ivar = 12
+ 1.times {
+ assert_equal 12, c.module_eval("@ivar")
+ assert_equal 13, c.module_eval("@@cvar")
+ assert_equal 14, c.module_eval("$gvar__eval")
+ assert_equal 15, c.module_eval("Const")
+ }
+ end
+
+ def test_module_eval_block_basic
+ c = self.class
+ assert_equal nil, c.module_eval { nil }
+ assert_equal true, c.module_eval { true }
+ assert_equal false, c.module_eval { false }
+ assert_equal c, c.module_eval { self }
+ assert_equal :sym, c.module_eval { :sym }
+ assert_equal 11, c.module_eval { 11 }
+ @ivar = 12
+ assert_equal 12, c.module_eval { @ivar }
+ assert_equal 13, c.module_eval { @@cvar }
+ assert_equal 14, c.module_eval { $gvar__eval }
+ assert_equal 15, c.module_eval { Const }
+ assert_equal 16, c.module_eval { 7 + 9 }
+ assert_equal 17, c.module_eval { "17".to_i }
+ assert_equal "18", c.module_eval { "18" }
+ assert_equal "19", c.module_eval { "1#{9}" }
+
+ @ivar = 12
+ 1.times {
+ assert_equal 12, c.module_eval { @ivar }
+ assert_equal 13, c.module_eval { @@cvar }
+ assert_equal 14, c.module_eval { $gvar__eval }
+ assert_equal 15, c.module_eval { Const }
+ }
+ end
+
+ def forall_TYPE(mid)
+ objects = [Object.new, [], nil, true, false, 77, :sym] # TODO: check
+ objects.each do |obj|
+ obj.instance_variable_set :@ivar, 12
+ send mid, obj
+ end
+ end
+
+ def test_instance_eval_string_basic
+ forall_TYPE :instance_eval_string_basic_i
+ end
+
+ def instance_eval_string_basic_i(o)
+ assert_equal nil, o.instance_eval("nil")
+ assert_equal true, o.instance_eval("true")
+ assert_equal false, o.instance_eval("false")
+ assert_equal o, o.instance_eval("self")
+ assert_equal 1, o.instance_eval("1")
+ assert_equal :sym, o.instance_eval(":sym")
+
+ assert_equal 11, o.instance_eval("11")
+ assert_equal 12, o.instance_eval("@ivar")
+ assert_equal 13, o.instance_eval("@@cvar")
+ assert_equal 14, o.instance_eval("$gvar__eval")
+ assert_equal 15, o.instance_eval("Const")
+ assert_equal 16, o.instance_eval("7 + 9")
+ assert_equal 17, o.instance_eval("17.to_i")
+ assert_equal "18", o.instance_eval(%q("18"))
+ assert_equal "19", o.instance_eval(%q("1#{9}"))
+
+ 1.times {
+ assert_equal 12, o.instance_eval("@ivar")
+ assert_equal 13, o.instance_eval("@@cvar")
+ assert_equal 14, o.instance_eval("$gvar__eval")
+ assert_equal 15, o.instance_eval("Const")
+ }
+ end
+
+ def test_instance_eval_block_basic
+ forall_TYPE :instance_eval_block_basic_i
+ end
+
+ def instance_eval_block_basic_i(o)
+ assert_equal nil, o.instance_eval { nil }
+ assert_equal true, o.instance_eval { true }
+ assert_equal false, o.instance_eval { false }
+ assert_equal o, o.instance_eval { self }
+ assert_equal 1, o.instance_eval { 1 }
+ assert_equal :sym, o.instance_eval { :sym }
+
+ assert_equal 11, o.instance_eval { 11 }
+ assert_equal 12, o.instance_eval { @ivar }
+ assert_equal 13, o.instance_eval { @@cvar }
+ assert_equal 14, o.instance_eval { $gvar__eval }
+ assert_equal 15, o.instance_eval { Const }
+ assert_equal 16, o.instance_eval { 7 + 9 }
+ assert_equal 17, o.instance_eval { 17.to_i }
+ assert_equal "18", o.instance_eval { "18" }
+ assert_equal "19", o.instance_eval { "1#{9}" }
+
+ 1.times {
+ assert_equal 12, o.instance_eval { @ivar }
+ assert_equal 13, o.instance_eval { @@cvar }
+ assert_equal 14, o.instance_eval { $gvar__eval }
+ assert_equal 15, o.instance_eval { Const }
+ }
+ end
+
+ def test_instance_eval_cvar
+ [Object.new, [], 7, :sym, true, false, nil].each do |obj|
+ assert_equal(13, obj.instance_eval("@@cvar"))
+ assert_equal(13, obj.instance_eval{@@cvar})
+ # assert_raise(NameError){obj.instance_eval("@@cvar")}
+ # assert_raise(NameError){obj.instance_eval{@@cvar}}
+ end
+ end
+
+ #
+ # From ruby/test/ruby/test_eval.rb
+ #
+
+ def test_ev
+ local1 = "local1"
+ lambda {
+ local2 = "local2"
+ return binding
+ }.call
+ end
+
+ def test_eval_orig
+ assert_nil(eval(""))
+ $bad=false
+ eval 'while false; $bad = true; print "foo\n" end'
+ assert(!$bad)
+
+ assert(eval('TRUE'))
+ assert(eval('true'))
+ assert(!eval('NIL'))
+ assert(!eval('nil'))
+ assert(!eval('FALSE'))
+ assert(!eval('false'))
+
+ $foo = 'assert(true)'
+ begin
+ eval $foo
+ rescue
+ assert(false)
+ end
+
+ assert_equal('assert(true)', eval("$foo"))
+ assert_equal(true, eval("true"))
+ i = 5
+ assert(eval("i == 5"))
+ assert_equal(5, eval("i"))
+ assert(eval("defined? i"))
+
+ $x = test_ev
+ assert_equal("local1", eval("local1", $x)) # normal local var
+ assert_equal("local2", eval("local2", $x)) # nested local var
+ $bad = true
+ begin
+ p eval("local1")
+ rescue NameError # must raise error
+ $bad = false
+ end
+ assert(!$bad)
+
+ # !! use class_eval to avoid nested definition
+ self.class.class_eval %q(
+ module EvTest
+ EVTEST1 = 25
+ evtest2 = 125
+ $x = binding
+ end
+ )
+ assert_equal(25, eval("EVTEST1", $x)) # constant in module
+ assert_equal(125, eval("evtest2", $x)) # local var in module
+ $bad = true
+ begin
+ eval("EVTEST1")
+ rescue NameError # must raise error
+ $bad = false
+ end
+ assert(!$bad)
+
+ if false
+ # Ruby 2.0 doesn't see Proc as Binding
+ x = proc{}
+ eval "i4 = 1", x
+ assert_equal(1, eval("i4", x))
+ x = proc{proc{}}.call
+ eval "i4 = 22", x
+ assert_equal(22, eval("i4", x))
+ $x = []
+ x = proc{proc{}}.call
+ eval "(0..9).each{|i5| $x[i5] = proc{i5*2}}", x
+ assert_equal(8, $x[4].call)
+ end
+
+ x = binding
+ eval "i = 1", x
+ assert_equal(1, eval("i", x))
+ x = proc{binding}.call
+ eval "i = 22", x
+ assert_equal(22, eval("i", x))
+ $x = []
+ x = proc{binding}.call
+ eval "(0..9).each{|i5| $x[i5] = proc{i5*2}}", x
+ assert_equal(8, $x[4].call)
+ x = proc{binding}.call
+ eval "for i6 in 1..1; j6=i6; end", x
+ assert(eval("defined? i6", x))
+ assert(eval("defined? j6", x))
+
+ proc {
+ p = binding
+ eval "foo11 = 1", p
+ foo22 = 5
+ proc{foo11=22}.call
+ proc{foo22=55}.call
+ # assert_equal(eval("foo11"), eval("foo11", p))
+ # assert_equal(1, eval("foo11"))
+ assert_equal(eval("foo22"), eval("foo22", p))
+ assert_equal(55, eval("foo22"))
+ }.call
+
+ if false
+ # Ruby 2.0 doesn't see Proc as Binding
+ p1 = proc{i7 = 0; proc{i7}}.call
+ assert_equal(0, p1.call)
+ eval "i7=5", p1
+ assert_equal(5, p1.call)
+ assert(!defined?(i7))
+ end
+
+ if false
+ # Ruby 2.0 doesn't see Proc as Binding
+ p1 = proc{i7 = 0; proc{i7}}.call
+ i7 = nil
+ assert_equal(0, p1.call)
+ eval "i7=1", p1
+ assert_equal(1, p1.call)
+ eval "i7=5", p1
+ assert_equal(5, p1.call)
+ assert_nil(i7)
+ end
+ end
+
+ def test_nil_instance_eval_cvar
+ def nil.test_binding
+ binding
+ end
+ bb = eval("nil.instance_eval \"binding\"", nil.test_binding)
+ assert_raise(NameError, "[ruby-dev:24103]") { eval("@@a", bb) }
+ class << nil
+ remove_method :test_binding
+ end
+ end
+
+ def test_fixnum_instance_eval_cvar
+ assert_raise(NameError, "[ruby-dev:24213]") { 1.instance_eval "@@a" }
+ end
+
+ def test_cvar_scope_with_instance_eval
+ # TODO: check
+ Fixnum.class_eval "@@test_cvar_scope_with_instance_eval = 1" # depends on [ruby-dev:24229]
+ @@test_cvar_scope_with_instance_eval = 4
+ assert_equal(4, 1.instance_eval("@@test_cvar_scope_with_instance_eval"), "[ruby-dev:24223]")
+ Fixnum.__send__(:remove_class_variable, :@@test_cvar_scope_with_instance_eval)
+ end
+
+ def test_eval_and_define_method
+ assert_nothing_raised("[ruby-dev:24228]") {
+ def temporally_method_for_test_eval_and_define_method(&block)
+ lambda {
+ class << Object.new; self end.send(:define_method, :zzz, &block)
+ }
+ end
+ v = eval("temporally_method_for_test_eval_and_define_method {}")
+ {}[0] = {}
+ v.call
+ }
+ end
+
+ def test_define_method_block
+ cc = Class.new do
+ define_method(:foo) {|&block|
+ block.call if block
+ }
+ end
+
+ c = cc.new
+ x = "ng"
+ c.foo() {x = "ok"}
+ assert_equal("ok", x)
+ end
+
+ def test_eval_using_integer_as_binding
+ assert_raise(TypeError) { eval("", 1) }
+ end
+
+ def test_eval_raise
+ assert_raise(RuntimeError) { eval("raise ''") }
+ end
+
+ def test_eval_using_untainted_binding_under_safe4
+ assert_raise(SecurityError) do
+ Thread.new do
+ b = binding
+ $SAFE = 4
+ eval("", b)
+ end.join
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_exception.rb b/trunk/test/ruby/test_exception.rb
new file mode 100644
index 0000000000..3300fcdd74
--- /dev/null
+++ b/trunk/test/ruby/test_exception.rb
@@ -0,0 +1,226 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestException < Test::Unit::TestCase
+ def test_exception
+ begin
+ raise "this must be handled"
+ assert(false)
+ rescue
+ assert(true)
+ end
+
+ $bad = true
+ begin
+ raise "this must be handled no.2"
+ rescue
+ if $bad
+ $bad = false
+ retry
+ assert(false)
+ end
+ end
+ assert(true)
+
+ # exception in rescue clause
+ $string = "this must be handled no.3"
+ e = assert_raises(RuntimeError) do
+ begin
+ raise "exception in rescue clause"
+ rescue
+ raise $string
+ end
+ assert(false)
+ end
+ assert_equal($string, e.message)
+
+ # exception in ensure clause
+ $string = "exception in ensure clause"
+ e = assert_raises(RuntimeError) do
+ begin
+ raise "this must be handled no.4"
+ ensure
+ assert_instance_of(RuntimeError, $!)
+ assert_equal("this must be handled no.4", $!.message)
+ raise "exception in ensure clause"
+ end
+ assert(false)
+ end
+ assert_equal($string, e.message)
+
+ $bad = true
+ begin
+ begin
+ raise "this must be handled no.5"
+ ensure
+ $bad = false
+ end
+ rescue
+ end
+ assert(!$bad)
+
+ $bad = true
+ begin
+ begin
+ raise "this must be handled no.6"
+ ensure
+ $bad = false
+ end
+ rescue
+ end
+ assert(!$bad)
+
+ $bad = true
+ while true
+ begin
+ break
+ ensure
+ $bad = false
+ end
+ end
+ assert(!$bad)
+
+ assert(catch(:foo) {
+ loop do
+ loop do
+ throw :foo, true
+ break
+ end
+ break
+ assert(false) # should no reach here
+ end
+ false
+ })
+
+ end
+
+ def test_else
+ begin
+ assert(true)
+ rescue
+ assert(false)
+ else
+ assert(true)
+ end
+
+ begin
+ assert(true)
+ raise
+ assert(false)
+ rescue
+ assert(true)
+ else
+ assert(false)
+ end
+
+ begin
+ assert(true)
+ begin
+ assert(true)
+ rescue
+ assert(false)
+ else
+ assert(true)
+ end
+ assert(true)
+ rescue
+ assert(false)
+ else
+ assert(true)
+ end
+
+ begin
+ assert(true)
+ begin
+ assert(true)
+ raise
+ assert(false)
+ rescue
+ assert(true)
+ else
+ assert(false)
+ end
+ assert(true)
+ rescue
+ assert(false)
+ else
+ assert(true)
+ end
+
+ begin
+ assert(true)
+ begin
+ assert(true)
+ rescue
+ assert(false)
+ else
+ assert(true)
+ end
+ assert(true)
+ raise
+ assert(false)
+ rescue
+ assert(true)
+ else
+ assert(false)
+ end
+
+ begin
+ assert(true)
+ begin
+ assert(true)
+ raise
+ assert(false)
+ rescue
+ assert(true)
+ else
+ assert(false)
+ end
+ assert(true)
+ raise
+ assert(false)
+ rescue
+ assert(true)
+ else
+ assert(false)
+ end
+ end
+
+ def test_raise_with_wrong_number_of_arguments
+ assert_raise(TypeError) { raise nil }
+ assert_raise(TypeError) { raise 1, 1 }
+ assert_raise(ArgumentError) { raise 1, 1, 1, 1 }
+ end
+
+ def test_errat
+ assert_in_out_err([], "p $@", %w(nil), [])
+
+ assert_in_out_err([], "$@ = 1", [], /\$! not set \(ArgumentError\)$/)
+
+ assert_in_out_err([], <<-INPUT, [], /backtrace must be Array of String \(TypeError\)$/)
+ begin
+ raise
+ rescue
+ $@ = 1
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, [], /^foo: unhandled exception$/)
+ begin
+ raise
+ rescue
+ $@ = 'foo'
+ raise
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, [], /^foo: unhandled exception\s+from bar\s+from baz$/)
+ begin
+ raise
+ rescue
+ $@ = %w(foo bar baz)
+ raise
+ end
+ INPUT
+ end
+end
diff --git a/trunk/test/ruby/test_fiber.rb b/trunk/test/ruby/test_fiber.rb
new file mode 100644
index 0000000000..fc9a49919a
--- /dev/null
+++ b/trunk/test/ruby/test_fiber.rb
@@ -0,0 +1,164 @@
+require 'test/unit'
+require 'fiber'
+require 'continuation'
+
+class TestFiber < Test::Unit::TestCase
+ def test_normal
+ f = Fiber.current
+ assert_equal(:ok2,
+ Fiber.new{|e|
+ assert_equal(:ok1, e)
+ Fiber.yield :ok2
+ }.resume(:ok1)
+ )
+ assert_equal([:a, :b], Fiber.new{|a, b| [a, b]}.resume(:a, :b))
+ end
+
+ def test_term
+ assert_equal(:ok, Fiber.new{:ok}.resume)
+ assert_equal([:a, :b, :c, :d, :e],
+ Fiber.new{
+ Fiber.new{
+ Fiber.new{
+ Fiber.new{
+ [:a]
+ }.resume + [:b]
+ }.resume + [:c]
+ }.resume + [:d]
+ }.resume + [:e])
+ end
+
+ def test_many_fibers
+ max = 10000
+ assert_equal(max, max.times{
+ Fiber.new{}
+ })
+ assert_equal(max,
+ max.times{|i|
+ Fiber.new{
+ }.resume
+ }
+ )
+ end
+
+ def test_many_fibers_with_threads
+ max = 1000
+ @cnt = 0
+ (1..100).map{|ti|
+ Thread.new{
+ max.times{|i|
+ Fiber.new{
+ @cnt += 1
+ }.resume
+ }
+ }
+ }.each{|t|
+ t.join
+ }
+ assert_equal(:ok, :ok)
+ end
+
+ def test_error
+ assert_raise(ArgumentError){
+ Fiber.new # Fiber without block
+ }
+ assert_raise(FiberError){
+ f = Fiber.new{}
+ Thread.new{f.resume}.join # Fiber yielding across thread
+ }
+ assert_raise(FiberError){
+ f = Fiber.new{}
+ f.resume
+ f.resume
+ }
+ assert_raise(RuntimeError){
+ f = Fiber.new{
+ @c = callcc{|c| @c = c}
+ }.resume
+ @c.call # cross fiber callcc
+ }
+ assert_raise(RuntimeError){
+ Fiber.new{
+ raise
+ }.resume
+ }
+ assert_raise(FiberError){
+ Fiber.yield
+ }
+ assert_raise(FiberError){
+ fib = Fiber.new{
+ fib.resume
+ }
+ fib.resume
+ }
+ assert_raise(FiberError){
+ fib = Fiber.new{
+ Fiber.new{
+ fib.resume
+ }.resume
+ }
+ fib.resume
+ }
+ end
+
+ def test_return
+ assert_raise(LocalJumpError){
+ Fiber.new do
+ return
+ end.resume
+ }
+ end
+
+ def test_throw
+ assert_raise(ArgumentError){
+ Fiber.new do
+ throw :a
+ end.resume
+ }
+ end
+
+ def test_transfer
+ ary = []
+ f2 = nil
+ f1 = Fiber.new{
+ ary << f2.transfer(:foo)
+ :ok
+ }
+ f2 = Fiber.new{
+ ary << f1.transfer(:baz)
+ :ng
+ }
+ assert_equal(:ok, f1.transfer)
+ assert_equal([:baz], ary)
+ end
+
+ def test_tls
+ #
+ def tvar(var, val)
+ old = Thread.current[var]
+ begin
+ Thread.current[var] = val
+ yield
+ ensure
+ Thread.current[var] = old
+ end
+ end
+
+ fb = Fiber.new {
+ assert_equal(nil, Thread.current[:v]); tvar(:v, :x) {
+ assert_equal(:x, Thread.current[:v]); Fiber.yield
+ assert_equal(:x, Thread.current[:v]); }
+ assert_equal(nil, Thread.current[:v]); Fiber.yield
+ raise # unreachable
+ }
+
+ assert_equal(nil, Thread.current[:v]); tvar(:v,1) {
+ assert_equal(1, Thread.current[:v]); tvar(:v,3) {
+ assert_equal(3, Thread.current[:v]); fb.resume
+ assert_equal(3, Thread.current[:v]); }
+ assert_equal(1, Thread.current[:v]); }
+ assert_equal(nil, Thread.current[:v]); fb.resume
+ assert_equal(nil, Thread.current[:v]);
+ end
+end
+
diff --git a/trunk/test/ruby/test_file.rb b/trunk/test/ruby/test_file.rb
new file mode 100644
index 0000000000..f6fcf89a14
--- /dev/null
+++ b/trunk/test/ruby/test_file.rb
@@ -0,0 +1,122 @@
+require 'test/unit'
+require 'tempfile'
+require_relative 'ut_eof'
+
+class TestFile < Test::Unit::TestCase
+
+ # I don't know Ruby's spec about "unlink-before-close" exactly.
+ # This test asserts current behaviour.
+ def test_unlink_before_close
+ Dir.mktmpdir('rubytest-file') {|tmpdir|
+ filename = tmpdir + '/' + File.basename(__FILE__) + ".#{$$}"
+ w = File.open(filename, "w")
+ w << "foo"
+ w.close
+ r = File.open(filename, "r")
+ begin
+ if /(mswin|bccwin|mingw|emx)/ =~ RUBY_PLATFORM
+ assert_raise(Errno::EACCES) {File.unlink(filename)}
+ else
+ assert_nothing_raised {File.unlink(filename)}
+ end
+ ensure
+ r.close
+ File.unlink(filename) if File.exist?(filename)
+ end
+ }
+ end
+
+ include TestEOF
+ def open_file(content)
+ f = Tempfile.new("test-eof")
+ f << content
+ f.rewind
+ yield f
+ end
+ alias open_file_rw open_file
+
+ include TestEOF::Seek
+
+ def test_truncate_wbuf
+ f = Tempfile.new("test-truncate")
+ f.print "abc"
+ f.truncate(0)
+ f.print "def"
+ f.close
+ assert_equal("\0\0\0def", File.read(f.path), "[ruby-dev:24191]")
+ end
+
+ def test_truncate_rbuf
+ f = Tempfile.new("test-truncate")
+ f.puts "abc"
+ f.puts "def"
+ f.close
+ f.open
+ assert_equal("abc\n", f.gets)
+ f.truncate(3)
+ assert_equal(nil, f.gets, "[ruby-dev:24197]")
+ end
+
+ def test_truncate_beyond_eof
+ f = Tempfile.new("test-truncate")
+ f.print "abc"
+ f.truncate 10
+ assert_equal("\0" * 7, f.read(100), "[ruby-dev:24532]")
+ end
+
+ def test_read_all_extended_file
+ f = Tempfile.new("test-extended-file")
+ assert_nil(f.getc)
+ open(f.path, "w") {|g| g.print "a" }
+ assert_equal("a", f.read)
+ end
+
+ def test_gets_extended_file
+ f = Tempfile.new("test-extended-file")
+ assert_nil(f.getc)
+ open(f.path, "w") {|g| g.print "a" }
+ assert_equal("a", f.gets("a"))
+ end
+
+ def test_gets_para_extended_file
+ f = Tempfile.new("test-extended-file")
+ assert_nil(f.getc)
+ open(f.path, "w") {|g| g.print "\na" }
+ assert_equal("a", f.gets(""))
+ end
+
+ def test_each_byte_extended_file
+ f = Tempfile.new("test-extended-file")
+ assert_nil(f.getc)
+ open(f.path, "w") {|g| g.print "a" }
+ result = []
+ f.each_byte {|b| result << b.chr }
+ assert_equal([?a], result)
+ end
+
+ def test_getc_extended_file
+ f = Tempfile.new("test-extended-file")
+ assert_nil(f.getc)
+ open(f.path, "w") {|g| g.print "a" }
+ assert_equal(?a, f.getc)
+ end
+
+ def test_s_chown
+ assert_nothing_raised { File.chown -1, -1 }
+ assert_nothing_raised { File.chown nil, nil }
+ end
+
+ def test_chown
+ assert_nothing_raised {
+ File.open(__FILE__) {|f| f.chown -1, -1 }
+ }
+ assert_nothing_raised("[ruby-dev:27140]") {
+ File.open(__FILE__) {|f| f.chown nil, nil }
+ }
+ end
+
+ def test_uninitialized
+ assert_raise(TypeError) { File::Stat.allocate.readable? }
+ assert_nothing_raised { File::Stat.allocate.inspect }
+ end
+end
diff --git a/trunk/test/ruby/test_file_exhaustive.rb b/trunk/test/ruby/test_file_exhaustive.rb
new file mode 100644
index 0000000000..eda3669681
--- /dev/null
+++ b/trunk/test/ruby/test_file_exhaustive.rb
@@ -0,0 +1,726 @@
+require "test/unit"
+require "fileutils"
+require "tmpdir"
+
+class TestFileExhaustive < Test::Unit::TestCase
+ def setup
+ @dir = Dir.mktmpdir("rubytest-file")
+ File.chown(-1, Process.gid, @dir)
+ @file = make_tmp_filename("file")
+ @zerofile = make_tmp_filename("zerofile")
+ @nofile = make_tmp_filename("nofile")
+ @symlinkfile = make_tmp_filename("symlinkfile")
+ @hardlinkfile = make_tmp_filename("hardlinkfile")
+ make_file("foo", @file)
+ make_file("", @zerofile)
+ @time = Time.now
+ begin
+ File.symlink(@file, @symlinkfile)
+ rescue NotImplementedError
+ @symlinkfile = nil
+ end
+ begin
+ File.link(@file, @hardlinkfile)
+ rescue NotImplementedError, Errno::EINVAL # EINVAL for Windows Vista
+ @hardlinkfile = nil
+ end
+ end
+
+ def teardown
+ GC.start
+ FileUtils.remove_entry_secure @dir
+ end
+
+ def make_file(content, file = @file)
+ open(file, "w") {|fh| fh << content }
+ end
+
+ def make_tmp_filename(prefix)
+ @hardlinkfile = @dir + "/" + prefix + File.basename(__FILE__) + ".#{$$}.test"
+ end
+
+ def test_path
+ file = @file
+
+ assert_equal(file, File.new(file).path)
+ assert_equal(file, File.path(file))
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:to_path) { file }
+ end
+ assert_equal(file, File.path(o))
+ end
+
+ def assert_integer(n)
+ assert(n.is_a?(Integer), n.inspect + " is not Fixnum.")
+ end
+
+ def assert_integer_or_nil(n)
+ assert(n.is_a?(Integer) || n.equal?(nil), n.inspect + " is neither Fixnum nor nil.")
+ end
+
+ def test_stat
+ sleep(@time - Time.now + 1.1)
+ make_file("foo", @file + "2")
+ fs1, fs2 = File.stat(@file), File.stat(@file + "2")
+ assert_nothing_raised do
+ assert_equal(0, fs1 <=> fs1)
+ assert_equal(-1, fs1 <=> fs2)
+ assert_equal(1, fs2 <=> fs1)
+ assert_nil(fs1 <=> nil)
+ assert_integer(fs1.dev)
+ assert_integer_or_nil(fs1.rdev)
+ assert_integer_or_nil(fs1.dev_major)
+ assert_integer_or_nil(fs1.dev_minor)
+ assert_integer_or_nil(fs1.rdev_major)
+ assert_integer_or_nil(fs1.rdev_minor)
+ assert_integer(fs1.ino)
+ assert_integer(fs1.mode)
+ unless /emx/ =~ RUBY_PLATFORM
+ assert_equal(@hardlinkfile ? 2 : 1, fs1.nlink)
+ end
+ assert_integer(fs1.uid)
+ assert_integer(fs1.gid)
+ assert_equal(3, fs1.size)
+ assert_integer_or_nil(fs1.blksize)
+ assert_integer_or_nil(fs1.blocks)
+ assert_kind_of(Time, fs1.atime)
+ assert_kind_of(Time, fs1.mtime)
+ assert_kind_of(Time, fs1.ctime)
+ assert_kind_of(String, fs1.inspect)
+ end
+ assert_raise(Errno::ENOENT) { File.stat(@nofile) }
+ assert_kind_of(File::Stat, File.new(@file).stat)
+ assert_raise(Errno::ENOENT) { File.lstat(@nofile) }
+ assert_kind_of(File::Stat, File.new(@file).lstat)
+ end
+
+ def test_directory_p
+ assert(File.directory?(@dir))
+ assert(!(File.directory?(@file)))
+ assert(!(File.directory?(@nofile)))
+ end
+
+ def test_pipe_p ## xxx
+ assert(!(File.pipe?(@dir)))
+ assert(!(File.pipe?(@file)))
+ assert(!(File.pipe?(@nofile)))
+ end
+
+ def test_symlink_p
+ assert(!(File.symlink?(@dir)))
+ assert(!(File.symlink?(@file)))
+ assert(File.symlink?(@symlinkfile)) if @symlinkfile
+ assert(!(File.symlink?(@hardlinkfile))) if @hardlinkfile
+ assert(!(File.symlink?(@nofile)))
+ end
+
+ def test_socket_p ## xxx
+ assert(!(File.socket?(@dir)))
+ assert(!(File.socket?(@file)))
+ assert(!(File.socket?(@nofile)))
+ end
+
+ def test_blockdev_p ## xxx
+ assert(!(File.blockdev?(@dir)))
+ assert(!(File.blockdev?(@file)))
+ assert(!(File.blockdev?(@nofile)))
+ end
+
+ def test_chardev_p ## xxx
+ assert(!(File.chardev?(@dir)))
+ assert(!(File.chardev?(@file)))
+ assert(!(File.chardev?(@nofile)))
+ end
+
+ def test_exist_p
+ assert(File.exist?(@dir))
+ assert(File.exist?(@file))
+ assert(!(File.exist?(@nofile)))
+ end
+
+ def test_readable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0200, @file)
+ assert(!(File.readable?(@file)))
+ File.chmod(0600, @file)
+ assert(File.readable?(@file))
+ assert(!(File.readable?(@nofile)))
+ end
+
+ def test_readable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0200, @file)
+ assert(!(File.readable_real?(@file)))
+ File.chmod(0600, @file)
+ assert(File.readable_real?(@file))
+ assert(!(File.readable_real?(@nofile)))
+ end
+
+ def test_world_readable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0006, @file)
+ assert(File.world_readable?(@file))
+ File.chmod(0060, @file)
+ assert(!(File.world_readable?(@file)))
+ File.chmod(0600, @file)
+ assert(!(File.world_readable?(@file)))
+ assert(!(File.world_readable?(@nofile)))
+ end
+
+ def test_writable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0400, @file)
+ assert(!(File.writable?(@file)))
+ File.chmod(0600, @file)
+ assert(File.writable?(@file))
+ assert(!(File.writable?(@nofile)))
+ end
+
+ def test_writable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0400, @file)
+ assert(!(File.writable_real?(@file)))
+ File.chmod(0600, @file)
+ assert(File.writable_real?(@file))
+ assert(!(File.writable_real?(@nofile)))
+ end
+
+ def test_world_writable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0006, @file)
+ assert(File.world_writable?(@file))
+ File.chmod(0060, @file)
+ assert(!(File.world_writable?(@file)))
+ File.chmod(0600, @file)
+ assert(!(File.world_writable?(@file)))
+ assert(!(File.world_writable?(@nofile)))
+ end
+
+ def test_executable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0100, @file)
+ assert(File.executable?(@file))
+ File.chmod(0600, @file)
+ assert(!(File.executable?(@file)))
+ assert(!(File.executable?(@nofile)))
+ end
+
+ def test_executable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0100, @file)
+ assert(File.executable_real?(@file))
+ File.chmod(0600, @file)
+ assert(!(File.executable_real?(@file)))
+ assert(!(File.executable_real?(@nofile)))
+ end
+
+ def test_file_p
+ assert(!(File.file?(@dir)))
+ assert(File.file?(@file))
+ assert(!(File.file?(@nofile)))
+ end
+
+ def test_zero_p
+ assert_nothing_raised { File.zero?(@dir) }
+ assert(!(File.zero?(@file)))
+ assert(File.zero?(@zerofile))
+ assert(!(File.zero?(@nofile)))
+ end
+
+ def test_size_p
+ assert_nothing_raised { File.size?(@dir) }
+ assert_equal(3, File.size?(@file))
+ assert(!(File.size?(@zerofile)))
+ assert(!(File.size?(@nofile)))
+ end
+
+ def test_owned_p ## xxx
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ assert(File.owned?(@file))
+ assert(File.grpowned?(@file))
+ end
+
+ def test_suid_sgid_sticky ## xxx
+ assert(!(File.setuid?(@file)))
+ assert(!(File.setgid?(@file)))
+ assert(!(File.sticky?(@file)))
+ end
+
+ def test_identical_p
+ assert(File.identical?(@file, @file))
+ assert(!(File.identical?(@file, @zerofile)))
+ assert(!(File.identical?(@file, @nofile)))
+ assert(!(File.identical?(@nofile, @file)))
+ end
+
+ def test_size
+ assert_integer(File.size(@dir))
+ assert_equal(3, File.size(@file))
+ assert_equal(0, File.size(@zerofile))
+ assert_raise(Errno::ENOENT) { File.size(@nofile) }
+ end
+
+ def test_ftype
+ assert_equal("directory", File.ftype(@dir))
+ assert_equal("file", File.ftype(@file))
+ assert_equal("link", File.ftype(@symlinkfile)) if @symlinkfile
+ assert_equal("file", File.ftype(@hardlinkfile)) if @hardlinkfile
+ assert_raise(Errno::ENOENT) { File.ftype(@nofile) }
+ end
+
+ def test_atime
+ t1 = File.atime(@file)
+ t2 = File.new(@file).atime
+ assert_kind_of(Time, t1)
+ assert_kind_of(Time, t2)
+ assert_equal(t1, t2)
+ assert_raise(Errno::ENOENT) { File.atime(@nofile) }
+ end
+
+ def test_mtime
+ t1 = File.mtime(@file)
+ t2 = File.new(@file).mtime
+ assert_kind_of(Time, t1)
+ assert_kind_of(Time, t2)
+ assert_equal(t1, t2)
+ assert_raise(Errno::ENOENT) { File.mtime(@nofile) }
+ end
+
+ def test_ctime
+ t1 = File.ctime(@file)
+ t2 = File.new(@file).ctime
+ assert_kind_of(Time, t1)
+ assert_kind_of(Time, t2)
+ assert_equal(t1, t2)
+ assert_raise(Errno::ENOENT) { File.ctime(@nofile) }
+ end
+
+ def test_chmod
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ assert_equal(1, File.chmod(0444, @file))
+ assert_equal(0444, File.stat(@file).mode % 01000)
+ assert_equal(0, File.new(@file).chmod(0222))
+ assert_equal(0222, File.stat(@file).mode % 01000)
+ File.chmod(0600, @file)
+ assert_raise(Errno::ENOENT) { File.chmod(0600, @nofile) }
+ end
+
+ def test_lchmod
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ assert_equal(1, File.lchmod(0444, @file))
+ assert_equal(0444, File.stat(@file).mode % 01000)
+ File.lchmod(0600, @file)
+ assert_raise(Errno::ENOENT) { File.lchmod(0600, @nofile) }
+ rescue NotImplementedError
+ end
+
+ def test_chown ## xxx
+ end
+
+ def test_lchown ## xxx
+ end
+
+ def test_symlink
+ return unless @symlinkfile
+ assert_equal("link", File.ftype(@symlinkfile))
+ assert_raise(Errno::EEXIST) { File.symlink(@file, @file) }
+ end
+
+ def test_utime
+ t = Time.local(2000)
+ File.utime(t + 1, t + 2, @zerofile)
+ assert_equal(t + 1, File.atime(@zerofile))
+ assert_equal(t + 2, File.mtime(@zerofile))
+ end
+
+ def test_hardlink
+ return unless @hardlinkfile
+ assert_equal("file", File.ftype(@hardlinkfile))
+ assert_raise(Errno::EEXIST) { File.link(@file, @file) }
+ end
+
+ def test_symlink2
+ return unless @symlinkfile
+ assert_equal(@file, File.readlink(@symlinkfile))
+ assert_raise(Errno::EINVAL) { File.readlink(@file) }
+ assert_raise(Errno::ENOENT) { File.readlink(@nofile) }
+ rescue NotImplementedError
+ end
+
+ def test_unlink
+ assert_equal(1, File.unlink(@file))
+ make_file("foo", @file)
+ assert_raise(Errno::ENOENT) { File.unlink(@nofile) }
+ end
+
+ def test_rename
+ assert_equal(0, File.rename(@file, @nofile))
+ assert(!(File.exist?(@file)))
+ assert(File.exist?(@nofile))
+ assert_equal(0, File.rename(@nofile, @file))
+ assert_raise(Errno::ENOENT) { File.rename(@nofile, @file) }
+ end
+
+ def test_umask
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ prev = File.umask(0777)
+ assert_equal(0777, File.umask)
+ open(@nofile, "w") { }
+ assert_equal(0, File.stat(@nofile).mode % 01000)
+ File.unlink(@nofile)
+ assert_equal(0777, File.umask(prev))
+ assert_raise(ArgumentError) { File.umask(0, 1, 2) }
+ end
+
+ def test_expand_path
+ assert_equal(@file, File.expand_path(File.basename(@file), File.dirname(@file)))
+ if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
+ assert_equal(@file, File.expand_path(@file + " "))
+ assert_equal(@file, File.expand_path(@file + "."))
+ assert_equal(@file, File.expand_path(@file + "::$DATA"))
+ end
+ end
+
+ def test_basename
+ assert_equal(File.basename(@file).sub(/\.test$/, ""), File.basename(@file, ".test"))
+ assert_equal("", File.basename(""))
+ assert_equal("foo", File.basename("foo"))
+ assert_equal("foo", File.basename("foo", ".ext"))
+ assert_equal("foo", File.basename("foo.ext", ".ext"))
+ assert_equal("foo", File.basename("foo.ext", ".*"))
+ if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
+ basename = File.basename(@file)
+ assert_equal(basename, File.basename(@file + " "))
+ assert_equal(basename, File.basename(@file + "."))
+ assert_equal(basename, File.basename(@file + "::$DATA"))
+ basename.chomp!(".test")
+ assert_equal(basename, File.basename(@file + " ", ".test"))
+ assert_equal(basename, File.basename(@file + ".", ".test"))
+ assert_equal(basename, File.basename(@file + "::$DATA", ".test"))
+ assert_equal(basename, File.basename(@file + " ", ".*"))
+ assert_equal(basename, File.basename(@file + ".", ".*"))
+ assert_equal(basename, File.basename(@file + "::$DATA", ".*"))
+ end
+ end
+
+ def test_dirname
+ assert(@file.start_with?(File.dirname(@file)))
+ assert_equal(".", File.dirname(""))
+ end
+
+ def test_extname
+ assert(".test", File.extname(@file))
+ assert_equal("", File.extname("foo"))
+ assert_equal("", File.extname("/foo"))
+ assert_equal("", File.extname(".foo"))
+ assert_equal("", File.extname("/.foo"))
+ assert_equal("", File.extname("bar/.foo"))
+ assert_equal("", File.extname("/bar/.foo"))
+ assert_equal(".ext", File.extname("foo.ext"))
+ assert_equal(".ext", File.extname("/foo.ext"))
+ assert_equal(".ext", File.extname(".foo.ext"))
+ assert_equal(".ext", File.extname("/.foo.ext"))
+ assert_equal(".ext", File.extname("bar/.foo.ext"))
+ assert_equal(".ext", File.extname("/bar/.foo.ext"))
+ assert_equal("", File.extname(""))
+ if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
+ assert_equal("", File.extname("foo "))
+ assert_equal(".ext", File.extname("foo.ext "))
+ assert_equal(".ext", File.extname("foo.ext."))
+ assert_equal(".ext", File.extname("foo.ext::$DATA"))
+ assert_equal("", File.extname("foo::$DATA.ext"))
+ end
+ end
+
+ def test_split
+ d, b = File.split(@file)
+ assert_equal(File.dirname(@file), d)
+ assert_equal(File.basename(@file), b)
+ end
+
+ def test_join
+ s = "foo" + File::SEPARATOR + "bar" + File::SEPARATOR + "baz"
+ assert_equal(s, File.join("foo", "bar", "baz"))
+ assert_equal(s, File.join(["foo", "bar", "baz"]))
+ o = Object.new
+ def o.to_path; "foo"; end
+ assert_equal(s, File.join(o, "bar", "baz"))
+ assert_equal(s, File.join("foo" + File::SEPARATOR, "bar", File::SEPARATOR + "baz"))
+ end
+
+ def test_truncate
+ assert_equal(0, File.truncate(@file, 1))
+ assert(File.exist?(@file))
+ assert_equal(1, File.size(@file))
+ assert_equal(0, File.truncate(@file, 0))
+ assert(File.exist?(@file))
+ assert(File.zero?(@file))
+ make_file("foo", @file)
+ assert_raise(Errno::ENOENT) { File.truncate(@nofile, 0) }
+
+ f = File.new(@file, "w")
+ assert_equal(0, f.truncate(2))
+ assert(File.exist?(@file))
+ assert_equal(2, File.size(@file))
+ assert_equal(0, f.truncate(0))
+ assert(File.exist?(@file))
+ assert(File.zero?(@file))
+ f.close
+ make_file("foo", @file)
+
+ assert_raise(IOError) { File.new(@file).truncate(0) }
+ rescue NotImplementedError
+ end
+
+ def test_flock ## xxx
+ f = File.new(@file, "r+")
+ f.flock(File::LOCK_EX)
+ f.flock(File::LOCK_SH)
+ f.flock(File::LOCK_UN)
+ f.close
+ rescue NotImplementedError
+ end
+
+ def test_test
+ sleep(@time - Time.now + 1.1)
+ make_file("foo", @file + "2")
+ [@dir, @file, @zerofile, @symlinkfile, @hardlinkfile].compact.each do |f|
+ assert_equal(File.atime(f), test(?A, f))
+ assert_equal(File.ctime(f), test(?C, f))
+ assert_equal(File.mtime(f), test(?M, f))
+ assert_equal(File.blockdev?(f), test(?b, f))
+ assert_equal(File.chardev?(f), test(?c, f))
+ assert_equal(File.directory?(f), test(?d, f))
+ assert_equal(File.exist?(f), test(?e, f))
+ assert_equal(File.file?(f), test(?f, f))
+ assert_equal(File.setgid?(f), test(?g, f))
+ assert_equal(File.grpowned?(f), test(?G, f))
+ assert_equal(File.sticky?(f), test(?k, f))
+ assert_equal(File.symlink?(f), test(?l, f))
+ assert_equal(File.owned?(f), test(?o, f))
+ assert_nothing_raised { test(?O, f) }
+ assert_equal(File.pipe?(f), test(?p, f))
+ assert_equal(File.readable?(f), test(?r, f))
+ assert_equal(File.readable_real?(f), test(?R, f))
+ assert_equal(File.size?(f), test(?s, f))
+ assert_equal(File.socket?(f), test(?S, f))
+ assert_equal(File.setuid?(f), test(?u, f))
+ assert_equal(File.writable?(f), test(?w, f))
+ assert_equal(File.world_writable?(f), test(?W, f))
+ assert_equal(File.executable?(f), test(?x, f))
+ assert_equal(File.executable_real?(f), test(?X, f))
+ assert_equal(File.zero?(f), test(?z, f))
+ end
+ assert_equal(false, test(?-, @dir, @file))
+ assert_equal(true, test(?-, @file, @file))
+ assert_equal(true, test(?=, @file, @file))
+ assert_equal(false, test(?>, @file, @file))
+ assert_equal(false, test(?<, @file, @file))
+ unless /cygwin/ =~ RUBY_PLATFORM
+ assert_equal(false, test(?=, @file, @file + "2"))
+ assert_equal(false, test(?>, @file, @file + "2"))
+ assert_equal(true, test(?>, @file + "2", @file))
+ assert_equal(true, test(?<, @file, @file + "2"))
+ assert_equal(false, test(?<, @file + "2", @file))
+ end
+ assert_raise(ArgumentError) { test }
+ assert_raise(Errno::ENOENT) { test(?A, @nofile) }
+ assert_raise(ArgumentError) { test(?a) }
+ assert_raise(ArgumentError) { test("\0".ord) }
+ end
+
+ def test_stat_init
+ sleep(@time - Time.now + 1.1)
+ make_file("foo", @file + "2")
+ fs1, fs2 = File::Stat.new(@file), File::Stat.new(@file + "2")
+ assert_nothing_raised do
+ assert_equal(0, fs1 <=> fs1)
+ assert_equal(-1, fs1 <=> fs2)
+ assert_equal(1, fs2 <=> fs1)
+ assert_nil(fs1 <=> nil)
+ assert_integer(fs1.dev)
+ assert_integer_or_nil(fs1.rdev)
+ assert_integer_or_nil(fs1.dev_major)
+ assert_integer_or_nil(fs1.dev_minor)
+ assert_integer_or_nil(fs1.rdev_major)
+ assert_integer_or_nil(fs1.rdev_minor)
+ assert_integer(fs1.ino)
+ assert_integer(fs1.mode)
+ unless /emx/ =~ RUBY_PLATFORM
+ assert_equal(@hardlinkfile ? 2 : 1, fs1.nlink)
+ end
+ assert_integer(fs1.uid)
+ assert_integer(fs1.gid)
+ assert_equal(3, fs1.size)
+ assert_integer_or_nil(fs1.blksize)
+ assert_integer_or_nil(fs1.blocks)
+ assert_kind_of(Time, fs1.atime)
+ assert_kind_of(Time, fs1.mtime)
+ assert_kind_of(Time, fs1.ctime)
+ assert_kind_of(String, fs1.inspect)
+ end
+ assert_raise(Errno::ENOENT) { File::Stat.new(@nofile) }
+ assert_kind_of(File::Stat, File::Stat.new(@file).dup)
+ assert_raise(TypeError) do
+ File::Stat.new(@file).instance_eval { initialize_copy(0) }
+ end
+ end
+
+ def test_stat_ftype
+ assert_equal("directory", File::Stat.new(@dir).ftype)
+ assert_equal("file", File::Stat.new(@file).ftype)
+ # File::Stat uses stat
+ assert_equal("file", File::Stat.new(@symlinkfile).ftype) if @symlinkfile
+ assert_equal("file", File::Stat.new(@hardlinkfile).ftype) if @hardlinkfile
+ end
+
+ def test_stat_directory_p
+ assert(File::Stat.new(@dir).directory?)
+ assert(!(File::Stat.new(@file).directory?))
+ end
+
+ def test_stat_pipe_p ## xxx
+ assert(!(File::Stat.new(@dir).pipe?))
+ assert(!(File::Stat.new(@file).pipe?))
+ end
+
+ def test_stat_symlink_p
+ assert(!(File::Stat.new(@dir).symlink?))
+ assert(!(File::Stat.new(@file).symlink?))
+ # File::Stat uses stat
+ assert(!(File::Stat.new(@symlinkfile).symlink?)) if @symlinkfile
+ assert(!(File::Stat.new(@hardlinkfile).symlink?)) if @hardlinkfile
+ end
+
+ def test_stat_socket_p ## xxx
+ assert(!(File::Stat.new(@dir).socket?))
+ assert(!(File::Stat.new(@file).socket?))
+ end
+
+ def test_stat_blockdev_p ## xxx
+ assert(!(File::Stat.new(@dir).blockdev?))
+ assert(!(File::Stat.new(@file).blockdev?))
+ end
+
+ def test_stat_chardev_p ## xxx
+ assert(!(File::Stat.new(@dir).chardev?))
+ assert(!(File::Stat.new(@file).chardev?))
+ end
+
+ def test_stat_readable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0200, @file)
+ assert(!(File::Stat.new(@file).readable?))
+ File.chmod(0600, @file)
+ assert(File::Stat.new(@file).readable?)
+ end
+
+ def test_stat_readable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0200, @file)
+ assert(!(File::Stat.new(@file).readable_real?))
+ File.chmod(0600, @file)
+ assert(File::Stat.new(@file).readable_real?)
+ end
+
+ def test_stat_world_readable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0006, @file)
+ assert(File::Stat.new(@file).world_readable?)
+ File.chmod(0060, @file)
+ assert(!(File::Stat.new(@file).world_readable?))
+ File.chmod(0600, @file)
+ assert(!(File::Stat.new(@file).world_readable?))
+ end
+
+ def test_stat_writable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0400, @file)
+ assert(!(File::Stat.new(@file).writable?))
+ File.chmod(0600, @file)
+ assert(File::Stat.new(@file).writable?)
+ end
+
+ def test_stat_writable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0400, @file)
+ assert(!(File::Stat.new(@file).writable_real?))
+ File.chmod(0600, @file)
+ assert(File::Stat.new(@file).writable_real?)
+ end
+
+ def test_stat_world_writable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0006, @file)
+ assert(File::Stat.new(@file).world_writable?)
+ File.chmod(0060, @file)
+ assert(!(File::Stat.new(@file).world_writable?))
+ File.chmod(0600, @file)
+ assert(!(File::Stat.new(@file).world_writable?))
+ end
+
+ def test_stat_executable_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0100, @file)
+ assert(File::Stat.new(@file).executable?)
+ File.chmod(0600, @file)
+ assert(!(File::Stat.new(@file).executable?))
+ end
+
+ def test_stat_executable_real_p
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ File.chmod(0100, @file)
+ assert(File::Stat.new(@file).executable_real?)
+ File.chmod(0600, @file)
+ assert(!(File::Stat.new(@file).executable_real?))
+ end
+
+ def test_stat_file_p
+ assert(!(File::Stat.new(@dir).file?))
+ assert(File::Stat.new(@file).file?)
+ end
+
+ def test_stat_zero_p
+ assert_nothing_raised { File::Stat.new(@dir).zero? }
+ assert(!(File::Stat.new(@file).zero?))
+ assert(File::Stat.new(@zerofile).zero?)
+ end
+
+ def test_stat_size_p
+ assert_nothing_raised { File::Stat.new(@dir).size? }
+ assert_equal(3, File::Stat.new(@file).size?)
+ assert(!(File::Stat.new(@zerofile).size?))
+ end
+
+ def test_stat_owned_p ## xxx
+ return if /cygwin|mswin|bccwin|mingw|emx/ =~ RUBY_PLATFORM
+ assert(File::Stat.new(@file).owned?)
+ assert(File::Stat.new(@file).grpowned?)
+ end
+
+ def test_stat_suid_sgid_sticky ## xxx
+ assert(!(File::Stat.new(@file).setuid?))
+ assert(!(File::Stat.new(@file).setgid?))
+ assert(!(File::Stat.new(@file).sticky?))
+ end
+
+ def test_stat_size
+ assert_integer(File::Stat.new(@dir).size)
+ assert_equal(3, File::Stat.new(@file).size)
+ assert_equal(0, File::Stat.new(@zerofile).size)
+ end
+
+ def test_path_check
+ assert_nothing_raised { ENV["PATH"] }
+ end
+
+ def test_find_file
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ load(@file)
+ end.join
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_fixnum.rb b/trunk/test/ruby/test_fixnum.rb
new file mode 100644
index 0000000000..8fa751ba98
--- /dev/null
+++ b/trunk/test/ruby/test_fixnum.rb
@@ -0,0 +1,241 @@
+require 'test/unit'
+
+class TestFixnum < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_pow
+ [1, 2, 2**64, 2**63*3, 2**64*3].each do |y|
+ [-1, 0, 1].each do |x|
+ z1 = x**y
+ z2 = (-x)**y
+ if y % 2 == 1
+ assert_equal(z2, -z1)
+ else
+ assert_equal(z2, z1)
+ end
+ end
+ end
+ end
+
+ def test_succ
+ assert_equal(0x40000000, 0x3fffffff.succ, "[ruby-dev:31189]")
+ assert_equal(0x4000000000000000, 0x3fffffffffffffff.succ, "[ruby-dev:31190]")
+ end
+
+ def test_pred
+ assert_equal(-0x40000001, (-0x40000000).pred)
+ assert_equal(-0x4000000000000001, (-0x4000000000000000).pred)
+ end
+
+ def test_plus
+ assert_equal(0x40000000, 0x3fffffff+1)
+ assert_equal(0x4000000000000000, 0x3fffffffffffffff+1)
+ assert_equal(-0x40000001, (-0x40000000)+(-1))
+ assert_equal(-0x4000000000000001, (-0x4000000000000000)+(-1))
+ assert_equal(-0x80000000, (-0x40000000)+(-0x40000000))
+ end
+
+ def test_sub
+ assert_equal(0x40000000, 0x3fffffff-(-1))
+ assert_equal(0x4000000000000000, 0x3fffffffffffffff-(-1))
+ assert_equal(-0x40000001, (-0x40000000)-1)
+ assert_equal(-0x4000000000000001, (-0x4000000000000000)-1)
+ assert_equal(-0x80000000, (-0x40000000)-0x40000000)
+ end
+
+ def test_mult
+ assert_equal(0x40000000, 0x20000000*2)
+ assert_equal(0x4000000000000000, 0x2000000000000000*2)
+ assert_equal(-0x40000001, 33025*(-32513))
+ assert_equal(-0x4000000000000001, 1380655685*(-3340214413))
+ assert_equal(0x40000000, (-0x40000000)*(-1))
+ end
+
+ def test_div
+ assert_equal(2, 5/2)
+ assert_equal(0, 1/2)
+ assert_equal(-1, -1/2)
+ assert_equal(0, -(1/2))
+ assert_equal(-1, (-1)/2)
+ assert_equal(0, (-1)/(-2))
+ assert_equal(-1, 1/(-2))
+ assert_equal(1, -(1/(-2)))
+ assert_equal(0x3fffffff, 0xbffffffd/3)
+ assert_equal(0x40000000, 0xc0000000/3)
+ assert_equal(0x4000000000000000, 0xc000000000000000/3)
+ assert_equal(-0x40000001, 0xc0000003/(-3))
+ assert_equal(-0x4000000000000001, 0xc000000000000003/(-3))
+ assert_equal(0x40000000, (-0x40000000)/(-1), "[ruby-dev:31210]")
+ assert_equal(0x4000000000000000, (-0x4000000000000000)/(-1))
+ end
+
+ def test_mod
+ assert_equal(2, (-0x40000000) % 3)
+ assert_equal(0, (-0x40000000) % (-1))
+ end
+
+ def test_divmod
+ (-5).upto(5) {|a|
+ (-5).upto(5) {|b|
+ next if b == 0
+ q, r = a.divmod(b)
+ assert_equal(a, b*q+r)
+ assert(r.abs < b.abs)
+ assert(0 < b ? (0 <= r && r < b) : (b < r && r <= 0))
+ assert_equal(q, a/b)
+ assert_equal(q, a.div(b))
+ assert_equal(r, a%b)
+ assert_equal(r, a.modulo(b))
+ }
+ }
+ end
+
+ def test_not
+ assert_equal(-0x40000000, ~0x3fffffff)
+ assert_equal(0x3fffffff, ~-0x40000000)
+ end
+
+ def test_lshift
+ assert_equal(0x40000000, 0x20000000<<1)
+ assert_equal(-0x40000000, (-0x20000000)<<1)
+ assert_equal(-0x80000000, (-0x40000000)<<1)
+ end
+
+ def test_rshift
+ assert_equal(0x20000000, 0x40000000>>1)
+ assert_equal(-0x20000000, (-0x40000000)>>1)
+ assert_equal(-0x40000000, (-0x80000000)>>1)
+ end
+
+ def test_abs
+ assert_equal(0x40000000, (-0x40000000).abs)
+ assert_equal(0x4000000000000000, (-0x4000000000000000).abs)
+ end
+
+ def test_induced_from
+ assert_equal(1, Fixnum.induced_from(1))
+ assert_raise(RangeError) do
+ Fixnum.induced_from(2**31-1)
+ Fixnum.induced_from(2**63-1)
+ end
+ assert_equal(1, Fixnum.induced_from((2**32).coerce(1).first))
+ end
+
+ def test_to_s
+ assert_equal("1010", 10.to_s(2))
+ assert_equal("a", 10.to_s(36))
+ assert_raise(ArgumentError) { 10.to_s(1) }
+ end
+
+ def test_plus2
+ assert_equal(2, 1 + 1)
+ assert_equal(4294967297, 1 + 2**32)
+ assert_equal(2.0, 1 + 1.0)
+ assert_raise(TypeError) { 1 + nil }
+ end
+
+ def test_minus
+ assert_equal(0, 1 - 1)
+ assert_equal(-4294967295, 1 - 2**32)
+ assert_equal(0.0, 1 - 1.0)
+ assert_raise(TypeError) { 1 - nil }
+ end
+
+ def test_mul
+ assert_equal(6, 2.send(:*, 3))
+ a = 2**30-1
+ assert_equal(1152921502459363329, a.send(:*, a))
+
+ assert_equal(6.0, 2 * 3.0)
+ assert_raise(TypeError) { 2 * nil }
+ end
+
+ def test_divide
+ assert_equal(2.0, 4.quo(2))
+ assert_equal(2.0, 4 / 2)
+ assert_equal(2.0, 4.div(2))
+
+ assert_equal(0.5**32, 1.quo(2**32))
+ assert_equal(0, 1 / (2**32))
+ assert_equal(0, 1.div(2**32))
+
+ assert_equal(0.5, 1.quo(2.0))
+ assert_equal(0.5, 1 / 2.0)
+ assert_equal(0, 1.div(2.0))
+
+ ### rational changes the behavior of Fixnum#quo
+ #assert_raise(TypeError) { 2.quo(nil) }
+ assert_raise(TypeError, NoMethodError) { 2.quo(nil) }
+ assert_raise(TypeError) { 2 / nil }
+ assert_raise(TypeError) { 2.div(nil) }
+
+ assert_equal(0, 4.modulo(2))
+ assert_equal(1, 1.modulo(2**32))
+ assert_equal(1, 1.modulo(2.0))
+ assert_raise(TypeError) { 2.modulo(nil) }
+
+ assert_equal([2, 0], 4.divmod(2))
+ assert_equal([0, 1], 1.divmod(2**32))
+ assert_equal([0, 1], 1.divmod(2.0))
+ assert_raise(TypeError) { 2.divmod(nil) }
+ end
+
+ def test_pow2
+ assert_equal(65536, 2**16)
+ assert_equal(4294967296, 2**32)
+ assert_equal(0.5**16, 2**-16)
+ assert_equal(1, (-1)**4294967296)
+ assert_equal(-1, (-1)**4294967295)
+ assert_equal(4, 2**((2**32).coerce(2).first))
+ assert_equal(2, 4**0.5)
+ assert_equal(0, 0**0.5)
+ assert((0**-1.0).infinite?)
+ ### rational changes the behavior of Fixnum#**
+ #assert_raise(TypeError) { 1 ** nil }
+ assert_raise(TypeError, NoMethodError) { 1 ** nil }
+ end
+
+ def test_cmp
+ assert(1 != nil)
+
+ assert_equal(0, 1 <=> 1)
+ assert_equal(-1, 1 <=> 4294967296)
+ assert_equal(0, 1 <=> 1.0)
+ assert_nil(1 <=> nil)
+
+ assert(1.send(:>, 0))
+ assert(!(1.send(:>, 1)))
+ assert(!(1.send(:>, 2)))
+ assert(!(1.send(:>, 4294967296)))
+ assert(1.send(:>, 0.0))
+ assert_raise(ArgumentError) { 1.send(:>, nil) }
+
+ assert(1.send(:>=, 0))
+ assert(1.send(:>=, 1))
+ assert(!(1.send(:>=, 2)))
+ assert(!(1.send(:>=, 4294967296)))
+ assert(1.send(:>=, 0.0))
+ assert_raise(ArgumentError) { 1.send(:>=, nil) }
+
+ assert(!(1.send(:<, 0)))
+ assert(!(1.send(:<, 1)))
+ assert(1.send(:<, 2))
+ assert(1.send(:<, 4294967296))
+ assert(!(1.send(:<, 0.0)))
+ assert_raise(ArgumentError) { 1.send(:<, nil) }
+
+ assert(!(1.send(:<=, 0)))
+ assert(1.send(:<=, 1))
+ assert(1.send(:<=, 2))
+ assert(1.send(:<=, 4294967296))
+ assert(!(1.send(:<=, 0.0)))
+ assert_raise(ArgumentError) { 1.send(:<=, nil) }
+ end
+end
diff --git a/trunk/test/ruby/test_float.rb b/trunk/test/ruby/test_float.rb
new file mode 100644
index 0000000000..d4bbd688d2
--- /dev/null
+++ b/trunk/test/ruby/test_float.rb
@@ -0,0 +1,433 @@
+require 'test/unit'
+
+class TestFloat < Test::Unit::TestCase
+ def test_float
+ assert_equal(2, 2.6.floor)
+ assert_equal(-3, (-2.6).floor)
+ assert_equal(3, 2.6.ceil)
+ assert_equal(-2, (-2.6).ceil)
+ assert_equal(2, 2.6.truncate)
+ assert_equal(-2, (-2.6).truncate)
+ assert_equal(3, 2.6.round)
+ assert_equal(-2, (-2.4).truncate)
+ assert((13.4 % 1 - 0.4).abs < 0.0001)
+ assert_equal(36893488147419111424,
+ 36893488147419107329.0.to_i)
+ end
+
+ def nan_test(x,y)
+ extend Test::Unit::Assertions
+ assert(x != y)
+ assert_equal(false, (x < y))
+ assert_equal(false, (x > y))
+ assert_equal(false, (x <= y))
+ assert_equal(false, (x >= y))
+ end
+ def test_nan
+ nan = 0.0/0
+ nan_test(nan, nan)
+ nan_test(nan, 0)
+ nan_test(nan, 1)
+ nan_test(nan, -1)
+ nan_test(nan, 1000)
+ nan_test(nan, -1000)
+ nan_test(nan, 1_000_000_000_000)
+ nan_test(nan, -1_000_000_000_000)
+ nan_test(nan, 100.0);
+ nan_test(nan, -100.0);
+ nan_test(nan, 0.001);
+ nan_test(nan, -0.001);
+ nan_test(nan, 1.0/0);
+ nan_test(nan, -1.0/0);
+ end
+
+ def test_precision
+ u = 3.7517675036461267e+17
+ v = sprintf("%.16e", u).to_f
+ assert_in_delta(u, v, u.abs * Float::EPSILON)
+ assert_in_delta(u, v, v.abs * Float::EPSILON)
+ end
+
+ def test_symmetry_bignum # [ruby-bugs-ja:118]
+ a = 100000000000000000000000
+ b = 100000000000000000000000.0
+ assert_equal(a == b, b == a)
+ end
+
+ def test_strtod
+ a = Float("0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("+0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("-0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("0.0000000000000000001")
+ assert(a != 0.0)
+ a = Float("+0.0000000000000000001")
+ assert(a != 0.0)
+ a = Float("-0.0000000000000000001")
+ assert(a != 0.0)
+ a = Float(".0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("+.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("-.0")
+ assert(a.abs < Float::EPSILON)
+ assert_raise(ArgumentError){Float("0.")}
+ assert_raise(ArgumentError){Float("+0.")}
+ assert_raise(ArgumentError){Float("-0.")}
+ assert_raise(ArgumentError){Float(".")}
+ assert_raise(ArgumentError){Float("+")}
+ assert_raise(ArgumentError){Float("+.")}
+ assert_raise(ArgumentError){Float("-")}
+ assert_raise(ArgumentError){Float("-.")}
+ assert_raise(ArgumentError){Float("1e")}
+ assert_raise(ArgumentError){Float("1__1")}
+ # add expected behaviour here.
+ assert_equal(10, Float("1_0"))
+ end
+
+ def test_divmod
+ assert_equal([2, 3.5], 11.5.divmod(4))
+ assert_equal([-3, -0.5], 11.5.divmod(-4))
+ assert_equal([-3, 0.5], (-11.5).divmod(4))
+ assert_equal([2, -3.5], (-11.5).divmod(-4))
+ end
+
+ def test_div
+ assert_equal(2, 11.5.div(4))
+ assert_equal(-3, 11.5.div(-4))
+ assert_equal(-3, (-11.5).div(4))
+ assert_equal(2, (-11.5).div(-4))
+ end
+
+ def test_modulo
+ assert_equal(3.5, 11.5.modulo(4))
+ assert_equal(-0.5, 11.5.modulo(-4))
+ assert_equal(0.5, (-11.5).modulo(4))
+ assert_equal(-3.5, (-11.5).modulo(-4))
+ end
+
+ def test_remainder
+ assert_equal(3.5, 11.5.remainder(4))
+ assert_equal(3.5, 11.5.remainder(-4))
+ assert_equal(-3.5, (-11.5).remainder(4))
+ assert_equal(-3.5, (-11.5).remainder(-4))
+ end
+
+ def test_to_s
+ inf = 1.0 / 0.0
+ assert_equal("Infinity", inf.to_s)
+ assert_equal("-Infinity", (-inf).to_s)
+ assert_equal("NaN", (inf / inf).to_s)
+
+ assert_equal("1.0e+14", 10000_00000_00000.0.to_s)
+ end
+
+ def test_coerce
+ assert_equal(Float, 1.0.coerce(1).first.class)
+ end
+
+ def test_plus
+ assert_equal(4.0, 2.0.send(:+, 2))
+ assert_equal(4.0, 2.0.send(:+, (2**32).coerce(2).first))
+ assert_equal(4.0, 2.0.send(:+, 2.0))
+ assert_raise(TypeError) { 2.0.send(:+, nil) }
+ end
+
+ def test_minus
+ assert_equal(0.0, 2.0.send(:-, 2))
+ assert_equal(0.0, 2.0.send(:-, (2**32).coerce(2).first))
+ assert_equal(0.0, 2.0.send(:-, 2.0))
+ assert_raise(TypeError) { 2.0.send(:-, nil) }
+ end
+
+ def test_mul
+ assert_equal(4.0, 2.0.send(:*, 2))
+ assert_equal(4.0, 2.0.send(:*, (2**32).coerce(2).first))
+ assert_equal(4.0, 2.0.send(:*, 2.0))
+ assert_raise(TypeError) { 2.0.send(:*, nil) }
+ end
+
+ def test_div2
+ assert_equal(1.0, 2.0.send(:/, 2))
+ assert_equal(1.0, 2.0.send(:/, (2**32).coerce(2).first))
+ assert_equal(1.0, 2.0.send(:/, 2.0))
+ assert_raise(TypeError) { 2.0.send(:/, nil) }
+ end
+
+ def test_modulo2
+ assert_equal(0.0, 2.0.send(:%, 2))
+ assert_equal(0.0, 2.0.send(:%, (2**32).coerce(2).first))
+ assert_equal(0.0, 2.0.send(:%, 2.0))
+ assert_raise(TypeError) { 2.0.send(:%, nil) }
+ end
+
+ def test_divmod2
+ assert_equal([1.0, 0.0], 2.0.divmod(2))
+ assert_equal([1.0, 0.0], 2.0.divmod((2**32).coerce(2).first))
+ assert_equal([1.0, 0.0], 2.0.divmod(2.0))
+ assert_raise(TypeError) { 2.0.divmod(nil) }
+
+ inf = 1.0 / 0.0
+ a, b = inf.divmod(0)
+ assert(a.infinite?)
+ assert(b.nan?)
+
+ a, b = (2.0**32).divmod(1.0)
+ assert_equal(2**32, a)
+ assert_equal(0, b)
+ end
+
+ def test_pow
+ assert_equal(1.0, 1.0 ** (2**32))
+ assert_equal(1.0, 1.0 ** 1.0)
+ assert_raise(TypeError) { 1.0 ** nil }
+ end
+
+ def test_eql
+ inf = 1.0 / 0.0
+ nan = inf / inf
+ assert(1.0.eql?(1.0))
+ assert(inf.eql?(inf))
+ assert(!(nan.eql?(nan)))
+ assert(!(1.0.eql?(nil)))
+
+ assert(1.0 == 1)
+ assert(1.0 != 2**32)
+ assert(1.0 != nan)
+ assert(1.0 != nil)
+ end
+
+ def test_cmp
+ inf = 1.0 / 0.0
+ nan = inf / inf
+ assert_equal(0, 1.0 <=> 1.0)
+ assert_equal(1, 1.0 <=> 0.0)
+ assert_equal(-1, 1.0 <=> 2.0)
+ assert_nil(1.0 <=> nil)
+ assert_nil(1.0 <=> nan)
+ assert_nil(nan <=> 1.0)
+
+ assert_equal(0, 1.0 <=> 1)
+ assert_equal(1, 1.0 <=> 0)
+ assert_equal(-1, 1.0 <=> 2)
+
+ assert_equal(-1, 1.0 <=> 2**32)
+
+ assert_raise(ArgumentError) { 1.0 > nil }
+ assert_raise(ArgumentError) { 1.0 >= nil }
+ assert_raise(ArgumentError) { 1.0 < nil }
+ assert_raise(ArgumentError) { 1.0 <= nil }
+ end
+
+ def test_zero_p
+ assert(0.0.zero?)
+ assert(!(1.0.zero?))
+ end
+
+ def test_infinite_p
+ inf = 1.0 / 0.0
+ assert(1, inf.infinite?)
+ assert(1, (-inf).infinite?)
+ assert_nil(1.0.infinite?)
+ end
+
+ def test_finite_p
+ inf = 1.0 / 0.0
+ assert(!(inf.finite?))
+ assert(!((-inf).finite?))
+ assert(1.0.finite?)
+ end
+
+ def test_floor_ceil_round_truncate
+ assert_equal(1, 1.5.floor)
+ assert_equal(2, 1.5.ceil)
+ assert_equal(2, 1.5.round)
+ assert_equal(1, 1.5.truncate)
+
+ assert_equal(2, 2.0.floor)
+ assert_equal(2, 2.0.ceil)
+ assert_equal(2, 2.0.round)
+ assert_equal(2, 2.0.truncate)
+
+ assert_equal(-2, (-1.5).floor)
+ assert_equal(-1, (-1.5).ceil)
+ assert_equal(-2, (-1.5).round)
+ assert_equal(-1, (-1.5).truncate)
+
+ assert_equal(-2, (-2.0).floor)
+ assert_equal(-2, (-2.0).ceil)
+ assert_equal(-2, (-2.0).round)
+ assert_equal(-2, (-2.0).truncate)
+
+ inf = 1.0/0.0
+ assert_raise(FloatDomainError) { inf.floor }
+ assert_raise(FloatDomainError) { inf.ceil }
+ assert_raise(FloatDomainError) { inf.round }
+ assert_raise(FloatDomainError) { inf.truncate }
+
+ assert_equal(1.100, 1.111.round(1))
+ assert_equal(1.110, 1.111.round(2))
+ assert_equal(11110.0, 11111.1.round(-1))
+ assert_equal(11100.0, 11111.1.round(-2))
+ end
+
+ def test_induced_from
+ assert_equal(1.0, Float.induced_from(1))
+ assert_equal(1.0, Float.induced_from(1.0))
+ assert_raise(TypeError) { Float.induced_from(nil) }
+ end
+
+
+ VS = [
+ 18446744073709551617.0,
+ 18446744073709551616.0,
+ 18446744073709551615.8,
+ 18446744073709551615.5,
+ 18446744073709551615.2,
+ 18446744073709551615.0,
+ 18446744073709551614.0,
+
+ 4611686018427387905.0,
+ 4611686018427387904.0,
+ 4611686018427387903.8,
+ 4611686018427387903.5,
+ 4611686018427387903.2,
+ 4611686018427387903.0,
+ 4611686018427387902.0,
+
+ 4294967297.0,
+ 4294967296.0,
+ 4294967295.8,
+ 4294967295.5,
+ 4294967295.2,
+ 4294967295.0,
+ 4294967294.0,
+
+ 1073741825.0,
+ 1073741824.0,
+ 1073741823.8,
+ 1073741823.5,
+ 1073741823.2,
+ 1073741823.0,
+ 1073741822.0,
+
+ -1073741823.0,
+ -1073741824.0,
+ -1073741824.2,
+ -1073741824.5,
+ -1073741824.8,
+ -1073741825.0,
+ -1073741826.0,
+
+ -4294967295.0,
+ -4294967296.0,
+ -4294967296.2,
+ -4294967296.5,
+ -4294967296.8,
+ -4294967297.0,
+ -4294967298.0,
+
+ -4611686018427387903.0,
+ -4611686018427387904.0,
+ -4611686018427387904.2,
+ -4611686018427387904.5,
+ -4611686018427387904.8,
+ -4611686018427387905.0,
+ -4611686018427387906.0,
+
+ -18446744073709551615.0,
+ -18446744073709551616.0,
+ -18446744073709551616.2,
+ -18446744073709551616.5,
+ -18446744073709551616.8,
+ -18446744073709551617.0,
+ -18446744073709551618.0,
+ ]
+
+ def test_truncate
+ VS.each {|f|
+ i = f.truncate
+ assert_equal(i, f.to_i)
+ if f < 0
+ assert_operator(i, :<, 0)
+ else
+ assert_operator(i, :>, 0)
+ end
+ assert_operator(i.abs, :<=, f.abs)
+ d = f.abs - i.abs
+ assert_operator(0, :<=, d)
+ assert_operator(d, :<, 1)
+ }
+ end
+
+ def test_ceil
+ VS.each {|f|
+ i = f.ceil
+ if f < 0
+ assert_operator(i, :<, 0)
+ else
+ assert_operator(i, :>, 0)
+ end
+ assert_operator(i, :>=, f)
+ d = f - i
+ assert_operator(-1, :<, d)
+ assert_operator(d, :<=, 0)
+ }
+ end
+
+ def test_floor
+ VS.each {|f|
+ i = f.floor
+ if f < 0
+ assert_operator(i, :<, 0)
+ else
+ assert_operator(i, :>, 0)
+ end
+ assert_operator(i, :<=, f)
+ d = f - i
+ assert_operator(0, :<=, d)
+ assert_operator(d, :<, 1)
+ }
+ end
+
+ def test_round
+ VS.each {|f|
+ i = f.round
+ if f < 0
+ assert_operator(i, :<, 0)
+ else
+ assert_operator(i, :>, 0)
+ end
+ d = f - i
+ assert_operator(-0.5, :<=, d)
+ assert_operator(d, :<=, 0.5)
+ }
+ end
+
+ def test_Float
+ assert_in_delta(0.125, Float("0.1_2_5"), 0.00001)
+ assert_in_delta(0.125, "0.1_2_5__".to_f, 0.00001)
+ assert(Float(([1] * 10000).join).infinite?)
+ assert(!Float(([1] * 10000).join("_")).infinite?) # is it really OK?
+ assert_raise(ArgumentError) { Float("1.0\x001") }
+ assert(Float("1e10_00").infinite?)
+ assert_raise(TypeError) { Float(nil) }
+ o = Object.new
+ def o.to_f; inf = 1.0/0.0; inf/inf; end
+ assert(Float(o).nan?)
+ end
+
+ def test_num2dbl
+ assert_raise(TypeError) do
+ 1.0.step(2.0, "0.5") {}
+ end
+ assert_raise(TypeError) do
+ 1.0.step(2.0, nil) {}
+ end
+ end
+
+end
diff --git a/trunk/test/ruby/test_fnmatch.rb b/trunk/test/ruby/test_fnmatch.rb
new file mode 100644
index 0000000000..1c1a158477
--- /dev/null
+++ b/trunk/test/ruby/test_fnmatch.rb
@@ -0,0 +1,104 @@
+require 'test/unit'
+
+class TestFnmatch < Test::Unit::TestCase
+
+ def bracket_test(s, t) # `s' should start with neither '!' nor '^'
+ 0x21.upto(0x7E) do |i|
+ assert_equal(t.include?(i.chr), File.fnmatch("[#{s}]", i.chr, File::FNM_DOTMATCH))
+ assert_equal(t.include?(i.chr), !File.fnmatch("[^#{s}]", i.chr, File::FNM_DOTMATCH))
+ assert_equal(t.include?(i.chr), !File.fnmatch("[!#{s}]", i.chr, File::FNM_DOTMATCH))
+ end
+ end
+ def test_fnmatch
+ assert(File.fnmatch('\[1\]' , '[1]'), "[ruby-dev:22819]")
+ assert(File.fnmatch('*?', 'a'), "[ruby-dev:22815]")
+ assert(File.fnmatch('*/', 'a/'))
+ assert(File.fnmatch('\[1\]' , '[1]', File::FNM_PATHNAME))
+ assert(File.fnmatch('*?', 'a', File::FNM_PATHNAME))
+ assert(File.fnmatch('*/', 'a/', File::FNM_PATHNAME))
+ # text
+ assert(File.fnmatch('cat', 'cat'))
+ assert(!File.fnmatch('cat', 'category'))
+ assert(!File.fnmatch('cat', 'wildcat'))
+ # '?' matches any one character
+ assert(File.fnmatch('?at', 'cat'))
+ assert(File.fnmatch('c?t', 'cat'))
+ assert(File.fnmatch('ca?', 'cat'))
+ assert(File.fnmatch('?a?', 'cat'))
+ assert(!File.fnmatch('c??t', 'cat'))
+ assert(!File.fnmatch('??at', 'cat'))
+ assert(!File.fnmatch('ca??', 'cat'))
+ # '*' matches any number (including 0) of any characters
+ assert(File.fnmatch('c*', 'cats'))
+ assert(File.fnmatch('c*ts', 'cats'))
+ assert(File.fnmatch('*ts', 'cats'))
+ assert(File.fnmatch('*c*a*t*s*', 'cats'))
+ assert(!File.fnmatch('c*t', 'cats'))
+ assert(!File.fnmatch('*abc', 'abcabz'))
+ assert(File.fnmatch('*abz', 'abcabz'))
+ assert(!File.fnmatch('a*abc', 'abc'))
+ assert(File.fnmatch('a*bc', 'abc'))
+ assert(!File.fnmatch('a*bc', 'abcd'))
+ # [seq] : matches any character listed between bracket
+ # [!seq] or [^seq] : matches any character except those listed between bracket
+ bracket_test("bd-gikl-mosv-x", "bdefgiklmosvwx")
+ # escaping character
+ assert(File.fnmatch('\?', '?'))
+ assert(!File.fnmatch('\?', '\?'))
+ assert(!File.fnmatch('\?', 'a'))
+ assert(!File.fnmatch('\?', '\a'))
+ assert(File.fnmatch('\*', '*'))
+ assert(!File.fnmatch('\*', '\*'))
+ assert(!File.fnmatch('\*', 'cats'))
+ assert(!File.fnmatch('\*', '\cats'))
+ assert(File.fnmatch('\a', 'a'))
+ assert(!File.fnmatch('\a', '\a'))
+ assert(File.fnmatch('[a\-c]', 'a'))
+ assert(File.fnmatch('[a\-c]', '-'))
+ assert(File.fnmatch('[a\-c]', 'c'))
+ assert(!File.fnmatch('[a\-c]', 'b'))
+ assert(!File.fnmatch('[a\-c]', '\\'))
+ # escaping character loses its meaning if FNM_NOESCAPE is set
+ assert(!File.fnmatch('\?', '?', File::FNM_NOESCAPE))
+ assert(File.fnmatch('\?', '\?', File::FNM_NOESCAPE))
+ assert(!File.fnmatch('\?', 'a', File::FNM_NOESCAPE))
+ assert(File.fnmatch('\?', '\a', File::FNM_NOESCAPE))
+ assert(!File.fnmatch('\*', '*', File::FNM_NOESCAPE))
+ assert(File.fnmatch('\*', '\*', File::FNM_NOESCAPE))
+ assert(!File.fnmatch('\*', 'cats', File::FNM_NOESCAPE))
+ assert(File.fnmatch('\*', '\cats', File::FNM_NOESCAPE))
+ assert(!File.fnmatch('\a', 'a', File::FNM_NOESCAPE))
+ assert(File.fnmatch('\a', '\a', File::FNM_NOESCAPE))
+ assert(File.fnmatch('[a\-c]', 'a', File::FNM_NOESCAPE))
+ assert(!File.fnmatch('[a\-c]', '-', File::FNM_NOESCAPE))
+ assert(File.fnmatch('[a\-c]', 'c', File::FNM_NOESCAPE))
+ assert(File.fnmatch('[a\-c]', 'b', File::FNM_NOESCAPE)) # '\\' < 'b' < 'c'
+ assert(File.fnmatch('[a\-c]', '\\', File::FNM_NOESCAPE))
+ # case is ignored if FNM_CASEFOLD is set
+ assert(!File.fnmatch('cat', 'CAT'))
+ assert(File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD))
+ assert(!File.fnmatch('[a-z]', 'D'))
+ assert(File.fnmatch('[a-z]', 'D', File::FNM_CASEFOLD))
+ # wildcard doesn't match '/' if FNM_PATHNAME is set
+ assert(File.fnmatch('foo?boo', 'foo/boo'))
+ assert(File.fnmatch('foo*', 'foo/boo'))
+ assert(!File.fnmatch('foo?boo', 'foo/boo', File::FNM_PATHNAME))
+ assert(!File.fnmatch('foo*', 'foo/boo', File::FNM_PATHNAME))
+ # wildcard matches leading period if FNM_DOTMATCH is set
+ assert(!File.fnmatch('*', '.profile'))
+ assert(File.fnmatch('*', '.profile', File::FNM_DOTMATCH))
+ assert(File.fnmatch('.*', '.profile'))
+ assert(File.fnmatch('*', 'dave/.profile'))
+ assert(File.fnmatch('*/*', 'dave/.profile'))
+ assert(!File.fnmatch('*/*', 'dave/.profile', File::FNM_PATHNAME))
+ assert(File.fnmatch('*/*', 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH))
+ # recursive matching
+ assert(File.fnmatch('**/foo', 'a/b/c/foo', File::FNM_PATHNAME))
+ assert(File.fnmatch('**/foo', '/foo', File::FNM_PATHNAME))
+ assert(!File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME))
+ assert(File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH))
+ assert(File.fnmatch('**/foo', '/root/foo', File::FNM_PATHNAME))
+ assert(File.fnmatch('**/foo', 'c:/root/foo', File::FNM_PATHNAME))
+ end
+
+end
diff --git a/trunk/test/ruby/test_gc.rb b/trunk/test/ruby/test_gc.rb
new file mode 100644
index 0000000000..42b249d0dc
--- /dev/null
+++ b/trunk/test/ruby/test_gc.rb
@@ -0,0 +1,54 @@
+require 'test/unit'
+
+class TestGc < Test::Unit::TestCase
+ class S
+ def initialize(a)
+ @a = a
+ end
+ end
+
+ def test_gc
+ prev_stress = GC.stress
+ GC.stress = false
+
+ assert_nothing_raised do
+ 1.upto(10000) {
+ tmp = [0,1,2,3,4,5,6,7,8,9]
+ }
+ tmp = nil
+ end
+ l=nil
+ 100000.times {
+ l = S.new(l)
+ }
+ GC.start
+ assert true # reach here or dumps core
+ l = []
+ 100000.times {
+ l.push([l])
+ }
+ GC.start
+ assert true # reach here or dumps core
+
+ GC.stress = prev_stress
+ end
+
+ def test_enable_disable
+ GC.enable
+ assert_equal(false, GC.enable)
+ assert_equal(false, GC.disable)
+ assert_equal(true, GC.disable)
+ assert_equal(true, GC.disable)
+ assert_nil(GC.start)
+ assert_equal(true, GC.enable)
+ assert_equal(false, GC.enable)
+ ensure
+ GC.enable
+ end
+
+ def test_count
+ c = GC.count
+ GC.start
+ assert_operator(c, :<, GC.count)
+ end
+end
diff --git a/trunk/test/ruby/test_hash.rb b/trunk/test/ruby/test_hash.rb
new file mode 100644
index 0000000000..de0ba37fb7
--- /dev/null
+++ b/trunk/test/ruby/test_hash.rb
@@ -0,0 +1,851 @@
+require 'test/unit'
+require 'continuation'
+
+class TestHash < Test::Unit::TestCase
+
+ def test_hash
+ x = {1=>2, 2=>4, 3=>6}
+ y = {1=>2, 2=>4, 3=>6} # y = {1, 2, 2, 4, 3, 6} # 1.9 doesn't support
+
+ assert_equal(2, x[1])
+
+ assert(begin
+ for k,v in y
+ raise if k*2 != v
+ end
+ true
+ rescue
+ false
+ end)
+
+ assert_equal(3, x.length)
+ assert(x.has_key?(1))
+ assert(x.has_value?(4))
+ assert_equal([4,6], x.values_at(2,3))
+ assert_equal({1=>2, 2=>4, 3=>6}, x)
+
+ z = y.keys.join(":")
+ assert_equal("1:2:3", z)
+
+ z = y.values.join(":")
+ assert_equal("2:4:6", z)
+ assert_equal(x, y)
+
+ y.shift
+ assert_equal(2, y.length)
+
+ z = [1,2]
+ y[z] = 256
+ assert_equal(256, y[z])
+
+ x = Hash.new(0)
+ x[1] = 1
+ assert_equal(1, x[1])
+ assert_equal(0, x[2])
+
+ x = Hash.new([])
+ assert_equal([], x[22])
+ assert_same(x[22], x[22])
+
+ x = Hash.new{[]}
+ assert_equal([], x[22])
+ assert_not_same(x[22], x[22])
+
+ x = Hash.new{|h,k| z = k; h[k] = k*2}
+ z = 0
+ assert_equal(44, x[22])
+ assert_equal(22, z)
+ z = 0
+ assert_equal(44, x[22])
+ assert_equal(0, z)
+ x.default = 5
+ assert_equal(5, x[23])
+
+ x = Hash.new
+ def x.default(k)
+ $z = k
+ self[k] = k*2
+ end
+ $z = 0
+ assert_equal(44, x[22])
+ assert_equal(22, $z)
+ $z = 0
+ assert_equal(44, x[22])
+ assert_equal(0, $z)
+ end
+
+ # From rubicon
+
+ def setup
+ @cls = Hash
+ @h = @cls[
+ 1 => 'one', 2 => 'two', 3 => 'three',
+ self => 'self', true => 'true', nil => 'nil',
+ 'nil' => nil
+ ]
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_s_AREF
+ h = @cls["a" => 100, "b" => 200]
+ assert_equal(100, h['a'])
+ assert_equal(200, h['b'])
+ assert_nil(h['c'])
+
+ h = @cls.[]("a" => 100, "b" => 200)
+ assert_equal(100, h['a'])
+ assert_equal(200, h['b'])
+ assert_nil(h['c'])
+ end
+
+ def test_s_new
+ h = @cls.new
+ assert_instance_of(@cls, h)
+ assert_nil(h.default)
+ assert_nil(h['spurious'])
+
+ h = @cls.new('default')
+ assert_instance_of(@cls, h)
+ assert_equal('default', h.default)
+ assert_equal('default', h['spurious'])
+
+ end
+
+ def test_AREF # '[]'
+ t = Time.now
+ h = @cls[
+ 1 => 'one', 2 => 'two', 3 => 'three',
+ self => 'self', t => 'time', nil => 'nil',
+ 'nil' => nil
+ ]
+
+ assert_equal('one', h[1])
+ assert_equal('two', h[2])
+ assert_equal('three', h[3])
+ assert_equal('self', h[self])
+ assert_equal('time', h[t])
+ assert_equal('nil', h[nil])
+ assert_equal(nil, h['nil'])
+ assert_equal(nil, h['koala'])
+
+ h1 = h.dup
+ h1.default = :default
+
+ assert_equal('one', h1[1])
+ assert_equal('two', h1[2])
+ assert_equal('three', h1[3])
+ assert_equal('self', h1[self])
+ assert_equal('time', h1[t])
+ assert_equal('nil', h1[nil])
+ assert_equal(nil, h1['nil'])
+ assert_equal(:default, h1['koala'])
+
+
+ end
+
+ def test_ASET # '[]='
+ t = Time.now
+ h = @cls.new
+ h[1] = 'one'
+ h[2] = 'two'
+ h[3] = 'three'
+ h[self] = 'self'
+ h[t] = 'time'
+ h[nil] = 'nil'
+ h['nil'] = nil
+ assert_equal('one', h[1])
+ assert_equal('two', h[2])
+ assert_equal('three', h[3])
+ assert_equal('self', h[self])
+ assert_equal('time', h[t])
+ assert_equal('nil', h[nil])
+ assert_equal(nil, h['nil'])
+ assert_equal(nil, h['koala'])
+
+ h[1] = 1
+ h[nil] = 99
+ h['nil'] = nil
+ z = [1,2]
+ h[z] = 256
+ assert_equal(1, h[1])
+ assert_equal('two', h[2])
+ assert_equal('three', h[3])
+ assert_equal('self', h[self])
+ assert_equal('time', h[t])
+ assert_equal(99, h[nil])
+ assert_equal(nil, h['nil'])
+ assert_equal(nil, h['koala'])
+ assert_equal(256, h[z])
+ end
+
+ def test_EQUAL # '=='
+ h1 = @cls[ "a" => 1, "c" => 2 ]
+ h2 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
+ h3 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
+ h4 = @cls[ ]
+ assert(h1 == h1)
+ assert(h2 == h2)
+ assert(h3 == h3)
+ assert(h4 == h4)
+ assert(!(h1 == h2))
+ assert(h2 == h3)
+ assert(!(h3 == h4))
+ end
+
+ def test_clear
+ assert(@h.size > 0)
+ @h.clear
+ assert_equal(0, @h.size)
+ assert_nil(@h[1])
+ end
+
+ def test_clone
+ for taint in [ false, true ]
+ for untrust in [ false, true ]
+ for frozen in [ false, true ]
+ a = @h.clone
+ a.taint if taint
+ a.untrust if untrust
+ a.freeze if frozen
+ b = a.clone
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert_equal(a.frozen?, b.frozen?)
+ assert_equal(a.untrusted?, b.untrusted?)
+ assert_equal(a.tainted?, b.tainted?)
+ end
+ end
+ end
+ end
+
+ def test_default
+ assert_nil(@h.default)
+ h = @cls.new(:xyzzy)
+ assert_equal(:xyzzy, h.default)
+ end
+
+ def test_default=
+ assert_nil(@h.default)
+ @h.default = :xyzzy
+ assert_equal(:xyzzy, @h.default)
+ end
+
+ def test_delete
+ h1 = @cls[ 1 => 'one', 2 => 'two', true => 'true' ]
+ h2 = @cls[ 1 => 'one', 2 => 'two' ]
+ h3 = @cls[ 2 => 'two' ]
+
+ assert_equal('true', h1.delete(true))
+ assert_equal(h2, h1)
+
+ assert_equal('one', h1.delete(1))
+ assert_equal(h3, h1)
+
+ assert_equal('two', h1.delete(2))
+ assert_equal(@cls[], h1)
+
+ assert_nil(h1.delete(99))
+ assert_equal(@cls[], h1)
+
+ assert_equal('default 99', h1.delete(99) {|i| "default #{i}" })
+ end
+
+ def test_delete_if
+ base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
+ h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
+ h2 = @cls[ 2 => false, 'cat' => 99 ]
+ h3 = @cls[ 2 => false ]
+
+ h = base.dup
+ assert_equal(h, h.delete_if { false })
+ assert_equal(@cls[], h.delete_if { true })
+
+ h = base.dup
+ assert_equal(h1, h.delete_if {|k,v| k.instance_of?(String) })
+ assert_equal(h1, h)
+
+ h = base.dup
+ assert_equal(h2, h.delete_if {|k,v| v.instance_of?(String) })
+ assert_equal(h2, h)
+
+ h = base.dup
+ assert_equal(h3, h.delete_if {|k,v| v })
+ assert_equal(h3, h)
+
+ h = base.dup
+ n = 0
+ h.delete_if {|*a|
+ n += 1
+ assert_equal(2, a.size)
+ assert_equal(base[a[0]], a[1])
+ h.shift
+ true
+ }
+ assert_equal(base.size, n)
+ end
+
+ def test_dup
+ for taint in [ false, true ]
+ for untrust in [ false, true ]
+ for frozen in [ false, true ]
+ a = @h.dup
+ a.taint if taint
+ a.freeze if frozen
+ b = a.dup
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert_equal(false, b.frozen?)
+ assert_equal(a.tainted?, b.tainted?)
+ assert_equal(a.untrusted?, b.untrusted?)
+ end
+ end
+ end
+ end
+
+ def test_each
+ count = 0
+ @cls[].each { |k, v| count + 1 }
+ assert_equal(0, count)
+
+ h = @h
+ h.each do |k, v|
+ assert_equal(v, h.delete(k))
+ end
+ assert_equal(@cls[], h)
+ end
+
+ def test_each_key
+ count = 0
+ @cls[].each_key { |k| count + 1 }
+ assert_equal(0, count)
+
+ h = @h
+ h.each_key do |k|
+ h.delete(k)
+ end
+ assert_equal(@cls[], h)
+ end
+
+ def test_each_pair
+ count = 0
+ @cls[].each_pair { |k, v| count + 1 }
+ assert_equal(0, count)
+
+ h = @h
+ h.each_pair do |k, v|
+ assert_equal(v, h.delete(k))
+ end
+ assert_equal(@cls[], h)
+ end
+
+ def test_each_value
+ res = []
+ @cls[].each_value { |v| res << v }
+ assert_equal(0, [].length)
+
+ @h.each_value { |v| res << v }
+ assert_equal(0, [].length)
+
+ expected = []
+ @h.each { |k, v| expected << v }
+
+ assert_equal([], expected - res)
+ assert_equal([], res - expected)
+ end
+
+ def test_empty?
+ assert(@cls[].empty?)
+ assert(!@h.empty?)
+ end
+
+ def test_fetch
+ assert_raise(KeyError) { @cls[].fetch(1) }
+ assert_raise(KeyError) { @h.fetch('gumby') }
+ assert_equal('gumbygumby', @h.fetch('gumby') {|k| k * 2 })
+ assert_equal('pokey', @h.fetch('gumby', 'pokey'))
+
+ assert_equal('one', @h.fetch(1))
+ assert_equal(nil, @h.fetch('nil'))
+ assert_equal('nil', @h.fetch(nil))
+ end
+
+ def test_key?
+ assert(!@cls[].key?(1))
+ assert(!@cls[].key?(nil))
+ assert(@h.key?(nil))
+ assert(@h.key?(1))
+ assert(!@h.key?('gumby'))
+ end
+
+ def test_value?
+ assert(!@cls[].value?(1))
+ assert(!@cls[].value?(nil))
+ assert(@h.value?('one'))
+ assert(@h.value?(nil))
+ assert(!@h.value?('gumby'))
+ end
+
+ def test_include?
+ assert(!@cls[].include?(1))
+ assert(!@cls[].include?(nil))
+ assert(@h.include?(nil))
+ assert(@h.include?(1))
+ assert(!@h.include?('gumby'))
+ end
+
+ def test_key
+ assert_equal(1, @h.key('one'))
+ assert_equal(nil, @h.key('nil'))
+ assert_equal('nil', @h.key(nil))
+
+ assert_equal(nil, @h.key('gumby'))
+ assert_equal(nil, @cls[].key('gumby'))
+ end
+
+ def test_values_at
+ res = @h.values_at('dog', 'cat', 'horse')
+ assert(res.length == 3)
+ assert_equal([nil, nil, nil], res)
+
+ res = @h.values_at
+ assert(res.length == 0)
+
+ res = @h.values_at(3, 2, 1, nil)
+ assert_equal 4, res.length
+ assert_equal %w( three two one nil ), res
+
+ res = @h.values_at(3, 99, 1, nil)
+ assert_equal 4, res.length
+ assert_equal ['three', nil, 'one', 'nil'], res
+ end
+
+
+ def test_invert
+ h = @h.invert
+ assert_equal(1, h['one'])
+ assert_equal(true, h['true'])
+ assert_equal(nil, h['nil'])
+
+ h.each do |k, v|
+ assert(@h.key?(v)) # not true in general, but works here
+ end
+
+ h = @cls[ 'a' => 1, 'b' => 2, 'c' => 1].invert
+ assert_equal(2, h.length)
+ assert(h[1] == 'a' || h[1] == 'c')
+ assert_equal('b', h[2])
+ end
+
+ def test_key?
+ assert(!@cls[].key?(1))
+ assert(!@cls[].key?(nil))
+ assert(@h.key?(nil))
+ assert(@h.key?(1))
+ assert(!@h.key?('gumby'))
+ end
+
+ def test_keys
+ assert_equal([], @cls[].keys)
+
+ keys = @h.keys
+ expected = []
+ @h.each { |k, v| expected << k }
+ assert_equal([], keys - expected)
+ assert_equal([], expected - keys)
+ end
+
+ def test_length
+ assert_equal(0, @cls[].length)
+ assert_equal(7, @h.length)
+ end
+
+ def test_member?
+ assert(!@cls[].member?(1))
+ assert(!@cls[].member?(nil))
+ assert(@h.member?(nil))
+ assert(@h.member?(1))
+ assert(!@h.member?('gumby'))
+ end
+
+ def test_rehash
+ a = [ "a", "b" ]
+ c = [ "c", "d" ]
+ h = @cls[ a => 100, c => 300 ]
+ assert_equal(100, h[a])
+ a[0] = "z"
+ assert_nil(h[a])
+ h.rehash
+ assert_equal(100, h[a])
+ end
+
+ def test_reject
+ base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
+ h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
+ h2 = @cls[ 2 => false, 'cat' => 99 ]
+ h3 = @cls[ 2 => false ]
+
+ h = base.dup
+ assert_equal(h, h.reject { false })
+ assert_equal(@cls[], h.reject { true })
+
+ h = base.dup
+ assert_equal(h1, h.reject {|k,v| k.instance_of?(String) })
+
+ assert_equal(h2, h.reject {|k,v| v.instance_of?(String) })
+
+ assert_equal(h3, h.reject {|k,v| v })
+ assert_equal(base, h)
+ end
+
+ def test_reject!
+ base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
+ h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
+ h2 = @cls[ 2 => false, 'cat' => 99 ]
+ h3 = @cls[ 2 => false ]
+
+ h = base.dup
+ assert_equal(nil, h.reject! { false })
+ assert_equal(@cls[], h.reject! { true })
+
+ h = base.dup
+ assert_equal(h1, h.reject! {|k,v| k.instance_of?(String) })
+ assert_equal(h1, h)
+
+ h = base.dup
+ assert_equal(h2, h.reject! {|k,v| v.instance_of?(String) })
+ assert_equal(h2, h)
+
+ h = base.dup
+ assert_equal(h3, h.reject! {|k,v| v })
+ assert_equal(h3, h)
+ end
+
+ def test_replace
+ h = @cls[ 1 => 2, 3 => 4 ]
+ h1 = h.replace(@cls[ 9 => 8, 7 => 6 ])
+ assert_equal(h, h1)
+ assert_equal(8, h[9])
+ assert_equal(6, h[7])
+ assert_nil(h[1])
+ assert_nil(h[2])
+ end
+
+ def test_shift
+ h = @h.dup
+
+ @h.length.times {
+ k, v = h.shift
+ assert(@h.key?(k))
+ assert_equal(@h[k], v)
+ }
+
+ assert_equal(0, h.length)
+ end
+
+ def test_size
+ assert_equal(0, @cls[].length)
+ assert_equal(7, @h.length)
+ end
+
+ def test_sort
+ h = @cls[].sort
+ assert_equal([], h)
+
+ h = @cls[ 1 => 1, 2 => 1 ].sort
+ assert_equal([[1,1], [2,1]], h)
+
+ h = @cls[ 'cat' => 'feline', 'ass' => 'asinine', 'bee' => 'beeline' ]
+ h1 = h.sort
+ assert_equal([ %w(ass asinine), %w(bee beeline), %w(cat feline)], h1)
+ end
+
+ def test_store
+ t = Time.now
+ h = @cls.new
+ h.store(1, 'one')
+ h.store(2, 'two')
+ h.store(3, 'three')
+ h.store(self, 'self')
+ h.store(t, 'time')
+ h.store(nil, 'nil')
+ h.store('nil', nil)
+ assert_equal('one', h[1])
+ assert_equal('two', h[2])
+ assert_equal('three', h[3])
+ assert_equal('self', h[self])
+ assert_equal('time', h[t])
+ assert_equal('nil', h[nil])
+ assert_equal(nil, h['nil'])
+ assert_equal(nil, h['koala'])
+
+ h.store(1, 1)
+ h.store(nil, 99)
+ h.store('nil', nil)
+ assert_equal(1, h[1])
+ assert_equal('two', h[2])
+ assert_equal('three', h[3])
+ assert_equal('self', h[self])
+ assert_equal('time', h[t])
+ assert_equal(99, h[nil])
+ assert_equal(nil, h['nil'])
+ assert_equal(nil, h['koala'])
+ end
+
+ def test_to_a
+ assert_equal([], @cls[].to_a)
+ assert_equal([[1,2]], @cls[ 1=>2 ].to_a)
+ a = @cls[ 1=>2, 3=>4, 5=>6 ].to_a
+ assert_equal([1,2], a.delete([1,2]))
+ assert_equal([3,4], a.delete([3,4]))
+ assert_equal([5,6], a.delete([5,6]))
+ assert_equal(0, a.length)
+
+ h = @cls[ 1=>2, 3=>4, 5=>6 ]
+ h.taint
+ h.untrust
+ a = h.to_a
+ assert_equal(true, a.tainted?)
+ assert_equal(true, a.untrusted?)
+ end
+
+ def test_to_hash
+ h = @h.to_hash
+ assert_equal(@h, h)
+ end
+
+ def test_to_s
+ h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ]
+ assert_equal(h.inspect, h.to_s)
+ $, = ":"
+ assert_equal(h.inspect, h.to_s)
+ h = @cls[]
+ assert_equal(h.inspect, h.to_s)
+ $, = nil
+ end
+
+ def test_update
+ h1 = @cls[ 1 => 2, 2 => 3, 3 => 4 ]
+ h2 = @cls[ 2 => 'two', 4 => 'four' ]
+
+ ha = @cls[ 1 => 2, 2 => 'two', 3 => 4, 4 => 'four' ]
+ hb = @cls[ 1 => 2, 2 => 3, 3 => 4, 4 => 'four' ]
+
+ assert_equal(ha, h1.update(h2))
+ assert_equal(ha, h1)
+
+ h1 = @cls[ 1 => 2, 2 => 3, 3 => 4 ]
+ h2 = @cls[ 2 => 'two', 4 => 'four' ]
+
+ assert_equal(hb, h2.update(h1))
+ assert_equal(hb, h2)
+ end
+
+ def test_value?
+ assert(!@cls[].value?(1))
+ assert(!@cls[].value?(nil))
+ assert(@h.value?(nil))
+ assert(@h.value?('one'))
+ assert(!@h.value?('gumby'))
+ end
+
+ def test_values
+ assert_equal([], @cls[].values)
+
+ vals = @h.values
+ expected = []
+ @h.each { |k, v| expected << v }
+ assert_equal([], vals - expected)
+ assert_equal([], expected - vals)
+ end
+
+ def test_security_check
+ h = {}
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ h[1] = 1
+ end.join
+ end
+ end
+
+ def test_intialize_wrong_arguments
+ assert_raise(ArgumentError) do
+ Hash.new(0) { }
+ end
+ end
+
+ def test_create
+ assert_equal({1=>2, 3=>4}, Hash[[[1,2],[3,4]]])
+ assert_raise(ArgumentError) { Hash[0, 1, 2] }
+ assert_equal({1=>2, 3=>4}, Hash[1,2,3,4])
+ o = Object.new
+ def o.to_hash() {1=>2} end
+ assert_equal({1=>2}, Hash[o], "[ruby-dev:34555]")
+ end
+
+ def test_rehash2
+ h = {1 => 2, 3 => 4}
+ assert_equal(h.dup, h.rehash)
+ assert_raise(RuntimeError) { h.each { h.rehash } }
+ assert_equal({}, {}.rehash)
+ end
+
+ def test_fetch2
+ assert_equal(:bar, @h.fetch(0, :foo) { :bar })
+ end
+
+ def test_default_proc
+ h = Hash.new {|h, k| h + k + "baz" }
+ assert_equal("foobarbaz", h.default_proc.call("foo", "bar"))
+ h = {}
+ assert_nil(h.default_proc)
+ end
+
+ def test_shift2
+ h = Hash.new {|h, k| :foo }
+ h[1] = 2
+ assert_equal([1, 2], h.shift)
+ assert_equal(:foo, h.shift)
+ assert_equal(:foo, h.shift)
+
+ h = Hash.new(:foo)
+ h[1] = 2
+ assert_equal([1, 2], h.shift)
+ assert_equal(:foo, h.shift)
+ assert_equal(:foo, h.shift)
+
+ h = {1=>2}
+ h.each { assert_equal([1, 2], h.shift) }
+ end
+
+ def test_reject_bang2
+ assert_equal({1=>2}, {1=>2,3=>4}.reject! {|k, v| k + v == 7 })
+ assert_nil({1=>2,3=>4}.reject! {|k, v| k == 5 })
+ assert_nil({}.reject! { })
+ end
+
+ def test_select
+ assert_equal({3=>4,5=>6}, {1=>2,3=>4,5=>6}.select {|k, v| k + v >= 7 })
+ end
+
+ def test_clear2
+ assert_equal({}, {1=>2,3=>4,5=>6}.clear)
+ h = {1=>2,3=>4,5=>6}
+ h.each { h.clear }
+ assert_equal({}, h)
+ end
+
+ def test_replace2
+ h1 = Hash.new { :foo }
+ h2 = {}
+ h2.replace h1
+ assert_equal(:foo, h2[0])
+ end
+
+ def test_size2
+ assert_equal(0, {}.size)
+ end
+
+ def test_equal2
+ assert({} != 0)
+ o = Object.new
+ def o.to_hash; {}; end
+ def o.==(x); true; end
+ assert({} == o)
+ def o.==(x); false; end
+ assert({} != o)
+
+ h1 = {1=>2}; h2 = {3=>4}
+ assert(h1 != h2)
+ h1 = {1=>2}; h2 = {1=>4}
+ assert(h1 != h2)
+
+ h1 = {}; h1[h1] = h1; h1.rehash
+ h2 = {}; h2[h2] = h2; h2.rehash
+ assert(h1 != h2)
+ end
+
+ def test_eql
+ assert(!({}.eql?(0)))
+ o = Object.new
+ def o.to_hash; {}; end
+ def o.eql?(x); true; end
+ assert({}.eql?(o))
+ def o.eql?(x); false; end
+ assert(!({}.eql?(o)))
+ end
+
+ def test_hash2
+ assert_kind_of(Integer, {}.hash)
+ end
+
+ def test_update2
+ h1 = {1=>2, 3=>4}
+ h2 = {1=>3, 5=>7}
+ h1.update(h2) {|k, v1, v2| k + v1 + v2 }
+ assert_equal({1=>6, 3=>4, 5=>7}, h1)
+ end
+
+ def test_merge
+ h1 = {1=>2, 3=>4}
+ h2 = {1=>3, 5=>7}
+ assert_equal({1=>3, 3=>4, 5=>7}, h1.merge(h2))
+ assert_equal({1=>6, 3=>4, 5=>7}, h1.merge(h2) {|k, v1, v2| k + v1 + v2 })
+ end
+
+ def test_assoc
+ assert_equal([3,4], {1=>2, 3=>4, 5=>6}.assoc(3))
+ assert_nil({1=>2, 3=>4, 5=>6}.assoc(4))
+ end
+
+ def test_rassoc
+ assert_equal([3,4], {1=>2, 3=>4, 5=>6}.rassoc(4))
+ assert_nil({1=>2, 3=>4, 5=>6}.rassoc(3))
+ end
+
+ def test_flatten
+ assert_equal([[1], [2]], {[1] => [2]}.flatten)
+ end
+
+ def test_callcc
+ h = {1=>2}
+ c = nil
+ f = false
+ h.each { callcc {|c2| c = c2 } }
+ unless f
+ f = true
+ c.call
+ end
+ assert_raise(RuntimeError) { h.each { h.rehash } }
+
+ h = {1=>2}
+ c = nil
+ assert_raise(RuntimeError) do
+ h.each { callcc {|c2| c = c2 } }
+ h.clear
+ c.call
+ end
+ end
+
+ def test_compare_by_identity
+ a = "foo"
+ assert(!{}.compare_by_identity?)
+ h = { a => "bar" }
+ assert(!h.compare_by_identity?)
+ h.compare_by_identity
+ assert(h.compare_by_identity?)
+ #assert_equal("bar", h[a])
+ assert_nil(h["foo"])
+ end
+
+ def test_hash_hash
+ assert_equal({0=>2,11=>1}.hash, {11=>1,0=>2}.hash)
+ end
+end
diff --git a/trunk/test/ruby/test_ifunless.rb b/trunk/test/ruby/test_ifunless.rb
new file mode 100644
index 0000000000..bffc794512
--- /dev/null
+++ b/trunk/test/ruby/test_ifunless.rb
@@ -0,0 +1,14 @@
+require 'test/unit'
+
+class TestIfunless < Test::Unit::TestCase
+ def test_if_unless
+ $x = 'test';
+ assert(if $x == $x then true else false end)
+ $bad = false
+ unless $x == $x
+ $bad = true
+ end
+ assert(!$bad)
+ assert(unless $x != $x then true else false end)
+ end
+end
diff --git a/trunk/test/ruby/test_integer.rb b/trunk/test/ruby/test_integer.rb
new file mode 100644
index 0000000000..e31fb1880d
--- /dev/null
+++ b/trunk/test/ruby/test_integer.rb
@@ -0,0 +1,193 @@
+require 'test/unit'
+
+class TestInteger < Test::Unit::TestCase
+ BDSIZE = 0x4000000000000000.coerce(0)[0].size
+ def self.bdsize(x)
+ ((x + 1) / 8 + BDSIZE) / BDSIZE * BDSIZE
+ end
+ def bdsize(x)
+ self.class.bdsize(x)
+ end
+
+ def test_aref
+ # assert_equal(1, (1 << 0x40000000)[0x40000000], "[ruby-dev:31271]")
+ # assert_equal(0, (-1 << 0x40000001)[0x40000000], "[ruby-dev:31271]")
+ big_zero = 0x40000000.coerce(0)[0]
+ assert_equal(0, (-0x40000002)[big_zero], "[ruby-dev:31271]")
+ assert_equal(1, 0x400000001[big_zero], "[ruby-dev:31271]")
+ end
+
+ def test_pow
+ assert_not_equal(0, begin
+ 0**-1
+ rescue
+ nil
+ end, "[ruby-dev:32084] [ruby-dev:34547]")
+ end
+
+ def test_lshift
+ assert_equal(0, 1 << -0x40000000)
+ assert_equal(0, 1 << -0x40000001)
+ assert_equal(0, 1 << -0x80000000)
+ assert_equal(0, 1 << -0x80000001)
+ # assert_equal(bdsize(0x80000000), (1 << 0x80000000).size)
+ end
+
+ def test_rshift
+ # assert_equal(bdsize(0x40000001), (1 >> -0x40000001).size)
+ assert((1 >> 0x80000000).zero?)
+ assert((1 >> 0xffffffff).zero?)
+ assert((1 >> 0x100000000).zero?)
+ # assert_equal((1 << 0x40000000), (1 >> -0x40000000))
+ # assert_equal((1 << 0x40000001), (1 >> -0x40000001))
+ end
+
+ def test_Integer
+ assert_raise(ArgumentError) {Integer("0x-1")}
+ assert_raise(ArgumentError) {Integer("-0x-1")}
+ assert_raise(ArgumentError) {Integer("0x 123")}
+ assert_raise(ArgumentError) {Integer("0x 123")}
+ assert_raise(ArgumentError) {Integer("0x0x5")}
+ assert_raise(ArgumentError) {Integer("0x0x000000005")}
+ assert_nothing_raised(ArgumentError) {
+ assert_equal(1540841, "0x0x5".to_i(36))
+ }
+ assert_raise(ArgumentError) { Integer("--0") }
+ assert_raise(ArgumentError) { Integer("-+0") }
+ assert_raise(ArgumentError) { Integer("++1") }
+ assert_raise(ArgumentError) { Integer("") }
+ assert_raise(ArgumentError) { Integer("10 x") }
+ assert_raise(ArgumentError) { Integer("1__2") }
+ assert_raise(ArgumentError) { Integer("1z") }
+ assert_raise(ArgumentError) { Integer("46116860184273__87904") }
+ assert_raise(ArgumentError) { Integer("4611686018427387904_") }
+ assert_raise(ArgumentError) { Integer("4611686018427387904 :") }
+ assert_equal(0x4000000000000000, Integer("46_11_686_0184273_87904"))
+ assert_raise(ArgumentError) { Integer("\0") }
+ assert_nothing_raised(ArgumentError, "[ruby-core:13873]") {
+ assert_equal(0, Integer("0 "))
+ }
+ assert_nothing_raised(ArgumentError, "[ruby-core:14139]") {
+ assert_equal(0377, Integer("0_3_7_7"))
+ }
+ assert_raise(ArgumentError, "[ruby-core:14139]") {Integer("0__3_7_7")}
+ end
+
+ def test_int_p
+ assert(!(1.0.integer?))
+ assert(1.integer?)
+ end
+
+ def test_odd_p_even_p
+ Fixnum.class_eval do
+ alias odd_bak odd?
+ alias even_bak even?
+ remove_method :odd?, :even?
+ end
+
+ assert(1.odd?)
+ assert(!(2.odd?))
+ assert(!(1.even?))
+ assert(2.even?)
+
+ ensure
+ Fixnum.class_eval do
+ alias odd? odd_bak
+ alias even? even_bak
+ remove_method :odd_bak, :even_bak
+ end
+ end
+
+ def test_succ
+ assert_equal(2, 1.send(:succ))
+
+ Fixnum.class_eval do
+ alias succ_bak succ
+ remove_method :succ
+ end
+
+ assert_equal(2, 1.succ)
+ assert_equal(4294967297, 4294967296.succ)
+
+ ensure
+ Fixnum.class_eval do
+ alias succ succ_bak
+ remove_method :succ_bak
+ end
+ end
+
+ def test_chr
+ assert_equal("a", "a".ord.chr)
+ assert_raise(RangeError) { (-1).chr }
+ assert_raise(RangeError) { 0x100.chr }
+ end
+
+ def test_induced_from
+ assert_equal(1, Integer.induced_from(1))
+ assert_equal(1, Integer.induced_from(1.0))
+ assert_raise(TypeError) { Integer.induced_from(nil) }
+ end
+
+ def test_upto
+ a = []
+ 1.upto(3) {|x| a << x }
+ assert_equal([1, 2, 3], a)
+
+ a = []
+ 1.upto(0) {|x| a << x }
+ assert_equal([], a)
+
+ x = 2**30 - 1
+ a = []
+ x.upto(x+2) {|x| a << x }
+ assert_equal([x, x+1, x+2], a)
+ end
+
+ def test_downto
+ a = []
+ -1.downto(-3) {|x| a << x }
+ assert_equal([-1, -2, -3], a)
+
+ a = []
+ 1.downto(2) {|x| a << x }
+ assert_equal([], a)
+
+ x = -(2**30)
+ a = []
+ x.downto(x-2) {|x| a << x }
+ assert_equal([x, x-1, x-2], a)
+ end
+
+ def test_times
+ (2**32).times do |i|
+ break if i == 2
+ end
+ end
+
+ def test_round
+ assert_equal(11111, 11111.round)
+ assert_equal(Fixnum, 11111.round.class)
+ assert_equal(11111, 11111.round(0))
+ assert_equal(Fixnum, 11111.round(0).class)
+
+ assert_equal(11111.0, 11111.round(1))
+ assert_equal(Float, 11111.round(1).class)
+ assert_equal(11111.0, 11111.round(2))
+ assert_equal(Float, 11111.round(2).class)
+
+ assert_equal(11110, 11111.round(-1))
+ assert_equal(Fixnum, 11111.round(-1).class)
+ assert_equal(11100, 11111.round(-2))
+ assert_equal(Fixnum, 11111.round(-2).class)
+
+ assert_equal(1111_1111_1111_1111_1111_1111_1111_1110, 1111_1111_1111_1111_1111_1111_1111_1111.round(-1))
+ assert_equal(Bignum, 1111_1111_1111_1111_1111_1111_1111_1111.round(-1).class)
+ assert_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).round(-1))
+ assert_equal(Bignum, (-1111_1111_1111_1111_1111_1111_1111_1111).round(-1).class)
+ end
+
+ def test_Integer2
+ assert_equal(2 ** 50, Integer(2.0 ** 50))
+ assert_raise(TypeError) { Integer(nil) }
+ end
+end
diff --git a/trunk/test/ruby/test_integer_comb.rb b/trunk/test/ruby/test_integer_comb.rb
new file mode 100644
index 0000000000..7cac5d6ad2
--- /dev/null
+++ b/trunk/test/ruby/test_integer_comb.rb
@@ -0,0 +1,620 @@
+require 'test/unit'
+
+class TestIntegerComb < Test::Unit::TestCase
+ VS = [
+ -0x1000000000000000000000000000000000000000000000002,
+ -0x1000000000000000000000000000000000000000000000001,
+ -0x1000000000000000000000000000000000000000000000000,
+ -0xffffffffffffffffffffffffffffffffffffffffffffffff,
+ -0x1000000000000000000000002,
+ -0x1000000000000000000000001,
+ -0x1000000000000000000000000,
+ -0xffffffffffffffffffffffff,
+ -0x10000000000000002,
+ -0x10000000000000001,
+ -0x10000000000000000,
+ -0xffffffffffffffff,
+ -0x4000000000000002,
+ -0x4000000000000001,
+ -0x4000000000000000,
+ -0x3fffffffffffffff,
+ -0x100000002,
+ -0x100000001,
+ -0x100000000,
+ -0xffffffff,
+ -0xc717a08d, # 0xc717a08d * 0x524b2245 = 0x4000000000000001
+ -0x80000002,
+ -0x80000001,
+ -0x80000000,
+ -0x7fffffff,
+ -0x524b2245,
+ -0x40000002,
+ -0x40000001,
+ -0x40000000,
+ -0x3fffffff,
+ -0x10002,
+ -0x10001,
+ -0x10000,
+ -0xffff,
+ -0x8101, # 0x8101 * 0x7f01 = 0x40000001
+ -0x8002,
+ -0x8001,
+ -0x8000,
+ -0x7fff,
+ -0x7f01,
+ -65,
+ -64,
+ -63,
+ -62,
+ -33,
+ -32,
+ -31,
+ -30,
+ -3,
+ -2,
+ -1,
+ 0,
+ 1,
+ 2,
+ 3,
+ 30,
+ 31,
+ 32,
+ 33,
+ 62,
+ 63,
+ 64,
+ 65,
+ 0x7f01,
+ 0x7ffe,
+ 0x7fff,
+ 0x8000,
+ 0x8001,
+ 0x8101,
+ 0xfffe,
+ 0xffff,
+ 0x10000,
+ 0x10001,
+ 0x3ffffffe,
+ 0x3fffffff,
+ 0x40000000,
+ 0x40000001,
+ 0x524b2245,
+ 0x7ffffffe,
+ 0x7fffffff,
+ 0x80000000,
+ 0x80000001,
+ 0xc717a08d,
+ 0xfffffffe,
+ 0xffffffff,
+ 0x100000000,
+ 0x100000001,
+ 0x3ffffffffffffffe,
+ 0x3fffffffffffffff,
+ 0x4000000000000000,
+ 0x4000000000000001,
+ 0xfffffffffffffffe,
+ 0xffffffffffffffff,
+ 0x10000000000000000,
+ 0x10000000000000001,
+ 0xffffffffffffffffffffffff,
+ 0x1000000000000000000000000,
+ 0x1000000000000000000000001,
+ 0xffffffffffffffffffffffffffffffffffffffffffffffff,
+ 0x1000000000000000000000000000000000000000000000000,
+ 0x1000000000000000000000000000000000000000000000001
+ ]
+
+ #VS.map! {|v| 0x4000000000000000.coerce(v)[0] }
+
+ min = -1
+ min *= 2 while min.class == Fixnum
+ FIXNUM_MIN = min/2
+ max = 1
+ max *= 2 while (max-1).class == Fixnum
+ FIXNUM_MAX = max/2-1
+
+ def test_fixnum_range
+ assert_instance_of(Bignum, FIXNUM_MIN-1)
+ assert_instance_of(Fixnum, FIXNUM_MIN)
+ assert_instance_of(Fixnum, FIXNUM_MAX)
+ assert_instance_of(Bignum, FIXNUM_MAX+1)
+ end
+
+ def check_class(n)
+ if FIXNUM_MIN <= n && n <= FIXNUM_MAX
+ assert_instance_of(Fixnum, n)
+ else
+ assert_instance_of(Bignum, n)
+ end
+ end
+
+ def test_aref
+ VS.each {|a|
+ 100.times {|i|
+ assert_equal((a >> i).odd? ? 1 : 0, a[i], "(#{a})[#{i}]")
+ }
+ }
+ VS.each {|a|
+ VS.each {|b|
+ c = nil
+ assert_nothing_raised("(#{a})[#{b}]") { c = a[b] }
+ check_class(c)
+ if b < 0
+ assert_equal(0, c, "(#{a})[#{b}]")
+ else
+ assert_equal((a >> b).odd? ? 1 : 0, c, "(#{a})[#{b}]")
+ end
+ }
+ }
+ end
+
+ def test_plus
+ VS.each {|a|
+ VS.each {|b|
+ c = a + b
+ check_class(c)
+ assert_equal(b + a, c, "#{a} + #{b}")
+ assert_equal(a, c - b, "(#{a} + #{b}) - #{b}")
+ assert_equal(a-~b-1, c, "#{a} + #{b}") # Hacker's Delight
+ assert_equal((a^b)+2*(a&b), c, "#{a} + #{b}") # Hacker's Delight
+ assert_equal((a|b)+(a&b), c, "#{a} + #{b}") # Hacker's Delight
+ assert_equal(2*(a|b)-(a^b), c, "#{a} + #{b}") # Hacker's Delight
+ }
+ }
+ end
+
+ def test_minus
+ VS.each {|a|
+ VS.each {|b|
+ c = a - b
+ check_class(c)
+ assert_equal(a, c + b, "(#{a} - #{b}) + #{b}")
+ assert_equal(-b, c - a, "(#{a} - #{b}) - #{a}")
+ assert_equal(a+~b+1, c, "#{a} - #{b}") # Hacker's Delight
+ assert_equal((a^b)-2*(b&~a), c, "#{a} - #{b}") # Hacker's Delight
+ assert_equal((a&~b)-(b&~a), c, "#{a} - #{b}") # Hacker's Delight
+ assert_equal(2*(a&~b)-(a^b), c, "#{a} - #{b}") # Hacker's Delight
+ }
+ }
+ end
+
+ def test_mult
+ VS.each {|a|
+ VS.each {|b|
+ c = a * b
+ check_class(c)
+ assert_equal(b * a, c, "#{a} * #{b}")
+ assert_equal(b, c / a, "(#{a} * #{b}) / #{a}") if a != 0
+ assert_equal(a.abs * b.abs, (a * b).abs, "(#{a} * #{b}).abs")
+ assert_equal((a-100)*(b-100)+(a-100)*100+(b-100)*100+10000, c, "#{a} * #{b}")
+ assert_equal((a+100)*(b+100)-(a+100)*100-(b+100)*100+10000, c, "#{a} * #{b}")
+ }
+ }
+ end
+
+ def test_divmod
+ VS.each {|a|
+ VS.each {|b|
+ if b == 0
+ assert_raise(ZeroDivisionError) { a.divmod(b) }
+ else
+ q, r = a.divmod(b)
+ check_class(q)
+ check_class(r)
+ assert_equal(a, b*q+r)
+ assert(r.abs < b.abs)
+ assert(0 < b ? (0 <= r && r < b) : (b < r && r <= 0))
+ assert_equal(q, a/b)
+ assert_equal(q, a.div(b))
+ assert_equal(r, a%b)
+ assert_equal(r, a.modulo(b))
+ end
+ }
+ }
+ end
+
+ def test_pow
+ small_values = VS.find_all {|v| 0 <= v && v < 1000 }
+ VS.each {|a|
+ small_values.each {|b|
+ c = a ** b
+ check_class(c)
+ d = 1
+ b.times { d *= a }
+ assert_equal(d, c, "(#{a}) ** #{b}")
+ if a != 0
+ d = c
+ b.times { d /= a }
+ assert_equal(1, d, "((#{a}) ** #{b}) / #{a} / ...(#{b} times)...")
+ end
+ }
+ }
+ end
+
+ def test_not
+ VS.each {|a|
+ b = ~a
+ check_class(b)
+ assert_equal(-1 ^ a, b, "~#{a}")
+ assert_equal(-a-1, b, "~#{a}") # Hacker's Delight
+ assert_equal(0, a & b, "#{a} & ~#{a}")
+ assert_equal(-1, a | b, "#{a} | ~#{a}")
+ }
+ end
+
+ def test_or
+ VS.each {|a|
+ VS.each {|b|
+ c = a | b
+ check_class(c)
+ assert_equal(b | a, c, "#{a} | #{b}")
+ assert_equal(a + b - (a&b), c, "#{a} | #{b}")
+ assert_equal((a & ~b) + b, c, "#{a} | #{b}") # Hacker's Delight
+ assert_equal(-1, c | ~a, "(#{a} | #{b}) | ~#{a})")
+ }
+ }
+ end
+
+ def test_and
+ VS.each {|a|
+ VS.each {|b|
+ c = a & b
+ check_class(c)
+ assert_equal(b & a, c, "#{a} & #{b}")
+ assert_equal(a + b - (a|b), c, "#{a} & #{b}")
+ assert_equal((~a | b) - ~a, c, "#{a} & #{b}") # Hacker's Delight
+ assert_equal(0, c & ~a, "(#{a} & #{b}) & ~#{a}")
+ }
+ }
+ end
+
+ def test_xor
+ VS.each {|a|
+ VS.each {|b|
+ c = a ^ b
+ check_class(c)
+ assert_equal(b ^ a, c, "#{a} ^ #{b}")
+ assert_equal((a|b)-(a&b), c, "#{a} ^ #{b}") # Hacker's Delight
+ assert_equal(b, c ^ a, "(#{a} ^ #{b}) ^ #{a}")
+ }
+ }
+ end
+
+ def test_lshift
+ small_values = VS.find_all {|v| v < 8000 }
+ VS.each {|a|
+ small_values.each {|b|
+ c = a << b
+ check_class(c)
+ if 0 <= b
+ assert_equal(a, c >> b, "(#{a} << #{b}) >> #{b}")
+ assert_equal(a * 2**b, c, "#{a} << #{b}")
+ end
+ 0.upto(c.size*8+10) {|nth|
+ assert_equal(a[nth-b], c[nth], "(#{a} << #{b})[#{nth}]")
+ }
+ }
+ }
+ end
+
+ def test_rshift
+ small_values = VS.find_all {|v| -8000 < v }
+ VS.each {|a|
+ small_values.each {|b|
+ c = a >> b
+ check_class(c)
+ if b <= 0
+ assert_equal(a, c << b, "(#{a} >> #{b}) << #{b}")
+ assert_equal(a * 2**(-b), c, "#{a} >> #{b}")
+ end
+ 0.upto(c.size*8+10) {|nth|
+ assert_equal(a[nth+b], c[nth], "(#{a} >> #{b})[#{nth}]")
+ }
+ }
+ }
+ end
+
+ def test_succ
+ VS.each {|a|
+ b = a.succ
+ check_class(b)
+ assert_equal(a+1, b, "(#{a}).succ")
+ assert_equal(a, b.pred, "(#{a}).succ.pred")
+ assert_equal(a, b-1, "(#{a}).succ - 1")
+ }
+ end
+
+ def test_pred
+ VS.each {|a|
+ b = a.pred
+ check_class(b)
+ assert_equal(a-1, b, "(#{a}).pred")
+ assert_equal(a, b.succ, "(#{a}).pred.succ")
+ assert_equal(a, b + 1, "(#{a}).pred + 1")
+ }
+ end
+
+ def test_unary_plus
+ VS.each {|a|
+ b = +a
+ check_class(b)
+ assert_equal(a, b, "+(#{a})")
+ }
+ end
+
+ def test_unary_minus
+ VS.each {|a|
+ b = -a
+ check_class(b)
+ assert_equal(0-a, b, "-(#{a})")
+ assert_equal(~a+1, b, "-(#{a})")
+ assert_equal(0, a+b, "#{a}+(-(#{a}))")
+ }
+ end
+
+ def test_cmp
+ VS.each_with_index {|a, i|
+ VS.each_with_index {|b, j|
+ assert_equal(i <=> j, a <=> b, "#{a} <=> #{b}")
+ assert_equal(i < j, a < b, "#{a} < #{b}")
+ assert_equal(i <= j, a <= b, "#{a} <= #{b}")
+ assert_equal(i > j, a > b, "#{a} > #{b}")
+ assert_equal(i >= j, a >= b, "#{a} >= #{b}")
+ }
+ }
+ end
+
+ def test_eq
+ VS.each_with_index {|a, i|
+ VS.each_with_index {|b, j|
+ c = a == b
+ assert_equal(b == a, c, "#{a} == #{b}")
+ assert_equal(i == j, c, "#{a} == #{b}")
+ }
+ }
+ end
+
+ def test_abs
+ VS.each {|a|
+ b = a.abs
+ check_class(b)
+ if a < 0
+ assert_equal(-a, b, "(#{a}).abs")
+ else
+ assert_equal(a, b, "(#{a}).abs")
+ end
+ }
+ end
+
+ def test_ceil
+ VS.each {|a|
+ b = a.ceil
+ check_class(b)
+ assert_equal(a, b, "(#{a}).ceil")
+ }
+ end
+
+ def test_floor
+ VS.each {|a|
+ b = a.floor
+ check_class(b)
+ assert_equal(a, b, "(#{a}).floor")
+ }
+ end
+
+ def test_round
+ VS.each {|a|
+ b = a.round
+ check_class(b)
+ assert_equal(a, b, "(#{a}).round")
+ }
+ end
+
+ def test_truncate
+ VS.each {|a|
+ b = a.truncate
+ check_class(b)
+ assert_equal(a, b, "(#{a}).truncate")
+ }
+ end
+
+ def test_remainder
+ VS.each {|a|
+ VS.each {|b|
+ if b == 0
+ assert_raise(ZeroDivisionError) { a.divmod(b) }
+ else
+ r = a.remainder(b)
+ check_class(r)
+ if a < 0
+ assert_operator(-b.abs, :<, r, "#{a}.remainder(#{b})")
+ assert_operator(0, :>=, r, "#{a}.remainder(#{b})")
+ elsif 0 < a
+ assert_operator(0, :<=, r, "#{a}.remainder(#{b})")
+ assert_operator(b.abs, :>, r, "#{a}.remainder(#{b})")
+ else
+ assert_equal(0, r, "#{a}.remainder(#{b})")
+ end
+ end
+ }
+ }
+ end
+
+ def test_zero_nonzero
+ VS.each {|a|
+ z = a.zero?
+ n = a.nonzero?
+ if a == 0
+ assert_equal(true, z, "(#{a}).zero?")
+ assert_equal(nil, n, "(#{a}).nonzero?")
+ else
+ assert_equal(false, z, "(#{a}).zero?")
+ assert_equal(a, n, "(#{a}).nonzero?")
+ check_class(n)
+ end
+ assert(z ^ n, "(#{a}).zero? ^ (#{a}).nonzero?")
+ }
+ end
+
+ def test_even_odd
+ VS.each {|a|
+ e = a.even?
+ o = a.odd?
+ assert_equal((a % 2) == 0, e, "(#{a}).even?")
+ assert_equal((a % 2) == 1, o, "(#{a}).odd")
+ assert_equal((a & 1) == 0, e, "(#{a}).even?")
+ assert_equal((a & 1) == 1, o, "(#{a}).odd")
+ assert(e ^ o, "(#{a}).even? ^ (#{a}).odd?")
+ }
+ end
+
+ def test_to_s
+ 2.upto(36) {|radix|
+ VS.each {|a|
+ s = a.to_s(radix)
+ b = s.to_i(radix)
+ assert_equal(a, b, "(#{a}).to_s(#{radix}).to_i(#{radix})")
+ }
+ }
+ end
+
+ def test_printf_x
+ VS.reverse_each {|a|
+ s = sprintf("%x", a)
+ if /\A\.\./ =~ s
+ b = -($'.tr('0123456789abcdef', 'fedcba9876543210').to_i(16) + 1)
+ else
+ b = s.to_i(16)
+ end
+ assert_equal(a, b, "sprintf('%x', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_x_sign
+ VS.reverse_each {|a|
+ s = sprintf("%+x", a)
+ b = s.to_i(16)
+ assert_equal(a, b, "sprintf('%+x', #{a}) = #{s.inspect}")
+ s = sprintf("% x", a)
+ b = s.to_i(16)
+ assert_equal(a, b, "sprintf('% x', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_o
+ VS.reverse_each {|a|
+ s = sprintf("%o", a)
+ if /\A\.\./ =~ s
+ b = -($'.tr('01234567', '76543210').to_i(8) + 1)
+ else
+ b = s.to_i(8)
+ end
+ assert_equal(a, b, "sprintf('%o', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_o_sign
+ VS.reverse_each {|a|
+ s = sprintf("%+o", a)
+ b = s.to_i(8)
+ assert_equal(a, b, "sprintf('%+o', #{a}) = #{s.inspect}")
+ s = sprintf("% o", a)
+ b = s.to_i(8)
+ assert_equal(a, b, "sprintf('% o', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_b
+ VS.reverse_each {|a|
+ s = sprintf("%b", a)
+ if /\A\.\./ =~ s
+ b = -($'.tr('01', '10').to_i(2) + 1)
+ else
+ b = s.to_i(2)
+ end
+ assert_equal(a, b, "sprintf('%b', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_b_sign
+ VS.reverse_each {|a|
+ s = sprintf("%+b", a)
+ b = s.to_i(2)
+ assert_equal(a, b, "sprintf('%+b', #{a}) = #{s.inspect}")
+ s = sprintf("% b", a)
+ b = s.to_i(2)
+ assert_equal(a, b, "sprintf('% b', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_printf_diu
+ VS.reverse_each {|a|
+ s = sprintf("%d", a)
+ b = s.to_i
+ assert_equal(a, b, "sprintf('%d', #{a}) = #{s.inspect}")
+ s = sprintf("%i", a)
+ b = s.to_i
+ assert_equal(a, b, "sprintf('%i', #{a}) = #{s.inspect}")
+ s = sprintf("%u", a)
+ b = s.to_i
+ assert_equal(a, b, "sprintf('%u', #{a}) = #{s.inspect}")
+ }
+ end
+
+ def test_marshal
+ VS.reverse_each {|a|
+ s = Marshal.dump(a)
+ b = Marshal.load(s)
+ assert_equal(a, b, "Marshal.load(Marshal.dump(#{a}))")
+ }
+ end
+
+ def test_pack
+ %w[c C s S s! S! i I i! I! l L l! L! q Q n N v V].each {|template|
+ size = [0].pack(template).size
+ mask = (1 << (size * 8)) - 1
+ if /[A-Znv]/ =~ template
+ min = 0
+ max = (1 << (size * 8))-1
+ else
+ min = -(1 << (size * 8 - 1))
+ max = (1 << (size * 8 - 1)) - 1
+ end
+ VS.reverse_each {|a|
+ s = [a].pack(template)
+ b = s.unpack(template)[0]
+ assert_equal(a & mask, b & mask, "[#{a}].pack(#{template.dump}).unpack(#{template.dump}) & #{mask}")
+ if min <= a && a <= max
+ assert_equal(a, b, "[#{a}].pack(#{template.dump}).unpack(#{template.dump})")
+ end
+ }
+ }
+ end
+
+ def test_pack_ber
+ template = "w"
+ VS.reverse_each {|a|
+ if a < 0
+ assert_raise(ArgumentError) { [a].pack(template) }
+ else
+ s = [a].pack(template)
+ b = s.unpack(template)[0]
+ assert_equal(a, b, "[#{a}].pack(#{template.dump}).unpack(#{template.dump})")
+ end
+ }
+ end
+
+ def test_pack_utf8
+ template = "U"
+ VS.reverse_each {|a|
+ if a < 0 || 0x7fffffff < a
+ assert_raise(RangeError) { [a].pack(template) }
+ else
+ s = [a].pack(template)
+ b = s.unpack(template)[0]
+ assert_equal(a, b, "[#{a}].pack(#{template.dump}).unpack(#{template.dump})")
+ end
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_io.rb b/trunk/test/ruby/test_io.rb
new file mode 100644
index 0000000000..de1a1526eb
--- /dev/null
+++ b/trunk/test/ruby/test_io.rb
@@ -0,0 +1,1276 @@
+require 'test/unit'
+require 'tmpdir'
+require 'io/nonblock'
+require 'socket'
+require 'stringio'
+require 'timeout'
+require 'tempfile'
+require_relative 'envutil'
+
+class TestIO < Test::Unit::TestCase
+ def test_gets_rs
+ # default_rs
+ r, w = IO.pipe
+ w.print "aaa\nbbb\n"
+ w.close
+ assert_equal "aaa\n", r.gets
+ assert_equal "bbb\n", r.gets
+ assert_nil r.gets
+ r.close
+
+ # nil
+ r, w = IO.pipe
+ w.print "a\n\nb\n\n"
+ w.close
+ assert_equal "a\n\nb\n\n", r.gets(nil)
+ assert_nil r.gets("")
+ r.close
+
+ # "\377"
+ r, w = IO.pipe('ascii-8bit')
+ w.print "\377xyz"
+ w.close
+ r.binmode
+ assert_equal("\377", r.gets("\377"), "[ruby-dev:24460]")
+ r.close
+
+ # ""
+ r, w = IO.pipe
+ w.print "a\n\nb\n\n"
+ w.close
+ assert_equal "a\n\n", r.gets(""), "[ruby-core:03771]"
+ assert_equal "b\n\n", r.gets("")
+ assert_nil r.gets("")
+ r.close
+ end
+
+ def test_gets_limit_extra_arg
+ with_pipe {|r, w|
+ r, w = IO.pipe
+ w << "0123456789"
+ w.close
+ assert_raise(TypeError) { r.gets(3,nil) }
+ }
+ end
+
+ # This test cause SEGV.
+ def test_ungetc
+ r, w = IO.pipe
+ w.close
+ assert_raise(IOError, "[ruby-dev:31650]") { 20000.times { r.ungetc "a" } }
+ ensure
+ r.close
+ end
+
+ def test_each_byte
+ r, w = IO.pipe
+ w << "abc def"
+ w.close
+ r.each_byte {|byte| break if byte == 32 }
+ assert_equal("def", r.read, "[ruby-dev:31659]")
+ ensure
+ r.close
+ end
+
+ def test_rubydev33072
+ assert_raise(Errno::ENOENT, "[ruby-dev:33072]") do
+ File.read("empty", nil, nil, {})
+ end
+ end
+
+ def with_pipe
+ r, w = IO.pipe
+ begin
+ yield r, w
+ ensure
+ r.close unless r.closed?
+ w.close unless w.closed?
+ end
+ end
+
+ def with_read_pipe(content)
+ r, w = IO.pipe
+ w << content
+ w.close
+ begin
+ yield r
+ ensure
+ r.close
+ end
+ end
+
+ def mkcdtmpdir
+ Dir.mktmpdir {|d|
+ Dir.chdir(d) {
+ yield
+ }
+ }
+ end
+
+ def test_copy_stream
+ mkcdtmpdir {
+
+ content = "foobar"
+ File.open("src", "w") {|f| f << content }
+ ret = IO.copy_stream("src", "dst")
+ assert_equal(content.bytesize, ret)
+ assert_equal(content, File.read("dst"))
+
+ # overwrite by smaller file.
+ content = "baz"
+ File.open("src", "w") {|f| f << content }
+ ret = IO.copy_stream("src", "dst")
+ assert_equal(content.bytesize, ret)
+ assert_equal(content, File.read("dst"))
+
+ ret = IO.copy_stream("src", "dst", 2)
+ assert_equal(2, ret)
+ assert_equal(content[0,2], File.read("dst"))
+
+ ret = IO.copy_stream("src", "dst", 0)
+ assert_equal(0, ret)
+ assert_equal("", File.read("dst"))
+
+ ret = IO.copy_stream("src", "dst", nil, 1)
+ assert_equal(content.bytesize-1, ret)
+ assert_equal(content[1..-1], File.read("dst"))
+
+ assert_raise(Errno::ENOENT) {
+ IO.copy_stream("nodir/foo", "dst")
+ }
+
+ assert_raise(Errno::ENOENT) {
+ IO.copy_stream("src", "nodir/bar")
+ }
+
+ with_pipe {|r, w|
+ ret = IO.copy_stream("src", w)
+ assert_equal(content.bytesize, ret)
+ w.close
+ assert_equal(content, r.read)
+ }
+
+ with_pipe {|r, w|
+ w.close
+ assert_raise(IOError) { IO.copy_stream("src", w) }
+ }
+
+ pipe_content = "abc"
+ with_read_pipe(pipe_content) {|r|
+ ret = IO.copy_stream(r, "dst")
+ assert_equal(pipe_content.bytesize, ret)
+ assert_equal(pipe_content, File.read("dst"))
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ w2.sync = false
+ w2 << "def"
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(2, ret)
+ w2.close
+ assert_equal("defbc", r2.read)
+ }
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ w2.sync = false
+ w2 << "def"
+ ret = IO.copy_stream(r1, w2, 1)
+ assert_equal(1, ret)
+ w2.close
+ assert_equal("defb", r2.read)
+ }
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(2, ret)
+ w2.close
+ assert_equal("bc", r2.read)
+ }
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ ret = IO.copy_stream(r1, w2, 1)
+ assert_equal(1, ret)
+ w2.close
+ assert_equal("b", r2.read)
+ }
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ ret = IO.copy_stream(r1, w2, 0)
+ assert_equal(0, ret)
+ w2.close
+ assert_equal("", r2.read)
+ }
+ }
+
+ with_pipe {|r1, w1|
+ w1 << "abc"
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ w1 << "def"
+ w1.close
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(5, ret)
+ w2.close
+ assert_equal("bcdef", r2.read)
+ }
+ }
+
+ with_pipe {|r, w|
+ ret = IO.copy_stream("src", w, 1, 1)
+ assert_equal(1, ret)
+ w.close
+ assert_equal(content[1,1], r.read)
+ }
+
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ w2.nonblock = true
+ s = w2.syswrite("a" * 100000)
+ t = Thread.new { sleep 0.1; r2.read }
+ ret = IO.copy_stream(r1, w2)
+ w2.close
+ assert_equal(2, ret)
+ assert_equal("a" * s + "bc", t.value)
+ }
+ }
+
+ bigcontent = "abc" * 123456
+ File.open("bigsrc", "w") {|f| f << bigcontent }
+ ret = IO.copy_stream("bigsrc", "bigdst")
+ assert_equal(bigcontent.bytesize, ret)
+ assert_equal(bigcontent, File.read("bigdst"))
+
+ File.unlink("bigdst")
+ ret = IO.copy_stream("bigsrc", "bigdst", nil, 100)
+ assert_equal(bigcontent.bytesize-100, ret)
+ assert_equal(bigcontent[100..-1], File.read("bigdst"))
+
+ File.unlink("bigdst")
+ ret = IO.copy_stream("bigsrc", "bigdst", 30000, 100)
+ assert_equal(30000, ret)
+ assert_equal(bigcontent[100, 30000], File.read("bigdst"))
+
+ File.open("bigsrc") {|f|
+ assert_equal(0, f.pos)
+ ret = IO.copy_stream(f, "bigdst", nil, 10)
+ assert_equal(bigcontent.bytesize-10, ret)
+ assert_equal(bigcontent[10..-1], File.read("bigdst"))
+ assert_equal(0, f.pos)
+ ret = IO.copy_stream(f, "bigdst", 40, 30)
+ assert_equal(40, ret)
+ assert_equal(bigcontent[30, 40], File.read("bigdst"))
+ assert_equal(0, f.pos)
+ }
+
+ with_pipe {|r, w|
+ w.close
+ assert_raise(IOError) { IO.copy_stream("src", w) }
+ }
+
+ megacontent = "abc" * 1234567
+ File.open("megasrc", "w") {|f| f << megacontent }
+
+ with_pipe {|r1, w1|
+ with_pipe {|r2, w2|
+ t1 = Thread.new { w1 << megacontent; w1.close }
+ t2 = Thread.new { r2.read }
+ r1.nonblock = true
+ w2.nonblock = true
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(megacontent.bytesize, ret)
+ w2.close
+ t1.join
+ assert_equal(megacontent, t2.value)
+ }
+ }
+
+ with_pipe {|r1, w1|
+ with_pipe {|r2, w2|
+ t1 = Thread.new { w1 << megacontent; w1.close }
+ t2 = Thread.new { r2.read }
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(megacontent.bytesize, ret)
+ w2.close
+ t1.join
+ assert_equal(megacontent, t2.value)
+ }
+ }
+
+ with_pipe {|r, w|
+ t = Thread.new { r.read }
+ ret = IO.copy_stream("megasrc", w)
+ assert_equal(megacontent.bytesize, ret)
+ w.close
+ assert_equal(megacontent, t.value)
+ }
+ }
+ end
+
+ def test_copy_stream_rbuf
+ mkcdtmpdir {
+ with_pipe {|r, w|
+ File.open("foo", "w") {|f| f << "abcd" }
+ File.open("foo") {|f|
+ f.read(1)
+ assert_equal(3, IO.copy_stream(f, w, 10, 1))
+ }
+ w.close
+ assert_equal("bcd", r.read)
+ }
+ }
+ end
+
+ def with_socketpair
+ s1, s2 = UNIXSocket.pair
+ begin
+ yield s1, s2
+ ensure
+ s1.close unless s1.closed?
+ s2.close unless s2.closed?
+ end
+ end
+
+ def test_copy_stream_socket
+ return unless defined? UNIXSocket
+ mkcdtmpdir {
+
+ content = "foobar"
+ File.open("src", "w") {|f| f << content }
+
+ with_socketpair {|s1, s2|
+ ret = IO.copy_stream("src", s1)
+ assert_equal(content.bytesize, ret)
+ s1.close
+ assert_equal(content, s2.read)
+ }
+
+ bigcontent = "abc" * 123456
+ File.open("bigsrc", "w") {|f| f << bigcontent }
+
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ ret = IO.copy_stream("bigsrc", s1)
+ assert_equal(bigcontent.bytesize, ret)
+ s1.close
+ result = t.value
+ assert_equal(bigcontent, result)
+ }
+
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ ret = IO.copy_stream("bigsrc", s1, 10000)
+ assert_equal(10000, ret)
+ s1.close
+ result = t.value
+ assert_equal(bigcontent[0,10000], result)
+ }
+
+ File.open("bigsrc") {|f|
+ assert_equal(0, f.pos)
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ ret = IO.copy_stream(f, s1, nil, 100)
+ assert_equal(bigcontent.bytesize-100, ret)
+ assert_equal(0, f.pos)
+ s1.close
+ result = t.value
+ assert_equal(bigcontent[100..-1], result)
+ }
+ }
+
+ File.open("bigsrc") {|f|
+ assert_equal(bigcontent[0,100], f.read(100))
+ assert_equal(100, f.pos)
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ ret = IO.copy_stream(f, s1)
+ assert_equal(bigcontent.bytesize-100, ret)
+ assert_equal(bigcontent.length, f.pos)
+ s1.close
+ result = t.value
+ assert_equal(bigcontent[100..-1], result)
+ }
+ }
+
+ megacontent = "abc" * 1234567
+ File.open("megasrc", "w") {|f| f << megacontent }
+
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ s1.nonblock = true
+ ret = IO.copy_stream("megasrc", s1)
+ assert_equal(megacontent.bytesize, ret)
+ s1.close
+ result = t.value
+ assert_equal(megacontent, result)
+ }
+ }
+ end
+
+ def test_copy_stream_strio
+ src = StringIO.new("abcd")
+ dst = StringIO.new
+ ret = IO.copy_stream(src, dst)
+ assert_equal(4, ret)
+ assert_equal("abcd", dst.string)
+ assert_equal(4, src.pos)
+ end
+
+ def test_copy_stream_strio_len
+ src = StringIO.new("abcd")
+ dst = StringIO.new
+ ret = IO.copy_stream(src, dst, 3)
+ assert_equal(3, ret)
+ assert_equal("abc", dst.string)
+ assert_equal(3, src.pos)
+ end
+
+ def test_copy_stream_strio_off
+ src = StringIO.new("abcd")
+ with_pipe {|r, w|
+ assert_raise(ArgumentError) {
+ IO.copy_stream(src, w, 3, 1)
+ }
+ }
+ end
+
+ def test_copy_stream_fname_to_strio
+ mkcdtmpdir {
+ File.open("foo", "w") {|f| f << "abcd" }
+ src = "foo"
+ dst = StringIO.new
+ ret = IO.copy_stream(src, dst, 3)
+ assert_equal(3, ret)
+ assert_equal("abc", dst.string)
+ }
+ end
+
+ def test_copy_stream_strio_to_fname
+ mkcdtmpdir {
+ # StringIO to filename
+ src = StringIO.new("abcd")
+ ret = IO.copy_stream(src, "fooo", 3)
+ assert_equal(3, ret)
+ assert_equal("abc", File.read("fooo"))
+ assert_equal(3, src.pos)
+ }
+ end
+
+ def test_copy_stream_io_to_strio
+ mkcdtmpdir {
+ # IO to StringIO
+ File.open("bar", "w") {|f| f << "abcd" }
+ File.open("bar") {|src|
+ dst = StringIO.new
+ ret = IO.copy_stream(src, dst, 3)
+ assert_equal(3, ret)
+ assert_equal("abc", dst.string)
+ assert_equal(3, src.pos)
+ }
+ }
+ end
+
+ def test_copy_stream_strio_to_io
+ mkcdtmpdir {
+ # StringIO to IO
+ src = StringIO.new("abcd")
+ ret = File.open("baz", "w") {|dst|
+ IO.copy_stream(src, dst, 3)
+ }
+ assert_equal(3, ret)
+ assert_equal("abc", File.read("baz"))
+ assert_equal(3, src.pos)
+ }
+ end
+
+ def test_copy_stream_strio_flush
+ with_pipe {|r, w|
+ w.sync = false
+ w.write "zz"
+ src = StringIO.new("abcd")
+ IO.copy_stream(src, w)
+ t = Thread.new {
+ w.close
+ }
+ assert_equal("zzabcd", r.read)
+ t.join
+ }
+ end
+
+ def test_copy_stream_strio_rbuf
+ with_pipe {|r, w|
+ w << "abcd"
+ w.close
+ assert_equal("a", r.read(1))
+ sio = StringIO.new
+ IO.copy_stream(r, sio)
+ assert_equal("bcd", sio.string)
+ }
+ end
+
+ def test_copy_stream_src_wbuf
+ mkcdtmpdir {
+ with_pipe {|r, w|
+ File.open("foe", "w+") {|f|
+ f.write "abcd\n"
+ f.rewind
+ f.write "xy"
+ IO.copy_stream(f, w)
+ }
+ assert_equal("xycd\n", File.read("foe"))
+ w.close
+ assert_equal("cd\n", r.read)
+ r.close
+ }
+ }
+ end
+
+ def test_copy_stream_dst_rbuf
+ mkcdtmpdir {
+ with_pipe {|r, w|
+ w << "xyz"
+ w.close
+ File.open("fom", "w+b") {|f|
+ f.write "abcd\n"
+ f.rewind
+ assert_equal("abc", f.read(3))
+ f.ungetc "c"
+ IO.copy_stream(r, f)
+ }
+ assert_equal("abxyz", File.read("fom"))
+ }
+ }
+ end
+
+ def safe_4
+ Thread.new do
+ Timeout.timeout(10) do
+ $SAFE = 4
+ yield
+ end
+ end.join
+ end
+
+ def pipe(wp, rp)
+ r, w = IO.pipe
+ rt = Thread.new { rp.call(r) }
+ wt = Thread.new { wp.call(w) }
+ flunk("timeout") unless rt.join(10) && wt.join(10)
+ ensure
+ r.close unless !r || r.closed?
+ w.close unless !w || w.closed?
+ (rt.kill; rt.join) if rt
+ (wt.kill; wt.join) if wt
+ end
+
+ def pipe2(&b)
+ a = []
+ a << IO.pipe while true
+ rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
+ yield(*a.last)
+ ensure
+ a.each do |r, w|
+ r.close unless !r || r.closed?
+ w.close unless !w || w.closed?
+ end
+ end
+
+ def ruby(*args)
+ args = ['-e', '$>.write($<.read)'] if args.empty?
+ ruby = EnvUtil.rubybin
+ f = IO.popen([ruby] + args, 'r+')
+ yield(f)
+ ensure
+ f.close unless !f || f.closed?
+ end
+
+ def test_try_convert
+ assert_equal(STDOUT, IO.try_convert(STDOUT))
+ assert_equal(nil, IO.try_convert("STDOUT"))
+ end
+
+ def test_ungetc2
+ f = false
+ pipe(proc do |w|
+ 0 until f
+ w.write("1" * 10000)
+ w.close
+ end, proc do |r|
+ r.ungetc("0" * 10000)
+ f = true
+ assert_equal("0" * 10000 + "1" * 10000, r.read)
+ end)
+ end
+
+ def test_write_non_writable
+ with_pipe do |r, w|
+ assert_raise(IOError) do
+ r.write "foobarbaz"
+ end
+ end
+ end
+
+ def test_dup
+ ruby do |f|
+ f2 = f.dup
+ f.puts "foo"
+ f2.puts "bar"
+ f.close_write
+ f2.close_write
+ assert_equal("foo\nbar\n", f.read)
+ assert_equal("", f2.read)
+ end
+
+ pipe2 do |r, w|
+ assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
+ r2, w2 = r.dup, w.dup
+ end
+ end
+ end
+
+ def test_inspect
+ with_pipe do |r, w|
+ assert(r.inspect =~ /^#<IO:0x[0-9a-f]+>$/)
+ assert_raise(SecurityError) do
+ safe_4 { r.inspect }
+ end
+ end
+ end
+
+ def test_readpartial
+ pipe(proc do |w|
+ w.write "foobarbaz"
+ w.close
+ end, proc do |r|
+ assert_raise(ArgumentError) { r.readpartial(-1) }
+ assert_equal("fooba", r.readpartial(5))
+ r.readpartial(5, s = "")
+ assert_equal("rbaz", s)
+ end)
+ end
+
+ def test_readpartial_error
+ with_pipe do |r, w|
+ s = ""
+ t = Thread.new { r.readpartial(5, s) }
+ 0 until s.size == 5
+ s.clear
+ w.write "foobarbaz"
+ w.close
+ assert_raise(RuntimeError) { t.join }
+ end
+ end
+
+ def test_read
+ pipe(proc do |w|
+ w.write "foobarbaz"
+ w.close
+ end, proc do |r|
+ assert_raise(ArgumentError) { r.read(-1) }
+ assert_equal("fooba", r.read(5))
+ r.read(nil, s = "")
+ assert_equal("rbaz", s)
+ end)
+ end
+
+ def test_read_error
+ with_pipe do |r, w|
+ s = ""
+ t = Thread.new { r.read(5, s) }
+ 0 until s.size == 5
+ s.clear
+ w.write "foobarbaz"
+ w.close
+ assert_raise(RuntimeError) { t.join }
+ end
+ end
+
+ def test_write_nonblock
+ pipe(proc do |w|
+ w.write_nonblock(1)
+ w.close
+ end, proc do |r|
+ assert_equal("1", r.read)
+ end)
+ end
+
+ def test_gets
+ pipe(proc do |w|
+ w.write "foobarbaz"
+ w.close
+ end, proc do |r|
+ assert_equal("", r.gets(0))
+ assert_equal("foobarbaz", s = r.gets(9))
+ end)
+ end
+
+ def test_close_read
+ ruby do |f|
+ f.close_read
+ f.write "foobarbaz"
+ assert_raise(IOError) { f.read }
+ end
+ end
+
+ def test_close_read_pipe
+ with_pipe do |r, w|
+ r.close_read
+ assert_raise(Errno::EPIPE) { w.write "foobarbaz" }
+ end
+ end
+
+ def test_close_read_security_error
+ with_pipe do |r, w|
+ assert_raise(SecurityError) do
+ safe_4 { r.close_read }
+ end
+ end
+ end
+
+ def test_close_read_non_readable
+ with_pipe do |r, w|
+ assert_raise(IOError) do
+ w.close_read
+ end
+ end
+ end
+
+ def test_close_write
+ ruby do |f|
+ f.write "foobarbaz"
+ f.close_write
+ assert_equal("foobarbaz", f.read)
+ end
+ end
+
+ def test_close_write_security_error
+ with_pipe do |r, w|
+ assert_raise(SecurityError) do
+ safe_4 { r.close_write }
+ end
+ end
+ end
+
+ def test_close_write_non_readable
+ with_pipe do |r, w|
+ assert_raise(IOError) do
+ r.close_write
+ end
+ end
+ end
+
+ def test_pid
+ r, w = IO.pipe
+ assert_equal(nil, r.pid)
+ assert_equal(nil, w.pid)
+
+ pipe = IO.popen(EnvUtil.rubybin, "r+")
+ pid1 = pipe.pid
+ pipe.puts "p $$"
+ pipe.close_write
+ pid2 = pipe.read.chomp.to_i
+ assert_equal(pid2, pid1)
+ assert_equal(pid2, pipe.pid)
+ pipe.close
+ assert_raise(IOError) { pipe.pid }
+ end
+
+ def make_tempfile
+ t = Tempfile.new("foo")
+ t.binmode
+ t.puts "foo"
+ t.puts "bar"
+ t.puts "baz"
+ t.close
+ t
+ end
+
+ def test_set_lineno
+ t = make_tempfile
+
+ ruby("-e", <<-SRC, t.path) do |f|
+ open(ARGV[0]) do |f|
+ p $.
+ f.gets; p $.
+ f.gets; p $.
+ f.lineno = 1000; p $.
+ f.gets; p $.
+ f.gets; p $.
+ f.rewind; p $.
+ f.gets; p $.
+ f.gets; p $.
+ f.gets; p $.
+ f.gets; p $.
+ end
+ SRC
+ assert_equal("nil,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
+ end
+
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ r.gets; assert_equal(1, $.)
+ r.gets; assert_equal(2, $.)
+ r.lineno = 1000; assert_equal(2, $.)
+ r.gets; assert_equal(1001, $.)
+ r.gets; assert_equal(1001, $.)
+ end)
+ end
+
+ def test_readline
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ r.readline; assert_equal(1, $.)
+ r.readline; assert_equal(2, $.)
+ r.lineno = 1000; assert_equal(2, $.)
+ r.readline; assert_equal(1001, $.)
+ assert_raise(EOFError) { r.readline }
+ end)
+ end
+
+ def test_each_char
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ a = []
+ r.each_char {|c| a << c }
+ assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a)
+ end)
+ end
+
+ def test_lines
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = r.lines
+ assert_equal("foo\n", e.next)
+ assert_equal("bar\n", e.next)
+ assert_equal("baz\n", e.next)
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
+ def test_bytes
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = r.bytes
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c.ord, e.next)
+ end
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
+ def test_chars
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = r.chars
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c, e.next)
+ end
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
+ def test_readbyte
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c.ord, r.readbyte)
+ end
+ assert_raise(EOFError) { r.readbyte }
+ end)
+ end
+
+ def test_readchar
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c, r.readchar)
+ end
+ assert_raise(EOFError) { r.readchar }
+ end)
+ end
+
+ def test_close_on_exec
+ # xxx
+ ruby do |f|
+ assert_equal(false, f.close_on_exec?)
+ f.close_on_exec = true
+ assert_equal(true, f.close_on_exec?)
+ f.close_on_exec = false
+ assert_equal(false, f.close_on_exec?)
+ end
+
+ with_pipe do |r, w|
+ assert_equal(false, r.close_on_exec?)
+ r.close_on_exec = true
+ assert_equal(true, r.close_on_exec?)
+ r.close_on_exec = false
+ assert_equal(false, r.close_on_exec?)
+
+ assert_equal(false, w.close_on_exec?)
+ w.close_on_exec = true
+ assert_equal(true, w.close_on_exec?)
+ w.close_on_exec = false
+ assert_equal(false, w.close_on_exec?)
+ end
+ end
+
+ def test_close_security_error
+ with_pipe do |r, w|
+ assert_raise(SecurityError) do
+ safe_4 { r.close }
+ end
+ end
+ end
+
+ def test_sysseek
+ t = make_tempfile
+
+ open(t.path) do |f|
+ f.sysseek(-4, IO::SEEK_END)
+ assert_equal("baz\n", f.read)
+ end
+
+ open(t.path) do |f|
+ a = [f.getc, f.getc, f.getc]
+ a.reverse_each {|c| f.ungetc c }
+ assert_raise(IOError) { f.sysseek(1) }
+ end
+ end
+
+ def test_syswrite
+ t = make_tempfile
+
+ open(t.path, "w") do |f|
+ o = Object.new
+ def o.to_s; "FOO\n"; end
+ f.syswrite(o)
+ end
+ assert_equal("FOO\n", File.read(t.path))
+ end
+
+ def test_sysread
+ t = make_tempfile
+
+ open(t.path) do |f|
+ a = [f.getc, f.getc, f.getc]
+ a.reverse_each {|c| f.ungetc c }
+ assert_raise(IOError) { f.sysread(1) }
+ end
+ end
+
+ def test_flag
+ t = make_tempfile
+
+ assert_raise(ArgumentError) do
+ open(t.path, "z") { }
+ end
+
+ assert_raise(ArgumentError) do
+ open(t.path, "rr") { }
+ end
+ end
+
+ def test_sysopen
+ t = make_tempfile
+
+ fd = IO.sysopen(t.path)
+ assert_kind_of(Integer, fd)
+ f = IO.for_fd(fd)
+ assert_equal("foo\nbar\nbaz\n", f.read)
+ f.close
+
+ fd = IO.sysopen(t.path, "w", 0666)
+ assert_kind_of(Integer, fd)
+ f = IO.for_fd(fd)
+ f.write("FOO\n")
+ f.close
+
+ fd = IO.sysopen(t.path, "r")
+ assert_kind_of(Integer, fd)
+ f = IO.for_fd(fd)
+ assert_equal("FOO\n", f.read)
+ f.close
+ end
+
+ def test_open_redirect
+ o = Object.new
+ def o.to_open; self; end
+ assert_equal(o, open(o))
+ o2 = nil
+ open(o) do |f|
+ o2 = f
+ end
+ assert_equal(o, o2)
+ end
+
+ def test_open_pipe
+ open("|" + EnvUtil.rubybin, "r+") do |f|
+ f.puts "puts 'foo'"
+ f.close_write
+ assert_equal("foo\n", f.read)
+ end
+ end
+
+ def test_reopen
+ t = make_tempfile
+
+ with_pipe do |r, w|
+ assert_raise(SecurityError) do
+ safe_4 { r.reopen(t.path) }
+ end
+ end
+
+ open(__FILE__) do |f|
+ f.gets
+ assert_nothing_raised {
+ f.reopen(t.path)
+ assert_equal("foo\n", f.gets)
+ }
+ end
+ end
+
+ def test_foreach
+ a = []
+ IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
+ assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+ t = make_tempfile
+
+ a = []
+ IO.foreach(t.path) {|x| a << x }
+ assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+ a = []
+ IO.foreach(t.path, {:mode => "r" }) {|x| a << x }
+ assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+ a = []
+ IO.foreach(t.path, {:open_args => [] }) {|x| a << x }
+ assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+ a = []
+ IO.foreach(t.path, {:open_args => ["r"] }) {|x| a << x }
+ assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+ a = []
+ IO.foreach(t.path, "b") {|x| a << x }
+ assert_equal(["foo\nb", "ar\nb", "az\n"], a)
+
+ a = []
+ IO.foreach(t.path, 3) {|x| a << x }
+ assert_equal(["foo", "\n", "bar", "\n", "baz", "\n"], a)
+
+ a = []
+ IO.foreach(t.path, "b", 3) {|x| a << x }
+ assert_equal(["foo", "\nb", "ar\n", "b", "az\n"], a)
+
+ end
+
+ def test_s_readlines
+ t = make_tempfile
+
+ assert_equal(["foo\n", "bar\n", "baz\n"], IO.readlines(t.path))
+ assert_equal(["foo\nb", "ar\nb", "az\n"], IO.readlines(t.path, "b"))
+ assert_equal(["fo", "o\n", "ba", "r\n", "ba", "z\n"], IO.readlines(t.path, 2))
+ assert_equal(["fo", "o\n", "b", "ar", "\nb", "az", "\n"], IO.readlines(t.path, "b", 2))
+ end
+
+ def test_printf
+ pipe(proc do |w|
+ printf(w, "foo %s baz\n", "bar")
+ w.close_write
+ end, proc do |r|
+ assert_equal("foo bar baz\n", r.read)
+ end)
+ end
+
+ def test_print
+ t = make_tempfile
+
+ assert_in_out_err(["-", t.path], "print while $<.gets", %w(foo bar baz), [])
+ end
+
+ def test_putc
+ pipe(proc do |w|
+ w.putc "A"
+ w.putc "BC"
+ w.putc 68
+ w.close_write
+ end, proc do |r|
+ assert_equal("ABD", r.read)
+ end)
+
+ assert_in_out_err([], "putc 65", %w(A), [])
+ end
+
+ def test_puts_recursive_array
+ a = ["foo"]
+ a << a
+ pipe(proc do |w|
+ w.puts a
+ w.close
+ end, proc do |r|
+ assert_equal("foo\n[...]\n", r.read)
+ end)
+ end
+
+ def test_display
+ pipe(proc do |w|
+ "foo".display(w)
+ w.close
+ end, proc do |r|
+ assert_equal("foo", r.read)
+ end)
+
+ assert_in_out_err([], "'foo'.display", %w(foo), [])
+ end
+
+ def test_set_stdout
+ assert_raise(TypeError) { $> = Object.new }
+
+ assert_in_out_err([], "$> = $stderr\nputs 'foo'", [], %w(foo))
+ end
+
+ def test_initialize
+ t = make_tempfile
+
+ fd = IO.sysopen(t.path)
+ assert_kind_of(Integer, fd)
+ f = IO.new(fd, "w")
+ f.write("FOO\n")
+ f.close
+
+ assert_equal("foo\nbar\nbaz\n", File.read(t.path))
+
+ with_pipe do |r, w|
+ assert_raise(RuntimeError) do
+ o = Object.new
+ class << o; self; end.instance_eval do
+ define_method(:to_io) { r }
+ end
+ w.instance_eval { initialize(o) }
+ end
+ end
+
+ pipe(proc do |w|
+ w = IO.new(w)
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ r = IO.new(r)
+ assert_equal("foo\nbar\nbaz\n", r.read)
+ end)
+
+ with_pipe do |r, w|
+ assert_raise(ArgumentError) { IO.new(r, "r+") }
+ end
+
+ f = open(t.path)
+ assert_raise(RuntimeError) do
+ f.instance_eval { initialize }
+ end
+ end
+
+ def test_new_with_block
+ assert_in_out_err([], "r, w = IO.pipe; IO.new(r) {}", [], /^.+$/)
+ end
+
+ def test_readline2
+ assert_in_out_err(["-e", <<-SRC], "foo\nbar\nbaz\n", %w(foo bar baz end), [])
+ puts readline
+ puts readline
+ puts readline
+ begin
+ puts readline
+ rescue EOFError
+ puts "end"
+ end
+ SRC
+ end
+
+ def test_readlines
+ assert_in_out_err(["-e", "p readlines"], "foo\nbar\nbaz\n",
+ ["[\"foo\\n\", \"bar\\n\", \"baz\\n\"]"], [])
+ end
+
+ def test_s_read
+ t = make_tempfile
+
+ assert_equal("foo\nbar\nbaz\n", File.read(t.path))
+ assert_equal("foo\nba", File.read(t.path, 6))
+ assert_equal("bar\n", File.read(t.path, 4, 4))
+ end
+
+ def test_uninitialized
+ assert_raise(IOError) { IO.allocate.print "" }
+ end
+
+ def test_nofollow
+ # O_NOFOLLOW is not standard.
+ return if /freebsd|linux/ !~ RUBY_PLATFORM
+ return unless defined? File::NOFOLLOW
+ mkcdtmpdir {
+ open("file", "w") {|f| f << "content" }
+ begin
+ File.symlink("file", "slnk")
+ rescue NotImplementedError
+ return
+ end
+ assert_raise(Errno::EMLINK, Errno::ELOOP) {
+ open("slnk", File::RDONLY|File::NOFOLLOW) {}
+ }
+ assert_raise(Errno::EMLINK, Errno::ELOOP) {
+ File.foreach("slnk", :open_args=>[File::RDONLY|File::NOFOLLOW]) {}
+ }
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_io_m17n.rb b/trunk/test/ruby/test_io_m17n.rb
new file mode 100644
index 0000000000..47d04a18d5
--- /dev/null
+++ b/trunk/test/ruby/test_io_m17n.rb
@@ -0,0 +1,1334 @@
+require 'test/unit'
+require 'tmpdir'
+require 'timeout'
+require_relative 'envutil'
+
+class TestIO_M17N < Test::Unit::TestCase
+ ENCS = [
+ Encoding::ASCII_8BIT,
+ Encoding::EUC_JP,
+ Encoding::Shift_JIS,
+ Encoding::UTF_8
+ ]
+
+ def with_tmpdir
+ Dir.mktmpdir {|dir|
+ Dir.chdir(dir) {
+ yield dir
+ }
+ }
+ end
+
+ def with_pipe(*args)
+ r, w = IO.pipe(*args)
+ begin
+ yield r, w
+ ensure
+ r.close if !r.closed?
+ w.close if !w.closed?
+ end
+ end
+
+ def generate_file(path, content)
+ open(path, "wb") {|f| f.write content }
+ end
+
+ def encdump(str)
+ "#{str.dump}.force_encoding(#{str.encoding.name.dump})"
+ end
+
+ def assert_str_equal(expected, actual, message=nil)
+ full_message = build_message(message, <<EOT)
+#{encdump expected} expected but not equal to
+#{encdump actual}.
+EOT
+ assert_block(full_message) { expected == actual }
+ end
+
+ def test_open_r
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r") {|f|
+ assert_equal(Encoding.default_external, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_rb
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "rb") {|f|
+ assert_equal(Encoding.default_external, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r:euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc_in_opt
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r", encoding: "euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc_in_opt2
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r", external_encoding: "euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc_enc
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r:euc-jp:utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc_enc_in_opt
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r", encoding: "euc-jp:utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_r_enc_enc_in_opt2
+ with_tmpdir {
+ generate_file('tmp', "")
+ open("tmp", "r", external_encoding: "euc-jp", internal_encoding: "utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w
+ with_tmpdir {
+ open("tmp", "w") {|f|
+ assert_equal(nil, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_wb
+ with_tmpdir {
+ open("tmp", "wb") {|f|
+ assert_equal(nil, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc
+ with_tmpdir {
+ open("tmp", "w:euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_in_opt
+ with_tmpdir {
+ open("tmp", "w", encoding: "euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_in_opt2
+ with_tmpdir {
+ open("tmp", "w", external_encoding: "euc-jp") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_enc
+ with_tmpdir {
+ open("tmp", "w:euc-jp:utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_enc_in_opt
+ with_tmpdir {
+ open("tmp", "w", encoding: "euc-jp:utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_enc_in_opt2
+ with_tmpdir {
+ open("tmp", "w", external_encoding: "euc-jp", internal_encoding: "utf-8") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_open_w_enc_enc_perm
+ with_tmpdir {
+ open("tmp", "w:euc-jp:utf-8", 0600) {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ }
+ }
+ end
+
+ def test_io_new_enc
+ with_tmpdir {
+ generate_file("tmp", "\xa1")
+ fd = IO.sysopen("tmp")
+ f = IO.new(fd, "r:sjis")
+ begin
+ assert_equal(Encoding::Shift_JIS, f.read.encoding)
+ ensure
+ f.close
+ end
+ }
+ end
+
+ def test_s_pipe_invalid
+ r, w = IO.pipe("utf-8", "euc-jp", :invalid=>:replace)
+ w << "\x80"
+ w.close
+ assert_equal("?", r.read)
+ ensure
+ r.close if r && !r.closed?
+ w.close if w && !w.closed?
+ end
+
+ def test_s_pipe_undef
+ r, w = IO.pipe("utf-8:euc-jp", :undef=>:replace)
+ w << "\ufffd"
+ w.close
+ assert_equal("?", r.read)
+ ensure
+ r.close if r && !r.closed?
+ w.close if w && !w.closed?
+ end
+
+ def test_dup
+ with_pipe("utf-8:euc-jp") {|r, w|
+ w << "\u3042"
+ w.close
+ r2 = r.dup
+ begin
+ assert_equal("\xA4\xA2".force_encoding("euc-jp"), r2.read)
+ ensure
+ r2.close
+ end
+
+ }
+ end
+
+ def test_dup_undef
+ with_pipe("utf-8:euc-jp", :undef=>:replace) {|r, w|
+ w << "\uFFFD"
+ w.close
+ r2 = r.dup
+ begin
+ assert_equal("?", r2.read)
+ ensure
+ r2.close
+ end
+ }
+ end
+
+ def test_stdin
+ assert_equal(Encoding.default_external, STDIN.external_encoding)
+ assert_equal(nil, STDIN.internal_encoding)
+ end
+
+ def test_stdout
+ assert_equal(nil, STDOUT.external_encoding)
+ assert_equal(nil, STDOUT.internal_encoding)
+ end
+
+ def test_stderr
+ assert_equal(nil, STDERR.external_encoding)
+ assert_equal(nil, STDERR.internal_encoding)
+ end
+
+ def test_terminator_conversion
+ with_tmpdir {
+ generate_file('tmp', "before \u00FF after")
+ s = open("tmp", "r:utf-8:iso-8859-1") {|f|
+ f.gets("\xFF".force_encoding("iso-8859-1"))
+ }
+ assert_equal(Encoding.find("iso-8859-1"), s.encoding)
+ assert_str_equal("before \xFF".force_encoding("iso-8859-1"), s, '[ruby-core:14288]')
+ }
+ end
+
+ def test_terminator_conversion2
+ with_tmpdir {
+ generate_file('tmp', "before \xA1\xA2\xA2\xA3 after")
+ s = open("tmp", "r:euc-jp:utf-8") {|f|
+ f.gets("\xA2\xA2".force_encoding("euc-jp").encode("utf-8"))
+ }
+ assert_equal(Encoding.find("utf-8"), s.encoding)
+ assert_str_equal("before \xA1\xA2\xA2\xA3 after".force_encoding("euc-jp").encode("utf-8"), s, '[ruby-core:14319]')
+ }
+ end
+
+ def test_terminator_stateful_conversion
+ with_tmpdir {
+ src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp")
+ generate_file('tmp', src)
+ s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+ f.gets("0".force_encoding("euc-jp"))
+ }
+ assert_equal(Encoding.find("euc-jp"), s.encoding)
+ assert_str_equal(src.encode("euc-jp"), s)
+ }
+ end
+
+ def test_nonascii_terminator
+ with_tmpdir {
+ generate_file('tmp', "before \xA2\xA2 after")
+ open("tmp", "r:euc-jp") {|f|
+ assert_raise(ArgumentError) {
+ f.gets("\xA2\xA2".force_encoding("utf-8"))
+ }
+ }
+ }
+ end
+
+ def test_pipe_terminator_conversion
+ with_pipe("euc-jp:utf-8") {|r, w|
+ w.write "before \xa2\xa2 after"
+ rs = "\xA2\xA2".encode("utf-8", "euc-jp")
+ w.close
+ timeout(1) {
+ assert_equal("before \xa2\xa2".encode("utf-8", "euc-jp"),
+ r.gets(rs))
+ }
+ }
+ end
+
+ def test_pipe_conversion
+ with_pipe("euc-jp:utf-8") {|r, w|
+ w.write "\xa1\xa1"
+ assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc)
+ }
+ end
+
+ def test_pipe_convert_partial_read
+ with_pipe("euc-jp:utf-8") {|r, w|
+ begin
+ t = Thread.new {
+ w.write "\xa1"
+ sleep 0.1
+ w.write "\xa1"
+ }
+ assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc)
+ ensure
+ t.join if t
+ end
+ }
+ end
+
+ def test_getc_invalid
+ with_pipe("euc-jp:utf-8") {|r, w|
+ w << "\xa1xyz"
+ w.close
+ err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ assert_equal("\xA1".force_encoding("ascii-8bit"), err.error_bytes)
+ assert_equal("xyz", r.read(10))
+ }
+ end
+
+ def test_getc_stateful_conversion
+ with_tmpdir {
+ src = "\e$B\x23\x30\x23\x31\e(B".force_encoding("iso-2022-jp")
+ generate_file('tmp', src)
+ open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+ assert_equal("\xa3\xb0".force_encoding("euc-jp"), f.getc)
+ assert_equal("\xa3\xb1".force_encoding("euc-jp"), f.getc)
+ }
+ }
+ end
+
+ def test_ungetc_stateful_conversion
+ with_tmpdir {
+ src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp")
+ generate_file('tmp', src)
+ s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+ f.ungetc("0".force_encoding("euc-jp"))
+ f.read
+ }
+ assert_equal(Encoding.find("euc-jp"), s.encoding)
+ assert_str_equal("0" + src.encode("euc-jp"), s)
+ }
+ end
+
+ def test_ungetc_stateful_conversion2
+ with_tmpdir {
+ src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp")
+ former = "before \e$B\x23\x30\e(B".force_encoding("iso-2022-jp")
+ rs = "\e$B\x23\x30\e(B".force_encoding("iso-2022-jp")
+ latter = "\e$B\x23\x31\e(B after".force_encoding("iso-2022-jp")
+ generate_file('tmp', src)
+ s = open("tmp", "r:iso-2022-jp:euc-jp") {|f|
+ assert_equal(former.encode("euc-jp", "iso-2022-jp"),
+ f.gets(rs.encode("euc-jp", "iso-2022-jp")))
+ f.ungetc("0")
+ f.read
+ }
+ assert_equal(Encoding.find("euc-jp"), s.encoding)
+ assert_str_equal("0" + latter.encode("euc-jp"), s)
+ }
+ end
+
+ def test_open_ascii
+ with_tmpdir {
+ src = "abc\n"
+ generate_file('tmp', "abc\n")
+ ENCS.each {|enc|
+ s = open('tmp', "r:#{enc}") {|f| f.gets }
+ assert_equal(enc, s.encoding)
+ assert_str_equal(src, s)
+ }
+ }
+ end
+
+ def test_open_nonascii
+ with_tmpdir {
+ src = "\xc2\xa1\n"
+ generate_file('tmp', src)
+ ENCS.each {|enc|
+ content = src.dup.force_encoding(enc)
+ s = open('tmp', "r:#{enc}") {|f| f.gets }
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ }
+ end
+
+ def test_read_encoding
+ with_tmpdir {
+ src = "\xc2\xa1\n".force_encoding("ASCII-8BIT")
+ generate_file('tmp', "\xc2\xa1\n")
+ ENCS.each {|enc|
+ content = src.dup.force_encoding(enc)
+ open('tmp', "r:#{enc}") {|f|
+ s = f.getc
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content[0], s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.readchar
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content[0], s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.gets
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.readline
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ lines = f.readlines
+ assert_equal(1, lines.length)
+ s = lines[0]
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ f.each_line {|s|
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.read
+ assert_equal(enc, s.encoding)
+ assert_str_equal(content, s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.read(1)
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_str_equal(src[0], s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.readpartial(1)
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_str_equal(src[0], s)
+ }
+ open('tmp', "r:#{enc}") {|f|
+ s = f.sysread(1)
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_str_equal(src[0], s)
+ }
+ }
+ }
+ end
+
+ def test_write_noenc
+ src = "\xc2\xa1\n".force_encoding("ascii-8bit")
+ with_tmpdir {
+ open('tmp', "w") {|f|
+ ENCS.each {|enc|
+ f.write src.dup.force_encoding(enc)
+ }
+ }
+ open('tmp', 'r:ascii-8bit') {|f|
+ assert_equal(src*ENCS.length, f.read)
+ }
+ }
+ end
+
+ def test_write_conversion
+ utf8 = "\u6666"
+ eucjp = "\xb3\xa2".force_encoding("EUC-JP")
+ with_tmpdir {
+ open('tmp', "w:EUC-JP") {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ f.print utf8
+ }
+ assert_equal(eucjp, File.read('tmp').force_encoding("EUC-JP"))
+ open('tmp', 'r:EUC-JP:UTF-8') {|f|
+ assert_equal(Encoding::EUC_JP, f.external_encoding)
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(utf8, f.read)
+ }
+ }
+ end
+
+ def test_pipe
+ utf8 = "\u6666"
+ eucjp = "\xb3\xa2".force_encoding("EUC-JP")
+
+ with_pipe {|r,w|
+ assert_equal(Encoding.default_external, r.external_encoding)
+ assert_equal(nil, r.internal_encoding)
+ w << utf8
+ w.close
+ s = r.read
+ assert_equal(Encoding.default_external, s.encoding)
+ assert_str_equal(utf8.dup.force_encoding(Encoding.default_external), s)
+ }
+
+ with_pipe("EUC-JP") {|r,w|
+ assert_equal(Encoding::EUC_JP, r.external_encoding)
+ assert_equal(nil, r.internal_encoding)
+ w << eucjp
+ w.close
+ assert_equal(eucjp, r.read)
+ }
+
+ with_pipe("UTF-8:EUC-JP") {|r,w|
+ assert_equal(Encoding::UTF_8, r.external_encoding)
+ assert_equal(Encoding::EUC_JP, r.internal_encoding)
+ w << utf8
+ w.close
+ assert_equal(eucjp, r.read)
+ }
+
+ ENCS.each {|enc|
+ with_pipe(enc) {|r, w|
+ w << "\xc2\xa1"
+ w.close
+ s = r.getc
+ assert_equal(enc, s.encoding)
+ }
+ }
+
+ ENCS.each {|enc|
+ next if enc == Encoding::ASCII_8BIT
+ next if enc == Encoding::UTF_8
+ with_pipe("#{enc}:UTF-8") {|r, w|
+ w << "\xc2\xa1"
+ w.close
+ s = r.read
+ assert_equal(Encoding::UTF_8, s.encoding)
+ assert_equal(s.encode("UTF-8"), s)
+ }
+ }
+
+ end
+
+ def test_marshal
+ with_pipe("EUC-JP") {|r, w|
+ data = 56225
+ Marshal.dump(data, w)
+ w.close
+ result = nil
+ assert_nothing_raised("[ruby-dev:33264]") { result = Marshal.load(r) }
+ assert_equal(data, result)
+ }
+ end
+
+ def test_gets_nil
+ with_pipe("UTF-8:EUC-JP") {|r, w|
+ w << "\u{3042}"
+ w.close
+ result = r.gets(nil)
+ assert_equal("\u{3042}".encode("euc-jp"), result)
+ }
+ end
+
+ def test_gets_limit
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(1))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(2))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(3))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(4))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(5))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(6))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(7))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(8))
+ }
+ with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close
+ assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(9))
+ }
+ end
+
+ def test_gets_invalid
+ with_pipe("utf-8:euc-jp") {|r, w|
+ before = "\u{3042}\u{3044}"
+ invalid = "\x80".force_encoding("utf-8")
+ after = "\u{3046}\u{3048}"
+ w << before + invalid + after
+ w.close
+ err = assert_raise(Encoding::InvalidByteSequence) { r.gets }
+ assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
+ assert_equal(after.encode("euc-jp"), r.gets)
+ }
+ end
+
+ def test_getc_invalid2
+ with_pipe("utf-8:euc-jp") {|r, w|
+ before1 = "\u{3042}"
+ before2 = "\u{3044}"
+ invalid = "\x80".force_encoding("utf-8")
+ after1 = "\u{3046}"
+ after2 = "\u{3048}"
+ w << before1 + before2 + invalid + after1 + after2
+ w.close
+ assert_equal(before1.encode("euc-jp"), r.getc)
+ assert_equal(before2.encode("euc-jp"), r.getc)
+ err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
+ assert_equal(after1.encode("euc-jp"), r.getc)
+ assert_equal(after2.encode("euc-jp"), r.getc)
+ }
+ end
+
+ def test_getc_invalid3
+ with_pipe("utf-16le:euc-jp") {|r, w|
+ before1 = "\x42\x30".force_encoding("utf-16le")
+ before2 = "\x44\x30".force_encoding("utf-16le")
+ invalid = "\x00\xd8".force_encoding("utf-16le")
+ after1 = "\x46\x30".force_encoding("utf-16le")
+ after2 = "\x48\x30".force_encoding("utf-16le")
+ w << before1 + before2 + invalid + after1 + after2
+ w.close
+ assert_equal(before1.encode("euc-jp"), r.getc)
+ assert_equal(before2.encode("euc-jp"), r.getc)
+ err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
+ assert_equal(after1.encode("euc-jp"), r.getc)
+ assert_equal(after2.encode("euc-jp"), r.getc)
+ }
+ end
+
+ def test_read_all
+ with_pipe("utf-8:euc-jp") {|r, w|
+ str = "\u3042\u3044"
+ w << str
+ w.close
+ assert_equal(str.encode("euc-jp"), r.read)
+ }
+ end
+
+ def test_read_all_invalid
+ with_pipe("utf-8:euc-jp") {|r, w|
+ before = "\u{3042}\u{3044}"
+ invalid = "\x80".force_encoding("utf-8")
+ after = "\u{3046}\u{3048}"
+ w << before + invalid + after
+ w.close
+ err = assert_raise(Encoding::InvalidByteSequence) { r.read }
+ assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
+ assert_equal(after.encode("euc-jp"), r.read)
+ }
+ end
+
+ def test_file_foreach
+ with_tmpdir {
+ generate_file('tst', 'a' * 8191 + "\xa1\xa1")
+ assert_nothing_raised {
+ File.foreach('tst', :encoding=>"euc-jp") {|line| line.inspect }
+ }
+ }
+ end
+
+ def test_set_encoding
+ with_pipe("utf-8:euc-jp") {|r, w|
+ s = "\u3042".force_encoding("ascii-8bit")
+ s << "\x82\xa0".force_encoding("ascii-8bit")
+ w << s
+ w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ r.set_encoding("shift_jis:euc-jp")
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ }
+ end
+
+ def test_set_encoding2
+ with_pipe("utf-8:euc-jp") {|r, w|
+ s = "\u3042".force_encoding("ascii-8bit")
+ s << "\x82\xa0".force_encoding("ascii-8bit")
+ w << s
+ w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ r.set_encoding("shift_jis", "euc-jp")
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ }
+ end
+
+ def test_set_encoding_nil
+ with_pipe("utf-8:euc-jp") {|r, w|
+ s = "\u3042".force_encoding("ascii-8bit")
+ s << "\x82\xa0".force_encoding("ascii-8bit")
+ w << s
+ w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ r.set_encoding(nil)
+ assert_equal("\x82\xa0".force_encoding(Encoding.default_external), r.read)
+ }
+ end
+
+ def test_set_encoding_enc
+ with_pipe("utf-8:euc-jp") {|r, w|
+ s = "\u3042".force_encoding("ascii-8bit")
+ s << "\x82\xa0".force_encoding("ascii-8bit")
+ w << s
+ w.close
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc)
+ r.set_encoding(Encoding::Shift_JIS)
+ assert_equal("\x82\xa0".force_encoding(Encoding::Shift_JIS), r.getc)
+ }
+ end
+
+ def test_set_encoding_invalid
+ with_pipe {|r, w|
+ w << "\x80"
+ w.close
+ r.set_encoding("utf-8:euc-jp", :invalid=>:replace)
+ assert_equal("?", r.read)
+ }
+ end
+
+ def test_set_encoding_undef
+ with_pipe {|r, w|
+ w << "\ufffd"
+ w.close
+ r.set_encoding("utf-8", "euc-jp", :undef=>:replace)
+ assert_equal("?", r.read)
+ }
+ end
+
+ def test_write_conversion_fixenc
+ with_pipe {|r, w|
+ w.set_encoding("iso-2022-jp:utf-8")
+ t = Thread.new { r.read.force_encoding("ascii-8bit") }
+ w << "\u3042"
+ w << "\u3044"
+ w.close
+ assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value)
+ }
+ end
+
+ def test_write_conversion_anyenc_stateful
+ with_pipe {|r, w|
+ w.set_encoding("iso-2022-jp")
+ t = Thread.new { r.read.force_encoding("ascii-8bit") }
+ w << "\u3042"
+ w << "\x82\xa2".force_encoding("sjis")
+ w.close
+ assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value)
+ }
+ end
+
+ def test_write_conversion_anyenc_stateless
+ with_pipe {|r, w|
+ w.set_encoding("euc-jp")
+ t = Thread.new { r.read.force_encoding("ascii-8bit") }
+ w << "\u3042"
+ w << "\x82\xa2".force_encoding("sjis")
+ w.close
+ assert_equal("\xa4\xa2\xa4\xa4".force_encoding("ascii-8bit"), t.value)
+ }
+ end
+
+ def test_write_conversion_anyenc_stateful_nosync
+ with_pipe {|r, w|
+ w.sync = false
+ w.set_encoding("iso-2022-jp")
+ t = Thread.new { r.read.force_encoding("ascii-8bit") }
+ w << "\u3042"
+ w << "\x82\xa2".force_encoding("sjis")
+ w.close
+ assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value)
+ }
+ end
+
+ def test_stdin_external_encoding_with_reopen
+ with_tmpdir {
+ open("tst", "w+") {|f|
+ pid = spawn(EnvUtil.rubybin, '-e', <<-'End', 10=>f)
+ io = IO.new(10, "r+")
+ STDIN.reopen(io)
+ STDIN.external_encoding
+ STDIN.write "\u3042"
+ STDIN.flush
+ End
+ Process.wait pid
+ f.rewind
+ result = f.read.force_encoding("ascii-8bit")
+ assert_equal("\u3042".force_encoding("ascii-8bit"), result)
+ }
+ }
+ end
+
+ def test_popen_r_enc
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ end
+
+ def test_popen_r_enc_in_opt
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r", encoding: "ascii-8bit") {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ end
+
+ def test_popen_r_enc_in_opt2
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r", external_encoding: "ascii-8bit") {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ end
+
+ def test_popen_r_enc_enc
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r:shift_jis:euc-jp") {|f|
+ assert_equal(Encoding::Shift_JIS, f.external_encoding)
+ assert_equal(Encoding::EUC_JP, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\x8e\xa1".force_encoding("euc-jp"), s)
+ }
+ end
+
+ def test_popen_r_enc_enc_in_opt
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r", encoding: "shift_jis:euc-jp") {|f|
+ assert_equal(Encoding::Shift_JIS, f.external_encoding)
+ assert_equal(Encoding::EUC_JP, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\x8e\xa1".force_encoding("euc-jp"), s)
+ }
+ end
+
+ def test_popen_r_enc_enc_in_opt2
+ IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r", external_encoding: "shift_jis", internal_encoding: "euc-jp") {|f|
+ assert_equal(Encoding::Shift_JIS, f.external_encoding)
+ assert_equal(Encoding::EUC_JP, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\x8e\xa1".force_encoding("euc-jp"), s)
+ }
+ end
+
+ def test_popenv_r_enc_enc_in_opt2
+ IO.popen([EnvUtil.rubybin, "-e", "putc 0xa1"], "r", external_encoding: "shift_jis", internal_encoding: "euc-jp") {|f|
+ assert_equal(Encoding::Shift_JIS, f.external_encoding)
+ assert_equal(Encoding::EUC_JP, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\x8e\xa1".force_encoding("euc-jp"), s)
+ }
+ end
+
+ def test_open_pipe_r_enc
+ open("|#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ end
+
+ def test_s_foreach_enc
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :mode => "r:ascii-8bit") {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_enc_in_opt
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :encoding => "ascii-8bit") {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_enc_in_opt2
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :external_encoding => "ascii-8bit") {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_enc_enc
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :mode => "r:utf-8:euc-jp") {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_enc_enc_in_opt
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :mode => "r", :encoding => "utf-8:euc-jp") {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_enc_enc_in_opt2
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :mode => "r", :external_encoding => "utf-8", :internal_encoding => "euc-jp") {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :open_args => ["r:ascii-8bit"]) {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc_in_opt
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :open_args => ["r", encoding: "ascii-8bit"]) {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc_in_opt2
+ with_tmpdir {
+ generate_file("t", "\xff")
+ IO.foreach("t", :open_args => ["r", external_encoding: "ascii-8bit"]) {|s|
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc_enc
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :open_args => ["r:utf-8:euc-jp"]) {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc_enc_in_opt
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :open_args => ["r", encoding: "utf-8:euc-jp"]) {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_s_foreach_open_args_enc_enc_in_opt2
+ with_tmpdir {
+ generate_file("t", "\u3042")
+ IO.foreach("t", :open_args => ["r", external_encoding: "utf-8", internal_encoding: "euc-jp"]) {|s|
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ assert_equal("\xa4\xa2".force_encoding("euc-jp"), s)
+ }
+ }
+ end
+
+ def test_both_textmode_binmode
+ assert_raise(ArgumentError) { open("not-exist", "r", :textmode=>true, :binmode=>true) }
+ end
+
+ def test_textmode_decode_universal_newline_read
+ with_tmpdir {
+ generate_file("t.crlf", "a\r\nb\r\nc\r\n")
+ assert_equal("a\nb\nc\n", File.read("t.crlf", mode:"rt:euc-jp:utf-8"))
+ assert_equal("a\nb\nc\n", File.read("t.crlf", mode:"rt"))
+ open("t.crlf", "rt:euc-jp:utf-8") {|f| assert_equal("a\nb\nc\n", f.read) }
+ open("t.crlf", "rt") {|f| assert_equal("a\nb\nc\n", f.read) }
+ open("t.crlf", "r", :textmode=>true) {|f| assert_equal("a\nb\nc\n", f.read) }
+
+ generate_file("t.cr", "a\rb\rc\r")
+ assert_equal("a\nb\nc\n", File.read("t.cr", mode:"rt:euc-jp:utf-8"))
+ assert_equal("a\nb\nc\n", File.read("t.cr", mode:"rt"))
+
+ generate_file("t.lf", "a\nb\nc\n")
+ assert_equal("a\nb\nc\n", File.read("t.cr", mode:"rt:euc-jp:utf-8"))
+ assert_equal("a\nb\nc\n", File.read("t.cr", mode:"rt"))
+ }
+ end
+
+ def test_textmode_decode_universal_newline_getc
+ with_tmpdir {
+ generate_file("t.crlf", "a\r\nb\r\nc\r\n")
+ open("t.crlf", "rt") {|f|
+ assert_equal("a", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("b", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("c", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal(nil, f.getc)
+ }
+
+ generate_file("t.cr", "a\rb\rc\r")
+ open("t.cr", "rt") {|f|
+ assert_equal("a", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("b", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("c", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal(nil, f.getc)
+ }
+
+ generate_file("t.lf", "a\nb\nc\n")
+ open("t.lf", "rt") {|f|
+ assert_equal("a", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("b", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("c", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal(nil, f.getc)
+ }
+ }
+ end
+
+ def test_textmode_decode_universal_newline_gets
+ with_tmpdir {
+ generate_file("t.crlf", "a\r\nb\r\nc\r\n")
+ open("t.crlf", "rt") {|f|
+ assert_equal("a\n", f.gets)
+ assert_equal("b\n", f.gets)
+ assert_equal("c\n", f.gets)
+ assert_equal(nil, f.gets)
+ }
+
+ generate_file("t.cr", "a\rb\rc\r")
+ open("t.cr", "rt") {|f|
+ assert_equal("a\n", f.gets)
+ assert_equal("b\n", f.gets)
+ assert_equal("c\n", f.gets)
+ assert_equal(nil, f.gets)
+ }
+
+ generate_file("t.lf", "a\nb\nc\n")
+ open("t.lf", "rt") {|f|
+ assert_equal("a\n", f.gets)
+ assert_equal("b\n", f.gets)
+ assert_equal("c\n", f.gets)
+ assert_equal(nil, f.gets)
+ }
+ }
+ end
+
+ def test_textmode_decode_universal_newline_utf16
+ with_tmpdir {
+ generate_file("t.utf16be.crlf", "\0a\0\r\0\n\0b\0\r\0\n\0c\0\r\0\n")
+ assert_equal("a\nb\nc\n", File.read("t.utf16be.crlf", mode:"rt:utf-16be:utf-8"))
+
+ generate_file("t.utf16le.crlf", "a\0\r\0\n\0b\0\r\0\n\0c\0\r\0\n\0")
+ assert_equal("a\nb\nc\n", File.read("t.utf16le.crlf", mode:"rt:utf-16le:utf-8"))
+
+ generate_file("t.utf16be.cr", "\0a\0\r\0b\0\r\0c\0\r")
+ assert_equal("a\nb\nc\n", File.read("t.utf16be.cr", mode:"rt:utf-16be:utf-8"))
+
+ generate_file("t.utf16le.cr", "a\0\r\0b\0\r\0c\0\r\0")
+ assert_equal("a\nb\nc\n", File.read("t.utf16le.cr", mode:"rt:utf-16le:utf-8"))
+
+ generate_file("t.utf16be.lf", "\0a\0\n\0b\0\n\0c\0\n")
+ assert_equal("a\nb\nc\n", File.read("t.utf16be.lf", mode:"rt:utf-16be:utf-8"))
+
+ generate_file("t.utf16le.lf", "a\0\n\0b\0\n\0c\0\n\0")
+ assert_equal("a\nb\nc\n", File.read("t.utf16le.lf", mode:"rt:utf-16le:utf-8"))
+ }
+ end
+
+ def system_newline
+ File::BINARY == 0 ? "\n" : "\r\n"
+ end
+
+ def test_textmode_encode_newline
+ with_tmpdir {
+ open("t.txt", "wt") {|f|
+ f.puts "abc"
+ f.puts "def"
+ }
+ content = File.read("t.txt", :mode=>"rb")
+ nl = system_newline
+ assert_equal("abc#{nl}def#{nl}", content)
+ }
+ end
+
+ def test_binary
+ with_tmpdir {
+ src = "a\nb\rc\r\nd\n"
+ generate_file("t.txt", src)
+ open("t.txt", "rb") {|f|
+ assert_equal(src, f.read)
+ }
+ open("t.txt", "r", :binmode=>true) {|f|
+ assert_equal(src, f.read)
+ }
+ if File::BINARY == 0
+ open("t.txt", "r") {|f|
+ assert_equal(src, f.read)
+ }
+ end
+ }
+ end
+
+ def test_binmode
+ with_tmpdir {
+ src = "a\r\nb\r\nc\r\n"
+ generate_file("t.txt", src)
+ open("t.txt", "rt") {|f|
+ assert_equal("a", f.getc)
+ assert_equal("\n", f.getc)
+ f.binmode
+ assert_equal("\n", f.getc)
+ assert_equal("b", f.getc)
+ assert_equal("\r", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("c", f.getc)
+ assert_equal("\r", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal(nil, f.getc)
+ }
+ }
+ end
+
+ def test_binmode2
+ with_tmpdir {
+ src = "a\r\nb\r\nc\r\n"
+ generate_file("t.txt", src)
+ open("t.txt", "rt:euc-jp:utf-8") {|f|
+ assert_equal("a", f.getc)
+ assert_equal("\n", f.getc)
+ f.binmode
+ assert_equal("\n", f.getc)
+ assert_equal("b", f.getc)
+ assert_equal("\r", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal("c", f.getc)
+ assert_equal("\r", f.getc)
+ assert_equal("\n", f.getc)
+ assert_equal(nil, f.getc)
+ }
+ }
+ end
+
+ def test_invalid_r
+ with_tmpdir {
+ generate_file("t.txt", "a\x80b")
+ open("t.txt", "r:utf-8:euc-jp", :invalid => :replace) {|f|
+ assert_equal("a?b", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :invalid => :ignore) {|f|
+ assert_equal("ab", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :undef => :replace) {|f|
+ assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_equal("b", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :undef => :ignore) {|f|
+ assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_equal("b", f.read)
+ }
+ }
+ end
+
+ def test_undef_r
+ with_tmpdir {
+ generate_file("t.txt", "a\uFFFDb")
+ open("t.txt", "r:utf-8:euc-jp", :undef => :replace) {|f|
+ assert_equal("a?b", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :undef => :ignore) {|f|
+ assert_equal("ab", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :invalid => :replace) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_equal("b", f.read)
+ }
+ open("t.txt", "r:utf-8:euc-jp", :invalid => :ignore) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_equal("b", f.read)
+ }
+ }
+ end
+
+ def test_invalid_w
+ with_tmpdir {
+ invalid_utf8 = "a\x80b".force_encoding("utf-8")
+ open("t.txt", "w:euc-jp", :invalid => :replace) {|f|
+ assert_nothing_raised { f.write invalid_utf8 }
+ }
+ assert_equal("a?b", File.read("t.txt"))
+
+ open("t.txt", "w:euc-jp", :invalid => :ignore) {|f|
+ assert_nothing_raised { f.write invalid_utf8 }
+ }
+ assert_equal("ab", File.read("t.txt"))
+
+ open("t.txt", "w:euc-jp", :undef => :replace) {|f|
+ assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ }
+ open("t.txt", "w:euc-jp", :undef => :ignore) {|f|
+ assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ }
+ }
+ end
+
+ def test_undef_w_stateless
+ with_tmpdir {
+ generate_file("t.txt", "a\uFFFDb")
+ open("t.txt", "w:euc-jp:utf-8", :undef => :replace) {|f|
+ assert_nothing_raised { f.write "a\uFFFDb" }
+ }
+ assert_equal("a?b", File.read("t.txt"))
+ open("t.txt", "w:euc-jp:utf-8", :undef => :ignore) {|f|
+ assert_nothing_raised { f.write "a\uFFFDb" }
+ }
+ assert_equal("ab", File.read("t.txt"))
+ open("t.txt", "w:euc-jp:utf-8", :invalid => :replace) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ }
+ open("t.txt", "w:euc-jp:utf-8", :invalid => :ignore) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ }
+ }
+ end
+
+ def test_undef_w_stateful
+ with_tmpdir {
+ generate_file("t.txt", "a\uFFFDb")
+ open("t.txt", "w:iso-2022-jp:utf-8", :undef => :replace) {|f|
+ assert_nothing_raised { f.write "a\uFFFDb" }
+ }
+ assert_equal("a?b", File.read("t.txt"))
+ open("t.txt", "w:iso-2022-jp:utf-8", :undef => :ignore) {|f|
+ assert_nothing_raised { f.write "a\uFFFDb" }
+ }
+ assert_equal("ab", File.read("t.txt"))
+ open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :replace) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ }
+ open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :ignore) {|f|
+ assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ }
+ }
+ end
+
+end
+
diff --git a/trunk/test/ruby/test_iterator.rb b/trunk/test/ruby/test_iterator.rb
new file mode 100644
index 0000000000..f6ac645321
--- /dev/null
+++ b/trunk/test/ruby/test_iterator.rb
@@ -0,0 +1,497 @@
+require 'test/unit'
+
+class Array
+ def iter_test1
+ collect{|e| [e, yield(e)]}.sort{|a,b|a[1]<=>b[1]}
+ end
+ def iter_test2
+ a = collect{|e| [e, yield(e)]}
+ a.sort{|a,b|a[1]<=>b[1]}
+ end
+end
+
+class TestIterator < Test::Unit::TestCase
+ def ttt
+ assert(iterator?)
+ end
+
+ def test_iterator
+ assert(!iterator?)
+
+ ttt{}
+
+ # yield at top level !! here's not toplevel
+ assert(!defined?(yield))
+ end
+
+ def test_array
+ $x = [1, 2, 3, 4]
+ $y = []
+
+ # iterator over array
+ for i in $x
+ $y.push i
+ end
+ assert_equal($x, $y)
+ end
+
+ def tt
+ 1.upto(10) {|i|
+ yield i
+ }
+ end
+
+ def tt2(dummy)
+ yield 1
+ end
+
+ def tt3(&block)
+ tt2(raise(ArgumentError,""),&block)
+ end
+
+ def test_nested_iterator
+ i = 0
+ tt{|i| break if i == 5}
+ assert_equal(0, i)
+
+ assert_raises(ArgumentError) do
+ tt3{}
+ end
+ end
+
+ def tt4 &block
+ tt2(raise(ArgumentError,""),&block)
+ end
+
+ def test_block_argument_without_paren
+ assert_raises(ArgumentError) do
+ tt4{}
+ end
+ end
+
+ # iterator break/redo/next
+ def test_break
+ done = true
+ loop{
+ break
+ done = false # should not reach here
+ }
+ assert(done)
+
+ done = false
+ $bad = false
+ loop {
+ break if done
+ done = true
+ next
+ $bad = true # should not reach here
+ }
+ assert(!$bad)
+
+ done = false
+ $bad = false
+ loop {
+ break if done
+ done = true
+ redo
+ $bad = true # should not reach here
+ }
+ assert(!$bad)
+
+ $x = []
+ for i in 1 .. 7
+ $x.push i
+ end
+ assert_equal(7, $x.size)
+ assert_equal([1, 2, 3, 4, 5, 6, 7], $x)
+ end
+
+ def test_append_method_to_built_in_class
+ $x = [[1,2],[3,4],[5,6]]
+ assert_equal($x.iter_test1{|x|x}, $x.iter_test2{|x|x})
+ end
+
+ class IterTest
+ def initialize(e); @body = e; end
+
+ def each0(&block); @body.each(&block); end
+ def each1(&block); @body.each {|*x| block.call(*x) } end
+ def each2(&block); @body.each {|*x| block.call(x) } end
+ def each3(&block); @body.each {|x| block.call(*x) } end
+ def each4(&block); @body.each {|x| block.call(x) } end
+ def each5; @body.each {|*x| yield(*x) } end
+ def each6; @body.each {|*x| yield(x) } end
+ def each7; @body.each {|x| yield(*x) } end
+ def each8; @body.each {|x| yield(x) } end
+
+ def f(a)
+ a
+ end
+ end
+
+ def test_itertest
+ assert_equal([1], IterTest.new(nil).method(:f).to_proc.call([1]))
+ m = /\w+/.match("abc")
+ assert_equal([m], IterTest.new(nil).method(:f).to_proc.call([m]))
+
+ IterTest.new([0]).each0 {|x| assert_equal(0, x)}
+ IterTest.new([1]).each1 {|x| assert_equal(1, x)}
+ IterTest.new([2]).each2 {|x| assert_equal([2], x)}
+ IterTest.new([4]).each4 {|x| assert_equal(4, x)}
+ IterTest.new([5]).each5 {|x| assert_equal(5, x)}
+ IterTest.new([6]).each6 {|x| assert_equal([6], x)}
+ IterTest.new([8]).each8 {|x| assert_equal(8, x)}
+
+ IterTest.new([[0]]).each0 {|x| assert_equal([0], x)}
+ IterTest.new([[1]]).each1 {|x| assert_equal([1], x)}
+ IterTest.new([[2]]).each2 {|x| assert_equal([[2]], x)}
+ IterTest.new([[3]]).each3 {|x| assert_equal(3, x)}
+ IterTest.new([[4]]).each4 {|x| assert_equal([4], x)}
+ IterTest.new([[5]]).each5 {|x| assert_equal([5], x)}
+ IterTest.new([[6]]).each6 {|x| assert_equal([[6]], x)}
+ IterTest.new([[7]]).each7 {|x| assert_equal(7, x)}
+ IterTest.new([[8]]).each8 {|x| assert_equal([8], x)}
+
+ IterTest.new([[0,0]]).each0 {|*x| assert_equal([[0,0]], x)}
+ IterTest.new([[8,8]]).each8 {|*x| assert_equal([[8,8]], x)}
+ end
+
+ def m(var)
+ var
+ end
+
+ def m1
+ m(block_given?)
+ end
+
+ def m2
+ m(block_given?,&proc{})
+ end
+
+ def test_block_given
+ assert(m1{p 'test'})
+ assert(m2{p 'test'})
+ assert(!m1())
+ assert(!m2())
+ end
+
+ def m3(var, &block)
+ m(yield(var), &block)
+ end
+
+ def m4(&block)
+ m(m1(), &block)
+ end
+
+ def test_block_passing
+ assert(!m4())
+ assert(!m4 {})
+ assert_equal(100, m3(10) {|x|x*x})
+ end
+
+ class C
+ include Enumerable
+ def initialize
+ @a = [1,2,3]
+ end
+ def each(&block)
+ @a.each(&block)
+ end
+ end
+
+ def test_collect
+ assert_equal([1,2,3], C.new.collect{|n| n})
+ end
+
+ def test_proc
+ assert_instance_of(Proc, lambda{})
+ assert_instance_of(Proc, Proc.new{})
+ lambda{|a|assert_equal(a, 1)}.call(1)
+ end
+
+ def test_block
+ assert_instance_of(NilClass, get_block)
+ assert_instance_of(Proc, get_block{})
+ end
+
+ def test_argument
+ assert_nothing_raised {lambda{||}.call}
+ assert_raises(ArgumentError) {lambda{||}.call(1)}
+ assert_nothing_raised {lambda{|a,|}.call(1)}
+ assert_raises(ArgumentError) {lambda{|a,|}.call()}
+ assert_raises(ArgumentError) {lambda{|a,|}.call(1,2)}
+ end
+
+ def get_block(&block)
+ block
+ end
+
+ def test_get_block
+ assert_instance_of(Proc, get_block{})
+ assert_nothing_raised {get_block{||}.call()}
+ assert_nothing_raised {get_block{||}.call(1)}
+ assert_nothing_raised {get_block{|a,|}.call(1)}
+ assert_nothing_raised {get_block{|a,|}.call()}
+ assert_nothing_raised {get_block{|a,|}.call(1,2)}
+
+ assert_nothing_raised {get_block(&lambda{||}).call()}
+ assert_raises(ArgumentError) {get_block(&lambda{||}).call(1)}
+ assert_nothing_raised {get_block(&lambda{|a,|}).call(1)}
+ assert_raises(ArgumentError) {get_block(&lambda{|a,|}).call(1,2)}
+
+ block = get_block{11}
+ assert_instance_of(Proc, block)
+ assert_instance_of(Proc, block.to_proc)
+ assert_equal(block.clone.call, 11)
+ assert_instance_of(Proc, get_block(&block))
+
+ lmd = lambda{44}
+ assert_instance_of(Proc, lmd)
+ assert_instance_of(Proc, lmd.to_proc)
+ assert_equal(lmd.clone.call, 44)
+ assert_instance_of(Proc, get_block(&lmd))
+
+ assert_equal(1, Proc.new{|a,| a}.call(1,2,3))
+ assert_nothing_raised {Proc.new{|a,|}.call(1,2)}
+ end
+
+ def return1_test
+ Proc.new {
+ return 55
+ }.call + 5
+ end
+
+ def test_return1
+ assert_equal(55, return1_test())
+ end
+
+ def return2_test
+ lambda {
+ return 55
+ }.call + 5
+ end
+
+ def test_return2
+ assert_equal(60, return2_test())
+ end
+
+ def proc_call(&b)
+ b.call
+ end
+ def proc_yield()
+ yield
+ end
+ def proc_return1
+ proc_call{return 42}+1
+ end
+
+ def test_proc_return1
+ assert_equal(42, proc_return1())
+ end
+
+ def proc_return2
+ proc_yield{return 42}+1
+ end
+
+ def test_proc_return2
+ assert_equal(42, proc_return2())
+ end
+
+ def test_ljump
+ assert_raises(LocalJumpError) {get_block{break}.call}
+
+ # cannot use assert_nothing_raised due to passing block.
+ begin
+ val = lambda{break 11}.call
+ rescue LocalJumpError
+ assert(false, "LocalJumpError occurred from break in lambda")
+ else
+ assert(11, val)
+ end
+
+ block = get_block{11}
+ lmd = lambda{44}
+ assert_equal(0, block.arity)
+ assert_equal(0, lmd.arity)
+ assert_equal(0, lambda{||}.arity)
+ assert_equal(1, lambda{|a|}.arity)
+ assert_equal(1, lambda{|a,|}.arity)
+ assert_equal(2, lambda{|a,b|}.arity)
+ end
+
+ def marity_test(m)
+ mobj = method(m)
+ assert_equal(mobj.arity, mobj.to_proc.arity)
+ end
+
+ def test_marity
+ marity_test(:assert)
+ marity_test(:marity_test)
+ marity_test(:p)
+
+ lambda(&method(:assert)).call(true)
+ lambda(&get_block{|a,n| assert(a,n)}).call(true, "marity")
+ end
+
+ def foo
+ yield(:key, :value)
+ end
+ def bar(&blk)
+ blk.call(:key, :value)
+ end
+
+ def test_yield_vs_call
+ foo{|k,v| assert_equal([:key, :value], [k,v])}
+ bar{|k,v| assert_equal([:key, :value], [k,v])}
+ end
+
+ class H
+ def each
+ yield [:key, :value]
+ end
+ alias each_pair each
+ end
+
+ def test_assoc_yield
+ [{:key=>:value}, H.new].each {|h|
+ h.each{|a| assert_equal([:key, :value], a)}
+ h.each{|a,| assert_equal(:key, a)}
+ h.each{|*a| assert_equal([[:key, :value]], a)}
+ h.each{|k,v| assert_equal([:key, :value], [k,v])}
+ h.each_pair{|a| assert_equal([:key, :value], a)}
+ h.each_pair{|a,| assert_equal(:key, a)}
+ h.each_pair{|*a| assert_equal([[:key, :value]], a)}
+ h.each_pair{|k,v| assert_equal([:key, :value], [k,v])}
+ }
+ end
+
+ class ITER_TEST1
+ def a
+ block_given?
+ end
+ end
+
+ class ITER_TEST2 < ITER_TEST1
+ include Test::Unit::Assertions
+ def a
+ assert(super)
+ super
+ end
+ end
+
+ def test_iter_test2
+ assert(ITER_TEST2.new.a {})
+ end
+
+ class ITER_TEST3
+ def foo x
+ return yield if block_given?
+ x
+ end
+ end
+
+ class ITER_TEST4 < ITER_TEST3
+ include Test::Unit::Assertions
+ def foo x
+ assert_equal(super, yield)
+ assert_equal(x, super(x, &nil))
+ end
+ end
+
+ def test_iter4
+ ITER_TEST4.new.foo(44){55}
+ end
+
+ def test_break__nested_loop1
+ _test_break__nested_loop1 do
+ break
+ end
+ end
+
+ def _test_break__nested_loop1
+ while true
+ yield
+ end
+ assert(false, "must not reach here")
+ end
+
+ def test_break__nested_loop2
+ _test_break__nested_loop2 do
+ break
+ end
+ end
+
+ def _test_break__nested_loop2
+ until false
+ yield
+ end
+ assert(false, "must not reach here")
+ end
+
+ def test_break__nested_loop3
+ _test_break__nested_loop3 do
+ break
+ end
+ end
+
+ def _test_break__nested_loop3
+ loop do
+ yield
+ end
+ assert(false, "must not reach here")
+ end
+
+ def test_break_from_enum
+ result = ["a"].inject("ng") {|x,y| break "ok"}
+ assert_equal("ok", result)
+ end
+
+ def _test_return_trace_func(x)
+ set_trace_func(proc {})
+ [].fetch(2) {return x}
+ ensure
+ set_trace_func(nil)
+ end
+
+ def test_return_trace_func
+ ok = "returned gracefully"
+ result = "skipped"
+ result = _test_return_trace_func(ok)
+ ensure
+ assert_equal(ok, result)
+ return
+ end
+
+ class IterString < ::String
+ def ===(other)
+ super if !block_given?
+ end
+ end
+
+ # Check that the block passed to an iterator
+ # does not get propagated inappropriately
+ def test_block_given_within_iterator
+ assert_equal(["b"], ["a", "b", "c"].grep(IterString.new("b")) {|s| s})
+ end
+
+ def test_enumerator
+ [1,2,3].each.with_index {|x,i|
+ assert_equal(x, i+1)
+ }
+
+ e = [1,2,3].each
+ assert_equal(1, e.next)
+ assert_equal(2, e.next)
+ assert_equal(3, e.next)
+ assert_raises(StopIteration){e.next}
+ e.rewind
+ assert_equal(1, e.next)
+ e.rewind
+ a = []
+ loop{a.push e.next}
+ assert_equal([1,2,3], a)
+
+ assert_equal([[8, 1, 10], [6, 2, 11], [4, 3, 12]],
+ [8,6,4].zip((1..10),(10..100)).to_a)
+ end
+end
diff --git a/trunk/test/ruby/test_lambda.rb b/trunk/test/ruby/test_lambda.rb
new file mode 100644
index 0000000000..bb0861ab53
--- /dev/null
+++ b/trunk/test/ruby/test_lambda.rb
@@ -0,0 +1,68 @@
+require 'test/unit'
+
+class TestLambdaParameters < Test::Unit::TestCase
+
+ def test_exact_parameter
+ assert_raise(ArgumentError){(1..3).each(&lambda{})}
+ end
+
+ def test_call_simple
+ assert_equal(1, lambda{|a| a}.call(1))
+ assert_equal([1,2], lambda{|a, b| [a,b]}.call(1,2))
+ assert_raises(ArgumentError) { lambda{|a|}.call(1,2) }
+ assert_raises(ArgumentError) { lambda{|a|}.call() }
+ assert_raises(ArgumentError) { lambda{}.call(1) }
+ assert_raises(ArgumentError) { lambda{|a, b|}.call(1,2,3) }
+
+ assert_equal(1, ->(a){ a }.call(1))
+ assert_equal([1,2], ->(a,b){ [a,b] }.call(1,2))
+ assert_raises(ArgumentError) { ->(a){ }.call(1,2) }
+ assert_raises(ArgumentError) { ->(a){ }.call() }
+ assert_raises(ArgumentError) { ->(){ }.call(1) }
+ assert_raises(ArgumentError) { ->(a,b){ }.call(1,2,3) }
+ end
+
+end
+
+__END__
+ def test_lambda_as_iterator
+ a = 0
+ 2.times(&->(_){ a += 1 })
+ assert_equal(a, 2)
+ end
+
+ def test_call_rest_args
+ assert_equal([1,2], ->(*a){ a }.call(1,2))
+ assert_equal([1,2,[]], ->(a,b,*c){ [a,b,c] }.call(1,2))
+ assert_raises(ArgumentError){ ->(a,*b){ }.call() }
+ end
+
+ def test_call_opt_args
+ assert_equal([1,2,3,4], ->(a,b,c=3,d=4){ [a,b,c,d] }.call(1,2))
+ assert_equal([1,2,3,4], ->(a,b,c=0,d=4){ [a,b,c,d] }.call(1,2,3))
+ assert_raises(ArgumentError){ ->(a,b=1){ }.call() }
+ assert_raises(ArgumentError){ ->(a,b=1){ }.call(1,2,3) }
+ end
+
+ def test_call_rest_and_opt
+ assert_equal([1,2,3,[]], ->(a,b=2,c=3,*d){ [a,b,c,d] }.call(1))
+ assert_equal([1,2,3,[]], ->(a,b=0,c=3,*d){ [a,b,c,d] }.call(1,2))
+ assert_equal([1,2,3,[4,5,6]], ->(a,b=0,c=0,*d){ [a,b,c,d] }.call(1,2,3,4,5,6))
+ assert_raises(ArgumentError){ ->(a,b=1,*c){ }.call() }
+ end
+
+ def test_call_with_block
+ f = ->(a,b,c=3,*d,&e){ [a,b,c,d,e.call(d + [a,b,c])] }
+ assert_equal([1,2,3,[],6], f.call(1,2){|z| z.inject{|s,x| s+x} } )
+ assert_equal(nil, ->(&b){ b }.call)
+ foo { puts "bogus block " }
+ assert_equal(1, ->(&b){ b.call }.call { 1 })
+ b = nil
+ assert_equal(1, ->(&b){ b.call }.call { 1 })
+ assert_nil(b)
+ end
+
+ def foo
+ assert_equal(nil, ->(&b){ b }.call)
+ end
+end
diff --git a/trunk/test/ruby/test_literal.rb b/trunk/test/ruby/test_literal.rb
new file mode 100644
index 0000000000..e87769a6c8
--- /dev/null
+++ b/trunk/test/ruby/test_literal.rb
@@ -0,0 +1,241 @@
+require 'test/unit'
+
+class TestRubyLiteral < Test::Unit::TestCase
+
+ def test_special_const
+ assert_equal 'true', true.inspect
+ assert_instance_of TrueClass, true
+ assert_equal 'false', false.inspect
+ assert_instance_of FalseClass, false
+ assert_equal 'nil', nil.inspect
+ assert_instance_of NilClass, nil
+ assert_equal ':sym', :sym.inspect
+ assert_instance_of Symbol, :sym
+ assert_equal '1234', 1234.inspect
+ assert_instance_of Fixnum, 1234
+ assert_equal '1234', 1_2_3_4.inspect
+ assert_instance_of Fixnum, 1_2_3_4
+ assert_equal '18', 0x12.inspect
+ assert_instance_of Fixnum, 0x12
+ assert_raise(SyntaxError) { eval("0x") }
+ assert_equal '15', 0o17.inspect
+ assert_instance_of Fixnum, 0o17
+ assert_raise(SyntaxError) { eval("0o") }
+ assert_equal '5', 0b101.inspect
+ assert_instance_of Fixnum, 0b101
+ assert_raise(SyntaxError) { eval("0b") }
+ assert_equal '123456789012345678901234567890', 123456789012345678901234567890.inspect
+ assert_instance_of Bignum, 123456789012345678901234567890
+ assert_instance_of Float, 1.3
+ end
+
+ def test_self
+ assert_equal self, self
+ assert_instance_of TestRubyLiteral, self
+ assert_respond_to self, :test_self
+ end
+
+ def test_string
+ assert_instance_of String, ?a
+ assert_equal "a", ?a
+ assert_instance_of String, ?A
+ assert_equal "A", ?A
+ assert_instance_of String, ?\n
+ assert_equal "\n", ?\n
+ assert_equal " ", ?\ # space
+ assert_equal '', ''
+ assert_equal 'string', 'string'
+ assert_equal 'string string', 'string string'
+ assert_equal ' ', ' '
+ assert_equal ' ', " "
+ assert_equal "\0", "\0"
+ assert_equal "\1", "\1"
+ assert_equal "3", "\x33"
+ assert_equal "\n", "\n"
+ end
+
+ def test_dstring
+ assert_equal '2', "#{1+1}"
+ assert_equal '16', "#{2 ** 4}"
+ s = "string"
+ assert_equal s, "#{s}"
+ end
+
+ def test_dsymbol
+ assert_equal :a3c, :"a#{1+2}c"
+ end
+
+ def test_xstring
+ assert_equal "foo\n", `echo foo`
+ s = 'foo'
+ assert_equal "foo\n", `echo #{s}`
+ end
+
+ def test_regexp
+ assert_instance_of Regexp, //
+ assert_match //, 'a'
+ assert_match //, ''
+ assert_instance_of Regexp, /a/
+ assert_match /a/, 'a'
+ assert_no_match /test/, 'tes'
+ re = /test/
+ assert_match re, 'test'
+ str = 'test'
+ assert_match re, str
+ assert_match /test/, str
+ assert_equal 0, (/test/ =~ 'test')
+ assert_equal 0, (re =~ 'test')
+ assert_equal 0, (/test/ =~ str)
+ assert_equal 0, (re =~ str)
+ assert_equal 0, ('test' =~ /test/)
+ assert_equal 0, ('test' =~ re)
+ assert_equal 0, (str =~ /test/)
+ assert_equal 0, (str =~ re)
+ end
+
+ def test_dregexp
+ assert_instance_of Regexp, /re#{'ge'}xp/
+ assert_equal(/regexp/, /re#{'ge'}xp/)
+ end
+
+ def test_array
+ assert_instance_of Array, []
+ assert_equal [], []
+ assert_equal 0, [].size
+ assert_instance_of Array, [0]
+ assert_equal [3], [3]
+ assert_equal 1, [3].size
+ a = [3]
+ assert_equal 3, a[0]
+ assert_instance_of Array, [1,2]
+ assert_equal [1,2], [1,2]
+ assert_instance_of Array, [1,2,3,4,5]
+ assert_equal [1,2,3,4,5], [1,2,3,4,5]
+ assert_equal 5, [1,2,3,4,5].size
+ a = [1,2]
+ assert_equal 1, a[0]
+ assert_equal 2, a[1]
+ a = [1 + 2, 3 + 4, 5 + 6]
+ assert_instance_of Array, a
+ assert_equal [3, 7, 11], a
+ assert_equal 7, a[1]
+ assert_equal 1, ([0][0] += 1)
+ assert_equal 1, ([2][0] -= 1)
+ a = [obj = Object.new]
+ assert_instance_of Array, a
+ assert_equal 1, a.size
+ assert_equal obj, a[0]
+ a = [1,2,3]
+ a[1] = 5
+ assert_equal 5, a[1]
+ end
+
+ def test_hash
+ assert_instance_of Hash, {}
+ assert_equal({}, {})
+ assert_instance_of Hash, {1 => 2}
+ assert_equal({1 => 2}, {1 => 2})
+ h = {1 => 2}
+ assert_equal 2, h[1]
+ h = {"string" => "literal", "goto" => "hell"}
+ assert_equal h, h
+ assert_equal 2, h.size
+ assert_equal h, h
+ assert_equal "literal", h["string"]
+ end
+
+ def test_range
+ assert_instance_of Range, (1..2)
+ assert_equal(1..2, 1..2)
+ r = 1..2
+ assert_equal 1, r.begin
+ assert_equal 2, r.end
+ assert_equal false, r.exclude_end?
+ assert_instance_of Range, (1...3)
+ assert_equal(1...3, 1...3)
+ r = 1...3
+ assert_equal 1, r.begin
+ assert_equal 3, r.end
+ assert_equal true, r.exclude_end?
+ r = 1+2 .. 3+4
+ assert_instance_of Range, r
+ assert_equal 3, r.begin
+ assert_equal 7, r.end
+ assert_equal false, r.exclude_end?
+ r = 1+2 ... 3+4
+ assert_instance_of Range, r
+ assert_equal 3, r.begin
+ assert_equal 7, r.end
+ assert_equal true, r.exclude_end?
+ assert_instance_of Range, 'a'..'c'
+ r = 'a'..'c'
+ assert_equal 'a', r.begin
+ assert_equal 'c', r.end
+ end
+
+ def test__FILE__
+ assert_instance_of String, __FILE__
+ assert_equal __FILE__, __FILE__
+ assert_equal 'test_literal.rb', File.basename(__FILE__)
+ end
+
+ def test__LINE__
+ assert_instance_of Fixnum, __LINE__
+ assert_equal __LINE__, __LINE__
+ end
+
+ def test_integer
+ head = ['', '0x', '0o', '0b', '0d', '-', '+']
+ chars = ['0', '1', '_', '9', 'f']
+ head.each {|h|
+ 4.times {|len|
+ a = [h]
+ len.times { a = a.product(chars).map {|x| x.join('') } }
+ a.each {|s|
+ next if s.empty?
+ begin
+ r1 = Integer(s)
+ rescue ArgumentError
+ r1 = :err
+ end
+ begin
+ r2 = eval(s)
+ rescue NameError, SyntaxError
+ r2 = :err
+ end
+ assert_equal(r1, r2, "Integer(#{s.inspect}) != eval(#{s.inspect})")
+ }
+ }
+ }
+ end
+
+ def test_float
+ head = ['', '-', '+']
+ chars = ['0', '1', '_', '9', 'f', '.']
+ head.each {|h|
+ 6.times {|len|
+ a = [h]
+ len.times { a = a.product(chars).map {|x| x.join('') } }
+ a.each {|s|
+ next if s.empty?
+ next if /\.\z/ =~ s
+ next if /\A[-+]?\./ =~ s
+ next if /\A[-+]?0/ =~ s
+ begin
+ r1 = Float(s)
+ rescue ArgumentError
+ r1 = :err
+ end
+ begin
+ r2 = eval(s)
+ rescue NameError, SyntaxError
+ r2 = :err
+ end
+ r2 = :err if Range === r2
+ assert_equal(r1, r2, "Float(#{s.inspect}) != eval(#{s.inspect})")
+ }
+ }
+ }
+ end
+
+end
diff --git a/trunk/test/ruby/test_m17n.rb b/trunk/test/ruby/test_m17n.rb
new file mode 100644
index 0000000000..e82e04beb7
--- /dev/null
+++ b/trunk/test/ruby/test_m17n.rb
@@ -0,0 +1,1290 @@
+require 'test/unit'
+require 'stringio'
+
+class TestM17N < Test::Unit::TestCase
+ def assert_encoding(encname, actual, message=nil)
+ assert_equal(Encoding.find(encname), actual, message)
+ end
+
+ module AESU
+ def a(str) str.dup.force_encoding("ASCII-8BIT") end
+ def e(str) str.dup.force_encoding("EUC-JP") end
+ def s(str) str.dup.force_encoding("Windows-31J") end
+ def u(str) str.dup.force_encoding("UTF-8") end
+ end
+ include AESU
+ extend AESU
+
+ def assert_strenc(bytes, enc, actual, message=nil)
+ assert_instance_of(String, actual, message)
+ enc = Encoding.find(enc) if String === enc
+ assert_equal(enc, actual.encoding, message)
+ assert_equal(a(bytes), a(actual), message)
+ end
+
+ def assert_warning(pat, mesg=nil)
+ begin
+ org_stderr = $stderr
+ $stderr = StringIO.new(warn = '')
+ yield
+ ensure
+ $stderr = org_stderr
+ end
+ assert_match(pat, warn, mesg)
+ end
+
+ def assert_regexp_generic_encoding(r)
+ assert(!r.fixed_encoding?)
+ %w[ASCII-8BIT EUC-JP Windows-31J UTF-8].each {|ename|
+ # "\xc2\xa1" is a valid sequence for ASCII-8BIT, EUC-JP, Windows-31J and UTF-8.
+ assert_nothing_raised { r =~ "\xc2\xa1".force_encoding(ename) }
+ }
+ end
+
+ def assert_regexp_fixed_encoding(r)
+ assert(r.fixed_encoding?)
+ %w[ASCII-8BIT EUC-JP Windows-31J UTF-8].each {|ename|
+ enc = Encoding.find(ename)
+ if enc == r.encoding
+ assert_nothing_raised { r =~ "\xc2\xa1".force_encoding(enc) }
+ else
+ assert_raise(ArgumentError) { r =~ "\xc2\xa1".force_encoding(enc) }
+ end
+ }
+ end
+
+ def assert_regexp_generic_ascii(r)
+ assert_encoding("US-ASCII", r.encoding)
+ assert_regexp_generic_encoding(r)
+ end
+
+ def assert_regexp_fixed_ascii8bit(r)
+ assert_encoding("ASCII-8BIT", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_eucjp(r)
+ assert_encoding("EUC-JP", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_sjis(r)
+ assert_encoding("Windows-31J", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_utf8(r)
+ assert_encoding("UTF-8", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_usascii_literal(r, enc, ex = nil)
+ code = "# -*- encoding: US-ASCII -*-\n#{r}.encoding"
+ if ex
+ assert_raise(ex) { eval(code) }
+ else
+ assert_equal(enc, eval(code))
+ end
+ end
+
+ def encdump(str)
+ d = str.dump
+ if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
+ d
+ else
+ "#{d}.force_encoding(#{str.encoding.name.dump})"
+ end
+ end
+
+ def encdumpargs(args)
+ r = '('
+ args.each_with_index {|a, i|
+ r << ',' if 0 < i
+ if String === a
+ r << encdump(a)
+ else
+ r << a.inspect
+ end
+ }
+ r << ')'
+ r
+ end
+
+ def assert_str_enc_propagation(t, s1, s2)
+ if !s1.ascii_only?
+ assert_equal(s1.encoding, t.encoding)
+ elsif !s2.ascii_only?
+ assert_equal(s2.encoding, t.encoding)
+ else
+ assert([s1.encoding, s2.encoding].include?(t.encoding))
+ end
+ end
+
+ def assert_same_result(expected_proc, actual_proc)
+ e = nil
+ begin
+ t = expected_proc.call
+ rescue
+ e = $!
+ end
+ if e
+ assert_raise(e.class) { actual_proc.call }
+ else
+ assert_equal(t, actual_proc.call)
+ end
+ end
+
+ def str_enc_compatible?(*strs)
+ encs = []
+ strs.each {|s|
+ encs << s.encoding if !s.ascii_only?
+ }
+ encs.uniq!
+ encs.length <= 1
+ end
+
+ # tests start
+
+ def test_string_ascii_literal
+ assert_encoding("US-ASCII", eval(a(%{""})).encoding)
+ assert_encoding("US-ASCII", eval(a(%{"a"})).encoding)
+ end
+
+ def test_string_eucjp_literal
+ assert_encoding("US-ASCII", eval(e(%{""})).encoding)
+ assert_encoding("US-ASCII", eval(e(%{"a"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\xa1\xa1"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\xa1\\xa1"})).encoding)
+ assert_encoding("US-ASCII", eval(e(%{"\\x20"})).encoding)
+ assert_encoding("US-ASCII", eval(e(%{"\\n"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\x80"})).encoding)
+ end
+
+ def test_utf8_literal
+ assert_equal(Encoding::UTF_8, "\u3042".encoding, "[ruby-dev:33406] \"\\u3042\".encoding")
+ assert_raise(SyntaxError) { eval(a('\u3052\x80')) }
+ end
+
+ def test_string_mixed_unicode
+ assert_raise(SyntaxError) { eval(a(%{"\xc2\xa1\\u{6666}"})) }
+ assert_raise(SyntaxError) { eval(e(%{"\xc2\xa1\\u{6666}"})) }
+ assert_raise(SyntaxError) { eval(s(%{"\xc2\xa1\\u{6666}"})) }
+ assert_nothing_raised { eval(u(%{"\xc2\xa1\\u{6666}"})) }
+ assert_raise(SyntaxError) { eval(a(%{"\\u{6666}\xc2\xa1"})) }
+ assert_raise(SyntaxError) { eval(e(%{"\\u{6666}\xc2\xa1"})) }
+ assert_raise(SyntaxError) { eval(s(%{"\\u{6666}\xc2\xa1"})) }
+ assert_nothing_raised { eval(u(%{"\\u{6666}\xc2\xa1"})) }
+ end
+
+ def test_string_inspect
+ assert_equal('"\xFE"', e("\xfe").inspect)
+ assert_equal('"\x8E"', e("\x8e").inspect)
+ assert_equal('"\x8F"', e("\x8f").inspect)
+ assert_equal('"\x8F\xA1"', e("\x8f\xa1").inspect)
+ assert_equal('"\xEF"', s("\xef").inspect)
+ assert_equal('"\xC2"', u("\xc2").inspect)
+ assert_equal('"\xE0\x80"', u("\xe0\x80").inspect)
+ assert_equal('"\xF0\x80\x80"', u("\xf0\x80\x80").inspect)
+ assert_equal('"\xF8\x80\x80\x80"', u("\xf8\x80\x80\x80").inspect)
+ assert_equal('"\xFC\x80\x80\x80\x80"', u("\xfc\x80\x80\x80\x80").inspect)
+
+ assert_equal('"\xFE "', e("\xfe ").inspect)
+ assert_equal('"\x8E "', e("\x8e ").inspect)
+ assert_equal('"\x8F "', e("\x8f ").inspect)
+ assert_equal('"\x8F\xA1 "', e("\x8f\xa1 ").inspect)
+ assert_equal('"\xEF "', s("\xef ").inspect)
+ assert_equal('"\xC2 "', u("\xc2 ").inspect)
+ assert_equal('"\xE0\x80 "', u("\xe0\x80 ").inspect)
+ assert_equal('"\xF0\x80\x80 "', u("\xf0\x80\x80 ").inspect)
+ assert_equal('"\xF8\x80\x80\x80 "', u("\xf8\x80\x80\x80 ").inspect)
+ assert_equal('"\xFC\x80\x80\x80\x80 "', u("\xfc\x80\x80\x80\x80 ").inspect)
+
+
+ assert_equal(e("\"\\xA1\x8f\xA1\xA1\""), e("\xa1\x8f\xa1\xa1").inspect)
+
+ assert_equal('"\x81."', s("\x81.").inspect)
+ assert_equal(s("\"\x81@\""), s("\x81@").inspect)
+
+ assert_equal('"\xFC"', u("\xfc").inspect)
+ end
+
+ def test_str_dump
+ [
+ e("\xfe"),
+ e("\x8e"),
+ e("\x8f"),
+ e("\x8f\xa1"),
+ s("\xef"),
+ u("\xc2"),
+ u("\xe0\x80"),
+ u("\xf0\x80\x80"),
+ u("\xf8\x80\x80\x80"),
+ u("\xfc\x80\x80\x80\x80"),
+
+ e("\xfe "),
+ e("\x8e "),
+ e("\x8f "),
+ e("\x8f\xa1 "),
+ s("\xef "),
+ u("\xc2 "),
+ u("\xe0\x80 "),
+ u("\xf0\x80\x80 "),
+ u("\xf8\x80\x80\x80 "),
+ u("\xfc\x80\x80\x80\x80 "),
+
+
+ e("\xa1\x8f\xa1\xa1"),
+
+ s("\x81."),
+ s("\x81@"),
+
+ u("\xfc"),
+ "\u3042",
+ "ascii",
+ ].each do |str|
+ assert_equal(str, eval(str.dump), "[ruby-dev:33142]")
+ end
+ end
+
+ def test_validate_redundant_utf8
+ bits_0x10ffff = "11110100 10001111 10111111 10111111"
+ [
+ "0xxxxxxx",
+ "110XXXXx 10xxxxxx",
+ "1110XXXX 10Xxxxxx 10xxxxxx",
+ "11110XXX 10XXxxxx 10xxxxxx 10xxxxxx",
+ "111110XX 10XXXxxx 10xxxxxx 10xxxxxx 10xxxxxx",
+ "1111110X 10XXXXxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx",
+ "11111110 10XXXXXx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx",
+ "11111111 10XXXXXX 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx",
+ ].each {|pat0|
+ [
+ pat0.gsub(/x/, '1'),
+ pat0.gsub(/x/, '0')
+ ].each {|pat1|
+ [
+ pat1.sub(/X([^X]*)\z/, '1\1').gsub(/X/, "0"),
+ pat1.gsub(/X/, "1"),
+ ].each {|pat2|
+ s = [pat2.gsub(/ /, "")].pack("B*").force_encoding("utf-8")
+ if pat2 <= bits_0x10ffff
+ assert(s.valid_encoding?, "#{pat2}")
+ else
+ assert(!s.valid_encoding?, "#{pat2}")
+ end
+ }
+ if / / =~ pat0
+ pat3 = pat1.gsub(/X/, "0")
+ s = [pat3.gsub(/ /, "")].pack("B*").force_encoding("utf-8")
+ assert(!s.valid_encoding?, "#{pat3}")
+ end
+ }
+ }
+ end
+
+ def test_validate_surrogate
+ # 1110XXXX 10Xxxxxx 10xxxxxx : 3 bytes UTF-8
+ pats = [
+ "11101101 10011111 10111111", # just before surrogate high
+ "11101101 1010xxxx 10xxxxxx", # surrogate high
+ "11101101 1011xxxx 10xxxxxx", # surrogate low
+ "11101110 10000000 10000000", # just after surrogate low
+ ]
+ pats.values_at(1,2).each {|pat0|
+ [
+ pat0.gsub(/x/, '0'),
+ pat0.gsub(/x/, '1'),
+ ].each {|pat1|
+ s = [pat1.gsub(/ /, "")].pack("B*").force_encoding("utf-8")
+ assert(!s.valid_encoding?, "#{pat1}")
+ }
+ }
+ pats.values_at(0,3).each {|pat|
+ s = [pat.gsub(/ /, "")].pack("B*").force_encoding("utf-8")
+ assert(s.valid_encoding?, "#{pat}")
+ }
+ end
+
+ def test_regexp_too_short_multibyte_character
+ assert_raise(SyntaxError) { eval('/\xfe/e') }
+ assert_raise(SyntaxError) { eval('/\x8e/e') }
+ assert_raise(SyntaxError) { eval('/\x8f/e') }
+ assert_raise(SyntaxError) { eval('/\x8f\xa1/e') }
+ assert_raise(SyntaxError) { eval('/\xef/s') }
+ assert_raise(SyntaxError) { eval('/\xc2/u') }
+ assert_raise(SyntaxError) { eval('/\xe0\x80/u') }
+ assert_raise(SyntaxError) { eval('/\xf0\x80\x80/u') }
+ assert_raise(SyntaxError) { eval('/\xf8\x80\x80\x80/u') }
+ assert_raise(SyntaxError) { eval('/\xfc\x80\x80\x80\x80/u') }
+
+ # raw 8bit
+ assert_raise(SyntaxError) { eval("/\xfe/e") }
+ assert_raise(SyntaxError) { eval("/\xc2/u") }
+
+ # invalid suffix
+ assert_raise(SyntaxError) { eval('/\xc2\xff/u') }
+ assert_raise(SyntaxError) { eval('/\xc2 /u') }
+ assert_raise(SyntaxError) { eval('/\xc2\x20/u') }
+ end
+
+ def test_regexp_generic
+ assert_regexp_generic_ascii(/a/)
+ assert_regexp_generic_ascii(Regexp.new(a("a")))
+ assert_regexp_generic_ascii(Regexp.new(e("a")))
+ assert_regexp_generic_ascii(Regexp.new(s("a")))
+ assert_regexp_generic_ascii(Regexp.new(u("a")))
+
+ [/a/, Regexp.new(a("a"))].each {|r|
+ assert_equal(0, r =~ a("a"))
+ assert_equal(0, r =~ e("a"))
+ assert_equal(0, r =~ s("a"))
+ assert_equal(0, r =~ u("a"))
+ assert_equal(nil, r =~ a("\xc2\xa1"))
+ assert_equal(nil, r =~ e("\xc2\xa1"))
+ assert_equal(nil, r =~ s("\xc2\xa1"))
+ assert_equal(nil, r =~ u("\xc2\xa1"))
+ }
+ end
+
+ def test_regexp_ascii_none
+ r = /a/n
+
+ assert_warning(%r{regexp match /.../n against to}) {
+ assert_regexp_generic_ascii(r)
+ }
+
+ assert_equal(0, r =~ a("a"))
+ assert_equal(0, r =~ e("a"))
+ assert_equal(0, r =~ s("a"))
+ assert_equal(0, r =~ u("a"))
+ assert_equal(nil, r =~ a("\xc2\xa1"))
+ assert_warning(%r{regexp match /.../n against to EUC-JP string}) {
+ assert_equal(nil, r =~ e("\xc2\xa1"))
+ }
+ assert_warning(%r{regexp match /.../n against to Windows-31J string}) {
+ assert_equal(nil, r =~ s("\xc2\xa1"))
+ }
+ assert_warning(%r{regexp match /.../n against to UTF-8 string}) {
+ assert_equal(nil, r =~ u("\xc2\xa1"))
+ }
+
+ assert_nothing_raised { eval(e("/\\x80/n")) }
+ end
+
+ def test_regexp_ascii
+ assert_regexp_fixed_ascii8bit(/\xc2\xa1/n)
+ assert_regexp_fixed_ascii8bit(eval(a(%{/\xc2\xa1/})))
+ assert_regexp_fixed_ascii8bit(eval(a(%{/\xc2\xa1/n})))
+ assert_regexp_fixed_ascii8bit(eval(a(%q{/\xc2\xa1/})))
+
+ assert_raise(SyntaxError) { eval("/\xa1\xa1/n".force_encoding("euc-jp")) }
+
+ [/\xc2\xa1/n, eval(a(%{/\xc2\xa1/})), eval(a(%{/\xc2\xa1/n}))].each {|r|
+ assert_equal(nil, r =~ a("a"))
+ assert_equal(nil, r =~ e("a"))
+ assert_equal(nil, r =~ s("a"))
+ assert_equal(nil, r =~ u("a"))
+ assert_equal(0, r =~ a("\xc2\xa1"))
+ assert_raise(ArgumentError) { r =~ e("\xc2\xa1") }
+ assert_raise(ArgumentError) { r =~ s("\xc2\xa1") }
+ assert_raise(ArgumentError) { r =~ u("\xc2\xa1") }
+ }
+ end
+
+ def test_regexp_euc
+ assert_regexp_fixed_eucjp(/a/e)
+ assert_regexp_fixed_eucjp(/\xc2\xa1/e)
+ assert_regexp_fixed_eucjp(eval(e(%{/\xc2\xa1/})))
+ assert_regexp_fixed_eucjp(eval(e(%q{/\xc2\xa1/})))
+
+ [/a/e].each {|r|
+ assert_equal(0, r =~ a("a"))
+ assert_equal(0, r =~ e("a"))
+ assert_equal(0, r =~ s("a"))
+ assert_equal(0, r =~ u("a"))
+ assert_raise(ArgumentError) { r =~ a("\xc2\xa1") }
+ assert_equal(nil, r =~ e("\xc2\xa1"))
+ assert_raise(ArgumentError) { r =~ s("\xc2\xa1") }
+ assert_raise(ArgumentError) { r =~ u("\xc2\xa1") }
+ }
+
+ [/\xc2\xa1/e, eval(e(%{/\xc2\xa1/})), eval(e(%q{/\xc2\xa1/}))].each {|r|
+ assert_equal(nil, r =~ a("a"))
+ assert_equal(nil, r =~ e("a"))
+ assert_equal(nil, r =~ s("a"))
+ assert_equal(nil, r =~ u("a"))
+ assert_raise(ArgumentError) { r =~ a("\xc2\xa1") }
+ assert_equal(0, r =~ e("\xc2\xa1"))
+ assert_raise(ArgumentError) { r =~ s("\xc2\xa1") }
+ assert_raise(ArgumentError) { r =~ u("\xc2\xa1") }
+ }
+ end
+
+ def test_regexp_sjis
+ assert_regexp_fixed_sjis(/a/s)
+ assert_regexp_fixed_sjis(/\xc2\xa1/s)
+ assert_regexp_fixed_sjis(eval(s(%{/\xc2\xa1/})))
+ assert_regexp_fixed_sjis(eval(s(%q{/\xc2\xa1/})))
+ end
+
+ def test_regexp_windows_31j
+ begin
+ Regexp.new("\xa1".force_encoding("windows-31j")) =~ "\xa1\xa1".force_encoding("euc-jp")
+ rescue ArgumentError
+ err = $!
+ end
+ assert_match(/windows-31j/i, err.message)
+ end
+
+ def test_regexp_embed
+ r = eval(e("/\xc2\xa1/"))
+ assert_raise(ArgumentError) { eval(s("/\xc2\xa1\#{r}/s")) }
+ assert_raise(ArgumentError) { eval(s("/\#{r}\xc2\xa1/s")) }
+
+ r = /\xc2\xa1/e
+ assert_raise(ArgumentError) { eval(s("/\xc2\xa1\#{r}/s")) }
+ assert_raise(ArgumentError) { eval(s("/\#{r}\xc2\xa1/s")) }
+
+ r = eval(e("/\xc2\xa1/"))
+ assert_raise(ArgumentError) { /\xc2\xa1#{r}/s }
+
+ r = /\xc2\xa1/e
+ assert_raise(ArgumentError) { /\xc2\xa1#{r}/s }
+
+ r1 = Regexp.new('foo'.force_encoding("ascii-8bit"))
+ r2 = eval('/bar#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::US_ASCII, r2.encoding)
+
+ r1 = Regexp.new('foo'.force_encoding("us-ascii"))
+ r2 = eval('/bar#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::US_ASCII, r2.encoding)
+
+ r1 = Regexp.new('foo'.force_encoding("ascii-8bit"))
+ r2 = eval('/bar#{r1}/'.force_encoding('us-ascii'))
+ assert_equal(Encoding::US_ASCII, r2.encoding)
+
+ r1 = Regexp.new('foo'.force_encoding("us-ascii"))
+ r2 = eval('/bar#{r1}/'.force_encoding('us-ascii'))
+ assert_equal(Encoding::US_ASCII, r2.encoding)
+
+ r1 = Regexp.new('\xa1'.force_encoding("ascii-8bit"))
+ r2 = eval('/bar#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::ASCII_8BIT, r2.encoding)
+
+ r1 = Regexp.new('\xa1'.force_encoding("ascii-8bit"))
+ r2 = eval('/bar#{r1}/'.force_encoding('us-ascii'))
+ assert_equal(Encoding::ASCII_8BIT, r2.encoding)
+
+ r1 = Regexp.new('foo'.force_encoding("ascii-8bit"))
+ r2 = eval('/\xa1#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::ASCII_8BIT, r2.encoding)
+
+ r1 = Regexp.new('foo'.force_encoding("us-ascii"))
+ r2 = eval('/\xa1#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::ASCII_8BIT, r2.encoding)
+
+ r1 = Regexp.new('\xa1'.force_encoding("ascii-8bit"))
+ r2 = eval('/\xa1#{r1}/'.force_encoding('ascii-8bit'))
+ assert_equal(Encoding::ASCII_8BIT, r2.encoding)
+ end
+
+ def test_regexp_named_class
+ assert_match(/[[:space:]]/u, "\u{00a0}")
+ assert_match(/[[:space:]]/, "\u{00a0}")
+ end
+
+ def test_regexp_property
+ s = '\p{Hiragana}'.force_encoding("euc-jp")
+ assert_equal(Encoding::EUC_JP, s.encoding)
+ r = nil
+ assert_nothing_raised {
+ r = Regexp.new(s)
+ }
+ assert(r.fixed_encoding?)
+ assert_match(r, "\xa4\xa2".force_encoding("euc-jp"))
+
+ r = eval('/\p{Hiragana}/'.force_encoding("euc-jp"))
+ assert(r.fixed_encoding?)
+ assert_match(r, "\xa4\xa2".force_encoding("euc-jp"))
+
+ r = /\p{Hiragana}/e
+ assert(r.fixed_encoding?)
+ assert_match(r, "\xa4\xa2".force_encoding("euc-jp"))
+
+ r = eval('/\u{3042}\p{Hiragana}/'.force_encoding("euc-jp"))
+ assert(r.fixed_encoding?)
+ assert_equal(Encoding::UTF_8, r.encoding)
+
+ r = eval('/\p{Hiragana}\u{3042}/'.force_encoding("euc-jp"))
+ assert(r.fixed_encoding?)
+ assert_equal(Encoding::UTF_8, r.encoding)
+ end
+
+ def test_regexp_embed_preprocess
+ r1 = /\xa4\xa2/e
+ r2 = /#{r1}/
+ assert(r2.source.include?(r1.source))
+ end
+
+ def test_begin_end_offset
+ str = e("\244\242\244\244\244\246\244\250\244\252a")
+ assert(/(a)/ =~ str)
+ assert_equal("a", $&)
+ assert_equal(5, $~.begin(0))
+ assert_equal(6, $~.end(0))
+ assert_equal([5,6], $~.offset(0))
+ assert_equal(5, $~.begin(1))
+ assert_equal(6, $~.end(1))
+ assert_equal([5,6], $~.offset(1))
+ end
+
+ def test_begin_end_offset_sjis
+ str = s("\x81@@")
+ assert(/@/ =~ str)
+ assert_equal(s("\x81@"), $`)
+ assert_equal("@", $&)
+ assert_equal("", $')
+ assert_equal([1,2], $~.offset(0))
+ end
+
+ def test_quote
+ assert_regexp_generic_ascii(/#{Regexp.quote(a("a"))}#{Regexp.quote(e("e"))}/)
+
+ assert_encoding("US-ASCII", Regexp.quote(a("")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(e("")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(s("")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(u("")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(a("a")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(e("a")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(s("a")).encoding)
+ assert_encoding("US-ASCII", Regexp.quote(u("a")).encoding)
+
+ assert_encoding("ASCII-8BIT", Regexp.quote(a("\xc2\xa1")).encoding)
+ assert_encoding("EUC-JP", Regexp.quote(e("\xc2\xa1")).encoding)
+ assert_encoding("Windows-31J", Regexp.quote(s("\xc2\xa1")).encoding)
+ assert_encoding("UTF-8", Regexp.quote(u("\xc2\xa1")).encoding)
+ end
+
+ def test_union_0
+ r = Regexp.union
+ assert_regexp_generic_ascii(r)
+ assert(r !~ a(""))
+ assert(r !~ e(""))
+ assert(r !~ s(""))
+ assert(r !~ u(""))
+ end
+
+ def test_union_1_asciionly_string
+ assert_regexp_generic_ascii(Regexp.union(a("")))
+ assert_regexp_generic_ascii(Regexp.union(e("")))
+ assert_regexp_generic_ascii(Regexp.union(s("")))
+ assert_regexp_generic_ascii(Regexp.union(u("")))
+ assert_regexp_generic_ascii(Regexp.union(a("a")))
+ assert_regexp_generic_ascii(Regexp.union(e("a")))
+ assert_regexp_generic_ascii(Regexp.union(s("a")))
+ assert_regexp_generic_ascii(Regexp.union(u("a")))
+ assert_regexp_generic_ascii(Regexp.union(a("\t")))
+ assert_regexp_generic_ascii(Regexp.union(e("\t")))
+ assert_regexp_generic_ascii(Regexp.union(s("\t")))
+ assert_regexp_generic_ascii(Regexp.union(u("\t")))
+ end
+
+ def test_union_1_nonascii_string
+ assert_regexp_fixed_ascii8bit(Regexp.union(a("\xc2\xa1")))
+ assert_regexp_fixed_eucjp(Regexp.union(e("\xc2\xa1")))
+ assert_regexp_fixed_sjis(Regexp.union(s("\xc2\xa1")))
+ assert_regexp_fixed_utf8(Regexp.union(u("\xc2\xa1")))
+ end
+
+ def test_union_1_regexp
+ assert_regexp_generic_ascii(Regexp.union(//))
+ assert_warning(%r{regexp match /.../n against to}) {
+ assert_regexp_generic_ascii(Regexp.union(//n))
+ }
+ assert_regexp_fixed_eucjp(Regexp.union(//e))
+ assert_regexp_fixed_sjis(Regexp.union(//s))
+ assert_regexp_fixed_utf8(Regexp.union(//u))
+ end
+
+ def test_union_2
+ ary = [
+ a(""), e(""), s(""), u(""),
+ a("\xc2\xa1"), e("\xc2\xa1"), s("\xc2\xa1"), u("\xc2\xa1")
+ ]
+ ary.each {|s1|
+ ary.each {|s2|
+ if s1.empty?
+ if s2.empty?
+ assert_regexp_generic_ascii(Regexp.union(s1, s2))
+ else
+ r = Regexp.union(s1, s2)
+ assert_regexp_fixed_encoding(r)
+ assert_equal(s2.encoding, r.encoding)
+ end
+ else
+ if s2.empty?
+ r = Regexp.union(s1, s2)
+ assert_regexp_fixed_encoding(r)
+ assert_equal(s1.encoding, r.encoding)
+ else
+ if s1.encoding == s2.encoding
+ r = Regexp.union(s1, s2)
+ assert_regexp_fixed_encoding(r)
+ assert_equal(s1.encoding, r.encoding)
+ else
+ assert_raise(ArgumentError) { Regexp.union(s1, s2) }
+ end
+ end
+ end
+ }
+ }
+ end
+
+ def test_dynamic_ascii_regexp
+ assert_warning(%r{regexp match /.../n against to}) {
+ assert_regexp_generic_ascii(/#{}/n)
+ }
+ assert_regexp_fixed_ascii8bit(/#{}\xc2\xa1/n)
+ assert_regexp_fixed_ascii8bit(/\xc2\xa1#{}/n)
+ assert_nothing_raised { s1, s2 = a('\xc2'), a('\xa1'); /#{s1}#{s2}/ }
+ end
+
+ def test_dynamic_eucjp_regexp
+ assert_regexp_fixed_eucjp(/#{}/e)
+ assert_regexp_fixed_eucjp(/#{}\xc2\xa1/e)
+ assert_regexp_fixed_eucjp(/\xc2\xa1#{}/e)
+ assert_raise(SyntaxError) { eval('/\xc2#{}/e') }
+ assert_raise(SyntaxError) { eval('/#{}\xc2/e') }
+ assert_raise(SyntaxError) { eval('/\xc2#{}\xa1/e') }
+ assert_raise(ArgumentError) { s1, s2 = e('\xc2'), e('\xa1'); /#{s1}#{s2}/ }
+ end
+
+ def test_dynamic_sjis_regexp
+ assert_regexp_fixed_sjis(/#{}/s)
+ assert_regexp_fixed_sjis(/#{}\xc2\xa1/s)
+ assert_regexp_fixed_sjis(/\xc2\xa1#{}/s)
+ assert_raise(SyntaxError) { eval('/\x81#{}/s') }
+ assert_raise(SyntaxError) { eval('/#{}\x81/s') }
+ assert_raise(SyntaxError) { eval('/\x81#{}\xa1/s') }
+ assert_raise(ArgumentError) { s1, s2 = s('\x81'), s('\xa1'); /#{s1}#{s2}/ }
+ end
+
+ def test_dynamic_utf8_regexp
+ assert_regexp_fixed_utf8(/#{}/u)
+ assert_regexp_fixed_utf8(/#{}\xc2\xa1/u)
+ assert_regexp_fixed_utf8(/\xc2\xa1#{}/u)
+ assert_raise(SyntaxError) { eval('/\xc2#{}/u') }
+ assert_raise(SyntaxError) { eval('/#{}\xc2/u') }
+ assert_raise(SyntaxError) { eval('/\xc2#{}\xa1/u') }
+ assert_raise(ArgumentError) { s1, s2 = u('\xc2'), u('\xa1'); /#{s1}#{s2}/ }
+ end
+
+ def test_regexp_unicode
+ assert_nothing_raised { eval '/\u{0}/u' }
+ assert_nothing_raised { eval '/\u{D7FF}/u' }
+ assert_raise(SyntaxError) { eval '/\u{D800}/u' }
+ assert_raise(SyntaxError) { eval '/\u{DFFF}/u' }
+ assert_nothing_raised { eval '/\u{E000}/u' }
+ assert_nothing_raised { eval '/\u{10FFFF}/u' }
+ assert_raise(SyntaxError) { eval '/\u{110000}/u' }
+ end
+
+ def test_regexp_mixed_unicode
+ assert_raise(SyntaxError) { eval(a(%{/\xc2\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\xc2\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\xc2\xa1\\u{6666}/})) }
+ assert_nothing_raised { eval(u(%{/\xc2\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(a(%{/\\u{6666}\xc2\xa1/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\u{6666}\xc2\xa1/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\u{6666}\xc2\xa1/})) }
+ assert_nothing_raised { eval(u(%{/\\u{6666}\xc2\xa1/})) }
+
+ assert_raise(SyntaxError) { eval(a(%{/\\xc2\\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\xc2\\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\xc2\\xa1\\u{6666}/})) }
+ assert_nothing_raised { eval(u(%{/\\xc2\\xa1\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(a(%{/\\u{6666}\\xc2\\xa1/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\u{6666}\\xc2\\xa1/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\u{6666}\\xc2\\xa1/})) }
+ assert_nothing_raised { eval(u(%{/\\u{6666}\\xc2\\xa1/})) }
+
+ assert_raise(SyntaxError) { eval(a(%{/\xc2\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\xc2\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\xc2\xa1#{}\\u{6666}/})) }
+ assert_nothing_raised { eval(u(%{/\xc2\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(a(%{/\\u{6666}#{}\xc2\xa1/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\u{6666}#{}\xc2\xa1/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\u{6666}#{}\xc2\xa1/})) }
+ assert_nothing_raised { eval(u(%{/\\u{6666}#{}\xc2\xa1/})) }
+
+ assert_raise(SyntaxError) { eval(a(%{/\\xc2\\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\xc2\\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\xc2\\xa1#{}\\u{6666}/})) }
+ assert_nothing_raised { eval(u(%{/\\xc2\\xa1#{}\\u{6666}/})) }
+ assert_raise(SyntaxError) { eval(a(%{/\\u{6666}#{}\\xc2\\xa1/})) }
+ assert_raise(SyntaxError) { eval(e(%{/\\u{6666}#{}\\xc2\\xa1/})) }
+ assert_raise(SyntaxError) { eval(s(%{/\\u{6666}#{}\\xc2\\xa1/})) }
+ assert_nothing_raised { eval(u(%{/\\u{6666}#{}\\xc2\\xa1/})) }
+ end
+
+ def test_str_allocate
+ s = String.allocate
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ end
+
+ def test_str_String
+ s = String(10)
+ assert_equal(Encoding::US_ASCII, s.encoding)
+ end
+
+ def test_sprintf_c
+ assert_strenc("\x80", 'ASCII-8BIT', a("%c") % 128)
+ #assert_raise(ArgumentError) { a("%c") % 0xc2a1 }
+ assert_strenc("\xc2\xa1", 'EUC-JP', e("%c") % 0xc2a1)
+ assert_raise(ArgumentError) { e("%c") % 0xc2 }
+ assert_strenc("\xc2", 'Windows-31J', s("%c") % 0xc2)
+ #assert_raise(ArgumentError) { s("%c") % 0xc2a1 }
+ assert_strenc("\u{c2a1}", 'UTF-8', u("%c") % 0xc2a1)
+ assert_strenc("\u{c2}", 'UTF-8', u("%c") % 0xc2)
+ assert_raise(EncodingCompatibilityError) {
+ "%s%s" % [s("\xc2\xa1"), e("\xc2\xa1")]
+ }
+ end
+
+ def test_sprintf_p
+ assert_strenc('""', 'ASCII-8BIT', a("%p") % a(""))
+ assert_strenc('""', 'EUC-JP', e("%p") % e(""))
+ assert_strenc('""', 'Windows-31J', s("%p") % s(""))
+ assert_strenc('""', 'UTF-8', u("%p") % u(""))
+
+ assert_strenc('"a"', 'ASCII-8BIT', a("%p") % a("a"))
+ assert_strenc('"a"', 'EUC-JP', e("%p") % e("a"))
+ assert_strenc('"a"', 'Windows-31J', s("%p") % s("a"))
+ assert_strenc('"a"', 'UTF-8', u("%p") % u("a"))
+
+ assert_strenc('"\xC2\xA1"', 'ASCII-8BIT', a("%p") % a("\xc2\xa1"))
+ assert_strenc("\"\xC2\xA1\"", 'EUC-JP', e("%p") % e("\xc2\xa1"))
+ #assert_strenc("\"\xC2\xA1\"", 'Windows-31J', s("%p") % s("\xc2\xa1"))
+ assert_strenc("\"\xC2\xA1\"", 'UTF-8', u("%p") % u("\xc2\xa1"))
+
+ assert_strenc('"\xC2\xA1"', 'US-ASCII', "%10p" % a("\xc2\xa1"))
+ assert_strenc(" \"\xC2\xA1\"", 'EUC-JP', "%10p" % e("\xc2\xa1"))
+ #assert_strenc(" \"\xC2\xA1\"", 'Windows-31J', "%10p" % s("\xc2\xa1"))
+ assert_strenc(" \"\xC2\xA1\"", 'UTF-8', "%10p" % u("\xc2\xa1"))
+
+ assert_strenc('"\x00"', 'ASCII-8BIT', a("%p") % a("\x00"))
+ assert_strenc('"\x00"', 'EUC-JP', e("%p") % e("\x00"))
+ assert_strenc('"\x00"', 'Windows-31J', s("%p") % s("\x00"))
+ assert_strenc('"\x00"', 'UTF-8', u("%p") % u("\x00"))
+ end
+
+ def test_sprintf_s
+ assert_strenc('', 'ASCII-8BIT', a("%s") % a(""))
+ assert_strenc('', 'EUC-JP', e("%s") % e(""))
+ assert_strenc('', 'Windows-31J', s("%s") % s(""))
+ assert_strenc('', 'UTF-8', u("%s") % u(""))
+
+ assert_strenc('a', 'ASCII-8BIT', a("%s") % a("a"))
+ assert_strenc('a', 'EUC-JP', e("%s") % e("a"))
+ assert_strenc('a', 'Windows-31J', s("%s") % s("a"))
+ assert_strenc('a', 'UTF-8', u("%s") % u("a"))
+
+ assert_strenc("\xC2\xA1", 'ASCII-8BIT', a("%s") % a("\xc2\xa1"))
+ assert_strenc("\xC2\xA1", 'EUC-JP', e("%s") % e("\xc2\xa1"))
+ #assert_strenc("\xC2\xA1", 'Windows-31J', s("%s") % s("\xc2\xa1"))
+ assert_strenc("\xC2\xA1", 'UTF-8', u("%s") % u("\xc2\xa1"))
+
+ assert_strenc(" \xC2\xA1", 'ASCII-8BIT', "%10s" % a("\xc2\xa1"))
+ assert_strenc(" \xA1\xA1", 'EUC-JP', "%10s" % e("\xa1\xa1"))
+ #assert_strenc(" \xC2\xA1", 'Windows-31J', "%10s" % s("\xc2\xa1"))
+ assert_strenc(" \xC2\xA1", 'UTF-8', "%10s" % u("\xc2\xa1"))
+
+ assert_strenc("\x00", 'ASCII-8BIT', a("%s") % a("\x00"))
+ assert_strenc("\x00", 'EUC-JP', e("%s") % e("\x00"))
+ assert_strenc("\x00", 'Windows-31J', s("%s") % s("\x00"))
+ assert_strenc("\x00", 'UTF-8', u("%s") % u("\x00"))
+ assert_equal("EUC-JP", (e("\xc2\xa1 %s") % "foo").encoding.name)
+ end
+
+ def test_str_lt
+ assert(a("a") < a("\xa1"))
+ assert(a("a") < s("\xa1"))
+ assert(s("a") < a("\xa1"))
+ end
+
+ def test_str_multiply
+ str = "\u3042"
+ assert_equal(true, (str * 0).ascii_only?, "[ruby-dev:33895]")
+ assert_equal(false, (str * 1).ascii_only?)
+ assert_equal(false, (str * 2).ascii_only?)
+ end
+
+ def test_str_aref
+ assert_equal(a("\xc2"), a("\xc2\xa1")[0])
+ assert_equal(a("\xa1"), a("\xc2\xa1")[1])
+ assert_equal(nil, a("\xc2\xa1")[2])
+ assert_equal(e("\xc2\xa1"), e("\xc2\xa1")[0])
+ assert_equal(nil, e("\xc2\xa1")[1])
+ assert_equal(s("\xc2"), s("\xc2\xa1")[0])
+ assert_equal(s("\xa1"), s("\xc2\xa1")[1])
+ assert_equal(nil, s("\xc2\xa1")[2])
+ assert_equal(u("\xc2\xa1"), u("\xc2\xa1")[0])
+ assert_equal(nil, u("\xc2\xa1")[1])
+
+ str = "\u3042"
+ assert_equal(true, str[0, 0].ascii_only?, "[ruby-dev:33895]")
+ assert_equal(false, str[0, 1].ascii_only?)
+ assert_equal(false, str[0..-1].ascii_only?)
+ end
+
+ def test_utf8str_aref
+ s = "abcdefghijklmnopqrstuvwxyz\u{3042 3044 3046 3048 304A}"
+ assert_equal("a", s[0])
+ assert_equal("h", s[7])
+ assert_equal("i", s[8])
+ assert_equal("j", s[9])
+ assert_equal("\u{3044}", s[27])
+ assert_equal("\u{3046}", s[28])
+ assert_equal("\u{3048}", s[29])
+ s = "abcdefghijklmnopqrstuvw\u{3042 3044 3046 3048 304A}"
+ assert_equal("\u{3044}", s[24])
+ end
+
+ def test_str_aref_len
+ assert_equal(a("\xa1"), a("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 1])
+ assert_equal(a("\xa1\xc2"), a("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 2])
+
+ assert_equal(e("\xc2\xa2"), e("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 1])
+ assert_equal(e("\xc2\xa2\xc2\xa3"), e("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 2])
+
+ assert_equal(s("\xa1"), s("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 1])
+ assert_equal(s("\xa1\xc2"), s("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 2])
+
+ assert_equal(u("\xc2\xa2"), u("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 1])
+ assert_equal(u("\xc2\xa2\xc2\xa3"), u("\xc2\xa1\xc2\xa2\xc2\xa3")[1, 2])
+ end
+
+ def test_str_aref_substr
+ assert_equal(a("\xa1\xc2"), a("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")])
+ assert_raise(EncodingCompatibilityError) { a("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")] }
+
+ assert_equal(nil, e("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")])
+ assert_raise(EncodingCompatibilityError) { e("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")] }
+
+ assert_equal(s("\xa1\xc2"), s("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")])
+ assert_raise(EncodingCompatibilityError) { s("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")] }
+
+ assert_equal(nil, u("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")])
+ assert_raise(EncodingCompatibilityError) { u("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")] }
+ assert_nil(e("\xa1\xa2\xa3\xa4")[e("\xa2\xa3")])
+ end
+
+ def test_aset
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s["\xb0\xa3"] = "foo"}
+ end
+
+ def test_str_center
+ assert_encoding("EUC-JP", "a".center(5, e("\xa1\xa2")).encoding)
+ assert_encoding("EUC-JP", e("\xa3\xb0").center(10).encoding)
+ end
+
+ def test_squeeze
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb1\xa3\xb3\xa3\xb4")
+ assert_equal(e("\xa3\xb0\xa3\xb1\xa3\xb3\xa3\xb4"), s.squeeze)
+ end
+
+ def test_tr
+ s = s("\x81\x41")
+ assert_equal(s.tr("A", "B"), s)
+ assert_equal(s.tr_s("A", "B"), s)
+
+ assert_nothing_raised {
+ "a".force_encoding("ASCII-8BIT").tr(a("a"), a("a"))
+ }
+
+ assert_equal(e("\xA1\xA1"), a("a").tr(a("a"), e("\xA1\xA1")))
+
+ assert_equal("X\u3042\u3044X", "A\u3042\u3044\u3046".tr("^\u3042\u3044", "X"))
+ assert_equal("\u3042\u3046" * 100, ("\u3042\u3044" * 100).tr("\u3044", "\u3046"))
+ end
+
+ def test_tr_s
+ assert_equal("\xA1\xA1".force_encoding("EUC-JP"),
+ "a".force_encoding("ASCII-8BIT").tr("a".force_encoding("ASCII-8BIT"), "\xA1\xA1".force_encoding("EUC-JP")))
+ end
+
+ def test_count
+ assert_equal(0, e("\xa1\xa2").count("z"))
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s.count(a("\xa3\xb0"))}
+ end
+
+ def test_delete
+ assert_equal(1, e("\xa1\xa2").delete("z").length)
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s.delete(a("\xa3\xb2"))}
+
+ a = "\u3042\u3044\u3046\u3042\u3044\u3046"
+ a.delete!("\u3042\u3044", "^\u3044")
+ assert_equal("\u3044\u3046\u3044\u3046", a)
+ end
+
+ def test_include?
+ assert_equal(false, e("\xa1\xa2\xa3\xa4").include?(e("\xa3")))
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_equal(false, s.include?(e("\xb0\xa3")))
+ end
+
+ def test_index
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_nil(s.index(e("\xb3\xa3")))
+ assert_nil(e("\xa1\xa2\xa3\xa4").index(e("\xa3")))
+ assert_nil(e("\xa1\xa2\xa3\xa4").rindex(e("\xa3")))
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s.rindex(a("\xb1\xa3"))}
+ end
+
+ def test_next
+ s1 = e("\xa1\xa1")
+ s2 = s1.dup
+ (94*94+94).times { s2.next! }
+ assert_not_equal(s1, s2)
+ end
+
+ def test_sub
+ s = "abc".sub(/b/, "\xa1\xa1".force_encoding("euc-jp"))
+ assert_encoding("EUC-JP", s.encoding)
+ assert_equal(Encoding::EUC_JP, "\xa4\xa2".force_encoding("euc-jp").sub(/./, '\&').encoding)
+ assert_equal(Encoding::EUC_JP, "\xa4\xa2".force_encoding("euc-jp").gsub(/./, '\&').encoding)
+ end
+
+ def test_insert
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_equal(e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4a"), s.insert(-1, "a"))
+ end
+
+ def test_scan
+ assert_equal(["a"], e("\xa1\xa2a\xa3\xa4").scan(/a/))
+ end
+
+ def test_dup_scan
+ s1 = e("\xa4\xa2")*100
+ s2 = s1.dup.force_encoding("ascii-8bit")
+ s2.scan(/\A./n) {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.encoding)
+ }
+ end
+
+ def test_dup_aref
+ s1 = e("\xa4\xa2")*100
+ s2 = s1.dup.force_encoding("ascii-8bit")
+ assert_equal(Encoding::ASCII_8BIT, s2[10..-1].encoding)
+ end
+
+ def test_upto
+ s1 = e("\xa1\xa2")
+ s2 = s("\xa1\xa2")
+ assert_raise(EncodingCompatibilityError){s1.upto(s2) {|x| break }}
+ end
+
+ def test_casecmp
+ s1 = s("\x81\x41")
+ s2 = s("\x81\x61")
+ assert_not_equal(0, s1.casecmp(s2))
+ end
+
+ def test_reverse
+ assert_equal(u("\xf0jihgfedcba"), u("abcdefghij\xf0").reverse)
+ end
+
+ def test_reverse_bang
+ s = u("abcdefghij\xf0")
+ s.reverse!
+ assert_equal(u("\xf0jihgfedcba"), s)
+ end
+
+ def test_plus
+ assert_raise(EncodingCompatibilityError){u("\xe3\x81\x82") + a("\xa1")}
+ end
+
+ def test_chomp
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s.chomp(s("\xa3\xb4"))}
+ end
+
+ def test_gsub
+ s = 'abc'
+ s.ascii_only?
+ s.gsub!(/b/, "\x80")
+ assert_equal(false, s.ascii_only?, "[ruby-core:14566] reported by Sam Ruby")
+
+ s = "abc".force_encoding(Encoding::ASCII_8BIT)
+ t = s.gsub(/b/, "\xa1\xa1".force_encoding("euc-jp"))
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+
+ assert_raise(EncodingCompatibilityError) {
+ "abc".gsub(/[ac]/) {
+ $& == "a" ? "\xc2\xa1".force_encoding("euc-jp") :
+ "\xc2\xa1".force_encoding("utf-8")
+ }
+ }
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_equal(e("\xa3\xb0z\xa3\xb2\xa3\xb3\xa3\xb4"), s.gsub(/\xa3\xb1/e, "z"))
+
+ assert_equal(Encoding::EUC_JP, (a("").gsub(//) { e("") }.encoding))
+ assert_equal(Encoding::EUC_JP, (a("a").gsub(/a/) { e("") }.encoding))
+ end
+
+ def test_end_with
+ s1 = s("\x81\x40")
+ s2 = "@"
+ assert_equal(false, s1.end_with?(s2), "#{encdump s1}.end_with?(#{encdump s2})")
+ end
+
+ def test_each_line
+ s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
+ assert_raise(EncodingCompatibilityError){s.each_line(a("\xa3\xb1")) {|l| }}
+ s = e("\xa4\xa2\nfoo")
+
+ actual = []
+ s.each_line {|line| actual << line }
+ expected = [e("\xa4\xa2\n"), e("foo")]
+ assert_equal(expected, actual)
+ end
+
+ def test_each_char
+ a = [e("\xa4\xa2"), "b", e("\xa4\xa4"), "c"]
+ s = "\xa4\xa2b\xa4\xa4c".force_encoding("euc-jp")
+ assert_equal(a, s.each_char.to_a, "[ruby-dev:33211] #{encdump s}.each_char.to_a")
+ end
+
+ def test_regexp_match
+ assert_equal([0,0], //.match("\xa1\xa1".force_encoding("euc-jp"),-1).offset(0))
+ assert_equal(0, // =~ :a)
+ end
+
+ def test_split
+ assert_equal(e("\xa1\xa2\xa1\xa3").split(//),
+ [e("\xa1\xa2"), e("\xa1\xa3")],
+ '[ruby-dev:32452]')
+ end
+
+ def test_nonascii_method_name
+ eval(e("def \xc2\xa1() @nonascii_method_name = :e end"))
+ eval(u("def \xc2\xa1() @nonascii_method_name = :u end"))
+ eval(e("\xc2\xa1()"))
+ assert_equal(:e, @nonascii_method_name)
+ eval(u("\xc2\xa1()"))
+ assert_equal(:u, @nonascii_method_name)
+ me = method(e("\xc2\xa1"))
+ mu = method(u("\xc2\xa1"))
+ assert_not_equal(me.name, mu.name)
+ assert_not_equal(me.inspect, mu.inspect)
+ assert_equal(e("\xc2\xa1"), me.name.to_s)
+ assert_equal(u("\xc2\xa1"), mu.name.to_s)
+ end
+
+ def test_symbol
+ s1 = "\xc2\xa1".force_encoding("euc-jp").intern
+ s2 = "\xc2\xa1".force_encoding("utf-8").intern
+ assert_not_equal(s1, s2)
+ end
+
+ def test_symbol_op
+ ops = %w[
+ .. ... + - +(binary) -(binary) * / % ** +@ -@ | ^ & ! <=> > >= < <= ==
+ === != =~ !~ ~ ! [] []= << >> :: `
+ ] #`
+ ops.each do |op|
+ assert_equal(Encoding::US_ASCII, op.intern.encoding, "[ruby-dev:33449]")
+ end
+ end
+
+ def test_chr
+ 0.upto(255) {|b|
+ assert_equal([b].pack("C"), b.chr)
+ }
+ end
+
+ def test_marshal
+ s1 = "\xa1\xa1".force_encoding("euc-jp")
+ s2 = Marshal.load(Marshal.dump(s1))
+ assert_equal(s1, s2)
+ end
+
+ def test_env
+ ENV.each {|k, v|
+ assert_equal(Encoding::ASCII_8BIT, k.encoding)
+ assert_equal(Encoding::ASCII_8BIT, v.encoding)
+ }
+ end
+
+ def test_empty_string
+ assert_equal(Encoding::US_ASCII, "".encoding)
+ end
+
+ def test_nil_to_s
+ assert_equal(Encoding::US_ASCII, nil.to_s.encoding)
+ end
+
+ def test_nil_inspect
+ assert_equal(Encoding::US_ASCII, nil.inspect.encoding)
+ end
+
+ def test_true_to_s
+ assert_equal(Encoding::US_ASCII, true.to_s.encoding)
+ end
+
+ def test_false_to_s
+ assert_equal(Encoding::US_ASCII, false.to_s.encoding)
+ end
+
+ def test_fixnum_to_s
+ assert_equal(Encoding::US_ASCII, 1.to_s.encoding)
+ end
+
+ def test_float_to_s
+ assert_equal(Encoding::US_ASCII, 1.0.to_s.encoding)
+ end
+
+ def test_bignum_to_s
+ assert_equal(Encoding::US_ASCII, (1<<129).to_s.encoding)
+ end
+
+ def test_array_to_s
+ assert_equal(Encoding::US_ASCII, [].to_s.encoding)
+ assert_equal(Encoding::US_ASCII, [nil].to_s.encoding)
+ assert_equal(Encoding::US_ASCII, [1].to_s.encoding)
+ assert_equal(Encoding::US_ASCII, [""].to_s.encoding)
+ assert_equal(Encoding::US_ASCII, ["a"].to_s.encoding)
+ assert_equal(Encoding::US_ASCII, [nil,1,"","a","\x20",[]].to_s.encoding)
+ end
+
+ def test_hash_to_s
+ assert_equal(Encoding::US_ASCII, {}.to_s.encoding)
+ assert_equal(Encoding::US_ASCII, {1=>nil,"foo"=>""}.to_s.encoding)
+ end
+
+ def test_encoding_find
+ assert_raise(TypeError) {Encoding.find(nil)}
+ assert_raise(TypeError) {Encoding.find(0)}
+ assert_raise(TypeError) {Encoding.find([])}
+ assert_raise(TypeError) {Encoding.find({})}
+ end
+
+ def test_encoding_to_s
+ assert_equal(Encoding::US_ASCII, Encoding::US_ASCII.to_s.encoding)
+ assert_equal(Encoding::US_ASCII, Encoding::US_ASCII.inspect.encoding)
+ end
+
+ def test_regexp_source
+ s = "\xa4\xa2".force_encoding("euc-jp")
+ r = Regexp.new(s)
+ t = r.source
+ assert_equal(s, t, "[ruby-dev:33377] Regexp.new(#{encdump s}).source")
+ end
+
+ def test_magic_comment
+ assert_equal(Encoding::US_ASCII, eval("__ENCODING__".force_encoding("US-ASCII")))
+ assert_equal(Encoding::ASCII_8BIT, eval("__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::US_ASCII, eval("# -*- encoding: US-ASCII -*-\n__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::ASCII_8BIT, eval("# -*- encoding: ASCII-8BIT -*-\n__ENCODING__".force_encoding("US-ASCII")))
+ end
+
+ def test_magic_comment_vim
+ assert_equal(Encoding::US_ASCII, eval("# vim: filetype=ruby, fileencoding: US-ASCII, ts=3, sw=3\n__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::ASCII_8BIT, eval("# vim: filetype=ruby, fileencoding: ASCII-8BIT, ts=3, sw=3\n__ENCODING__".force_encoding("US-ASCII")))
+ end
+
+ def test_magic_comment_at_various_positions
+ # after shebang
+ assert_equal(Encoding::US_ASCII, eval("#!/usr/bin/ruby\n# -*- encoding: US-ASCII -*-\n__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::ASCII_8BIT, eval("#!/usr/bin/ruby\n# -*- encoding: ASCII-8BIT -*-\n__ENCODING__".force_encoding("US-ASCII")))
+ # wrong position
+ assert_equal(Encoding::ASCII_8BIT, eval("\n# -*- encoding: US-ASCII -*-\n__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::US_ASCII, eval("\n# -*- encoding: ASCII-8BIT -*-\n__ENCODING__".force_encoding("US-ASCII")))
+
+ # leading expressions
+ assert_equal(Encoding::ASCII_8BIT, eval("1+1 # -*- encoding: US-ASCII -*-\n__ENCODING__".force_encoding("ASCII-8BIT")))
+ assert_equal(Encoding::US_ASCII, eval("1+1 # -*- encoding: ASCII-8BIT -*-\n__ENCODING__".force_encoding("US-ASCII")))
+ end
+
+ def test_regexp_usascii
+ assert_regexp_usascii_literal('//', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/#{}/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/#{"a"}/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/#{%q"\x80"}/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/#{"\x80"}/', nil, SyntaxError)
+
+ assert_regexp_usascii_literal('/a/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/a#{}/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/a#{"a"}/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/a#{%q"\x80"}/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/a#{"\x80"}/', nil, SyntaxError)
+
+ assert_regexp_usascii_literal('/\x80/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/\x80#{}/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/\x80#{"a"}/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/\x80#{%q"\x80"}/', Encoding::ASCII_8BIT)
+ assert_regexp_usascii_literal('/\x80#{"\x80"}/', nil, SyntaxError)
+
+ assert_regexp_usascii_literal('/\u1234/', Encoding::UTF_8)
+ assert_regexp_usascii_literal('/\u1234#{}/', Encoding::UTF_8)
+ assert_regexp_usascii_literal('/\u1234#{"a"}/', Encoding::UTF_8)
+ assert_regexp_usascii_literal('/\u1234#{%q"\x80"}/', nil, SyntaxError)
+ assert_regexp_usascii_literal('/\u1234#{"\x80"}/', nil, SyntaxError)
+ assert_regexp_usascii_literal('/\u1234\x80/', nil, SyntaxError)
+ assert_regexp_usascii_literal('/\u1234#{}\x80/', nil, ArgumentError)
+ end
+
+ def test_gbk
+ assert_equal("", "\x81\x40".force_encoding("GBK").chop)
+ end
+
+ def test_euc_tw
+ assert_equal("a", "a\x8e\xa2\xa1\xa1".force_encoding("euc-tw").chop)
+ end
+
+ def test_valid_encoding
+ s = "\xa1".force_encoding("euc-jp")
+ assert_equal(false, s.valid_encoding?)
+ assert_equal(true, (s+s).valid_encoding?, "[ruby-dev:33826]")
+ assert_equal(true, (s*2).valid_encoding?, "[ruby-dev:33826]")
+ assert_equal(true, ("%s%s" % [s, s]).valid_encoding?)
+ assert_equal(true, (s.dup << s).valid_encoding?)
+ assert_equal(true, "".center(2, s).valid_encoding?)
+
+ s = "\xa1\xa1\x8f".force_encoding("euc-jp")
+ assert_equal(false, s.valid_encoding?)
+ assert_equal(true, s.reverse.valid_encoding?)
+ end
+
+ def test_getbyte
+ assert_equal(0x82, u("\xE3\x81\x82\xE3\x81\x84").getbyte(2))
+ assert_equal(0x82, u("\xE3\x81\x82\xE3\x81\x84").getbyte(-4))
+ assert_nil(u("\xE3\x81\x82\xE3\x81\x84").getbyte(100))
+ end
+
+ def test_setbyte
+ s = u("\xE3\x81\x82\xE3\x81\x84")
+ s.setbyte(2, 0x84)
+ assert_equal(u("\xE3\x81\x84\xE3\x81\x84"), s)
+
+ s = u("\xE3\x81\x82\xE3\x81\x84")
+ assert_raise(IndexError) { s.setbyte(100, 0) }
+
+ s = u("\xE3\x81\x82\xE3\x81\x84")
+ s.setbyte(-4, 0x84)
+ assert_equal(u("\xE3\x81\x84\xE3\x81\x84"), s)
+ end
+
+ def test_compatible
+ assert_equal(nil, Encoding.compatible?("",0), "moved from btest/knownbug")
+ end
+
+ def test_force_encoding
+ assert(("".center(1, "\x80".force_encoding("utf-8")); true),
+ "moved from btest/knownbug, [ruby-dev:33807]")
+ end
+end
diff --git a/trunk/test/ruby/test_m17n_comb.rb b/trunk/test/ruby/test_m17n_comb.rb
new file mode 100644
index 0000000000..37b1a687a2
--- /dev/null
+++ b/trunk/test/ruby/test_m17n_comb.rb
@@ -0,0 +1,1623 @@
+require 'test/unit'
+require 'stringio'
+require_relative 'allpairs'
+
+class TestM17NComb < Test::Unit::TestCase
+ def assert_encoding(encname, actual, message=nil)
+ assert_equal(Encoding.find(encname), actual, message)
+ end
+
+ module AESU
+ def a(str) str.dup.force_encoding("ASCII-8BIT") end
+ def e(str) str.dup.force_encoding("EUC-JP") end
+ def s(str) str.dup.force_encoding("Shift_JIS") end
+ def u(str) str.dup.force_encoding("UTF-8") end
+ end
+ include AESU
+ extend AESU
+
+ def assert_strenc(bytes, enc, actual, message=nil)
+ assert_instance_of(String, actual, message)
+ enc = Encoding.find(enc) if String === enc
+ assert_equal(enc, actual.encoding, message)
+ assert_equal(a(bytes), a(actual), message)
+ end
+
+ def assert_warning(pat, mesg=nil)
+ begin
+ org_stderr = $stderr
+ $stderr = StringIO.new(warn = '')
+ yield
+ ensure
+ $stderr = org_stderr
+ end
+ assert_match(pat, warn, mesg)
+ end
+
+ def assert_regexp_generic_encoding(r)
+ assert(!r.fixed_encoding?)
+ %w[ASCII-8BIT EUC-JP Shift_JIS UTF-8].each {|ename|
+ # "\xc2\xa1" is a valid sequence for ASCII-8BIT, EUC-JP, Shift_JIS and UTF-8.
+ assert_nothing_raised { r =~ "\xc2\xa1".force_encoding(ename) }
+ }
+ end
+
+ def assert_regexp_fixed_encoding(r)
+ assert(r.fixed_encoding?)
+ %w[ASCII-8BIT EUC-JP Shift_JIS UTF-8].each {|ename|
+ enc = Encoding.find(ename)
+ if enc == r.encoding
+ assert_nothing_raised { r =~ "\xc2\xa1".force_encoding(enc) }
+ else
+ assert_raise(ArgumentError) { r =~ "\xc2\xa1".force_encoding(enc) }
+ end
+ }
+ end
+
+ def assert_regexp_generic_ascii(r)
+ assert_encoding("ASCII-8BIT", r.encoding)
+ assert_regexp_generic_encoding(r)
+ end
+
+ def assert_regexp_fixed_ascii8bit(r)
+ assert_encoding("ASCII-8BIT", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_eucjp(r)
+ assert_encoding("EUC-JP", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_sjis(r)
+ assert_encoding("Shift_JIS", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ def assert_regexp_fixed_utf8(r)
+ assert_encoding("UTF-8", r.encoding)
+ assert_regexp_fixed_encoding(r)
+ end
+
+ STRINGS = [
+ a(""), e(""), s(""), u(""),
+ a("a"), e("a"), s("a"), u("a"),
+ a("."), e("."), s("."), u("."),
+
+ # single character
+ a("\x80"), a("\xff"),
+ e("\xa1\xa1"), e("\xfe\xfe"),
+ e("\x8e\xa1"), e("\x8e\xfe"),
+ e("\x8f\xa1\xa1"), e("\x8f\xfe\xfe"),
+ s("\x81\x40"), s("\xfc\xfc"),
+ s("\xa1"), s("\xdf"),
+ u("\xc2\x80"), u("\xf4\x8f\xbf\xbf"),
+
+ # same byte sequence
+ a("\xc2\xa1"), e("\xc2\xa1"), s("\xc2\xa1"), u("\xc2\xa1"),
+
+ s("\x81A"), # mutibyte character which contains "A"
+ s("\x81a"), # mutibyte character which contains "a"
+
+ # invalid
+ e("\xa1"), e("\x80"),
+ s("\x81"), s("\x80"),
+ u("\xc2"), u("\x80"),
+
+ # for transitivity test
+ u("\xe0\xa0\xa1"),
+ e("\xe0\xa0\xa1"),
+ s("\xe0\xa0\xa1"),
+
+ #"aa".force_encoding("utf-16be"),
+ #"aaaa".force_encoding("utf-32be"),
+ #"aaa".force_encoding("utf-32be"),
+ ]
+
+ def combination(*args, &b)
+ AllPairs.each(*args, &b)
+ end
+
+ def encdump(str)
+ d = str.dump
+ if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
+ d
+ else
+ "#{d}.force_encoding(#{str.encoding.name.dump})"
+ end
+ end
+
+ def encdumpargs(args)
+ r = '('
+ args.each_with_index {|a, i|
+ r << ',' if 0 < i
+ if String === a
+ r << encdump(a)
+ else
+ r << a.inspect
+ end
+ }
+ r << ')'
+ r
+ end
+
+ def enccall(recv, meth, *args, &block)
+ desc = ''
+ if String === recv
+ desc << encdump(recv)
+ else
+ desc << recv.inspect
+ end
+ desc << '.' << meth.to_s
+ if !args.empty?
+ desc << '('
+ args.each_with_index {|a, i|
+ desc << ',' if 0 < i
+ if String === a
+ desc << encdump(a)
+ else
+ desc << a.inspect
+ end
+ }
+ desc << ')'
+ end
+ if block
+ desc << ' {}'
+ end
+ result = nil
+ assert_nothing_raised(desc) {
+ result = recv.send(meth, *args, &block)
+ }
+ result
+ end
+
+ def assert_str_enc_propagation(t, s1, s2)
+ if !s1.ascii_only?
+ assert_equal(s1.encoding, t.encoding)
+ elsif !s2.ascii_only?
+ assert_equal(s2.encoding, t.encoding)
+ else
+ assert([s1.encoding, s2.encoding].include?(t.encoding))
+ end
+ end
+
+ def assert_same_result(expected_proc, actual_proc)
+ e = nil
+ begin
+ t = expected_proc.call
+ rescue
+ e = $!
+ end
+ if e
+ assert_raise(e.class) { actual_proc.call }
+ else
+ assert_equal(t, actual_proc.call)
+ end
+ end
+
+ def each_slice_call
+ combination(STRINGS, -2..2) {|s, nth|
+ yield s, nth
+ }
+ combination(STRINGS, -2..2, 0..2) {|s, nth, len|
+ yield s, nth, len
+ }
+ combination(STRINGS, STRINGS) {|s, substr|
+ yield s, substr
+ }
+ combination(STRINGS, -2..2, 0..2) {|s, first, last|
+ yield s, first..last
+ yield s, first...last
+ }
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s2.valid_encoding?
+ next
+ end
+ yield s1, Regexp.new(Regexp.escape(s2))
+ }
+ combination(STRINGS, STRINGS, 0..2) {|s1, s2, nth|
+ if !s2.valid_encoding?
+ next
+ end
+ yield s1, Regexp.new(Regexp.escape(s2)), nth
+ }
+ end
+
+ ASCII_INCOMPATIBLE_ENCODINGS = %w[
+ UTF-16BE
+ UTF-16LE
+ UTF-32BE
+ UTF-32LE
+ ]
+ def str_enc_compatible?(*strs)
+ encs = []
+ ascii_incompatible_encodings = {}
+ has_ascii_compatible = false
+ strs.each {|s|
+ encs << s.encoding if !s.ascii_only?
+ if /\A#{Regexp.union ASCII_INCOMPATIBLE_ENCODINGS}\z/o =~ s.encoding.name
+ ascii_incompatible_encodings[s.encoding] = true
+ else
+ has_ascii_compatible = true
+ end
+ }
+ if ascii_incompatible_encodings.empty?
+ encs.uniq!
+ encs.length <= 1
+ else
+ !has_ascii_compatible && ascii_incompatible_encodings.size == 1
+ end
+ end
+
+ # tests start
+
+ def test_str_new
+ STRINGS.each {|s|
+ t = String.new(s)
+ assert_strenc(a(s), s.encoding, t)
+ }
+ end
+
+ def test_str_plus
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if s1.encoding != s2.encoding && !s1.ascii_only? && !s2.ascii_only?
+ assert_raise(EncodingCompatibilityError) { s1 + s2 }
+ else
+ t = enccall(s1, :+, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert_equal(a(s1) + a(s2), a(t))
+ assert_str_enc_propagation(t, s1, s2)
+ end
+ }
+ end
+
+ def test_str_times
+ STRINGS.each {|s|
+ [0,1,2].each {|n|
+ t = s * n
+ assert(t.valid_encoding?) if s.valid_encoding?
+ assert_strenc(a(s) * n, s.encoding, t)
+ }
+ }
+ end
+
+ def test_sprintf_s
+ STRINGS.each {|s|
+ assert_strenc(a(s), s.encoding, "%s".force_encoding(s.encoding) % s)
+ if !s.empty? # xxx
+ t = enccall(a("%s"), :%, s)
+ assert_strenc(a(s), s.encoding, t)
+ end
+ }
+ end
+
+ def test_str_eq_reflexive
+ STRINGS.each {|s|
+ assert(s == s, "#{encdump s} == #{encdump s}")
+ }
+ end
+
+ def test_str_eq_symmetric
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if s1 == s2
+ assert(s2 == s1, "#{encdump s2} == #{encdump s1}")
+ else
+ assert(!(s2 == s1), "!(#{encdump s2} == #{encdump s1})")
+ end
+ }
+ end
+
+ def test_str_eq_transitive
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ if s1 == s2 && s2 == s3
+ assert(s1 == s3, "transitive: #{encdump s1} == #{encdump s2} == #{encdump s3}")
+ end
+ }
+ end
+
+ def test_str_eq
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc_eq = "#{encdump s1} == #{encdump s2}"
+ if s1.ascii_only? && s2.ascii_only? && a(s1) == a(s2)
+ assert(s1 == s2, desc_eq)
+ assert(s1.eql?(s2), desc_eq)
+ elsif s1.encoding == s2.encoding && a(s1) == a(s2)
+ assert(s1 == s2, desc_eq)
+ assert(!(s1 != s2))
+ assert_equal(0, s1 <=> s2)
+ assert(s1.eql?(s2), desc_eq)
+ else
+ assert(!(s1 == s2), "!(#{desc_eq})")
+ assert(s1 != s2)
+ assert_not_equal(0, s1 <=> s2)
+ assert(!s1.eql?(s2))
+ end
+ }
+ end
+
+ def test_str_concat
+ combination(STRINGS, STRINGS) {|s1, s2|
+ s = s1.dup
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ s << s2
+ assert(s.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert_equal(a(s), a(s1) + a(s2))
+ assert_str_enc_propagation(s, s1, s2)
+ else
+ assert_raise(EncodingCompatibilityError) { s << s2 }
+ end
+ }
+ end
+
+ def test_str_aref
+ STRINGS.each {|s|
+ t = ''.force_encoding(s.encoding)
+ 0.upto(s.length-1) {|i|
+ u = s[i]
+ assert(u.valid_encoding?) if s.valid_encoding?
+ t << u
+ }
+ assert_equal(t, s)
+ }
+ end
+
+ def test_str_aref_len
+ STRINGS.each {|s|
+ t = ''.force_encoding(s.encoding)
+ 0.upto(s.length-1) {|i|
+ u = s[i,1]
+ assert(u.valid_encoding?) if s.valid_encoding?
+ t << u
+ }
+ assert_equal(t, s)
+ }
+
+ STRINGS.each {|s|
+ t = ''.force_encoding(s.encoding)
+ 0.step(s.length-1, 2) {|i|
+ u = s[i,2]
+ assert(u.valid_encoding?) if s.valid_encoding?
+ t << u
+ }
+ assert_equal(t, s)
+ }
+ end
+
+ def test_str_aref_substr
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ t = enccall(s1, :[], s2)
+ if t != nil
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert_equal(s2, t)
+ assert_match(/#{Regexp.escape(a(s2))}/, a(s1))
+ if s1.valid_encoding?
+ assert_match(/#{Regexp.escape(s2)}/, s1)
+ end
+ end
+ else
+ assert_raise(EncodingCompatibilityError) { s1[s2] }
+ end
+ }
+ end
+
+ def test_str_aref_range2
+ combination(STRINGS, -2..2, -2..2) {|s, first, last|
+ desc = "#{encdump s}[#{first}..#{last}]"
+ t = s[first..last]
+ if first < 0
+ first += s.length
+ if first < 0
+ assert_nil(t, desc)
+ next
+ end
+ end
+ if s.length < first
+ assert_nil(t, desc)
+ next
+ end
+ assert(t.valid_encoding?) if s.valid_encoding?
+ if last < 0
+ last += s.length
+ end
+ t2 = ''
+ first.upto(last) {|i|
+ c = s[i]
+ t2 << c if c
+ }
+ assert_equal(t2, t, desc)
+ }
+ end
+
+ def test_str_aref_range3
+ combination(STRINGS, -2..2, -2..2) {|s, first, last|
+ desc = "#{encdump s}[#{first}..#{last}]"
+ t = s[first...last]
+ if first < 0
+ first += s.length
+ if first < 0
+ assert_nil(t, desc)
+ next
+ end
+ end
+ if s.length < first
+ assert_nil(t, desc)
+ next
+ end
+ if last < 0
+ last += s.length
+ end
+ assert(t.valid_encoding?) if s.valid_encoding?
+ t2 = ''
+ first.upto(last-1) {|i|
+ c = s[i]
+ t2 << c if c
+ }
+ assert_equal(t2, t, desc)
+ }
+ end
+
+ def test_str_assign
+ combination(STRINGS, STRINGS) {|s1, s2|
+ (-2).upto(2) {|i|
+ t = s1.dup
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ if i < -s1.length || s1.length < i
+ assert_raise(IndexError) { t[i] = s2 }
+ else
+ t[i] = s2
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s2)))
+ if s1.valid_encoding? && s2.valid_encoding?
+ if i == s1.length && s2.empty?
+ assert_nil(t[i])
+ elsif i < 0
+ assert_equal(s2, t[i-s2.length+1,s2.length],
+ "t = #{encdump(s1)}; t[#{i}] = #{encdump(s2)}; t[#{i-s2.length+1},#{s2.length}]")
+ else
+ assert_equal(s2, t[i,s2.length],
+ "t = #{encdump(s1)}; t[#{i}] = #{encdump(s2)}; t[#{i},#{s2.length}]")
+ end
+ end
+ end
+ else
+ assert_raise(EncodingCompatibilityError) { t[i] = s2 }
+ end
+ }
+ }
+ end
+
+ def test_str_assign_len
+ combination(STRINGS, -2..2, 0..2, STRINGS) {|s1, i, len, s2|
+ t = s1.dup
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ if i < -s1.length || s1.length < i
+ assert_raise(IndexError) { t[i,len] = s2 }
+ else
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ t[i,len] = s2
+ assert(a(t).index(a(s2)))
+ if s1.valid_encoding? && s2.valid_encoding?
+ if i == s1.length && s2.empty?
+ assert_nil(t[i])
+ elsif i < 0
+ if -i < len
+ len = -i
+ end
+ assert_equal(s2, t[i-s2.length+len,s2.length],
+ "t = #{encdump(s1)}; t[#{i},#{len}] = #{encdump(s2)}; t[#{i-s2.length+len},#{s2.length}]")
+ else
+ assert_equal(s2, t[i,s2.length],
+ "t = #{encdump(s1)}; t[#{i},#{len}] = #{encdump(s2)}; t[#{i},#{s2.length}]")
+ end
+ end
+ end
+ else
+ assert_raise(EncodingCompatibilityError) { t[i,len] = s2 }
+ end
+ }
+ end
+
+ def test_str_assign_substr
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ t = s1.dup
+ encs = [
+ !s1.ascii_only? ? s1.encoding : nil,
+ !s2.ascii_only? ? s2.encoding : nil,
+ !s3.ascii_only? ? s3.encoding : nil].uniq.compact
+ if 1 < encs.length
+ assert_raise(EncodingCompatibilityError, IndexError) { t[s2] = s3 }
+ else
+ if encs.empty?
+ encs = [
+ s1.encoding,
+ s2.encoding,
+ s3.encoding].uniq.reject {|e| e == Encoding.find("ASCII-8BIT") }
+ if encs.empty?
+ encs = [Encoding.find("ASCII-8BIT")]
+ end
+ end
+ if !t[s2]
+ else
+ enccall(t, :[]=, s2, s3)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding? && s3.valid_encoding?
+ end
+ end
+ }
+ end
+
+ def test_str_assign_range2
+ combination(STRINGS, -2..2, -2..2, STRINGS) {|s1, first, last, s2|
+ t = s1.dup
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ if first < -s1.length || s1.length < first
+ assert_raise(RangeError) { t[first..last] = s2 }
+ else
+ enccall(t, :[]=, first..last, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s2)))
+ if s1.valid_encoding? && s2.valid_encoding?
+ if first < 0
+ assert_equal(s2, t[s1.length+first, s2.length])
+ else
+ assert_equal(s2, t[first, s2.length])
+ end
+ end
+ end
+ else
+ assert_raise(EncodingCompatibilityError, RangeError,
+ "t=#{encdump(s1)};t[#{first}..#{last}]=#{encdump(s2)}") {
+ t[first..last] = s2
+ }
+ end
+ }
+ end
+
+ def test_str_assign_range3
+ combination(STRINGS, -2..2, -2..2, STRINGS) {|s1, first, last, s2|
+ t = s1.dup
+ if s1.ascii_only? || s2.ascii_only? || s1.encoding == s2.encoding
+ if first < -s1.length || s1.length < first
+ assert_raise(RangeError) { t[first...last] = s2 }
+ else
+ enccall(t, :[]=, first...last, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s2)))
+ if s1.valid_encoding? && s2.valid_encoding?
+ if first < 0
+ assert_equal(s2, t[s1.length+first, s2.length])
+ else
+ assert_equal(s2, t[first, s2.length])
+ end
+ end
+ end
+ else
+ assert_raise(EncodingCompatibilityError, RangeError,
+ "t=#{encdump(s1)};t[#{first}...#{last}]=#{encdump(s2)}") {
+ t[first...last] = s2
+ }
+ end
+ }
+ end
+
+ def test_str_cmp
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc = "#{encdump s1} <=> #{encdump s2}"
+ r = s1 <=> s2
+ if s1 == s2
+ assert_equal(0, r, desc)
+ else
+ assert_not_equal(0, r, desc)
+ end
+ }
+ end
+
+ def test_str_capitalize
+ STRINGS.each {|s|
+ begin
+ t1 = s.capitalize
+ rescue ArgumentError
+ assert(!s.valid_encoding?)
+ next
+ end
+ assert(t1.valid_encoding?) if s.valid_encoding?
+ assert(t1.casecmp(s))
+ t2 = s.dup
+ t2.capitalize!
+ assert_equal(t1, t2)
+ r = s.downcase
+ r = enccall(r, :sub, /\A[a-z]/) {|ch| a(ch).upcase }
+ assert_equal(r, t1)
+ }
+ end
+
+ def test_str_casecmp
+ combination(STRINGS, STRINGS) {|s1, s2|
+ #puts "#{encdump(s1)}.casecmp(#{encdump(s2)})"
+ begin
+ r = s1.casecmp(s2)
+ rescue ArgumentError
+ assert(!s1.valid_encoding? || !s2.valid_encoding?)
+ next
+ end
+ #assert_equal(s1.upcase <=> s2.upcase, r)
+ }
+ end
+
+ def test_str_center
+ combination(STRINGS, [0,1,2,3,10]) {|s1, width|
+ t = s1.center(width)
+ assert(a(t).index(a(s1)))
+ }
+ combination(STRINGS, [0,1,2,3,10], STRINGS) {|s1, width, s2|
+ if s2.empty?
+ assert_raise(ArgumentError) { s1.center(width, s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.center(width, s2) }
+ next
+ end
+ t = enccall(s1, :center, width, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s1)))
+ assert_str_enc_propagation(t, s1, s2) if (t != s1)
+ }
+ end
+
+ def test_str_ljust
+ combination(STRINGS, [0,1,2,3,10]) {|s1, width|
+ t = s1.ljust(width)
+ assert(a(t).index(a(s1)))
+ }
+ combination(STRINGS, [0,1,2,3,10], STRINGS) {|s1, width, s2|
+ if s2.empty?
+ assert_raise(ArgumentError) { s1.ljust(width, s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.ljust(width, s2) }
+ next
+ end
+ t = enccall(s1, :ljust, width, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s1)))
+ assert_str_enc_propagation(t, s1, s2) if (t != s1)
+ }
+ end
+
+ def test_str_rjust
+ combination(STRINGS, [0,1,2,3,10]) {|s1, width|
+ t = s1.rjust(width)
+ assert(a(t).index(a(s1)))
+ }
+ combination(STRINGS, [0,1,2,3,10], STRINGS) {|s1, width, s2|
+ if s2.empty?
+ assert_raise(ArgumentError) { s1.rjust(width, s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.rjust(width, s2) }
+ next
+ end
+ t = enccall(s1, :rjust, width, s2)
+ assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
+ assert(a(t).index(a(s1)))
+ assert_str_enc_propagation(t, s1, s2) if (t != s1)
+ }
+ end
+
+ def test_str_chomp
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s1.ascii_only? && !s2.ascii_only? && !Encoding.compatible?(s1,s2)
+ if s1.bytesize > s2.bytesize
+ assert_raise(EncodingCompatibilityError) { s1.chomp(s2) }
+ end
+ next
+ end
+ t = enccall(s1, :chomp, s2)
+ assert(t.valid_encoding?, "#{encdump(s1)}.chomp(#{encdump(s2)})") if s1.valid_encoding? && s2.valid_encoding?
+ assert_equal(s1.encoding, t.encoding)
+ t2 = s1.dup
+ t2.chomp!(s2)
+ assert_equal(t, t2)
+ }
+ end
+
+ def test_str_chop
+ STRINGS.each {|s|
+ s = s.dup
+ desc = "#{encdump s}.chop"
+ if !s.valid_encoding?
+ #assert_raise(ArgumentError, desc) { s.chop }
+ begin
+ s.chop
+ rescue ArgumentError
+ e = $!
+ end
+ next if e
+ end
+ t = nil
+ assert_nothing_raised(desc) { t = s.chop }
+ assert(t.valid_encoding?) if s.valid_encoding?
+ assert(a(s).index(a(t)))
+ t2 = s.dup
+ t2.chop!
+ assert_equal(t, t2)
+ }
+ end
+
+ def test_str_clear
+ STRINGS.each {|s|
+ t = s.dup
+ t.clear
+ assert(t.valid_encoding?)
+ assert(t.empty?)
+ }
+ end
+
+ def test_str_clone
+ STRINGS.each {|s|
+ t = s.clone
+ assert_equal(s, t)
+ assert_equal(s.encoding, t.encoding)
+ assert_equal(a(s), a(t))
+ }
+ end
+
+ def test_str_dup
+ STRINGS.each {|s|
+ t = s.dup
+ assert_equal(s, t)
+ assert_equal(s.encoding, t.encoding)
+ assert_equal(a(s), a(t))
+ }
+ end
+
+ def test_str_count
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_raise(ArgumentError, EncodingCompatibilityError) { s1.count(s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.count(s2) }
+ next
+ end
+ n = enccall(s1, :count, s2)
+ n0 = a(s1).count(a(s2))
+ assert_operator(n, :<=, n0)
+ }
+ end
+
+ def test_str_crypt
+ combination(STRINGS, STRINGS) {|str, salt|
+ if a(salt).length < 2
+ assert_raise(ArgumentError) { str.crypt(salt) }
+ next
+ end
+ t = str.crypt(salt)
+ assert_equal(a(str).crypt(a(salt)), t, "#{encdump(str)}.crypt(#{encdump(salt)})")
+ assert_encoding('ASCII-8BIT', t.encoding)
+ }
+ end
+
+ def test_str_delete
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if s1.empty?
+ assert_equal(s1, s1.delete(s2))
+ next
+ end
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_raise(ArgumentError, EncodingCompatibilityError) { s1.delete(s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.delete(s2) }
+ next
+ end
+ t = enccall(s1, :delete, s2)
+ assert(t.valid_encoding?)
+ assert_equal(t.encoding, s1.encoding)
+ assert_operator(t.length, :<=, s1.length)
+ t2 = s1.dup
+ t2.delete!(s2)
+ assert_equal(t, t2)
+ }
+ end
+
+ def test_str_downcase
+ STRINGS.each {|s|
+ if !s.valid_encoding?
+ assert_raise(ArgumentError) { s.downcase }
+ next
+ end
+ t = s.downcase
+ assert(t.valid_encoding?)
+ assert_equal(t.encoding, s.encoding)
+ assert(t.casecmp(s))
+ t2 = s.dup
+ t2.downcase!
+ assert_equal(t, t2)
+ }
+ end
+
+ def test_str_dump
+ STRINGS.each {|s|
+ t = s.dump
+ assert(t.valid_encoding?)
+ assert(t.ascii_only?)
+ u = eval(t)
+ assert_equal(a(s), a(u))
+ }
+ end
+
+ def test_str_each_line
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_raise(ArgumentError, EncodingCompatibilityError) { s1.each_line(s2) {} }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.each_line(s2) {} }
+ next
+ end
+ lines = []
+ enccall(s1, :each_line, s2) {|line|
+ assert(line.valid_encoding?)
+ assert_equal(s1.encoding, line.encoding)
+ lines << line
+ }
+ next if lines.size == 0
+ s2 = lines.join('')
+ assert_equal(s1.encoding, s2.encoding)
+ assert_equal(s1, s2)
+ }
+ end
+
+ def test_str_each_byte
+ STRINGS.each {|s|
+ bytes = []
+ s.each_byte {|b|
+ bytes << b
+ }
+ a(s).split(//).each_with_index {|ch, i|
+ assert_equal(ch.ord, bytes[i])
+ }
+ }
+ end
+
+ def test_str_empty?
+ STRINGS.each {|s|
+ if s.length == 0
+ assert(s.empty?)
+ else
+ assert(!s.empty?)
+ end
+ }
+ end
+
+ def test_str_hex
+ STRINGS.each {|s|
+ t = s.hex
+ t2 = a(s)[/\A[0-9a-fA-Fx]*/].hex
+ assert_equal(t2, t)
+ }
+ end
+
+ def test_str_include?
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.include?(s2) }
+ assert_raise(EncodingCompatibilityError) { s1.index(s2) }
+ assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ next
+ end
+ t = enccall(s1, :include?, s2)
+ if t
+ assert(a(s1).include?(a(s2)))
+ assert(s1.index(s2))
+ assert(s1.rindex(s2))
+ else
+ assert(!s1.index(s2))
+ assert(!s1.rindex(s2), "!#{encdump(s1)}.rindex(#{encdump(s2)})")
+ end
+ if s2.empty?
+ assert_equal(true, t)
+ next
+ end
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_equal(false, t, "#{encdump s1}.include?(#{encdump s2})")
+ next
+ end
+ if t && s1.valid_encoding? && s2.valid_encoding?
+ assert_match(/#{Regexp.escape(s2)}/, s1)
+ else
+ assert_no_match(/#{Regexp.escape(s2)}/, s1)
+ end
+ }
+ end
+
+ def test_str_index
+ combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.index(s2) }
+ next
+ end
+ t = enccall(s1, :index, s2, pos)
+ if s2.empty?
+ if pos < 0 && pos+s1.length < 0
+ assert_equal(nil, t, "#{encdump s1}.index(#{encdump s2}, #{pos})");
+ elsif pos < 0
+ assert_equal(s1.length+pos, t, "#{encdump s1}.index(#{encdump s2}, #{pos})");
+ elsif s1.length < pos
+ assert_equal(nil, t, "#{encdump s1}.index(#{encdump s2}, #{pos})");
+ else
+ assert_equal(pos, t, "#{encdump s1}.index(#{encdump s2}, #{pos})");
+ end
+ next
+ end
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_equal(nil, t, "#{encdump s1}.index(#{encdump s2}, #{pos})");
+ next
+ end
+ if t
+ re = /#{Regexp.escape(s2)}/
+ assert(re.match(s1, pos))
+ assert_equal($`.length, t, "#{encdump s1}.index(#{encdump s2}, #{pos})")
+ else
+ assert_no_match(/#{Regexp.escape(s2)}/, s1[pos..-1])
+ end
+ }
+ end
+
+ def test_str_rindex
+ combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ next
+ end
+ t = enccall(s1, :rindex, s2, pos)
+ if s2.empty?
+ if pos < 0 && pos+s1.length < 0
+ assert_equal(nil, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ elsif pos < 0
+ assert_equal(s1.length+pos, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ elsif s1.length < pos
+ assert_equal(s1.length, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ else
+ assert_equal(pos, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ end
+ next
+ end
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_equal(nil, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ next
+ end
+ if t
+ #puts "#{encdump s1}.rindex(#{encdump s2}, #{pos}) => #{t}"
+ assert(a(s1).index(a(s2)))
+ pos2 = pos
+ pos2 += s1.length if pos < 0
+ re = /\A(.{0,#{pos2}})#{Regexp.escape(s2)}/m
+ m = enccall(re, :match, s1)
+ assert(m, "#{re.inspect}.match(#{encdump(s1)})")
+ assert_equal(m[1].length, t, "#{encdump s1}.rindex(#{encdump s2}, #{pos})")
+ else
+ re = /#{Regexp.escape(s2)}/
+ n = re =~ s1
+ if n
+ if pos < 0
+ assert_operator(n, :>, s1.length+pos)
+ else
+ assert_operator(n, :>, pos)
+ end
+ end
+ end
+ }
+ end
+
+ def test_str_insert
+ combination(STRINGS, 0..2, STRINGS) {|s1, nth, s2|
+ t1 = s1.dup
+ t2 = s1.dup
+ begin
+ t1[nth, 0] = s2
+ rescue EncodingCompatibilityError, IndexError => e1
+ end
+ begin
+ t2.insert(nth, s2)
+ rescue EncodingCompatibilityError, IndexError => e2
+ end
+ assert_equal(t1, t2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
+ assert_equal(e1.class, e2.class, "begin #{encdump s1}.insert(#{nth},#{encdump s2}); rescue ArgumentError, IndexError => e; e end")
+ }
+ combination(STRINGS, -2..-1, STRINGS) {|s1, nth, s2|
+ next if s1.length + nth < 0
+ next unless s1.valid_encoding?
+ next unless s2.valid_encoding?
+ t1 = s1.dup
+ begin
+ t1.insert(nth, s2)
+ slen = s2.length
+ assert_equal(t1[nth-slen+1,slen], s2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
+ rescue EncodingCompatibilityError, IndexError => e
+ end
+ }
+ end
+
+ def test_str_intern
+ STRINGS.each {|s|
+ if /\0/ =~ a(s)
+ assert_raise(ArgumentError) { s.intern }
+ else
+ sym = s.intern
+ assert_equal(s, sym.to_s, "#{encdump s}.intern.to_s")
+ assert_equal(sym, s.to_sym)
+ end
+ }
+ end
+
+ def test_str_length
+ STRINGS.each {|s|
+ assert_operator(s.length, :<=, s.bytesize)
+ }
+ end
+
+ def test_str_oct
+ STRINGS.each {|s|
+ t = s.oct
+ t2 = a(s)[/\A[0-9a-fA-FxXbB]*/].oct
+ assert_equal(t2, t)
+ }
+ end
+
+ def test_str_replace
+ combination(STRINGS, STRINGS) {|s1, s2|
+ t = s1.dup
+ t.replace s2
+ assert_equal(s2, t)
+ assert_equal(s2.encoding, t.encoding)
+ }
+ end
+
+ def test_str_reverse
+ STRINGS.each {|s|
+ t = s.reverse
+ assert_equal(s.bytesize, t.bytesize)
+ if !s.valid_encoding?
+ assert_operator(t.length, :<=, s.length)
+ next
+ end
+ assert_equal(s, t.reverse)
+ }
+ end
+
+ def test_str_scan
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s2.valid_encoding?
+ assert_raise(RegexpError) { s1.scan(s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(ArgumentError) { s1.scan(s2) }
+ next
+ end
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError) { s1.scan(s2) }
+ next
+ end
+ r = enccall(s1, :scan, s2)
+ r.each {|t|
+ assert_equal(s2, t)
+ }
+ }
+ end
+
+ def test_str_slice
+ each_slice_call {|obj, *args|
+ assert_same_result(lambda { obj[*args] }, lambda { obj.slice(*args) })
+ }
+ end
+
+ def test_str_slice!
+ each_slice_call {|s, *args|
+ desc_slice = "#{encdump s}.slice#{encdumpargs args}"
+ desc_slice_bang = "#{encdump s}.slice!#{encdumpargs args}"
+ t = s.dup
+ begin
+ r = t.slice!(*args)
+ rescue
+ e = $!
+ end
+ if e
+ assert_raise(e.class, desc_slice) { s.slice(*args) }
+ next
+ end
+ if !r
+ assert_nil(s.slice(*args), desc_slice)
+ next
+ end
+ assert_equal(s.slice(*args), r, desc_slice_bang)
+ assert_equal(s.bytesize, r.bytesize + t.bytesize)
+ if args.length == 1 && String === args[0]
+ assert_equal(args[0].encoding, r.encoding,
+ "#{encdump s}.slice!#{encdumpargs args}.encoding")
+ else
+ assert_equal(s.encoding, r.encoding,
+ "#{encdump s}.slice!#{encdumpargs args}.encoding")
+ end
+ if [s, *args].all? {|o| !(String === o) || o.valid_encoding? }
+ assert(r.valid_encoding?)
+ assert(t.valid_encoding?)
+ assert_equal(s.length, r.length + t.length)
+ end
+ }
+ end
+
+ def test_str_split
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s2.valid_encoding?
+ assert_raise(RegexpError) { s1.split(s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(ArgumentError) { s1.split(s2) }
+ next
+ end
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError) { s1.split(s2) }
+ next
+ end
+ t = enccall(s1, :split, s2)
+ t.each {|r|
+ assert(a(s1).include?(a(r)))
+ assert_equal(s1.encoding, r.encoding)
+ }
+ assert(a(s1).include?(t.map {|u| a(u) }.join(a(s2))))
+ if s1.valid_encoding? && s2.valid_encoding?
+ t.each {|r|
+ assert(r.valid_encoding?)
+ }
+ end
+ }
+ end
+
+ def test_str_squeeze
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if !s1.valid_encoding? || !s2.valid_encoding?
+ assert_raise(ArgumentError, EncodingCompatibilityError, "#{encdump s1}.squeeze(#{encdump s2})") { s1.squeeze(s2) }
+ next
+ end
+ if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
+ assert_raise(EncodingCompatibilityError) { s1.squeeze(s2) }
+ next
+ end
+ t = enccall(s1, :squeeze, s2)
+ assert_operator(t.length, :<=, s1.length)
+ t2 = s1.dup
+ t2.squeeze!(s2)
+ assert_equal(t, t2)
+ }
+ end
+
+ def test_str_strip
+ STRINGS.each {|s|
+ if !s.valid_encoding?
+ assert_raise(ArgumentError, "#{encdump s}.strip") { s.strip }
+ next
+ end
+ t = s.strip
+ l = s.lstrip
+ r = s.rstrip
+ assert_operator(l.length, :<=, s.length)
+ assert_operator(r.length, :<=, s.length)
+ assert_operator(t.length, :<=, l.length)
+ assert_operator(t.length, :<=, r.length)
+ t2 = s.dup
+ t2.strip!
+ assert_equal(t, t2)
+ l2 = s.dup
+ l2.lstrip!
+ assert_equal(l, l2)
+ r2 = s.dup
+ r2.rstrip!
+ assert_equal(r, r2)
+ }
+ end
+
+ def test_str_sum
+ STRINGS.each {|s|
+ assert_equal(a(s).sum, s.sum)
+ }
+ end
+
+ def test_str_swapcase
+ STRINGS.each {|s|
+ if !s.valid_encoding?
+ assert_raise(ArgumentError, "#{encdump s}.swapcase") { s.swapcase }
+ next
+ end
+ t1 = s.swapcase
+ assert(t1.valid_encoding?) if s.valid_encoding?
+ assert(t1.casecmp(s))
+ t2 = s.dup
+ t2.swapcase!
+ assert_equal(t1, t2)
+ t3 = t1.swapcase
+ assert_equal(s, t3);
+ }
+ end
+
+
+ def test_str_to_f
+ STRINGS.each {|s|
+ assert_nothing_raised { s.to_f }
+ }
+ end
+
+ def test_str_to_i
+ STRINGS.each {|s|
+ assert_nothing_raised { s.to_i }
+ 2.upto(36) {|radix|
+ assert_nothing_raised { s.to_i(radix) }
+ }
+ }
+ end
+
+ def test_str_to_s
+ STRINGS.each {|s|
+ assert_same(s, s.to_s)
+ assert_same(s, s.to_str)
+ }
+ end
+
+ def test_tr
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ desc = "#{encdump s1}.tr(#{encdump s2}, #{encdump s3})"
+ if s1.empty?
+ assert_equal(s1, s1.tr(s2, s3), desc)
+ next
+ end
+ if !str_enc_compatible?(s1, s2, s3)
+ assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ next
+ end
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError, desc) { s1.tr(s2, s3) }
+ next
+ end
+ if s2.empty?
+ t = enccall(s1, :tr, s2, s3)
+ assert_equal(s1, t, desc)
+ next
+ end
+ if !s2.valid_encoding? || !s3.valid_encoding?
+ assert_raise(ArgumentError, desc) { s1.tr(s2, s3) }
+ next
+ end
+ t = enccall(s1, :tr, s2, s3)
+ assert_operator(s1.length, :>=, t.length, desc)
+ }
+ end
+
+ def test_tr_s
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ desc = "#{encdump s1}.tr_s(#{encdump s2}, #{encdump s3})"
+ if s1.empty?
+ assert_equal(s1, s1.tr_s(s2, s3), desc)
+ next
+ end
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError, EncodingCompatibilityError, desc) { s1.tr_s(s2, s3) }
+ next
+ end
+ if !str_enc_compatible?(s1, s2, s3)
+ assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ next
+ end
+ if s2.empty?
+ t = enccall(s1, :tr_s, s2, s3)
+ assert_equal(s1, t, desc)
+ next
+ end
+ if !s2.valid_encoding? || !s3.valid_encoding?
+ assert_raise(ArgumentError, desc) { s1.tr_s(s2, s3) }
+ next
+ end
+
+ t = enccall(s1, :tr_s, s2, s3)
+ assert_operator(s1.length, :>=, t.length, desc)
+ }
+ end
+
+ def test_str_upcase
+ STRINGS.each {|s|
+ desc = "#{encdump s}.upcase"
+ if !s.valid_encoding?
+ assert_raise(ArgumentError, desc) { s.upcase }
+ next
+ end
+ t1 = s.upcase
+ assert(t1.valid_encoding?)
+ assert(t1.casecmp(s))
+ t2 = s.dup
+ t2.upcase!
+ assert_equal(t1, t2)
+ }
+ end
+
+ def test_str_succ
+ STRINGS.each {|s0|
+ next if s0.empty?
+ s = s0.dup
+ n = 1000
+ h = {}
+ n.times {|i|
+ if h[s]
+ assert(false, "#{encdump s} cycle with succ #{i-h[s]} times")
+ end
+ h[s] = i
+ assert_operator(s.length, :<=, s0.length + Math.log2(i+1) + 1, "#{encdump s0} succ #{i} times => #{encdump s}")
+ #puts encdump(s)
+ t = s.succ
+ if s.valid_encoding?
+ assert(t.valid_encoding?, "#{encdump s}.succ.valid_encoding?")
+ end
+ s = t
+ }
+ }
+ end
+
+ def test_str_hash
+ combination(STRINGS, STRINGS) {|s1, s2|
+ if s1.eql?(s2)
+ assert_equal(s1.hash, s2.hash, "#{encdump s1}.hash == #{encdump s2}.dump")
+ end
+ }
+ end
+
+ def test_marshal
+ STRINGS.each {|s|
+ m = Marshal.dump(s)
+ t = Marshal.load(m)
+ assert_equal(s, t)
+ }
+ end
+
+ def test_str_sub
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ if !s2.valid_encoding?
+ assert_raise(RegexpError) { Regexp.new(Regexp.escape(s2)) }
+ next
+ end
+ r2 = Regexp.new(Regexp.escape(s2))
+ [
+ [
+ "#{encdump s1}.sub(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { s1.sub(r2, s3) }
+ ],
+ [
+ "#{encdump s1}.sub(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { s1.sub(r2) { s3 } }
+ ],
+ [
+ "#{encdump s1}.gsub(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { s1.gsub(r2, s3) }
+ ],
+ [
+ "#{encdump s1}.gsub(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { s1.gsub(r2) { s3 } }
+ ]
+ ].each {|desc, doit|
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError, desc) { doit.call }
+ next
+ end
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(ArgumentError, desc) { doit.call }
+ next
+ end
+ if !enccall(s1, :include?, s2)
+ assert_equal(s1, doit.call)
+ next
+ end
+ if !str_enc_compatible?(s1.gsub(r2, ''), s3)
+ assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ next
+ end
+ t = nil
+ assert_nothing_raised(desc) {
+ t = doit.call
+ }
+ if s2 == s3
+ assert_equal(s1, t, desc)
+ else
+ assert_not_equal(s1, t, desc)
+ end
+ }
+ }
+ end
+
+ def test_str_sub!
+ combination(STRINGS, STRINGS, STRINGS) {|s1, s2, s3|
+ if !s2.valid_encoding?
+ assert_raise(RegexpError) { Regexp.new(Regexp.escape(s2)) }
+ next
+ end
+ r2 = Regexp.new(Regexp.escape(s2))
+ [
+ [
+ "t=#{encdump s1}.dup;t.sub!(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { t=s1.dup; [t, t.sub!(r2, s3)] }
+ ],
+ [
+ "t=#{encdump s1}.dup;t.sub!(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { t=s1.dup; [t, t.sub!(r2) { s3 }] }
+ ],
+ [
+ "t=#{encdump s1}.dup;t.gsub!(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { t=s1.dup; [t, t.gsub!(r2, s3)] }
+ ],
+ [
+ "t=#{encdump s1}.dup;t.gsub!(Regexp.new(#{encdump s2}), #{encdump s3})",
+ lambda { t=s1.dup; [t, t.gsub!(r2) { s3 }] }
+ ]
+ ].each {|desc, doit|
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError, desc) { doit.call }
+ next
+ end
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(ArgumentError, desc) { doit.call }
+ next
+ end
+ if !enccall(s1, :include?, s2)
+ assert_equal([s1, nil], doit.call)
+ next
+ end
+ if !str_enc_compatible?(s1.gsub(r2, ''), s3)
+ assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ next
+ end
+ t = ret = nil
+ assert_nothing_raised(desc) {
+ t, ret = doit.call
+ }
+ assert(ret)
+ if s2 == s3
+ assert_equal(s1, t, desc)
+ else
+ assert_not_equal(s1, t, desc)
+ end
+ }
+ }
+ end
+
+ def test_str_bytes
+ STRINGS.each {|s1|
+ ary = []
+ s1.bytes.each {|b|
+ ary << b
+ }
+ assert_equal(s1.unpack("C*"), ary)
+ }
+ end
+
+ def test_str_bytesize
+ STRINGS.each {|s1|
+ assert_equal(s1.unpack("C*").length, s1.bytesize)
+ }
+ end
+
+ def test_str_chars
+ STRINGS.each {|s1|
+ ary = []
+ s1.chars.each {|c|
+ ary << c
+ }
+ expected = []
+ s1.length.times {|i|
+ expected << s1[i]
+ }
+ assert_equal(expected, ary)
+ }
+ end
+
+ def test_str_chr
+ STRINGS.each {|s1|
+ if s1.empty?
+ assert_equal("", s1.chr)
+ next
+ end
+ assert_equal(s1[0], s1.chr)
+ }
+ end
+
+ def test_str_end_with?
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc = "#{encdump s1}.end_with?(#{encdump s2})"
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(EncodingCompatibilityError, desc) { s1.end_with?(s2) }
+ next
+ end
+ if s1.length < s2.length
+ assert_equal(false, enccall(s1, :end_with?, s2), desc)
+ next
+ end
+ if s1[s1.length-s2.length, s2.length] == s2
+ assert_equal(true, enccall(s1, :end_with?, s2), desc)
+ next
+ end
+ assert_equal(false, enccall(s1, :end_with?, s2), desc)
+ }
+ end
+
+ def test_str_start_with?
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc = "#{encdump s1}.start_with?(#{encdump s2})"
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(EncodingCompatibilityError, desc) { s1.start_with?(s2) }
+ next
+ end
+ s1 = s1.dup.force_encoding("ASCII-8BIT")
+ s2 = s2.dup.force_encoding("ASCII-8BIT")
+ if s1.length < s2.length
+ assert_equal(false, enccall(s1, :start_with?, s2), desc)
+ next
+ end
+ if s1[0, s2.length] == s2
+ assert_equal(true, enccall(s1, :start_with?, s2), desc)
+ next
+ end
+ assert_equal(false, enccall(s1, :start_with?, s2), desc)
+ }
+ end
+
+ def test_str_ord
+ STRINGS.each {|s1|
+ if s1.empty?
+ assert_raise(ArgumentError) { s1.ord }
+ next
+ end
+ if !s1.valid_encoding?
+ assert_raise(ArgumentError) { s1.ord }
+ next
+ end
+ assert_equal(s1[0].ord, s1.ord)
+ }
+ end
+
+ def test_str_partition
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc = "#{encdump s1}.partition(#{encdump s2})"
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(EncodingCompatibilityError, desc) { s1.partition(s2) }
+ next
+ end
+ i = enccall(s1, :index, s2)
+ if !i
+ assert_equal([s1, "", ""], s1.partition(s2), desc)
+ next
+ end
+ assert_equal([s1[0,i], s2, s1[(i+s2.length)..-1]], s1.partition(s2), desc)
+ }
+ end
+
+ def test_str_rpartition
+ combination(STRINGS, STRINGS) {|s1, s2|
+ desc = "#{encdump s1}.rpartition(#{encdump s2})"
+ if !str_enc_compatible?(s1, s2)
+ assert_raise(EncodingCompatibilityError, desc) { s1.rpartition(s2) }
+ next
+ end
+ i = enccall(s1, :rindex, s2)
+ if !i
+ assert_equal(["", "", s1], s1.rpartition(s2), desc)
+ next
+ end
+ assert_equal([s1[0,i], s2, s1[(i+s2.length)..-1]], s1.rpartition(s2), desc)
+ }
+ end
+
+end
diff --git a/trunk/test/ruby/test_marshal.rb b/trunk/test/ruby/test_marshal.rb
new file mode 100644
index 0000000000..af389d2b2d
--- /dev/null
+++ b/trunk/test/ruby/test_marshal.rb
@@ -0,0 +1,194 @@
+require 'test/unit'
+require_relative 'marshaltestlib'
+
+class TestMarshal < Test::Unit::TestCase
+ include MarshalTestLib
+
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def encode(o)
+ Marshal.dump(o)
+ end
+
+ def decode(s)
+ Marshal.load(s)
+ end
+
+ def fact(n)
+ return 1 if n == 0
+ f = 1
+ while n>0
+ f *= n
+ n -= 1
+ end
+ return f
+ end
+
+ def test_marshal
+ x = [1, 2, 3, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
+ assert_equal x, Marshal.load(Marshal.dump(x))
+
+ [[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z|
+ obj = (x.to_f + y.to_f / z.to_f) * Math.exp(w.to_f / (x.to_f + y.to_f / z.to_f))
+ assert_equal obj, Marshal.load(Marshal.dump(obj))
+ }
+ end
+
+ StrClone = String.clone
+ def test_marshal_cloned_class
+ assert_instance_of(StrClone, Marshal.load(Marshal.dump(StrClone.new("abc"))))
+ end
+
+ def test_inconsistent_struct
+ TestMarshal.const_set :StructOrNot, Struct.new(:a)
+ s = Marshal.dump(StructOrNot.new(1))
+ TestMarshal.instance_eval { remove_const :StructOrNot }
+ TestMarshal.const_set :StructOrNot, Class.new
+ assert_raise(TypeError, "[ruby-dev:31709]") { Marshal.load(s) }
+ end
+
+ def test_struct_invalid_members
+ TestMarshal.const_set :StructInvalidMembers, Struct.new(:a)
+ Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo")
+ assert_raise(TypeError, "[ruby-dev:31759]") {
+ TestMarshal::StructInvalidMembers.members
+ }
+ end
+
+ class C
+ def initialize(str)
+ @str = str
+ end
+ attr_reader :str
+ def _dump(limit)
+ @str
+ end
+ def self._load(s)
+ new(s)
+ end
+ end
+
+ def test_too_long_string
+ data = Marshal.dump(C.new("a".force_encoding("ascii-8bit")))
+ data[-2, 1] = "\003\377\377\377"
+ e = assert_raise(ArgumentError, "[ruby-dev:32054]") {
+ Marshal.load(data)
+ }
+ assert_equal("marshal data too short", e.message)
+ end
+
+
+ def test_userdef_encoding
+ s1 = "\xa4\xa4".force_encoding("euc-jp")
+ o1 = C.new(s1)
+ m = Marshal.dump(o1)
+ o2 = Marshal.load(m)
+ s2 = o2.str
+ assert_equal(s1, s2)
+ end
+
+ def test_pipe
+ o1 = C.new("a" * 10000)
+
+ r, w = IO.pipe
+ t = Thread.new { Marshal.load(r) }
+ Marshal.dump(o1, w)
+ o2 = t.value
+ assert_equal(o1.str, o2.str)
+
+ r, w = IO.pipe
+ t = Thread.new { Marshal.load(r) }
+ Marshal.dump(o1, w, 2)
+ o2 = t.value
+ assert_equal(o1.str, o2.str)
+
+ assert_raise(TypeError) { Marshal.dump("foo", Object.new) }
+ assert_raise(TypeError) { Marshal.load(Object.new) }
+ end
+
+ def test_limit
+ assert_equal([[[]]], Marshal.load(Marshal.dump([[[]]], 3)))
+ assert_raise(ArgumentError) { Marshal.dump([[[]]], 2) }
+ end
+
+ def test_userdef_invalid
+ o = C.new(nil)
+ assert_raise(TypeError) { Marshal.dump(o) }
+ end
+
+ def test_class
+ o = class << Object.new; self; end
+ assert_raise(TypeError) { Marshal.dump(o) }
+ assert_equal(Object, Marshal.load(Marshal.dump(Object)))
+ assert_equal(Enumerable, Marshal.load(Marshal.dump(Enumerable)))
+ end
+
+ class C2
+ def initialize(ary)
+ @ary = ary
+ end
+ def _dump(s)
+ @ary.clear
+ "foo"
+ end
+ end
+
+ def test_modify_array_during_dump
+ a = []
+ o = C2.new(a)
+ a << o << nil
+ assert_raise(RuntimeError) { Marshal.dump(a) }
+ end
+
+ def test_change_class_name
+ eval("class C3; def _dump(s); 'foo'; end; end")
+ m = Marshal.dump(C3.new)
+ assert_raise(TypeError) { Marshal.load(m) }
+ eval("C3 = nil")
+ assert_raise(TypeError) { Marshal.load(m) }
+ end
+
+ def test_change_struct
+ eval("C3 = Struct.new(:foo, :bar)")
+ m = Marshal.dump(C3.new("FOO", "BAR"))
+ eval("C3 = Struct.new(:foo)")
+ assert_raise(TypeError) { Marshal.load(m) }
+ eval("C3 = Struct.new(:foo, :baz)")
+ assert_raise(TypeError) { Marshal.load(m) }
+ end
+
+ class C4
+ def initialize(gc)
+ @gc = gc
+ end
+ def _dump(s)
+ GC.start if @gc
+ "foo"
+ end
+ end
+
+ def test_gc
+ assert_nothing_raised do
+ Marshal.dump((0..1000).map {|x| C4.new(x % 50 == 25) })
+ end
+ end
+
+ def test_taint_and_untrust
+ x = Object.new
+ x.taint
+ x.untrust
+ s = Marshal.dump(x)
+ assert_equal(true, s.tainted?)
+ assert_equal(true, s.untrusted?)
+ y = Marshal.load(s)
+ assert_equal(true, y.tainted?)
+ assert_equal(true, y.untrusted?)
+ end
+end
diff --git a/trunk/test/ruby/test_math.rb b/trunk/test/ruby/test_math.rb
new file mode 100644
index 0000000000..55f354664c
--- /dev/null
+++ b/trunk/test/ruby/test_math.rb
@@ -0,0 +1,239 @@
+require 'test/unit'
+
+class TestMath < Test::Unit::TestCase
+ def check(a, b)
+ err = [Float::EPSILON * 4, [a.abs, b.abs].max * Float::EPSILON * 256].max
+ assert_in_delta(a, b, err)
+ end
+
+ def test_atan2
+ check(0, Math.atan2(0, 1))
+ check(Math::PI / 4, Math.atan2(1, 1))
+ check(Math::PI / 2, Math.atan2(1, 0))
+ end
+
+ def test_cos
+ check(1.0, Math.cos(0 * Math::PI / 4))
+ check(1.0 / Math.sqrt(2), Math.cos(1 * Math::PI / 4))
+ check(0.0, Math.cos(2 * Math::PI / 4))
+ check(-1.0, Math.cos(4 * Math::PI / 4))
+ check(0.0, Math.cos(6 * Math::PI / 4))
+ end
+
+ def test_sin
+ check(0.0, Math.sin(0 * Math::PI / 4))
+ check(1.0 / Math.sqrt(2), Math.sin(1 * Math::PI / 4))
+ check(1.0, Math.sin(2 * Math::PI / 4))
+ check(0.0, Math.sin(4 * Math::PI / 4))
+ check(-1.0, Math.sin(6 * Math::PI / 4))
+ end
+
+ def test_tan
+ check(0.0, Math.tan(0 * Math::PI / 4))
+ check(1.0, Math.tan(1 * Math::PI / 4))
+ assert(Math.tan(2 * Math::PI / 4).abs > 1024)
+ check(0.0, Math.tan(4 * Math::PI / 4))
+ assert(Math.tan(6 * Math::PI / 4).abs > 1024)
+ end
+
+ def test_acos
+ check(0 * Math::PI / 4, Math.acos( 1.0))
+ check(1 * Math::PI / 4, Math.acos( 1.0 / Math.sqrt(2)))
+ check(2 * Math::PI / 4, Math.acos( 0.0))
+ check(4 * Math::PI / 4, Math.acos(-1.0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.acos(2.0) }
+ end
+
+ def test_asin
+ check( 0 * Math::PI / 4, Math.asin( 0.0))
+ check( 1 * Math::PI / 4, Math.asin( 1.0 / Math.sqrt(2)))
+ check( 2 * Math::PI / 4, Math.asin( 1.0))
+ check(-2 * Math::PI / 4, Math.asin(-1.0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.asin(2.0) }
+ end
+
+ def test_atan
+ check( 0 * Math::PI / 4, Math.atan( 0.0))
+ check( 1 * Math::PI / 4, Math.atan( 1.0))
+ check( 2 * Math::PI / 4, Math.atan(1.0 / 0.0))
+ check(-1 * Math::PI / 4, Math.atan(-1.0))
+ end
+
+ def test_cosh
+ check(1, Math.cosh(0))
+ check((Math::E ** 1 + Math::E ** -1) / 2, Math.cosh(1))
+ check((Math::E ** 2 + Math::E ** -2) / 2, Math.cosh(2))
+ end
+
+ def test_sinh
+ check(0, Math.sinh(0))
+ check((Math::E ** 1 - Math::E ** -1) / 2, Math.sinh(1))
+ check((Math::E ** 2 - Math::E ** -2) / 2, Math.sinh(2))
+ end
+
+ def test_tanh
+ check(Math.sinh(0) / Math.cosh(0), Math.tanh(0))
+ check(Math.sinh(1) / Math.cosh(1), Math.tanh(1))
+ check(Math.sinh(2) / Math.cosh(2), Math.tanh(2))
+ end
+
+ def test_acosh
+ check(0, Math.acosh(1))
+ check(1, Math.acosh((Math::E ** 1 + Math::E ** -1) / 2))
+ check(2, Math.acosh((Math::E ** 2 + Math::E ** -2) / 2))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.acosh(0) }
+ end
+
+ def test_asinh
+ check(0, Math.asinh(0))
+ check(1, Math.asinh((Math::E ** 1 - Math::E ** -1) / 2))
+ check(2, Math.asinh((Math::E ** 2 - Math::E ** -2) / 2))
+ end
+
+ def test_atanh
+ check(0, Math.atanh(Math.sinh(0) / Math.cosh(0)))
+ check(1, Math.atanh(Math.sinh(1) / Math.cosh(1)))
+ check(2, Math.atanh(Math.sinh(2) / Math.cosh(2)))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.atanh(-1) }
+ end
+
+ def test_exp
+ check(1, Math.exp(0))
+ check(Math.sqrt(Math::E), Math.exp(0.5))
+ check(Math::E, Math.exp(1))
+ check(Math::E ** 2, Math.exp(2))
+ end
+
+ def test_log
+ check(0, Math.log(1))
+ check(1, Math.log(Math::E))
+ check(0, Math.log(1, 10))
+ check(1, Math.log(10, 10))
+ check(2, Math.log(100, 10))
+ assert_equal(1.0/0, Math.log(1.0/0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(0) }
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(-1) }
+ end
+
+ def test_log2
+ check(0, Math.log2(1))
+ check(1, Math.log2(2))
+ check(2, Math.log2(4))
+ assert_equal(1.0/0, Math.log2(1.0/0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log2(0) }
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log2(-1) }
+ end
+
+ def test_log10
+ check(0, Math.log10(1))
+ check(1, Math.log10(10))
+ check(2, Math.log10(100))
+ assert_equal(1.0/0, Math.log10(1.0/0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log10(0) }
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log10(-1) }
+ end
+
+ def test_sqrt
+ check(0, Math.sqrt(0))
+ check(1, Math.sqrt(1))
+ check(2, Math.sqrt(4))
+ assert_equal(1.0/0, Math.sqrt(1.0/0))
+ assert_raise(Errno::EDOM, Errno::ERANGE) { Math.sqrt(-1) }
+ end
+
+ def test_frexp
+ check(0.0, Math.frexp(0.0).first)
+ assert_equal(0, Math.frexp(0).last)
+ check(0.5, Math.frexp(0.5).first)
+ assert_equal(0, Math.frexp(0.5).last)
+ check(0.5, Math.frexp(1.0).first)
+ assert_equal(1, Math.frexp(1.0).last)
+ check(0.5, Math.frexp(2.0).first)
+ assert_equal(2, Math.frexp(2.0).last)
+ check(0.75, Math.frexp(3.0).first)
+ assert_equal(2, Math.frexp(3.0).last)
+ end
+
+ def test_ldexp
+ check(0.0, Math.ldexp(0.0, 0.0))
+ check(0.5, Math.ldexp(0.5, 0.0))
+ check(1.0, Math.ldexp(0.5, 1.0))
+ check(2.0, Math.ldexp(0.5, 2.0))
+ check(3.0, Math.ldexp(0.75, 2.0))
+ end
+
+ def test_hypot
+ check(5, Math.hypot(3, 4))
+ end
+
+ def test_erf
+ check(0, Math.erf(0))
+ check(1, Math.erf(1.0 / 0.0))
+ end
+
+ def test_erfc
+ check(1, Math.erfc(0))
+ check(0, Math.erfc(1.0 / 0.0))
+ end
+
+ def test_gamma
+ sqrt_pi = Math.sqrt(Math::PI)
+ check(4 * sqrt_pi / 3, Math.gamma(-1.5))
+ check(-2 * sqrt_pi, Math.gamma(-0.5))
+ check(sqrt_pi, Math.gamma(0.5))
+ check(1, Math.gamma(1))
+ check(sqrt_pi / 2, Math.gamma(1.5))
+ check(1, Math.gamma(2))
+ check(3 * sqrt_pi / 4, Math.gamma(2.5))
+ check(2, Math.gamma(3))
+ check(15 * sqrt_pi / 8, Math.gamma(3.5))
+ check(6, Math.gamma(4))
+ end
+
+ def test_lgamma
+ sqrt_pi = Math.sqrt(Math::PI)
+
+ g, s = Math.lgamma(-1.5)
+ check(Math.log(4 * sqrt_pi / 3), g)
+ assert_equal(s, 1)
+
+ g, s = Math.lgamma(-0.5)
+ check(Math.log(2 * sqrt_pi), g)
+ assert_equal(s, -1)
+
+ g, s = Math.lgamma(0.5)
+ check(Math.log(sqrt_pi), g)
+ assert_equal(s, 1)
+
+ assert_equal([0, 1], Math.lgamma(1))
+
+ g, s = Math.lgamma(1.5)
+ check(Math.log(sqrt_pi / 2), g)
+ assert_equal(s, 1)
+
+ assert_equal([0, 1], Math.lgamma(2))
+
+ g, s = Math.lgamma(2.5)
+ check(Math.log(3 * sqrt_pi / 4), g)
+ assert_equal(s, 1)
+
+ g, s = Math.lgamma(3)
+ check(Math.log(2), g)
+ assert_equal(s, 1)
+
+ g, s = Math.lgamma(3.5)
+ check(Math.log(15 * sqrt_pi / 8), g)
+ assert_equal(s, 1)
+
+ g, s = Math.lgamma(4)
+ check(Math.log(6), g)
+ assert_equal(s, 1)
+ end
+
+ def test_cbrt
+ check(1, Math.cbrt(1))
+ check(-2, Math.cbrt(-8))
+ check(3, Math.cbrt(27))
+ check(-0.1, Math.cbrt(-0.001))
+ end
+end
diff --git a/trunk/test/ruby/test_method.rb b/trunk/test/ruby/test_method.rb
new file mode 100644
index 0000000000..d978050dc8
--- /dev/null
+++ b/trunk/test/ruby/test_method.rb
@@ -0,0 +1,224 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestMethod < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def m0() end
+ def m1(a) end
+ def m2(a, b) end
+ def mo1(a = nil, &b) end
+ def mo2(a, b = nil) end
+ def mo3(*a) end
+ def mo4(a, *b, &c) end
+ def mo5(a, *b, c) end
+ def mo6(a, *b, c, &d) end
+
+ class Base
+ def foo() :base end
+ end
+ class Derived < Base
+ def foo() :derived end
+ end
+
+ def test_arity
+ assert_equal(0, method(:m0).arity)
+ assert_equal(1, method(:m1).arity)
+ assert_equal(2, method(:m2).arity)
+ assert_equal(-1, method(:mo1).arity)
+ assert_equal(-2, method(:mo2).arity)
+ assert_equal(-1, method(:mo3).arity)
+ assert_equal(-2, method(:mo4).arity)
+ assert_equal(-3, method(:mo5).arity)
+ assert_equal(-3, method(:mo6).arity)
+ end
+
+ def test_unbind
+ assert_equal(:derived, Derived.new.foo)
+ um = Derived.new.method(:foo).unbind
+ assert_instance_of(UnboundMethod, um)
+ Derived.class_eval do
+ def foo() :changed end
+ end
+ assert_equal(:changed, Derived.new.foo)
+ assert_equal(:derived, um.bind(Derived.new).call)
+ assert_raise(TypeError) do
+ um.bind(Base.new)
+ end
+ end
+
+ def test_callee
+ assert_equal(:test_callee, __method__)
+ assert_equal(:m, Class.new {def m; __method__; end}.new.m)
+ assert_equal(:m, Class.new {def m; tap{return __method__}; end}.new.m)
+ assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
+ assert_equal(:m, Class.new {define_method(:m) {tap{return __method__}}}.new.m)
+ assert_nil(eval("class TestCallee; __method__; end"))
+ end
+
+ def test_body
+ o = Object.new
+ def o.foo; end
+ assert_nothing_raised { RubyVM::InstructionSequence.disasm(o.method(:foo)) }
+ end
+
+ def test_new
+ c1 = Class.new
+ c1.class_eval { def foo; :foo; end }
+ c2 = Class.new(c1)
+ c2.class_eval { private :foo }
+ o = c2.new
+ o.extend(Module.new)
+ assert_raise(NameError) { o.method(:bar) }
+ assert_raise(NameError) { o.public_method(:foo) }
+ assert_equal(:foo, o.method(:foo).call)
+ end
+
+ def test_eq
+ o = Object.new
+ class << o
+ def foo; end
+ alias bar foo
+ def baz; end
+ end
+ assert_not_equal(o.method(:foo), nil)
+ m = o.method(:foo)
+ def m.foo; end
+ assert_not_equal(o.method(:foo), m)
+ assert_equal(o.method(:foo), o.method(:foo))
+ assert_equal(o.method(:foo), o.method(:bar))
+ assert_not_equal(o.method(:foo), o.method(:baz))
+ end
+
+ def test_hash
+ o = Object.new
+ def o.foo; end
+ assert_kind_of(Integer, o.method(:foo).hash)
+ end
+
+ def test_receiver_name_owner
+ o = Object.new
+ def o.foo; end
+ m = o.method(:foo)
+ assert_equal(o, m.receiver)
+ assert_equal(:foo, m.name)
+ assert_equal(class << o; self; end, m.owner)
+ assert_equal(:foo, m.unbind.name)
+ assert_equal(class << o; self; end, m.unbind.owner)
+ end
+
+ def test_instance_method
+ c = Class.new
+ c.class_eval do
+ def foo; :foo; end
+ private :foo
+ end
+ o = c.new
+ o.method(:foo).unbind
+ assert_raise(NoMethodError) { o.foo }
+ c.instance_method(:foo).bind(o)
+ assert_equal(:foo, o.instance_eval { foo })
+ assert_raise(NameError) { c.public_instance_method(:foo) }
+ def o.bar; end
+ m = o.method(:bar).unbind
+ assert_raise(TypeError) { m.bind(Object.new) }
+ end
+
+ def test_define_method
+ c = Class.new
+ c.class_eval { def foo; :foo; end }
+ o = c.new
+ def o.bar; :bar; end
+ assert_raise(TypeError) do
+ c.class_eval { define_method(:foo, :foo) }
+ end
+ assert_raise(ArgumentError) do
+ c.class_eval { define_method }
+ end
+ c2 = Class.new(c)
+ c2.class_eval { define_method(:baz, o.method(:foo)) }
+ assert_equal(:foo, c2.new.baz)
+ assert_raise(TypeError) do
+ Class.new.class_eval { define_method(:foo, o.method(:foo)) }
+ end
+ assert_raise(TypeError) do
+ Class.new.class_eval { define_method(:bar, o.method(:bar)) }
+ end
+
+ o = Object.new
+ def o.foo(c)
+ c.class_eval { define_method(:foo) }
+ end
+ c = Class.new
+ o.foo(c) { :foo }
+ assert_equal(:foo, c.new.foo)
+
+ o = Object.new
+ o.instance_eval { define_singleton_method(:foo) { :foo } }
+ assert_equal(:foo, o.foo)
+ end
+
+ def test_clone
+ o = Object.new
+ def o.foo; :foo; end
+ m = o.method(:foo)
+ def m.bar; :bar; end
+ assert_equal(:foo, m.clone.call)
+ assert_equal(:bar, m.clone.bar)
+ end
+
+ def test_call
+ o = Object.new
+ def o.foo; p 1; end
+ def o.bar(x); x; end
+ m = o.method(:foo)
+ m.taint
+ assert_raise(SecurityError) { m.call }
+ end
+
+ def test_inspect
+ o = Object.new
+ def o.foo; end
+ m = o.method(:foo)
+ assert_equal("#<Method: #{ o.inspect }.foo>", m.inspect)
+ m = o.method(:foo)
+ assert_equal("#<UnboundMethod: #{ class << o; self; end.inspect }#foo>", m.unbind.inspect)
+
+ c = Class.new
+ c.class_eval { def foo; end; }
+ m = c.new.method(:foo)
+ assert_equal("#<Method: #{ c.inspect }#foo>", m.inspect)
+ m = c.instance_method(:foo)
+ assert_equal("#<UnboundMethod: #{ c.inspect }#foo>", m.inspect)
+
+ c2 = Class.new(c)
+ c2.class_eval { private :foo }
+ m2 = c2.new.method(:foo)
+ assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo>", m2.inspect)
+ end
+
+ def test_callee_top_level
+ assert_in_out_err([], "p __callee__", %w(nil), [])
+ end
+
+ def test_caller_negative_level
+ assert_raise(ArgumentError) { caller(-1) }
+ end
+
+ def test_attrset_ivar
+ c = Class.new
+ c.class_eval { attr_accessor :foo }
+ o = c.new
+ o.method(:foo=).call(42)
+ assert_equal(42, o.foo)
+ assert_raise(ArgumentError) { o.method(:foo=).call(1, 2, 3) }
+ assert_raise(ArgumentError) { o.method(:foo).call(1) }
+ end
+end
diff --git a/trunk/test/ruby/test_mixed_unicode_escapes.rb b/trunk/test/ruby/test_mixed_unicode_escapes.rb
new file mode 100644
index 0000000000..f274ae7090
--- /dev/null
+++ b/trunk/test/ruby/test_mixed_unicode_escapes.rb
@@ -0,0 +1,25 @@
+# -*- coding: sjis -*-
+# This test is in a differnt file than TestUnicodeEscapes
+# So that we can have a different coding comment above
+
+require 'test/unit'
+
+class TestMixedUnicodeEscape < Test::Unit::TestCase
+ def test_basic
+ # Unicode escapes do work in an sjis encoded file, but only
+ # if they don't contain other multi-byte chars
+ assert_equal("A", "\u0041")
+ # 8-bit character escapes are okay.
+ assert_equal("B\xFF", "\u0042\xFF")
+
+ # sjis mb chars mixed with Unicode shound not work
+ assert_raise(SyntaxError) { eval %q("é\u1234")}
+ assert_raise(SyntaxError) { eval %q("\u{1234}é")}
+
+ # String interpolation turns into an expression and we get
+ # a different kind of error, but we still can't mix these
+ assert_raise(EncodingCompatibilityError) { eval %q("\u{1234}#{nil}é")}
+ assert_raise(EncodingCompatibilityError) { eval %q("é#{nil}\u1234")}
+
+ end
+end
diff --git a/trunk/test/ruby/test_module.rb b/trunk/test/ruby/test_module.rb
new file mode 100644
index 0000000000..edbbf250dd
--- /dev/null
+++ b/trunk/test/ruby/test_module.rb
@@ -0,0 +1,720 @@
+require 'test/unit'
+require 'pp'
+require_relative 'envutil'
+
+$m0 = Module.nesting
+
+class TestModule < Test::Unit::TestCase
+ def assert_method_defined?(klass, mid, message="")
+ message = build_message(message, "#{klass}\##{mid} expected to be defined.")
+ _wrap_assertion do
+ klass.method_defined?(mid) or
+ raise Test::Unit::AssertionFailedError, message, caller(3)
+ end
+ end
+
+ def assert_method_not_defined?(klass, mid, message="")
+ message = build_message(message, "#{klass}\##{mid} expected to not be defined.")
+ _wrap_assertion do
+ klass.method_defined?(mid) and
+ raise Test::Unit::AssertionFailedError, message, caller(3)
+ end
+ end
+
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_LT_0
+ assert_equal true, String < Object
+ assert_equal false, Object < String
+ assert_nil String < Array
+ assert_equal true, Array < Enumerable
+ assert_equal false, Enumerable < Array
+ assert_nil Proc < Comparable
+ assert_nil Comparable < Proc
+ end
+
+ def test_GT_0
+ assert_equal false, String > Object
+ assert_equal true, Object > String
+ assert_nil String > Array
+ assert_equal false, Array > Enumerable
+ assert_equal true, Enumerable > Array
+ assert_nil Comparable > Proc
+ assert_nil Proc > Comparable
+ end
+
+ def test_CMP_0
+ assert_equal -1, (String <=> Object)
+ assert_equal 1, (Object <=> String)
+ assert_nil(Array <=> String)
+ end
+
+ ExpectedException = NoMethodError
+
+ # Support stuff
+
+ def remove_pp_mixins(list)
+ list.reject {|c| c == PP::ObjectMixin }
+ end
+
+ def remove_json_mixins(list)
+ list.reject {|c| c.to_s.start_with?("JSON") }
+ end
+
+ module Mixin
+ MIXIN = 1
+ def mixin
+ end
+ end
+
+ module User
+ USER = 2
+ include Mixin
+ def user
+ end
+ end
+
+ module Other
+ def other
+ end
+ end
+
+ class AClass
+ def AClass.cm1
+ "cm1"
+ end
+ def AClass.cm2
+ cm1 + "cm2" + cm3
+ end
+ def AClass.cm3
+ "cm3"
+ end
+
+ private_class_method :cm1, "cm3"
+
+ def aClass
+ end
+
+ def aClass1
+ end
+
+ def aClass2
+ end
+
+ private :aClass1
+ protected :aClass2
+ end
+
+ class BClass < AClass
+ def bClass1
+ end
+
+ private
+
+ def bClass2
+ end
+
+ protected
+ def bClass3
+ end
+ end
+
+ MyClass = AClass.clone
+ class MyClass
+ public_class_method :cm1
+ end
+
+ # -----------------------------------------------------------
+
+ def test_CMP # '<=>'
+ assert_equal( 0, Mixin <=> Mixin)
+ assert_equal(-1, User <=> Mixin)
+ assert_equal( 1, Mixin <=> User)
+
+ assert_equal( 0, Object <=> Object)
+ assert_equal(-1, String <=> Object)
+ assert_equal( 1, Object <=> String)
+ end
+
+ def test_GE # '>='
+ assert(Mixin >= User)
+ assert(Mixin >= Mixin)
+ assert(!(User >= Mixin))
+
+ assert(Object >= String)
+ assert(String >= String)
+ assert(!(String >= Object))
+ end
+
+ def test_GT # '>'
+ assert(Mixin > User)
+ assert(!(Mixin > Mixin))
+ assert(!(User > Mixin))
+
+ assert(Object > String)
+ assert(!(String > String))
+ assert(!(String > Object))
+ end
+
+ def test_LE # '<='
+ assert(User <= Mixin)
+ assert(Mixin <= Mixin)
+ assert(!(Mixin <= User))
+
+ assert(String <= Object)
+ assert(String <= String)
+ assert(!(Object <= String))
+ end
+
+ def test_LT # '<'
+ assert(User < Mixin)
+ assert(!(Mixin < Mixin))
+ assert(!(Mixin < User))
+
+ assert(String < Object)
+ assert(!(String < String))
+ assert(!(Object < String))
+ end
+
+ def test_VERY_EQUAL # '==='
+ assert(Object === self)
+ assert(Test::Unit::TestCase === self)
+ assert(TestModule === self)
+ assert(!(String === self))
+ end
+
+ def test_ancestors
+ assert_equal([User, Mixin], User.ancestors)
+ assert_equal([Mixin], Mixin.ancestors)
+
+ assert_equal([Object, Kernel, BasicObject],
+ remove_json_mixins(remove_pp_mixins(Object.ancestors)))
+ assert_equal([String, Comparable, Object, Kernel, BasicObject],
+ remove_json_mixins(remove_pp_mixins(String.ancestors)))
+ end
+
+ def test_class_eval
+ Other.class_eval("CLASS_EVAL = 1")
+ assert_equal(1, Other::CLASS_EVAL)
+ assert(Other.constants.include?(:CLASS_EVAL))
+ end
+
+ def test_class_variable_set
+ # TODO
+ end
+
+ def test_class_variable_get
+ # TODO
+ end
+
+ def test_const_defined?
+ assert(Math.const_defined?(:PI))
+ assert(Math.const_defined?("PI"))
+ assert(!Math.const_defined?(:IP))
+ assert(!Math.const_defined?("IP"))
+ end
+
+ def test_const_get
+ assert_equal(Math::PI, Math.const_get("PI"))
+ assert_equal(Math::PI, Math.const_get(:PI))
+ end
+
+ def test_const_set
+ assert(!Other.const_defined?(:KOALA))
+ Other.const_set(:KOALA, 99)
+ assert(Other.const_defined?(:KOALA))
+ assert_equal(99, Other::KOALA)
+ Other.const_set("WOMBAT", "Hi")
+ assert_equal("Hi", Other::WOMBAT)
+ end
+
+ def test_constants
+ assert_equal([:MIXIN], Mixin.constants)
+ assert_equal([:MIXIN, :USER], User.constants.sort)
+ end
+
+ def test_included_modules
+ assert_equal([], Mixin.included_modules)
+ assert_equal([Mixin], User.included_modules)
+ assert_equal([Kernel],
+ remove_json_mixins(remove_pp_mixins(Object.included_modules)))
+ assert_equal([Comparable, Kernel],
+ remove_json_mixins(remove_pp_mixins(String.included_modules)))
+ end
+
+ def test_instance_methods
+ assert_equal([:user], User.instance_methods(false))
+ assert_equal([:user, :mixin].sort, User.instance_methods(true).sort)
+ assert_equal([:mixin], Mixin.instance_methods)
+ assert_equal([:mixin], Mixin.instance_methods(true))
+ # Ruby 1.8 feature change:
+ # #instance_methods includes protected methods.
+ #assert_equal([:aClass], AClass.instance_methods(false))
+ assert_equal([:aClass, :aClass2], AClass.instance_methods(false).sort)
+ assert_equal([:aClass, :aClass2],
+ (AClass.instance_methods(true) - Object.instance_methods(true)).sort)
+ end
+
+ def test_method_defined?
+ assert_method_not_defined?(User, :wombat)
+ assert_method_defined?(User, :user)
+ assert_method_defined?(User, :mixin)
+ assert_method_not_defined?(User, :wombat)
+ assert_method_defined?(User, :user)
+ assert_method_defined?(User, :mixin)
+ end
+
+ def module_exec_aux
+ Proc.new do
+ def dynamically_added_method_3; end
+ end
+ end
+ def module_exec_aux_2(&block)
+ User.module_exec(&block)
+ end
+
+ def test_module_exec
+ User.module_exec do
+ def dynamically_added_method_1; end
+ end
+ assert_method_defined?(User, :dynamically_added_method_1)
+
+ block = Proc.new do
+ def dynamically_added_method_2; end
+ end
+ User.module_exec(&block)
+ assert_method_defined?(User, :dynamically_added_method_2)
+
+ User.module_exec(&module_exec_aux)
+ assert_method_defined?(User, :dynamically_added_method_3)
+
+ module_exec_aux_2 do
+ def dynamically_added_method_4; end
+ end
+ assert_method_defined?(User, :dynamically_added_method_4)
+ end
+
+ def test_module_eval
+ User.module_eval("MODULE_EVAL = 1")
+ assert_equal(1, User::MODULE_EVAL)
+ assert(User.constants.include?(:MODULE_EVAL))
+ User.instance_eval("remove_const(:MODULE_EVAL)")
+ assert(!User.constants.include?(:MODULE_EVAL))
+ end
+
+ def test_name
+ assert_equal("Fixnum", Fixnum.name)
+ assert_equal("TestModule::Mixin", Mixin.name)
+ assert_equal("TestModule::User", User.name)
+ end
+
+ def test_private_class_method
+ assert_raise(ExpectedException) { AClass.cm1 }
+ assert_raise(ExpectedException) { AClass.cm3 }
+ assert_equal("cm1cm2cm3", AClass.cm2)
+ end
+
+ def test_private_instance_methods
+ assert_equal([:aClass1], AClass.private_instance_methods(false))
+ assert_equal([:bClass2], BClass.private_instance_methods(false))
+ assert_equal([:aClass1, :bClass2],
+ (BClass.private_instance_methods(true) -
+ Object.private_instance_methods(true)).sort)
+ end
+
+ def test_protected_instance_methods
+ assert_equal([:aClass2], AClass.protected_instance_methods)
+ assert_equal([:bClass3], BClass.protected_instance_methods(false))
+ assert_equal([:bClass3, :aClass2].sort,
+ (BClass.protected_instance_methods(true) -
+ Object.protected_instance_methods(true)).sort)
+ end
+
+ def test_public_class_method
+ assert_equal("cm1", MyClass.cm1)
+ assert_equal("cm1cm2cm3", MyClass.cm2)
+ assert_raise(ExpectedException) { eval "MyClass.cm3" }
+ end
+
+ def test_public_instance_methods
+ assert_equal([:aClass], AClass.public_instance_methods(false))
+ assert_equal([:bClass1], BClass.public_instance_methods(false))
+ end
+
+ def test_s_constants
+ c1 = Module.constants
+ Object.module_eval "WALTER = 99"
+ c2 = Module.constants
+ assert_equal([:WALTER], c2 - c1)
+ end
+
+ module M1
+ $m1 = Module.nesting
+ module M2
+ $m2 = Module.nesting
+ end
+ end
+
+ def test_s_nesting
+ assert_equal([], $m0)
+ assert_equal([TestModule::M1, TestModule], $m1)
+ assert_equal([TestModule::M1::M2,
+ TestModule::M1, TestModule], $m2)
+ end
+
+ def test_s_new
+ m = Module.new
+ assert_instance_of(Module, m)
+ end
+
+ def test_freeze
+ m = Module.new
+ m.freeze
+ assert_raise(RuntimeError) do
+ m.module_eval do
+ def foo; end
+ end
+ end
+ end
+
+ def test_attr_obsoleted_flag
+ c = Class.new
+ c.class_eval do
+ def initialize
+ @foo = :foo
+ @bar = :bar
+ end
+ attr :foo, true
+ attr :bar, false
+ end
+ o = c.new
+ assert_equal(true, o.respond_to?(:foo))
+ assert_equal(true, o.respond_to?(:foo=))
+ assert_equal(true, o.respond_to?(:bar))
+ assert_equal(false, o.respond_to?(:bar=))
+ end
+
+ def test_const_get2
+ c1 = Class.new
+ c2 = Class.new(c1)
+
+ eval("c1::Foo = :foo")
+ assert_equal(:foo, c1::Foo)
+ assert_equal(:foo, c2::Foo)
+ assert_equal(:foo, c2.const_get(:Foo))
+ assert_raise(NameError) { c2.const_get(:Foo, false) }
+
+ eval("c1::Foo = :foo")
+ assert_raise(NameError) { c1::Bar }
+ assert_raise(NameError) { c2::Bar }
+ assert_raise(NameError) { c2.const_get(:Bar) }
+ assert_raise(NameError) { c2.const_get(:Bar, false) }
+
+ c1.instance_eval do
+ def const_missing(x)
+ x
+ end
+ end
+
+ assert_equal(:Bar, c1::Bar)
+ assert_equal(:Bar, c2::Bar)
+ assert_equal(:Bar, c2.const_get(:Bar))
+ assert_equal(:Bar, c2.const_get(:Bar, false))
+
+ assert_raise(NameError) { c1.const_get(:foo) }
+ end
+
+ def test_const_set2
+ c1 = Class.new
+ assert_raise(NameError) { c1.const_set(:foo, :foo) }
+ end
+
+ def test_const_get3
+ c1 = Class.new
+ assert_raise(NameError) { c1.const_defined?(:foo) }
+ end
+
+ def test_class_variable_get2
+ c = Class.new
+ c.class_eval { @@foo = :foo }
+ assert_equal(:foo, c.class_variable_get(:@@foo))
+ assert_raise(NameError) { c.class_variable_get(:@@bar) } # c.f. instance_variable_get
+ assert_raise(NameError) { c.class_variable_get(:foo) }
+ end
+
+ def test_class_variable_set2
+ c = Class.new
+ c.class_variable_set(:@@foo, :foo)
+ assert_equal(:foo, c.class_eval { @@foo })
+ assert_raise(NameError) { c.class_variable_set(:foo, 1) }
+ end
+
+ def test_class_variable_defined
+ c = Class.new
+ c.class_eval { @@foo = :foo }
+ assert_equal(true, c.class_variable_defined?(:@@foo))
+ assert_equal(false, c.class_variable_defined?(:@@bar))
+ assert_raise(NameError) { c.class_variable_defined?(:foo) }
+ end
+
+ def test_export_method
+ m = Module.new
+ assert_raise(NameError) do
+ m.instance_eval { public(:foo) }
+ end
+ end
+
+ def test_attr
+ assert_in_out_err([], <<-INPUT, %w(:ok nil), /warning: private attribute\?$/)
+ $VERBOSE = true
+ c = Class.new
+ c.instance_eval do
+ private
+ attr_reader :foo
+ end
+ o = c.new
+ o.foo rescue p(:ok)
+ p(o.instance_eval { foo })
+ INPUT
+
+ c = Class.new
+ assert_raise(NameError) do
+ c.instance_eval { attr_reader :"$" }
+ end
+ end
+
+ def test_undef
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ Class.instance_eval { undef_method(:foo) }
+ end.join
+ end
+
+ c = Class.new
+ assert_raise(NameError) do
+ c.instance_eval { undef_method(:foo) }
+ end
+
+ m = Module.new
+ assert_raise(NameError) do
+ m.instance_eval { undef_method(:foo) }
+ end
+
+ o = Object.new
+ assert_raise(NameError) do
+ class << o; self; end.instance_eval { undef_method(:foo) }
+ end
+
+ %w(object_id __send__ initialize).each do |m|
+ assert_in_out_err([], <<-INPUT, [], /warning: undefining `#{m}' may cause serious problem$/)
+ $VERBOSE = false
+ Class.new.instance_eval { undef_method(:#{m}) }
+ INPUT
+ end
+ end
+
+ def test_alias
+ m = Module.new
+ assert_raise(NameError) do
+ m.class_eval { alias foo bar }
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(2), /warning: discarding old foo$/)
+ $VERBOSE = true
+ c = Class.new
+ c.class_eval do
+ def foo; 1; end
+ def bar; 2; end
+ end
+ c.class_eval { alias foo bar }
+ p c.new.foo
+ INPUT
+ end
+
+ def test_mod_constants
+ Module.const_set(:Foo, :foo)
+ assert_equal([:Foo], Module.constants(true))
+ assert_equal([:Foo], Module.constants(false))
+ Module.instance_eval { remove_const(:Foo) }
+ end
+
+ def test_frozen_class
+ m = Module.new
+ m.freeze
+ assert_raise(RuntimeError) do
+ m.instance_eval { undef_method(:foo) }
+ end
+
+ c = Class.new
+ c.freeze
+ assert_raise(RuntimeError) do
+ c.instance_eval { undef_method(:foo) }
+ end
+
+ o = Object.new
+ c = class << o; self; end
+ c.freeze
+ assert_raise(RuntimeError) do
+ c.instance_eval { undef_method(:foo) }
+ end
+ end
+
+ def test_method_defined
+ c = Class.new
+ c.class_eval do
+ def foo; end
+ def bar; end
+ def baz; end
+ public :foo
+ protected :bar
+ private :baz
+ end
+
+ assert_equal(true, c.public_method_defined?(:foo))
+ assert_equal(false, c.public_method_defined?(:bar))
+ assert_equal(false, c.public_method_defined?(:baz))
+
+ assert_equal(false, c.protected_method_defined?(:foo))
+ assert_equal(true, c.protected_method_defined?(:bar))
+ assert_equal(false, c.protected_method_defined?(:baz))
+
+ assert_equal(false, c.private_method_defined?(:foo))
+ assert_equal(false, c.private_method_defined?(:bar))
+ assert_equal(true, c.private_method_defined?(:baz))
+ end
+
+ def test_change_visibility_under_safe4
+ c = Class.new
+ c.class_eval do
+ def foo; end
+ end
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ c.class_eval { private :foo }
+ end.join
+ end
+ end
+
+ def test_top_public_private
+ assert_in_out_err([], <<-INPUT, %w([:foo] [:bar]), [])
+ private
+ def foo; :foo; end
+ public
+ def bar; :bar; end
+ p self.private_methods.grep(/^foo$|^bar$/)
+ p self.methods.grep(/^foo$|^bar$/)
+ INPUT
+ end
+
+ def test_append_features
+ t = nil
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:append_features) do |mod|
+ t = mod
+ super(mod)
+ end
+ end
+
+ m2 = Module.new
+ m2.module_eval { include(m) }
+ assert_equal(m2, t)
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(true, o.respond_to?(:foo))
+ end
+
+ def test_append_features_raise
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:append_features) {|mod| raise }
+ end
+
+ m2 = Module.new
+ assert_raise(RuntimeError) do
+ m2.module_eval { include(m) }
+ end
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(false, o.respond_to?(:foo))
+ end
+
+ def test_append_features_type_error
+ assert_raise(TypeError) do
+ Module.new.instance_eval { append_features(1) }
+ end
+ end
+
+ def test_included
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:included) {|mod| raise }
+ end
+
+ m2 = Module.new
+ assert_raise(RuntimeError) do
+ m2.module_eval { include(m) }
+ end
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(true, o.respond_to?(:foo))
+ end
+
+ def test_cyclic_include
+ m1 = Module.new
+ m2 = Module.new
+ m1.instance_eval { include(m2) }
+ assert_raise(ArgumentError) do
+ m2.instance_eval { include(m1) }
+ end
+ end
+
+ def test_include_p
+ m = Module.new
+ c1 = Class.new
+ c1.instance_eval { include(m) }
+ c2 = Class.new(c1)
+ assert_equal(true, c1.include?(m))
+ assert_equal(true, c2.include?(m))
+ assert_equal(false, m.include?(m))
+ end
+
+ def test_include_under_safe4
+ m = Module.new
+ c1 = Class.new
+ assert_raise(SecurityError) do
+ lambda {
+ $SAFE = 4
+ c1.instance_eval { include(m) }
+ }.call
+ end
+ assert_nothing_raised do
+ lambda {
+ $SAFE = 4
+ c2 = Class.new
+ c2.instance_eval { include(m) }
+ }.call
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_numeric.rb b/trunk/test/ruby/test_numeric.rb
new file mode 100644
index 0000000000..3db054fdae
--- /dev/null
+++ b/trunk/test/ruby/test_numeric.rb
@@ -0,0 +1,217 @@
+require 'test/unit'
+
+class TestNumeric < Test::Unit::TestCase
+ class DummyNumeric < Numeric
+ end
+
+ def test_coerce
+ a, b = 1.coerce(2)
+ assert_equal(Fixnum, a.class)
+ assert_equal(Fixnum, b.class)
+
+ a, b = 1.coerce(2.0)
+ assert_equal(Float, a.class)
+ assert_equal(Float, b.class)
+
+ assert_raise(TypeError) { -Numeric.new }
+ end
+
+ def test_dummynumeric
+ a = DummyNumeric.new
+
+ DummyNumeric.class_eval do
+ def coerce(x); nil; end
+ end
+ assert_raise(TypeError) { -a }
+ assert_nil(1 <=> a)
+ assert_raise(ArgumentError) { 1 <= a }
+
+ DummyNumeric.class_eval do
+ def coerce(x); 1.coerce(x); end
+ end
+ assert_equal(2, 1 + a)
+ assert_equal(0, 1 <=> a)
+ assert(1 <= a)
+
+ DummyNumeric.class_eval do
+ def coerce(x); [x, 1]; end
+ end
+ assert_equal(-1, -a)
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :coerce
+ end
+ end
+
+ def test_numeric
+ a = Numeric.new
+ assert_raise(TypeError) { def a.foo; end }
+ assert_raise(TypeError) { a.dup }
+ end
+
+ def test_quo
+ assert_raise(ArgumentError) {DummyNumeric.new.quo(1)}
+ end
+
+ def test_divmod
+ DummyNumeric.class_eval do
+ def /(x); 42.0; end
+ def %(x); :mod; end
+ end
+
+ assert_equal(42, DummyNumeric.new.div(1))
+ assert_equal(:mod, DummyNumeric.new.modulo(1))
+ assert_equal([42, :mod], DummyNumeric.new.divmod(1))
+
+ assert_kind_of(Integer, 11.divmod(3.5).first, '[ruby-dev:34006]')
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :/, :%
+ end
+ end
+
+ def test_scalar_p
+ assert(Numeric.new.scalar?)
+ end
+
+ def test_integer_p
+ assert(!Numeric.new.integer?)
+ end
+
+ def test_abs
+ a = DummyNumeric.new
+ DummyNumeric.class_eval do
+ def -@; :ok; end
+ def <(x); true; end
+ end
+
+ assert_equal(:ok, a.abs)
+
+ DummyNumeric.class_eval do
+ def <(x); false; end
+ end
+
+ assert_equal(a, a.abs)
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :-@, :<
+ end
+ end
+
+ def test_zero_p
+ DummyNumeric.class_eval do
+ def ==(x); true; end
+ end
+
+ assert(DummyNumeric.new.zero?)
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :==
+ end
+ end
+
+ def test_to_int
+ DummyNumeric.class_eval do
+ def to_i; :ok; end
+ end
+
+ assert_equal(:ok, DummyNumeric.new.to_int)
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :to_i
+ end
+ end
+
+ def test_cmp
+ a = Numeric.new
+ assert_equal(0, a <=> a)
+ assert_nil(a <=> :foo)
+ end
+
+ def test_floor_ceil_round_truncate
+ DummyNumeric.class_eval do
+ def to_f; 1.5; end
+ end
+
+ a = DummyNumeric.new
+ assert_equal(1, a.floor)
+ assert_equal(2, a.ceil)
+ assert_equal(2, a.round)
+ assert_equal(1, a.truncate)
+
+ DummyNumeric.class_eval do
+ def to_f; 1.4; end
+ end
+
+ a = DummyNumeric.new
+ assert_equal(1, a.floor)
+ assert_equal(2, a.ceil)
+ assert_equal(1, a.round)
+ assert_equal(1, a.truncate)
+
+ DummyNumeric.class_eval do
+ def to_f; -1.5; end
+ end
+
+ a = DummyNumeric.new
+ assert_equal(-2, a.floor)
+ assert_equal(-1, a.ceil)
+ assert_equal(-2, a.round)
+ assert_equal(-1, a.truncate)
+
+ ensure
+ DummyNumeric.class_eval do
+ remove_method :to_f
+ end
+ end
+
+ def test_step
+ a = []
+ 1.step(10) {|x| a << x }
+ assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)
+
+ a = []
+ 1.step(10, 2) {|x| a << x }
+ assert_equal([1, 3, 5, 7, 9], a)
+
+ assert_raise(ArgumentError) { 1.step(10, 1, 0) { } }
+ assert_raise(ArgumentError) { 1.step(10, 0) { } }
+
+ a = []
+ 10.step(1, -2) {|x| a << x }
+ assert_equal([10, 8, 6, 4, 2], a)
+
+ a = []
+ 1.0.step(10.0, 2.0) {|x| a << x }
+ assert_equal([1.0, 3.0, 5.0, 7.0, 9.0], a)
+
+ a = []
+ 1.step(10, 2**32) {|x| a << x }
+ assert_equal([1], a)
+
+ a = []
+ 10.step(1, -(2**32)) {|x| a << x }
+ assert_equal([10], a)
+ end
+
+ def test_num2long
+ assert_raise(TypeError) { 1 & nil }
+ assert_raise(TypeError) { 1 & 1.0 }
+ assert_raise(TypeError) { 1 & 2147483648.0 }
+ assert_raise(TypeError) { 1 & 9223372036854777856.0 }
+ o = Object.new
+ def o.to_int; 1; end
+ assert_equal(1, 1 & o)
+ end
+
+ def test_eql
+ assert(1 == 1.0)
+ assert(!(1.eql?(1.0)))
+ assert(!(1.eql?(2)))
+ end
+end
diff --git a/trunk/test/ruby/test_object.rb b/trunk/test/ruby/test_object.rb
new file mode 100644
index 0000000000..5190eb69e5
--- /dev/null
+++ b/trunk/test/ruby/test_object.rb
@@ -0,0 +1,401 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestObject < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_dup
+ assert_raise(TypeError) { 1.dup }
+ assert_raise(TypeError) { true.dup }
+ assert_raise(TypeError) { nil.dup }
+
+ assert_raise(TypeError) do
+ Object.new.instance_eval { initialize_copy(1) }
+ end
+ end
+
+ def test_instance_of
+ assert_raise(TypeError) { 1.instance_of?(1) }
+ end
+
+ def test_kind_of
+ assert_raise(TypeError) { 1.kind_of?(1) }
+ end
+
+ def test_taint_frozen_obj
+ o = Object.new
+ o.freeze
+ assert_raise(RuntimeError) { o.taint }
+
+ o = Object.new
+ o.taint
+ o.freeze
+ assert_raise(RuntimeError) { o.untaint }
+ end
+
+ def test_freeze_under_safe_4
+ o = Object.new
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ o.freeze
+ end.join
+ end
+ end
+
+ def test_freeze_immediate
+ assert_equal(false, 1.frozen?)
+ 1.freeze
+ assert_equal(true, 1.frozen?)
+ assert_equal(false, 2.frozen?)
+ end
+
+ def test_nil_to_f
+ assert_equal(0.0, nil.to_f)
+ end
+
+ def test_not
+ assert_equal(false, Object.new.send(:!))
+ assert_equal(true, nil.send(:!))
+ end
+
+ def test_true_and
+ assert_equal(true, true & true)
+ assert_equal(true, true & 1)
+ assert_equal(false, true & false)
+ assert_equal(false, true & nil)
+ end
+
+ def test_true_or
+ assert_equal(true, true | true)
+ assert_equal(true, true | 1)
+ assert_equal(true, true | false)
+ assert_equal(true, true | nil)
+ end
+
+ def test_true_xor
+ assert_equal(false, true ^ true)
+ assert_equal(false, true ^ 1)
+ assert_equal(true, true ^ false)
+ assert_equal(true, true ^ nil)
+ end
+
+ def test_false_and
+ assert_equal(false, false & true)
+ assert_equal(false, false & 1)
+ assert_equal(false, false & false)
+ assert_equal(false, false & nil)
+ end
+
+ def test_false_or
+ assert_equal(true, false | true)
+ assert_equal(true, false | 1)
+ assert_equal(false, false | false)
+ assert_equal(false, false | nil)
+ end
+
+ def test_false_xor
+ assert_equal(true, false ^ true)
+ assert_equal(true, false ^ 1)
+ assert_equal(false, false ^ false)
+ assert_equal(false, false ^ nil)
+ end
+
+ def test_methods
+ o = Object.new
+ a1 = o.methods
+ a2 = o.methods(false)
+
+ def o.foo; end
+
+ assert_equal([:foo], o.methods(true) - a1)
+ assert_equal([:foo], o.methods(false) - a2)
+ end
+
+ def test_methods2
+ c0 = Class.new
+ c1 = Class.new(c0)
+ c1.module_eval do
+ public ; def foo; end
+ protected; def bar; end
+ private ; def baz; end
+ end
+ c2 = Class.new(c1)
+ c2.module_eval do
+ public ; def foo2; end
+ protected; def bar2; end
+ private ; def baz2; end
+ end
+
+ o0 = c0.new
+ o2 = c2.new
+
+ assert_equal([:baz, :baz2], (o2.private_methods - o0.private_methods).sort)
+ assert_equal([:baz2], (o2.private_methods(false) - o0.private_methods(false)).sort)
+
+ assert_equal([:bar, :bar2], (o2.protected_methods - o0.protected_methods).sort)
+ assert_equal([:bar2], (o2.protected_methods(false) - o0.protected_methods(false)).sort)
+
+ assert_equal([:foo, :foo2], (o2.public_methods - o0.public_methods).sort)
+ assert_equal([:foo2], (o2.public_methods(false) - o0.public_methods(false)).sort)
+ end
+
+ def test_instance_variable_get
+ o = Object.new
+ o.instance_eval { @foo = :foo }
+ assert_equal(:foo, o.instance_variable_get(:@foo))
+ assert_equal(nil, o.instance_variable_get(:@bar))
+ assert_raise(NameError) { o.instance_variable_get(:foo) }
+ end
+
+ def test_instance_variable_set
+ o = Object.new
+ o.instance_variable_set(:@foo, :foo)
+ assert_equal(:foo, o.instance_eval { @foo })
+ assert_raise(NameError) { o.instance_variable_set(:foo, 1) }
+ end
+
+ def test_instance_variable_defined
+ o = Object.new
+ o.instance_eval { @foo = :foo }
+ assert_equal(true, o.instance_variable_defined?(:@foo))
+ assert_equal(false, o.instance_variable_defined?(:@bar))
+ assert_raise(NameError) { o.instance_variable_defined?(:foo) }
+ end
+
+ def test_convert_type
+ o = Object.new
+ def o.to_s; 1; end
+ assert_raise(TypeError) { String(o) }
+ end
+
+ def test_check_convert_type
+ o = Object.new
+ def o.to_a; 1; end
+ assert_raise(TypeError) { Array(o) }
+ end
+
+ def test_to_integer
+ o = Object.new
+ def o.to_i; nil; end
+ assert_raise(TypeError) { Integer(o) }
+ end
+
+ class MyInteger
+ def initialize(n); @num = n; end
+ def to_int; @num; end
+ def <=>(n); @num <=> n.to_int; end
+ def <=(n); @num <= n.to_int; end
+ def +(n); MyInteger.new(@num + n.to_int); end
+ end
+
+ def test_check_to_integer
+ o1 = MyInteger.new(1)
+ o9 = MyInteger.new(9)
+ n = 0
+ Range.new(o1, o9).step(2) {|x| n += x.to_int }
+ assert_equal(1+3+5+7+9, n)
+ end
+
+ def test_add_method_under_safe4
+ o = Object.new
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ def o.foo
+ end
+ end.join
+ end
+ end
+
+ def test_redefine_method_under_verbose
+ assert_in_out_err([], <<-INPUT, %w(2), /warning: method redefined; discarding old foo$/)
+ $VERBOSE = true
+ o = Object.new
+ def o.foo; 1; end
+ def o.foo; 2; end
+ p o.foo
+ INPUT
+ end
+
+ def test_redefine_method_which_may_case_serious_problem
+ assert_in_out_err([], <<-INPUT, [], /warning: redefining `object_id' may cause serious problem$/)
+ $VERBOSE = false
+ def (Object.new).object_id; end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, [], /warning: redefining `__send__' may cause serious problem$/)
+ $VERBOSE = false
+ def (Object.new).__send__; end
+ INPUT
+ end
+
+ def test_remove_method
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ Object.instance_eval { remove_method(:foo) }
+ end.join
+ end
+
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ Class.instance_eval { remove_method(:foo) }
+ end.join
+ end
+
+ c = Class.new
+ c.freeze
+ assert_raise(RuntimeError) do
+ c.instance_eval { remove_method(:foo) }
+ end
+
+ %w(object_id __send__ initialize).each do |m|
+ assert_in_out_err([], <<-INPUT, %w(:ok), /warning: removing `#{m}' may cause serious problem$/)
+ $VERBOSE = false
+ begin
+ Class.new.instance_eval { remove_method(:#{m}) }
+ rescue NameError
+ p :ok
+ end
+ INPUT
+ end
+ end
+
+ def test_method_missing
+ assert_raise(ArgumentError) do
+ 1.instance_eval { method_missing }
+ end
+
+ c = Class.new
+ c.class_eval do
+ protected
+ def foo; end
+ end
+ assert_raise(NoMethodError) do
+ c.new.foo
+ end
+
+ assert_raise(NoMethodError) do
+ 1.instance_eval { method_missing(:method_missing) }
+ end
+ end
+
+ def test_send_with_no_arguments
+ assert_raise(ArgumentError) { 1.send }
+ end
+
+ def test_specific_eval_with_wrong_arguments
+ assert_raise(ArgumentError) do
+ 1.instance_eval("foo") { foo }
+ end
+
+ assert_raise(ArgumentError) do
+ 1.instance_eval
+ end
+
+ assert_raise(ArgumentError) do
+ 1.instance_eval("", 1, 1, 1)
+ end
+ end
+
+ def test_instance_exec
+ x = 1.instance_exec(42) {|a| self + a }
+ assert_equal(43, x)
+
+ x = "foo".instance_exec("bar") {|a| self + a }
+ assert_equal("foobar", x)
+ end
+
+ def test_extend
+ assert_raise(ArgumentError) do
+ 1.extend
+ end
+ end
+
+ def test_untrusted
+ obj = lambda {
+ $SAFE = 4
+ x = Object.new
+ x.instance_eval { @foo = 1 }
+ x
+ }.call
+ assert_equal(true, obj.untrusted?)
+ assert_equal(true, obj.tainted?)
+
+ x = Object.new
+ assert_equal(false, x.untrusted?)
+ assert_raise(SecurityError) do
+ lambda {
+ $SAFE = 4
+ x.instance_eval { @foo = 1 }
+ }.call
+ end
+
+ x = Object.new
+ x.taint
+ assert_raise(SecurityError) do
+ lambda {
+ $SAFE = 4
+ x.instance_eval { @foo = 1 }
+ }.call
+ end
+
+ x.untrust
+ assert_equal(true, x.untrusted?)
+ assert_nothing_raised do
+ lambda {
+ $SAFE = 4
+ x.instance_eval { @foo = 1 }
+ }.call
+ end
+
+ x.trust
+ assert_equal(false, x.untrusted?)
+ assert_raise(SecurityError) do
+ lambda {
+ $SAFE = 4
+ x.instance_eval { @foo = 1 }
+ }.call
+ end
+
+ a = Object.new
+ a.untrust
+ assert_equal(true, a.untrusted?)
+ b = a.dup
+ assert_equal(true, b.untrusted?)
+ c = a.clone
+ assert_equal(true, c.untrusted?)
+
+ a = Object.new
+ b = lambda {
+ $SAFE = 4
+ a.dup
+ }.call
+ assert_equal(true, b.untrusted?)
+
+ a = Object.new
+ b = lambda {
+ $SAFE = 4
+ a.clone
+ }.call
+ assert_equal(true, b.untrusted?)
+ end
+
+ def test_to_s
+ x = Object.new
+ x.taint
+ x.untrust
+ s = x.to_s
+ assert_equal(true, s.untrusted?)
+ assert_equal(true, s.tainted?)
+ end
+end
diff --git a/trunk/test/ruby/test_objectspace.rb b/trunk/test/ruby/test_objectspace.rb
new file mode 100644
index 0000000000..571c725986
--- /dev/null
+++ b/trunk/test/ruby/test_objectspace.rb
@@ -0,0 +1,67 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestObjectSpace < Test::Unit::TestCase
+ def self.deftest_id2ref(obj)
+ /:(\d+)/ =~ caller[0]
+ file = $`
+ line = $1.to_i
+ code = <<"End"
+ define_method("test_id2ref_#{line}") {\
+ o = ObjectSpace._id2ref(obj.object_id);\
+ assert_same(obj, o, "didn't round trip: \#{obj.inspect}");\
+ }
+End
+ eval code, binding, file, line
+ end
+
+ deftest_id2ref(-0x4000000000000001)
+ deftest_id2ref(-0x4000000000000000)
+ deftest_id2ref(-0x40000001)
+ deftest_id2ref(-0x40000000)
+ deftest_id2ref(-1)
+ deftest_id2ref(0)
+ deftest_id2ref(1)
+ deftest_id2ref(0x3fffffff)
+ deftest_id2ref(0x40000000)
+ deftest_id2ref(0x3fffffffffffffff)
+ deftest_id2ref(0x4000000000000000)
+ deftest_id2ref(:a)
+ deftest_id2ref(:abcdefghijilkjl)
+ deftest_id2ref(:==)
+ deftest_id2ref(Object.new)
+ deftest_id2ref(self)
+ deftest_id2ref(true)
+ deftest_id2ref(false)
+ deftest_id2ref(nil)
+
+ def test_count_objects
+ h = {}
+ ObjectSpace.count_objects(h)
+ assert_kind_of(Hash, h)
+ assert(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) })
+ assert(h.values.all? {|x| x.is_a?(Integer) })
+
+ h = ObjectSpace.count_objects
+ assert_kind_of(Hash, h)
+ assert(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) })
+ assert(h.values.all? {|x| x.is_a?(Integer) })
+
+ assert_raise(TypeError) { ObjectSpace.count_objects(1) }
+
+ h0 = {:T_FOO=>1000}
+ h = ObjectSpace.count_objects(h0)
+ assert_same(h0, h)
+ assert_equal(0, h0[:T_FOO])
+ end
+
+ def test_finalizer
+ assert_in_out_err(["-e", <<-END], "", %w(:ok :ok :ok :ok), [])
+ a = []
+ ObjectSpace.define_finalizer(a) { p :ok }
+ b = a.dup
+ ObjectSpace.define_finalizer(a) { p :ok }
+ END
+ assert_raise(ArgumentError) { ObjectSpace.define_finalizer([], Object.new) }
+ end
+end
diff --git a/trunk/test/ruby/test_optimization.rb b/trunk/test/ruby/test_optimization.rb
new file mode 100644
index 0000000000..8e8311e6ef
--- /dev/null
+++ b/trunk/test/ruby/test_optimization.rb
@@ -0,0 +1,140 @@
+require 'test/unit'
+
+class TestRubyOptimization < Test::Unit::TestCase
+
+ BIGNUM_POS_MIN_32 = 1073741824 # 2 ** 30
+ if BIGNUM_POS_MIN_32.kind_of?(Fixnum)
+ FIXNUM_MAX = 4611686018427387903 # 2 ** 62 - 1
+ else
+ FIXNUM_MAX = 1073741823 # 2 ** 30 - 1
+ end
+
+ BIGNUM_NEG_MAX_32 = -1073741825 # -2 ** 30 - 1
+ if BIGNUM_NEG_MAX_32.kind_of?(Fixnum)
+ FIXNUM_MIN = -4611686018427387904 # -2 ** 62
+ else
+ FIXNUM_MIN = -1073741824 # -2 ** 30
+ end
+
+ def redefine_method(klass, method)
+ (@redefine_method_seq ||= 0)
+ seq = (@redefine_method_seq += 1)
+ eval(<<-End, ::TOPLEVEL_BINDING)
+ class #{klass}
+ alias redefine_method_orig_#{seq} #{method}
+ undef #{method}
+ def #{method}(*args)
+ args[0]
+ end
+ end
+ End
+ begin
+ return yield
+ ensure
+ eval(<<-End, ::TOPLEVEL_BINDING)
+ class #{klass}
+ undef #{method}
+ alias #{method} redefine_method_orig_#{seq}
+ end
+ End
+ end
+ end
+
+ def test_fixnum_plus
+ a, b = 1, 2
+ assert_equal 3, a + b
+ assert_instance_of Fixnum, FIXNUM_MAX
+ assert_instance_of Bignum, FIXNUM_MAX + 1
+
+ assert_equal 21, 10 + 11
+ assert_equal 11, redefine_method('Fixnum', '+') { 10 + 11 }
+ assert_equal 21, 10 + 11
+ end
+
+ def test_fixnum_minus
+ assert_equal 5, 8 - 3
+ assert_instance_of Fixnum, FIXNUM_MIN
+ assert_instance_of Bignum, FIXNUM_MIN - 1
+
+ assert_equal 5, 8 - 3
+ assert_equal 3, redefine_method('Fixnum', '-') { 8 - 3 }
+ assert_equal 5, 8 - 3
+ end
+
+ def test_fixnum_mul
+ assert_equal 15, 3 * 5
+ end
+
+ def test_fixnum_div
+ assert_equal 3, 15 / 5
+ end
+
+ def test_fixnum_mod
+ assert_equal 1, 8 % 7
+ end
+
+ def test_float_plus
+ assert_equal 4.0, 2.0 + 2.0
+ assert_equal 2.0, redefine_method('Float', '+') { 2.0 + 2.0 }
+ assert_equal 4.0, 2.0 + 2.0
+ end
+
+ def test_string_length
+ assert_equal 6, "string".length
+ assert_nil redefine_method('String', 'length') { "string".length }
+ assert_equal 6, "string".length
+ end
+
+ def test_string_plus
+ assert_equal "", "" + ""
+ assert_equal "x", "x" + ""
+ assert_equal "x", "" + "x"
+ assert_equal "ab", "a" + "b"
+ assert_equal 'b', redefine_method('String', '+') { "a" + "b" }
+ assert_equal "ab", "a" + "b"
+ end
+
+ def test_string_succ
+ assert_equal 'b', 'a'.succ
+ assert_equal 'B', 'A'.succ
+ end
+
+ def test_string_format
+ assert_equal '2', '%d' % 2
+ end
+
+ def test_array_plus
+ assert_equal [1,2], [1]+[2]
+ end
+
+ def test_array_minus
+ assert_equal [2], [1,2] - [1]
+ end
+
+ def test_array_length
+ assert_equal 0, [].length
+ assert_equal 3, [1,2,3].length
+ end
+
+ def test_hash_length
+ assert_equal 0, {}.length
+ assert_equal 1, {1=>1}.length
+ end
+
+ class MyObj
+ def ==(other)
+ true
+ end
+ end
+
+ def test_eq
+ assert_equal true, nil == nil
+ assert_equal true, 1 == 1
+ assert_equal true, 'string' == 'string'
+ assert_equal true, 1 == MyObj.new
+ assert_equal false, nil == MyObj.new
+ assert_equal true, MyObj.new == 1
+ assert_equal true, MyObj.new == nil
+ end
+
+end
diff --git a/trunk/test/ruby/test_pack.rb b/trunk/test/ruby/test_pack.rb
new file mode 100644
index 0000000000..30ffe13426
--- /dev/null
+++ b/trunk/test/ruby/test_pack.rb
@@ -0,0 +1,448 @@
+require 'test/unit'
+
+class TestPack < Test::Unit::TestCase
+ def test_pack
+ $format = "c2x5CCxsdils_l_a6";
+ # Need the expression in here to force ary[5] to be numeric. This avoids
+ # test2 failing because ary2 goes str->numeric->str and ary does not.
+ ary = [1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,-32767,-123456,"abcdef"]
+ $x = ary.pack($format)
+ ary2 = $x.unpack($format)
+
+ assert_equal(ary.length, ary2.length)
+ assert_equal(ary.join(':'), ary2.join(':'))
+ assert_match(/def/, $x)
+
+ $x = [-1073741825]
+ assert_equal($x, $x.pack("q").unpack("q"))
+
+ $x = [-1]
+ assert_equal($x, $x.pack("l").unpack("l"))
+ end
+
+ def test_pack_N
+ assert_equal "\000\000\000\000", [0].pack('N')
+ assert_equal "\000\000\000\001", [1].pack('N')
+ assert_equal "\000\000\000\002", [2].pack('N')
+ assert_equal "\000\000\000\003", [3].pack('N')
+ assert_equal "\377\377\377\376", [4294967294].pack('N')
+ assert_equal "\377\377\377\377", [4294967295].pack('N')
+
+ assert_equal "\200\000\000\000", [2**31].pack('N')
+ assert_equal "\177\377\377\377", [-2**31-1].pack('N')
+ assert_equal "\377\377\377\377", [-1].pack('N')
+
+ assert_equal "\000\000\000\001\000\000\000\001", [1,1].pack('N*')
+ assert_equal "\000\000\000\001\000\000\000\001\000\000\000\001", [1,1,1].pack('N*')
+ end
+
+ def test_unpack_N
+ assert_equal 1, "\000\000\000\001".unpack('N')[0]
+ assert_equal 2, "\000\000\000\002".unpack('N')[0]
+ assert_equal 3, "\000\000\000\003".unpack('N')[0]
+ assert_equal 3, "\000\000\000\003".unpack('N')[0]
+ assert_equal 4294967295, "\377\377\377\377".unpack('N')[0]
+ assert_equal [1,1], "\000\000\000\001\000\000\000\001".unpack('N*')
+ assert_equal [1,1,1], "\000\000\000\001\000\000\000\001\000\000\000\001".unpack('N*')
+ end
+
+ def test_pack_U
+ assert_raises(RangeError) { [-0x40000001].pack("U") }
+ assert_raises(RangeError) { [-0x40000000].pack("U") }
+ assert_raises(RangeError) { [-1].pack("U") }
+ assert_equal "\000", [0].pack("U")
+ assert_equal "\374\277\277\277\277\277", [0x3fffffff].pack("U")
+ assert_equal "\375\200\200\200\200\200", [0x40000000].pack("U")
+ assert_equal "\375\277\277\277\277\277", [0x7fffffff].pack("U")
+ assert_raises(RangeError) { [0x80000000].pack("U") }
+ assert_raises(RangeError) { [0x100000000].pack("U") }
+ end
+
+ def test_pack_P
+ a = ["abc"]
+ assert_equal a, a.pack("P").unpack("P*")
+ assert_equal "a", a.pack("P").unpack("P")[0]
+ assert_equal a, a.pack("P").freeze.unpack("P*")
+ assert_raise(ArgumentError) { (a.pack("P") + "").unpack("P*") }
+ end
+
+ def test_pack_p
+ a = ["abc"]
+ assert_equal a, a.pack("p").unpack("p*")
+ assert_equal a[0], a.pack("p").unpack("p")[0]
+ assert_equal a, a.pack("p").freeze.unpack("p*")
+ assert_raise(ArgumentError) { (a.pack("p") + "").unpack("p*") }
+ end
+
+ def test_format_string_modified
+ fmt = "CC"
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:to_int) { fmt.clear; 0 }
+ end
+ assert_raise(RuntimeError) do
+ [o, o].pack(fmt)
+ end
+ end
+
+ def test_comment
+ assert_equal("\0\1", [0,1].pack(" C #foo \n C "))
+ assert_equal([0,1], "\0\1".unpack(" C #foo \n C "))
+ end
+
+ def test_illegal_bang
+ assert_raise(ArgumentError) { [].pack("a!") }
+ assert_raise(ArgumentError) { "".unpack("a!") }
+ end
+
+ def test_pack_unpack_aA
+ assert_equal("f", ["foo"].pack("A"))
+ assert_equal("f", ["foo"].pack("a"))
+ assert_equal("foo", ["foo"].pack("A*"))
+ assert_equal("foo", ["foo"].pack("a*"))
+ assert_equal("fo", ["foo"].pack("A2"))
+ assert_equal("fo", ["foo"].pack("a2"))
+ assert_equal("foo ", ["foo"].pack("A4"))
+ assert_equal("foo\0", ["foo"].pack("a4"))
+ assert_equal(" ", [nil].pack("A"))
+ assert_equal("\0", [nil].pack("a"))
+ assert_equal("", [nil].pack("A*"))
+ assert_equal("", [nil].pack("a*"))
+ assert_equal(" ", [nil].pack("A2"))
+ assert_equal("\0\0", [nil].pack("a2"))
+
+ assert_equal("foo" + "\0" * 27, ["foo"].pack("a30"))
+
+ assert_equal(["f"], "foo\0".unpack("A"))
+ assert_equal(["f"], "foo\0".unpack("a"))
+ assert_equal(["foo"], "foo\0".unpack("A4"))
+ assert_equal(["foo\0"], "foo\0".unpack("a4"))
+ assert_equal(["foo"], "foo ".unpack("A4"))
+ assert_equal(["foo "], "foo ".unpack("a4"))
+ assert_equal(["foo"], "foo".unpack("A4"))
+ assert_equal(["foo"], "foo".unpack("a4"))
+ end
+
+ def test_pack_unpack_Z
+ assert_equal("f", ["foo"].pack("Z"))
+ assert_equal("foo\0", ["foo"].pack("Z*"))
+ assert_equal("fo", ["foo"].pack("Z2"))
+ assert_equal("foo\0\0", ["foo"].pack("Z5"))
+ assert_equal("\0", [nil].pack("Z"))
+ assert_equal("\0", [nil].pack("Z*"))
+ assert_equal("\0\0", [nil].pack("Z2"))
+
+ assert_equal(["f"], "foo\0".unpack("Z"))
+ assert_equal(["foo"], "foo".unpack("Z*"))
+ assert_equal(["foo"], "foo\0".unpack("Z*"))
+ assert_equal(["foo"], "foo".unpack("Z5"))
+ end
+
+ def test_pack_unpack_bB
+ assert_equal("\xff\x00", ["1111111100000000"].pack("b*"))
+ assert_equal("\x01\x02", ["1000000001000000"].pack("b*"))
+ assert_equal("", ["1"].pack("b0"))
+ assert_equal("\x01", ["1"].pack("b1"))
+ assert_equal("\x01\x00", ["1"].pack("b2"))
+ assert_equal("\x01\x00", ["1"].pack("b3"))
+ assert_equal("\x01\x00\x00", ["1"].pack("b4"))
+ assert_equal("\x01\x00\x00", ["1"].pack("b5"))
+ assert_equal("\x01\x00\x00\x00", ["1"].pack("b6"))
+
+ assert_equal("\xff\x00", ["1111111100000000"].pack("B*"))
+ assert_equal("\x01\x02", ["0000000100000010"].pack("B*"))
+ assert_equal("", ["1"].pack("B0"))
+ assert_equal("\x80", ["1"].pack("B1"))
+ assert_equal("\x80\x00", ["1"].pack("B2"))
+ assert_equal("\x80\x00", ["1"].pack("B3"))
+ assert_equal("\x80\x00\x00", ["1"].pack("B4"))
+ assert_equal("\x80\x00\x00", ["1"].pack("B5"))
+ assert_equal("\x80\x00\x00\x00", ["1"].pack("B6"))
+
+ assert_equal(["1111111100000000"], "\xff\x00".unpack("b*"))
+ assert_equal(["1000000001000000"], "\x01\x02".unpack("b*"))
+ assert_equal([""], "".unpack("b0"))
+ assert_equal(["1"], "\x01".unpack("b1"))
+ assert_equal(["10"], "\x01".unpack("b2"))
+ assert_equal(["100"], "\x01".unpack("b3"))
+
+ assert_equal(["1111111100000000"], "\xff\x00".unpack("B*"))
+ assert_equal(["0000000100000010"], "\x01\x02".unpack("B*"))
+ assert_equal([""], "".unpack("B0"))
+ assert_equal(["1"], "\x80".unpack("B1"))
+ assert_equal(["10"], "\x80".unpack("B2"))
+ assert_equal(["100"], "\x80".unpack("B3"))
+ end
+
+ def test_pack_unpack_hH
+ assert_equal("\x01\xfe", ["10ef"].pack("h*"))
+ assert_equal("", ["10ef"].pack("h0"))
+ assert_equal("\x01\x0e", ["10ef"].pack("h3"))
+ assert_equal("\x01\xfe\x0", ["10ef"].pack("h5"))
+
+ assert_equal("\x10\xef", ["10ef"].pack("H*"))
+ assert_equal("", ["10ef"].pack("H0"))
+ assert_equal("\x10\xe0", ["10ef"].pack("H3"))
+ assert_equal("\x10\xef\x0", ["10ef"].pack("H5"))
+
+ assert_equal(["10ef"], "\x01\xfe".unpack("h*"))
+ assert_equal([""], "\x01\xfe".unpack("h0"))
+ assert_equal(["1"], "\x01\xfe".unpack("h1"))
+ assert_equal(["10"], "\x01\xfe".unpack("h2"))
+ assert_equal(["10e"], "\x01\xfe".unpack("h3"))
+ assert_equal(["10ef"], "\x01\xfe".unpack("h4"))
+ assert_equal(["10ef"], "\x01\xfe".unpack("h5"))
+
+ assert_equal(["10ef"], "\x10\xef".unpack("H*"))
+ assert_equal([""], "\x10\xef".unpack("H0"))
+ assert_equal(["1"], "\x10\xef".unpack("H1"))
+ assert_equal(["10"], "\x10\xef".unpack("H2"))
+ assert_equal(["10e"], "\x10\xef".unpack("H3"))
+ assert_equal(["10ef"], "\x10\xef".unpack("H4"))
+ assert_equal(["10ef"], "\x10\xef".unpack("H5"))
+ end
+
+ def test_pack_unpack_cC
+ assert_equal("\0\1\xff", [0, 1, 255].pack("c*"))
+ assert_equal("\0\1\xff", [0, 1, -1].pack("c*"))
+
+ assert_equal("\0\1\xff", [0, 1, 255].pack("C*"))
+ assert_equal("\0\1\xff", [0, 1, -1].pack("C*"))
+
+ assert_equal([0, 1, -1], "\0\1\xff".unpack("c*"))
+
+ assert_equal([0, 1, 255], "\0\1\xff".unpack("C*"))
+ end
+
+ def test_pack_unpack_sS
+ s1 = [513, -514].pack("s*")
+ s2 = [513, 65022].pack("S*")
+ assert_equal(s1, s2)
+ assert_equal([513, -514], s2.unpack("s*"))
+ assert_equal([513, 65022], s1.unpack("S*"))
+
+ s1 = [513, -514].pack("s!*")
+ s2 = [513, 65022].pack("S!*")
+ assert_equal(s1, s2)
+ assert_equal([513, -514], s2.unpack("s!*"))
+ assert_equal([513, 65022], s1.unpack("S!*"))
+ end
+
+ def test_pack_unpack_iI
+ s1 = [67305985, -50462977].pack("i*")
+ s2 = [67305985, 4244504319].pack("I*")
+ assert_equal(s1, s2)
+ assert_equal([67305985, -50462977], s2.unpack("i*"))
+ assert_equal([67305985, 4244504319], s1.unpack("I*"))
+
+ s1 = [67305985, -50462977].pack("i!*")
+ s2 = [67305985, 4244504319].pack("I!*")
+ assert_equal([67305985, -50462977], s1.unpack("i!*"))
+ assert_equal([67305985, 4244504319], s2.unpack("I!*"))
+ end
+
+ def test_pack_unpack_lL
+ s1 = [67305985, -50462977].pack("l*")
+ s2 = [67305985, 4244504319].pack("L*")
+ assert_equal(s1, s2)
+ assert_equal([67305985, -50462977], s2.unpack("l*"))
+ assert_equal([67305985, 4244504319], s1.unpack("L*"))
+
+ s1 = [67305985, -50462977].pack("l!*")
+ s2 = [67305985, 4244504319].pack("L!*")
+ assert_equal([67305985, -50462977], s1.unpack("l!*"))
+ assert_equal([67305985, 4244504319], s2.unpack("L!*"))
+ end
+
+ def test_pack_unpack_qQ
+ s1 = [578437695752307201, -506097522914230529].pack("q*")
+ s2 = [578437695752307201, 17940646550795321087].pack("Q*")
+ assert_equal(s1, s2)
+ assert_equal([578437695752307201, -506097522914230529], s2.unpack("q*"))
+ assert_equal([578437695752307201, 17940646550795321087], s1.unpack("Q*"))
+ end
+
+ def test_pack_unpack_nN
+ assert_equal("\000\000\000\001\377\377\177\377\200\000\377\377", [0,1,-1,32767,-32768,65535].pack("n*"))
+ assert_equal("\000\000\000\000\000\000\000\001\377\377\377\377", [0,1,-1].pack("N*"))
+
+ assert_equal([0,1,65535,32767,32768,65535], "\000\000\000\001\377\377\177\377\200\000\377\377".unpack("n*"))
+ assert_equal([0,1,4294967295], "\000\000\000\000\000\000\000\001\377\377\377\377".unpack("N*"))
+ end
+
+ def test_pack_unpack_vV
+ assert_equal("\000\000\001\000\377\377\377\177\000\200\377\377", [0,1,-1,32767,-32768,65535].pack("v*"))
+ assert_equal("\000\000\000\000\001\000\000\000\377\377\377\377", [0,1,-1].pack("V*"))
+
+ assert_equal([0,1,65535,32767,32768,65535], "\000\000\001\000\377\377\377\177\000\200\377\377".unpack("v*"))
+ assert_equal([0,1,4294967295], "\000\000\000\000\001\000\000\000\377\377\377\377".unpack("V*"))
+ end
+
+ def test_pack_unpack_fdeEgG
+ inf = 1.0/0.0
+ nan = inf/inf
+ [0.0, 1.0, 3.0, inf, -inf, nan].each do |x|
+ %w(f d e E g G).each do |f|
+ v = [x].pack(f).unpack(f)
+ if x.nan?
+ assert(v.first.nan?)
+ else
+ assert_equal([x], v)
+ end
+ end
+ end
+ end
+
+ def test_pack_unpack_x
+ assert_equal("", [].pack("x0"))
+ assert_equal("\0", [].pack("x"))
+ assert_equal("\0" * 30, [].pack("x30"))
+
+ assert_equal([0, 2], "\x00\x00\x02".unpack("CxC"))
+ assert_raise(ArgumentError) { "".unpack("x") }
+ end
+
+ def test_pack_unpack_X
+ assert_equal("\x00\x02", [0, 1, 2].pack("CCXC"))
+ assert_equal("\x02", [0, 1, 2].pack("CCX2C"))
+ assert_raise(ArgumentError) { [].pack("X") }
+
+ assert_equal([0, 2, 2], "\x00\x02".unpack("CCXC"))
+ assert_raise(ArgumentError) { "".unpack("X") }
+ end
+
+ def test_pack_unpack_atmark
+ assert_equal("\x01\x00\x00\x02", [1, 2].pack("C@3C"))
+ assert_equal("\x02", [1, 2].pack("C@0C"))
+ assert_equal("\x01\x02", [1, 2].pack("C@1C"))
+
+ assert_equal([1, 2], "\x01\x00\x00\x02".unpack("C@3C"))
+ assert_equal([nil], "\x00".unpack("@1C")) # is it OK?
+ assert_raise(ArgumentError) { "\x00".unpack("@2C") }
+ end
+
+ def test_pack_unpack_percent
+ assert_raise(ArgumentError) { [].pack("%") }
+ assert_raise(ArgumentError) { "".unpack("%") }
+ end
+
+ def test_pack_unpack_U
+ assert_equal([0], [0].pack("U").unpack("U"))
+ assert_equal([0x80], [0x80].pack("U").unpack("U"))
+ assert_equal([0x800], [0x800].pack("U").unpack("U"))
+ assert_equal([0x10000], [0x10000].pack("U").unpack("U"))
+ assert_equal([0x400000], [0x400000].pack("U").unpack("U"))
+
+ assert_raise(ArgumentError) { "\x80".unpack("U") }
+ assert_raise(ArgumentError) { "\xff".unpack("U") }
+ assert_raise(ArgumentError) { "\xfc\x00".unpack("U") }
+ assert_raise(ArgumentError) { "\xc0\xc0".unpack("U") }
+ assert_raise(ArgumentError) { "\xe0\x80\x80".unpack("U") }
+ end
+
+ def test_pack_unpack_u
+ assert_equal("", [""].pack("u"))
+ assert_equal("!80``\n", ["a"].pack("u"))
+ assert_equal("#86)C\n", ["abc"].pack("u"))
+ assert_equal("$86)C9```\n", ["abcd"].pack("u"))
+ assert_equal("M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n", ["a"*45].pack("u"))
+ assert_equal("M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n!80``\n", ["a"*46].pack("u"))
+ assert_equal("&86)C9&5F\n#9VAI\n", ["abcdefghi"].pack("u6"))
+
+ assert_equal([""], "".unpack("u"))
+ assert_equal(["a"], "!80``\n".unpack("u"))
+ assert_equal(["abc"], "#86)C\n".unpack("u"))
+ assert_equal(["abcd"], "$86)C9```\n".unpack("u"))
+ assert_equal(["a"*45], "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n".unpack("u"))
+ assert_equal(["a"*46], "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n!80``\n".unpack("u"))
+ assert_equal(["abcdefghi"], "&86)C9&5F\n#9VAI\n".unpack("u"))
+
+ assert_equal(["\x00"], "\"\n".unpack("u"))
+ assert_equal(["\x00"], "! \r \n".unpack("u"))
+ end
+
+ def test_pack_unpack_m
+ assert_equal("", [""].pack("m"))
+ assert_equal("AA==\n", ["\0"].pack("m"))
+ assert_equal("AAA=\n", ["\0\0"].pack("m"))
+ assert_equal("AAAA\n", ["\0\0\0"].pack("m"))
+ assert_equal("/w==\n", ["\377"].pack("m"))
+ assert_equal("//8=\n", ["\377\377"].pack("m"))
+ assert_equal("////\n", ["\377\377\377"].pack("m"))
+
+ assert_equal([""], "".unpack("m"))
+ assert_equal(["\0"], "AA==\n".unpack("m"))
+ assert_equal(["\0\0"], "AAA=\n".unpack("m"))
+ assert_equal(["\0\0\0"], "AAAA\n".unpack("m"))
+ assert_equal(["\377"], "/w==\n".unpack("m"))
+ assert_equal(["\377\377"], "//8=\n".unpack("m"))
+ assert_equal(["\377\377\377"], "////\n".unpack("m"))
+ end
+
+ def test_pack_unpack_M
+ assert_equal("a b c\td =\n\ne=\n", ["a b c\td \ne"].pack("M"))
+ assert_equal(["a b c\td \ne"], "a b c\td =\n\ne=\n".unpack("M"))
+ assert_equal("=00=\n", ["\0"].pack("M"))
+ assert_equal("a"*73+"=\na=\n", ["a"*74].pack("M"))
+ assert_equal(("a"*73+"=\n")*14+"a=\n", ["a"*1023].pack("M"))
+ assert_equal(["\0"], "=00=\n".unpack("M"))
+ assert_equal(["a"*74], ("a"*73+"=\na=\n").unpack("M"))
+ assert_equal(["a"*1023], (("a"*73+"=\n")*14+"a=\n").unpack("M"))
+ assert_equal(["\x0a"], "=0a=\n".unpack("M"))
+ assert_equal(["\x0a"], "=0A=\n".unpack("M"))
+ assert_equal([""], "=0Z=\n".unpack("M"))
+ assert_equal([""], "=\r\n".unpack("M"))
+ end
+
+ def test_pack_unpack_P2
+ assert_raise(ArgumentError) { ["abc"].pack("P4") }
+ assert_raise(ArgumentError) { [""].pack("P") }
+
+ assert_equal([], ".".unpack("P"))
+ assert_equal([], ".".unpack("p"))
+ assert_equal([nil], ("\0" * 1024).unpack("P"))
+ end
+
+ def test_pack_p2
+ assert([nil].pack("p") =~ /\A\0*\Z/)
+ end
+
+ def test_pack_unpack_w
+ assert_equal("\000", [0].pack("w"))
+ assert_equal("\001", [1].pack("w"))
+ assert_equal("\177", [127].pack("w"))
+ assert_equal("\201\000", [128].pack("w"))
+ assert_equal("\377\177", [0x3fff].pack("w"))
+ assert_equal("\201\200\000", [0x4000].pack("w"))
+ assert_equal("\203\377\377\377\177", [0x3fffffff].pack("w"))
+ assert_equal("\204\200\200\200\000", [0x40000000].pack("w"))
+ assert_equal("\217\377\377\377\177", [0xffffffff].pack("w"))
+ assert_equal("\220\200\200\200\000", [0x100000000].pack("w"))
+ assert_raise(ArgumentError) { [-1].pack("w") }
+
+ assert_equal([0], "\000".unpack("w"))
+ assert_equal([1], "\001".unpack("w"), [1])
+ assert_equal([127], "\177".unpack("w"), [127])
+ assert_equal([128], "\201\000".unpack("w"), [128])
+ assert_equal([0x3fff], "\377\177".unpack("w"), [0x3fff])
+ assert_equal([0x4000], "\201\200\000".unpack("w"), [0x4000])
+ assert_equal([0x3fffffff], "\203\377\377\377\177".unpack("w"), [0x3fffffff])
+ assert_equal([0x40000000], "\204\200\200\200\000".unpack("w"), [0x40000000])
+ assert_equal([0xffffffff], "\217\377\377\377\177".unpack("w"), [0xffffffff])
+ assert_equal([0x100000000], "\220\200\200\200\000".unpack("w"), [0x100000000])
+ end
+
+ def test_modify_under_safe4
+ s = "foo"
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ s.clear
+ end.join
+ end
+ end
+
+ def test_length_too_big
+ assert_raise(RangeError) { [].pack("C100000000000000000000") }
+ end
+end
diff --git a/trunk/test/ruby/test_parse.rb b/trunk/test/ruby/test_parse.rb
new file mode 100644
index 0000000000..e372ff6367
--- /dev/null
+++ b/trunk/test/ruby/test_parse.rb
@@ -0,0 +1,826 @@
+require 'test/unit'
+require 'stringio'
+
+class TestParse < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_else_without_rescue
+ x = eval <<-END
+ begin
+ else
+ 42
+ end
+ END
+ assert_equal(42, x)
+ end
+
+ def test_alias_backref
+ assert_raise(SyntaxError) do
+ eval <<-END
+ alias $foo $1
+ END
+ end
+ end
+
+ def test_command_call
+ t = Object.new
+ def t.foo(x); x; end
+
+ a = false
+ b = c = d = true
+ assert_nothing_raised do
+ eval <<-END
+ a &&= t.foo 42
+ b &&= t.foo 42
+ c &&= t.foo nil
+ d &&= t.foo false
+ END
+ end
+ assert_equal([false, 42, nil, false], [a, b, c, d])
+
+ a = 3
+ assert_nothing_raised { eval("a &= t.foo 5") }
+ assert_equal(1, a)
+
+ a = [nil, nil, true, true]
+ assert_nothing_raised do
+ eval <<-END
+ a[0] ||= t.foo 42
+ a[1] &&= t.foo 42
+ a[2] ||= t.foo 42
+ a[3] &&= t.foo 42
+ END
+ end
+ assert_equal([42, nil, true, 42], a)
+
+ o = Object.new
+ class << o
+ attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
+ end
+ o.foo = o.Foo = o::baz = nil
+ o.bar = o.Bar = o::qux = 1
+ assert_nothing_raised do
+ eval <<-END
+ o.foo ||= t.foo 42
+ o.bar &&= t.foo 42
+ o.Foo ||= t.foo 42
+ o.Bar &&= t.foo 42
+ o::baz ||= t.foo 42
+ o::qux &&= t.foo 42
+ END
+ end
+ assert_equal([42, 42], [o.foo, o.bar])
+ assert_equal([42, 42], [o.Foo, o.Bar])
+ assert_equal([42, 42], [o::baz, o::qux])
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ $1 ||= t.foo 42
+ END
+ end
+
+ def t.bar(x); x + yield; end
+
+ a = b = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = t.bar "foo" do
+ "bar"
+ end.gsub "ob", "OB"
+ b = t.bar "foo" do
+ "bar"
+ end::gsub "ob", "OB"
+ END
+ end
+ assert_equal("foOBar", a)
+ assert_equal("foOBar", b)
+
+ a = nil
+ assert_nothing_raised do
+ t.instance_eval <<-END
+ a = bar "foo" { "bar" }
+ END
+ end
+ assert_equal("foobar", a)
+
+ a = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = t::bar "foo" { "bar" }
+ END
+ end
+ assert_equal("foobar", a)
+
+ def t.baz(*r)
+ @baz = r + (block_given? ? [yield] : [])
+ end
+
+ assert_nothing_raised do
+ t.instance_eval "baz (1), 2"
+ end
+ assert_equal([1, 2], t.instance_eval { @baz })
+ end
+
+ def test_mlhs_node
+ c = Class.new
+ class << c
+ attr_accessor :foo, :bar, :Foo, :Bar
+ FOO = BAR = nil
+ end
+
+ assert_nothing_raised do
+ eval <<-END
+ c::foo, c::bar = 1, 2
+ c.Foo, c.Bar = 1, 2
+ c::FOO, c::BAR = 1, 2
+ END
+ end
+ assert_equal([1, 2], [c::foo, c::bar])
+ assert_equal([1, 2], [c.Foo, c.Bar])
+ assert_equal([1, 2], [c::FOO, c::BAR])
+ end
+
+ def test_dynamic_constant_assignment
+ assert_raise(SyntaxError) do
+ Object.new.instance_eval <<-END
+ def foo
+ self::FOO, self::BAR = 1, 2
+ ::FOO, ::BAR = 1, 2
+ end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ $1, $2 = 1, 2
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ Object.new.instance_eval <<-END
+ def foo
+ ::FOO = 1
+ end
+ END
+ end
+
+ c = Class.new
+ assert_raise(SyntaxError) do
+ eval <<-END
+ c::FOO &= 1
+ ::FOO &= 1
+ END
+ end
+
+ c = Class.new
+ assert_raise(SyntaxError) do
+ eval <<-END
+ $1 &= 1
+ END
+ end
+ end
+
+ def test_class_module
+ assert_raise(SyntaxError) do
+ eval <<-END
+ class foo; end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo
+ class Foo; end
+ module Bar; end
+ end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ class Foo Bar; end
+ END
+ end
+ end
+
+ def test_op_name
+ o = Object.new
+ def o.>(x); x; end
+ def o./(x); x; end
+
+ a = nil
+ assert_nothing_raised do
+ o.instance_eval <<-END
+ undef >, /
+ END
+ end
+ end
+
+ def test_arg
+ o = Object.new
+ class << o
+ attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
+ end
+ o.foo = o.Foo = o::baz = nil
+ o.bar = o.Bar = o::qux = 1
+ assert_nothing_raised do
+ eval <<-END
+ o.foo ||= 42
+ o.bar &&= 42
+ o.Foo ||= 42
+ o.Bar &&= 42
+ o::baz ||= 42
+ o::qux &&= 42
+ END
+ end
+ assert_equal([42, 42], [o.foo, o.bar])
+ assert_equal([42, 42], [o.Foo, o.Bar])
+ assert_equal([42, 42], [o::baz, o::qux])
+
+ a = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = -2.0 ** 2
+ END
+ end
+ assert_equal(-4.0, a)
+ end
+
+ def test_block_variable
+ o = Object.new
+ def o.foo(*r); yield(*r); end
+
+ a = nil
+ assert_nothing_raised do
+ eval <<-END
+ o.foo 1 {|; a| a = 42 }
+ END
+ end
+ assert_nil(a)
+ end
+
+ def test_bad_arg
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo(FOO); end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo(@foo); end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo($foo); end
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo(@@foo); end
+ END
+ end
+
+ o = Object.new
+ def o.foo(*r); yield(*r); end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ o.foo 1 {|; @a| @a = 42 }
+ END
+ end
+ end
+
+ def test_do_lambda
+ a = b = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = -> do
+ b = 42
+ end
+ END
+ end
+ a.call
+ assert_equal(42, b)
+ end
+
+ def test_block_call_colon2
+ o = Object.new
+ def o.foo(x); x + yield; end
+
+ a = b = nil
+ assert_nothing_raised do
+ o.instance_eval <<-END
+ a = foo 1 do 42 end.to_s
+ b = foo 1 do 42 end::to_s
+ END
+ end
+ assert_equal("43", a)
+ assert_equal("43", b)
+ end
+
+ def test_call_method
+ a = b = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = proc {|x| x + "bar" }.("foo")
+ b = proc {|x| x + "bar" }::("foo")
+ END
+ end
+ assert_equal("foobar", a)
+ assert_equal("foobar", b)
+ end
+
+ def test_xstring
+ assert_raise(Errno::ENOENT) do
+ eval("``")
+ end
+ end
+
+ def test_words
+ assert_equal([], %W( ))
+ end
+
+ def test_dstr
+ @@foo = 1
+ assert_equal("foo 1 bar", "foo #@@foo bar")
+ "1" =~ /(.)/
+ assert_equal("foo 1 bar", "foo #$1 bar")
+ end
+
+ def test_dsym
+ assert_nothing_raised { eval(':""') }
+ end
+
+ def test_arg2
+ o = Object.new
+
+ assert_nothing_raised do
+ eval <<-END
+ def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end
+ END
+ end
+ assert_equal(-1405, o.foo(1,2,3,4) {|x| -x })
+ assert_equal(-1302, o.foo(1,2,3) {|x| -x })
+ assert_equal(-1200, o.foo(1,2) {|x| -x })
+ assert_equal(-42100, o.foo(1) {|x| -x })
+ assert_raise(ArgumentError) { o.foo() }
+
+ assert_nothing_raised do
+ eval <<-END
+ def o.foo(a=42,z,&b); b.call(a*1000+z*100); end
+ END
+ end
+ assert_equal(-1200, o.foo(1,2) {|x| -x } )
+ assert_equal(-42100, o.foo(1) {|x| -x } )
+ assert_raise(ArgumentError) { o.foo() }
+
+ assert_nothing_raised do
+ eval <<-END
+ def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end
+ END
+ end
+ assert_equal(-303, o.foo(1,2,3) {|x| -x } )
+ assert_equal(-201, o.foo(1,2) {|x| -x } )
+ assert_equal(-100, o.foo(1) {|x| -x } )
+ assert_raise(ArgumentError) { o.foo() }
+ end
+
+ def test_duplicate_argument
+ assert_raise(SyntaxError) do
+ eval <<-END
+ 1.times {|&b?| }
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ 1.times {|a, a|}
+ END
+ end
+
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo(a, a); end
+ END
+ end
+ end
+
+ def test_define_singleton_error
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def ("foo").foo; end
+ END
+ end
+ end
+
+ def test_backquote
+ t = Object.new
+
+ assert_nothing_raised do
+ eval <<-END
+ def t.`(x); "foo" + x + "bar"; end
+ END
+ end
+ a = b = nil
+ assert_nothing_raised do
+ eval <<-END
+ a = t.` "zzz"
+ 1.times {|;z| t.` ("zzz") }
+ END
+ t.instance_eval <<-END
+ b = `zzz`
+ END
+ end
+ assert_equal("foozzzbar", a)
+ assert_equal("foozzzbar", b)
+ end
+
+ def test_carrige_return
+ assert_equal(2, eval("1 +\r\n1"))
+ end
+
+ def test_string
+ assert_raise(SyntaxError) do
+ eval '"\xg1"'
+ end
+
+ assert_raise(SyntaxError) do
+ eval '"\u{1234"'
+ end
+
+ assert_raise(SyntaxError) do
+ eval '"\M1"'
+ end
+
+ assert_raise(SyntaxError) do
+ eval '"\C1"'
+ end
+
+ assert_equal("\x81", eval('"\C-\M-a"'))
+ assert_equal("\177", eval('"\c?"'))
+ end
+
+ def test_question
+ assert_raise(SyntaxError) { eval('?') }
+ assert_raise(SyntaxError) { eval('? ') }
+ assert_raise(SyntaxError) { eval("?\n") }
+ assert_raise(SyntaxError) { eval("?\t") }
+ assert_raise(SyntaxError) { eval("?\v") }
+ assert_raise(SyntaxError) { eval("?\r") }
+ assert_raise(SyntaxError) { eval("?\f") }
+ assert_equal("\u{1234}", eval("?\u{1234}"))
+ assert_equal("\u{1234}", eval('?\u{1234}'))
+ end
+
+ def test_percent
+ assert_equal(:foo, eval('%s(foo)'))
+ assert_raise(SyntaxError) { eval('%s') }
+ assert_raise(SyntaxError) { eval('%ss') }
+ assert_raise(SyntaxError) { eval('%z()') }
+ end
+
+ def test_symbol
+ assert_raise(SyntaxError) do
+ eval ":'foo\0bar'"
+ end
+ assert_raise(SyntaxError) do
+ eval ':"foo\u0000bar"'
+ end
+ assert_raise(SyntaxError) do
+ eval ':"foo\u{0}bar"'
+ end
+ assert_raise(SyntaxError) do
+ eval ':"foo\u{}bar"'
+ end
+ end
+
+ def test_parse_string
+ assert_raise(SyntaxError) do
+ eval <<-END
+/
+ END
+ end
+ end
+
+ def test_here_document
+ x = nil
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<FOO
+ )
+ end
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<FOO
+#$
+FOO
+ )
+ end
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<"
+ )
+ end
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<``
+ )
+ end
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<--
+ )
+ end
+
+ assert_raise(SyntaxError) do
+ eval %q(
+<<FOO
+#$
+foo
+FOO
+ )
+ end
+
+ assert_nothing_raised do
+ eval "x = <<FOO\r\n1\r\nFOO"
+ end
+ assert_equal("1\n", x)
+ end
+
+ def test_magic_comment
+ x = nil
+ assert_nothing_raised do
+ eval <<-END
+# coding = utf-8
+x = __ENCODING__
+ END
+ end
+ assert_equal(Encoding.find("UTF-8"), x)
+
+ assert_raise(ArgumentError) do
+ eval <<-END
+# coding = foobarbazquxquux_dummy_enconding
+x = __ENCODING__
+ END
+ end
+ end
+
+ def test_utf8_bom
+ x = nil
+ assert_nothing_raised do
+ eval "\xef\xbb\xbf x = __ENCODING__"
+ end
+ assert_equal(Encoding.find("UTF-8"), x)
+ assert_raise(NameError) { eval "\xef" }
+ end
+
+ def test_dot_in_next_line
+ x = nil
+ assert_nothing_raised do
+ eval <<-END
+ x = 1
+ .to_s
+ END
+ end
+ assert_equal("1", x)
+ end
+
+ def test_pow_asgn
+ x = 3
+ assert_nothing_raised { eval("x **= 2") }
+ assert_equal(9, x)
+ end
+
+ def test_embedded_rd
+ assert_raise(SyntaxError) do
+ eval <<-END
+=begin
+ END
+ end
+ end
+
+ def test_float
+ assert_equal(1.0/0, eval("1e10000"))
+ assert_raise(SyntaxError) { eval('1_E') }
+ assert_raise(SyntaxError) { eval('1E1E1') }
+ end
+
+ def test_global_variable
+ assert_equal(nil, eval('$-x'))
+ assert_equal(nil, eval('alias $preserve_last_match $&'))
+ assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
+ $test_parse_foobarbazqux = nil
+ assert_equal(nil, $&)
+ assert_equal(nil, eval('alias $& $preserve_last_match'))
+ assert_raise(SyntaxError) { eval('$#') }
+ end
+
+ def test_invalid_instance_variable
+ assert_raise(SyntaxError) { eval('@#') }
+ end
+
+ def test_invalid_class_variable
+ assert_raise(SyntaxError) { eval('@@1') }
+ end
+
+ def test_invalid_char
+ x = 1
+ assert_equal(1, eval("\x01x"))
+ assert_equal(nil, eval("\x04x"))
+ end
+
+ def test_literal_concat
+ x = "baz"
+ assert_equal("foobarbaz", eval('"foo" "bar#{x}"'))
+ end
+
+ def test_unassignable
+ assert_raise(SyntaxError) do
+ eval %q(self = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(nil = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(true = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(false = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(__FILE__ = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(__LINE__ = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval %q(__ENCODING__ = 1)
+ end
+ assert_raise(SyntaxError) do
+ eval <<-END
+ def foo
+ FOO = 1
+ end
+ END
+ end
+ end
+
+ def test_block_dup
+ assert_raise(SyntaxError) do
+ eval <<-END
+ foo(&proc{}) {}
+ END
+ end
+ end
+
+ def test_set_backref
+ assert_raise(SyntaxError) do
+ eval <<-END
+ $& = 1
+ END
+ end
+ end
+
+ def test_arg_concat
+ o = Object.new
+ class << o; self; end.instance_eval do
+ define_method(:[]=) {|*r, &b| b.call(r) }
+ end
+ r = nil
+ assert_nothing_raised do
+ eval <<-END
+ o[&proc{|x| r = x }] = 1
+ END
+ end
+ assert_equal([1], r)
+ end
+
+ def test_void_expr_stmts_value
+ # This test checks if void contexts are warned correctly.
+ # Thus, warnings MUST NOT be suppressed.
+ $VERBOSE = true
+ stderr = $stderr
+ $stderr = StringIO.new("")
+ x = 1
+ assert_nil eval("x; nil")
+ assert_nil eval("1+1; nil")
+ assert_nil eval("TestParse; nil")
+ assert_nil eval("::TestParse; nil")
+ assert_nil eval("x..x; nil")
+ assert_nil eval("x...x; nil")
+ assert_nil eval("self; nil")
+ assert_nil eval("nil; nil")
+ assert_nil eval("true; nil")
+ assert_nil eval("false; nil")
+ assert_nil eval("defined?(1); nil")
+
+ assert_raise(SyntaxError) do
+ eval %q(1; next; 2)
+ end
+
+ o = Object.new
+ assert_nothing_raised do
+ eval <<-END
+ x = def o.foo; end
+ END
+ end
+ assert_equal($stderr.string.lines.to_a.size, 14)
+ $stderr = stderr
+ end
+
+ def test_assign_in_conditional
+ assert_raise(SyntaxError) do
+ eval <<-END
+ (x, y = 1, 2) ? 1 : 2
+ END
+ end
+
+ assert_nothing_raised do
+ eval <<-END
+ if @x = true
+ 1
+ else
+ 2
+ end
+ END
+ end
+ end
+
+ def test_literal_in_conditional
+ assert_nothing_raised do
+ eval <<-END
+ "foo" ? 1 : 2
+ END
+ end
+
+ assert_nothing_raised do
+ x = "bar"
+ eval <<-END
+ /foo#{x}baz/ ? 1 : 2
+ END
+ end
+
+ assert_nothing_raised do
+ eval <<-END
+ (true..false) ? 1 : 2
+ END
+ end
+
+ assert_nothing_raised do
+ eval <<-END
+ ("foo".."bar") ? 1 : 2
+ END
+ end
+
+ assert_nothing_raised do
+ x = "bar"
+ eval <<-END
+ :"foo#{"x"}baz" ? 1 : 2
+ END
+ end
+ end
+
+ def test_no_blockarg
+ assert_raise(SyntaxError) do
+ eval <<-END
+ yield(&:+)
+ END
+ end
+ end
+
+ def test_intern
+ assert_equal(':""', ''.intern.inspect)
+ assert_equal(':$foo', '$foo'.intern.inspect)
+ assert_equal(':"!foo"', '!foo'.intern.inspect)
+ assert_equal(':"foo=="', "foo==".intern.inspect)
+ end
+
+ def test_all_symbols
+ x = Symbol.all_symbols
+ assert_kind_of(Array, x)
+ assert(x.all? {|s| s.is_a?(Symbol) })
+ end
+
+ def test_is_class_id
+ c = Class.new
+ assert_raise(NameError) do
+ c.instance_eval { remove_class_variable(:@var) }
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_path.rb b/trunk/test/ruby/test_path.rb
new file mode 100644
index 0000000000..18c701f033
--- /dev/null
+++ b/trunk/test/ruby/test_path.rb
@@ -0,0 +1,224 @@
+require 'test/unit'
+
+class TestPath < Test::Unit::TestCase
+ def test_path
+ assert_equal("a", File.basename("a"))
+ assert_equal("b", File.basename("a/b"))
+ assert_equal("b", File.basename("a/b/"))
+ assert_equal("/", File.basename("/"))
+ assert_equal("/", File.basename("//"))
+ assert_equal("/", File.basename("///"))
+ assert_equal("b", File.basename("a/b////"))
+ assert_equal("a", File.basename("a.rb", ".rb"))
+ assert_equal("a", File.basename("a.rb///", ".rb"))
+ assert_equal("a", File.basename("a.rb///", ".*"))
+ assert_equal("a.rb", File.basename("a.rb///", ".c"))
+ assert_equal(".", File.dirname("a"))
+ assert_equal("/", File.dirname("/"))
+ assert_equal("/", File.dirname("/a"))
+ assert_equal("a", File.dirname("a/b"))
+ assert_equal("a/b", File.dirname("a/b/c"))
+ assert_equal("/a/b", File.dirname("/a/b/c"))
+ assert_equal("/a", File.dirname("/a/b/"))
+ assert_equal("/a", File.dirname("/a/b///"))
+ case Dir.pwd
+ when %r'\A\w:'
+ assert_match(/\A\w:\/\z/, File.expand_path(".", "/"))
+ assert_match(/\A\w:\/a\z/, File.expand_path("a", "/"))
+ dosish = true
+ when %r'\A//'
+ assert_match(%r'\A//[^/]+/[^/]+\z', File.expand_path(".", "/"))
+ assert_match(%r'\A//[^/]+/[^/]+/a\z', File.expand_path(".", "/"))
+ dosish = true
+ else
+ assert_equal("/", File.expand_path(".", "/"))
+ assert_equal("/sub", File.expand_path("sub", "/"))
+ end
+ if dosish
+ assert_equal("//machine/share", File.expand_path("/", "//machine/share/sub"))
+ assert_equal("//machine/share/dir", File.expand_path("/dir", "//machine/share/sub"))
+ assert_equal("z:/", File.expand_path("/", "z:/sub"))
+ assert_equal("z:/dir", File.expand_path("/dir", "z:/sub"))
+ end
+ assert_equal("//", File.expand_path(".", "//"))
+ assert_equal("//sub", File.expand_path("sub", "//"))
+ end
+
+ def test_dirname
+ if /(bcc|ms)win\d|mingw|cygwin|djgpp|human|emx/ =~ RUBY_PLATFORM
+ # DOSISH_DRIVE_LETTER
+ assert_equal('C:.', File.dirname('C:'))
+ assert_equal('C:.', File.dirname('C:a'))
+ assert_equal('C:.', File.dirname('C:a/'))
+ assert_equal('C:a', File.dirname('C:a/b'), "[ruby-dev:27738]")
+
+ assert_equal('C:/', File.dirname('C:/'))
+ assert_equal('C:/', File.dirname('C:/a'))
+ assert_equal('C:/', File.dirname('C:/a/'))
+ assert_equal('C:/a', File.dirname('C:/a/b'))
+
+ assert_equal('C:/', File.dirname('C://'))
+ assert_equal('C:/', File.dirname('C://a'))
+ assert_equal('C:/', File.dirname('C://a/'))
+ assert_equal('C:/a', File.dirname('C://a/b'))
+
+ assert_equal('C:/', File.dirname('C:///'), "[ruby-dev:27738]")
+ assert_equal('C:/', File.dirname('C:///a'))
+ assert_equal('C:/', File.dirname('C:///a/'))
+ assert_equal('C:/a', File.dirname('C:///a/b'))
+ else
+ # others
+ assert_equal('.', File.dirname('C:'))
+ assert_equal('.', File.dirname('C:a'))
+ assert_equal('.', File.dirname('C:a/'))
+ assert_equal('C:a', File.dirname('C:a/b'))
+
+ assert_equal('.', File.dirname('C:/'))
+ assert_equal('C:', File.dirname('C:/a'))
+ assert_equal('C:', File.dirname('C:/a/'))
+ assert_equal('C:/a', File.dirname('C:/a/b'))
+
+ assert_equal('.', File.dirname('C://'))
+ assert_equal('C:', File.dirname('C://a'))
+ assert_equal('C:', File.dirname('C://a/'))
+ # not spec.
+ #assert_equal('C://a', File.dirname('C://a/b'))
+
+ assert_equal('.', File.dirname('C:///'))
+ assert_equal('C:', File.dirname('C:///a'))
+ assert_equal('C:', File.dirname('C:///a/'))
+ # not spec.
+ #assert_equal('C:///a', File.dirname('C:///a/b'))
+ end
+
+ assert_equal('.', File.dirname(''))
+ assert_equal('.', File.dirname('a'))
+ assert_equal('.', File.dirname('a/'))
+ assert_equal('a', File.dirname('a/b'))
+
+ assert_equal('/', File.dirname('/'))
+ assert_equal('/', File.dirname('/a'))
+ assert_equal('/', File.dirname('/a/'))
+ assert_equal('/a', File.dirname('/a/b'))
+
+ if /(bcc|ms|cyg)win|mingw|djgpp|human|emx/ =~ RUBY_PLATFORM
+ # DOSISH_UNC
+ assert_equal('//', File.dirname('//'))
+ assert_equal('//a', File.dirname('//a'))
+ assert_equal('//a', File.dirname('//a/'))
+ assert_equal('//a/b', File.dirname('//a/b'))
+ assert_equal('//a/b', File.dirname('//a/b/'))
+ assert_equal('//a/b', File.dirname('//a/b/c'))
+
+ assert_equal('//', File.dirname('///'))
+ assert_equal('//a', File.dirname('///a'))
+ assert_equal('//a', File.dirname('///a/'))
+ assert_equal('//a/b', File.dirname('///a/b'))
+ assert_equal('//a/b', File.dirname('///a/b/'))
+ assert_equal('//a/b', File.dirname('///a/b/c'))
+ else
+ # others
+ assert_equal('/', File.dirname('//'))
+ assert_equal('/', File.dirname('//a'))
+ assert_equal('/', File.dirname('//a/'))
+ assert_equal('/a', File.dirname('//a/b'))
+ assert_equal('/a', File.dirname('//a/b/'))
+ assert_equal('/a/b', File.dirname('//a/b/c'))
+
+ assert_equal('/', File.dirname('///'))
+ assert_equal('/', File.dirname('///a'))
+ assert_equal('/', File.dirname('///a/'))
+ assert_equal('/a', File.dirname('///a/b'))
+ assert_equal('/a', File.dirname('///a/b/'))
+ assert_equal('/a/b', File.dirname('///a/b/c'))
+ end
+ end
+
+ def test_basename
+ if /(bcc|ms)win\d|mingw|cygwin|djgpp|human|emx/ =~ RUBY_PLATFORM
+ # DOSISH_DRIVE_LETTER
+ assert_equal('', File.basename('C:'))
+ assert_equal('a', File.basename('C:a'))
+ assert_equal('a', File.basename('C:a/'))
+ assert_equal('b', File.basename('C:a/b'))
+
+ assert_equal('/', File.basename('C:/'))
+ assert_equal('a', File.basename('C:/a'))
+ assert_equal('a', File.basename('C:/a/'))
+ assert_equal('b', File.basename('C:/a/b'))
+
+ assert_equal('/', File.basename('C://'))
+ assert_equal('a', File.basename('C://a'))
+ assert_equal('a', File.basename('C://a/'))
+ assert_equal('b', File.basename('C://a/b'))
+
+ assert_equal('/', File.basename('C:///'))
+ assert_equal('a', File.basename('C:///a'))
+ assert_equal('a', File.basename('C:///a/'))
+ assert_equal('b', File.basename('C:///a/b'))
+ else
+ # others
+ assert_equal('C:', File.basename('C:'))
+ assert_equal('C:a', File.basename('C:a'))
+ assert_equal('C:a', File.basename('C:a/'))
+ assert_equal('b', File.basename('C:a/b'))
+
+ assert_equal('C:', File.basename('C:/'))
+ assert_equal('a', File.basename('C:/a'))
+ assert_equal('a', File.basename('C:/a/'))
+ assert_equal('b', File.basename('C:/a/b'))
+
+ assert_equal('C:', File.basename('C://'))
+ assert_equal('a', File.basename('C://a'))
+ assert_equal('a', File.basename('C://a/'))
+ assert_equal('b', File.basename('C://a/b'))
+
+ assert_equal('C:', File.basename('C:///'))
+ assert_equal('a', File.basename('C:///a'))
+ assert_equal('a', File.basename('C:///a/'))
+ assert_equal('b', File.basename('C:///a/b'))
+ end
+
+ assert_equal('', File.basename(''))
+ assert_equal('a', File.basename('a'))
+ assert_equal('a', File.basename('a/'))
+ assert_equal('b', File.basename('a/b'))
+
+ assert_equal('/', File.basename('/'))
+ assert_equal('a', File.basename('/a'))
+ assert_equal('a', File.basename('/a/'))
+ assert_equal('b', File.basename('/a/b'))
+
+ if /(bcc|ms|cyg)win|mingw|djgpp|human|emx/ =~ RUBY_PLATFORM
+ # DOSISH_UNC
+ assert_equal('/', File.basename('//'))
+ assert_equal('/', File.basename('//a'))
+ assert_equal('/', File.basename('//a/'))
+ assert_equal('/', File.basename('//a/b'), "[ruby-dev:27776]")
+ assert_equal('/', File.basename('//a/b/'))
+ assert_equal('c', File.basename('//a/b/c'))
+
+ assert_equal('/', File.basename('///'))
+ assert_equal('/', File.basename('///a'))
+ assert_equal('/', File.basename('///a/'))
+ assert_equal('/', File.basename('///a/b'))
+ assert_equal('/', File.basename('///a/b/'))
+ assert_equal('c', File.basename('///a/b/c'))
+ else
+ # others
+ assert_equal('/', File.basename('//'))
+ assert_equal('a', File.basename('//a'))
+ assert_equal('a', File.basename('//a/'))
+ assert_equal('b', File.basename('//a/b'))
+ assert_equal('b', File.basename('//a/b/'))
+ assert_equal('c', File.basename('//a/b/c'))
+
+ assert_equal('/', File.basename('///'))
+ assert_equal('a', File.basename('///a'))
+ assert_equal('a', File.basename('///a/'))
+ assert_equal('b', File.basename('///a/b'))
+ assert_equal('b', File.basename('///a/b/'))
+ assert_equal('c', File.basename('///a/b/c'))
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_pipe.rb b/trunk/test/ruby/test_pipe.rb
new file mode 100644
index 0000000000..34f231ad8c
--- /dev/null
+++ b/trunk/test/ruby/test_pipe.rb
@@ -0,0 +1,16 @@
+require 'test/unit'
+require_relative 'ut_eof'
+
+class TestPipe < Test::Unit::TestCase
+ include TestEOF
+ def open_file(content)
+ r, w = IO.pipe
+ w << content
+ w.close
+ begin
+ yield r
+ ensure
+ r.close
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_prec.rb b/trunk/test/ruby/test_prec.rb
new file mode 100644
index 0000000000..d872242c11
--- /dev/null
+++ b/trunk/test/ruby/test_prec.rb
@@ -0,0 +1,21 @@
+require 'test/unit'
+
+class TestPrecision < Test::Unit::TestCase
+ def test_prec_i
+ assert_same(1, 1.0.prec(Integer))
+ assert_same(1, 1.0.prec_i)
+ assert_same(1, Integer.induced_from(1.0))
+ end
+
+ def test_prec_f
+ assert_equal(1.0, 1.prec(Float))
+ assert_equal(1.0, 1.prec_f)
+ assert_equal(1.0, Float.induced_from(1))
+ end
+
+ def test_induced_from
+ m = Module.new
+ m.instance_eval { include(Precision) }
+ assert_raise(TypeError) { m.induced_from(0) }
+ end
+end
diff --git a/trunk/test/ruby/test_primitive.rb b/trunk/test/ruby/test_primitive.rb
new file mode 100644
index 0000000000..8ffbe549d6
--- /dev/null
+++ b/trunk/test/ruby/test_primitive.rb
@@ -0,0 +1,397 @@
+require 'test/unit'
+
+class TestRubyPrimitive < Test::Unit::TestCase
+
+ def test_not
+ assert_equal false, !true
+ assert_equal true, !false
+ assert_equal true, !nil
+ assert_equal false, !(1+1)
+ assert_equal false, !!nil
+ assert_equal true, !!1
+ end
+
+ def test_lvar
+ a = 1
+ assert_equal 1, a
+ b = 2
+ assert_equal 1, a
+ a = b = 3
+ assert_equal 3, a
+ assert_equal 3, b
+ a = b = c = 4
+ assert_equal 4, a
+ assert_equal 4, b
+ assert_equal 4, c
+ end
+
+ C = 1
+ class A
+ Const = 1
+ class B
+ Const = 2
+ class C
+ Const = 3
+ def const
+ Const
+ end
+ end
+ end
+ end
+ (1..2).map {
+ A::B::C::Const
+ }
+
+ def test_constant
+ assert_equal 1, C
+ assert_equal 1, C
+ assert_equal 1, A::Const
+ assert_equal 2, A::B::Const
+ assert_equal 3, A::B::C::Const
+ assert_equal 3, A::B::C.new.const
+ assert_equal 1, ::TestRubyPrimitive::A::Const
+ A::B::C.send(:remove_const, :Const)
+ assert_equal 2, A::B::C.new.const
+ assert_raise(TypeError) {
+ C::CONST
+ }
+ end
+
+ class A2
+ class B2
+ class C2
+ C = 7
+ end
+ end
+ end
+
+ def test_constant_cache
+ i = 0
+ while i < 3
+ r = A2::B2::C2::C
+ i += 1
+ end
+ assert_equal 7, r
+ end
+
+ class A3
+ class B3
+ C = 99
+ end
+ end
+ i = 0
+ while i < 3
+ r = A3::B3::C # cache
+ class A3::B3
+ remove_const :C
+ end
+ A3::B3::C = i ** i
+ i += 1
+ end
+
+ def test_constant_cache2
+ assert_equal 4, A3::B3::C
+ end
+
+ class A4
+ Const = 7
+ (1..3).map {
+ $test_ruby_primitive_constant_cache3 = self::Const
+ }
+ end
+
+ def test_constant_cache3
+ assert_equal 7, $test_ruby_primitive_constant_cache3
+ end
+
+ class A5
+ Const = 8
+ (1..3).map {
+ $test_ruby_primitive_constant_cache4 = eval('self')::Const
+ }
+ end
+
+ def test_constatant_cache4
+ assert_equal 8, $test_ruby_primitive_constant_cache4
+ end
+
+ class A6
+ Const = 0
+ def self.foo
+ self::Const
+ end
+ end
+ class B6 < A6
+ Const = 1
+ end
+ class C6 < B6
+ Const = 2
+ end
+ $test_ruby_primitive_constant_cache5 = [A6.foo, B6.foo, C6.foo]
+
+ def test_constant_cache5
+ assert_equal [0, 1, 2], $test_ruby_primitive_constant_cache5
+ end
+
+ def test_gvar
+ $test_ruby_primitive_gvar = 7
+ assert_equal 7, $test_ruby_primitive_gvar
+ assert_equal 7, $test_ruby_primitive_gvar
+ $test_ruby_primitive_gvar = 88
+ assert_equal 88, $test_ruby_primitive_gvar
+ assert_equal 88, $test_ruby_primitive_gvar
+ assert_equal 7, ($test_ruby_primitive_gvar = 7)
+ assert_equal 7, ($test_ruby_primitive_gvar = 7)
+ end
+
+ class A7
+ @@c = 1
+ def m
+ @@c += 1
+ end
+ end
+
+ def test_cvar_from_instance_method
+ assert_equal 2, A7.new.m
+ assert_equal 3, A7.new.m
+ assert_equal 4, A7.new.m
+ end
+
+ class A8
+ @@c = 1
+ class << self
+ def m
+ @@c += 1
+ end
+ end
+ end
+
+ def test_cvar_from_singleton_method
+ assert_equal 2, A8.m
+ assert_equal 3, A8.m
+ assert_equal 4, A8.m
+ end
+
+ class A9
+ @@c = 1
+ def self.m
+ @@c += 1
+ end
+ end
+
+ def test_cvar_from_singleton_method2
+ assert_equal 2, A9.m
+ assert_equal 3, A9.m
+ assert_equal 4, A9.m
+ end
+
+ class A10
+ attr_accessor :a
+ end
+
+ def test_opassign
+ i = 0
+ i += 1
+ assert_equal 1, i
+
+ @iv = 2
+ @iv += 2
+ assert_equal 4, @iv
+
+ @@cv ||= 1
+ assert_equal 1, @@cv
+ @@cv &&= 2
+ assert_equal 2, @@cv
+ @@cv ||= 99
+ assert_equal 2, @@cv
+
+ $gv = 3
+ $gv += 4
+ assert_equal 7, $gv
+
+ obj = A10.new
+ obj.a = 9
+ obj.a &&= 7
+ assert_equal 7, obj.a
+
+ obj.a = nil
+ obj.a ||= 2
+ assert_equal 2, obj.a
+
+ obj.a &&= 3
+ assert_equal 3, obj.a
+
+ a = []
+ a[0] ||= 3
+ assert_equal 3, a[0]
+ a[0] &&= 7
+ assert_equal 7, a[0]
+ a[0] ||= 3
+ assert_equal 7, a[0]
+ end
+
+ def test_opassign_and_or
+ a = 1
+ a ||= 2
+ assert_equal 1, a
+ a = nil
+ a ||= 2
+ assert_equal 2, a
+ a = 1
+ a &&= 3
+ assert_equal 3, a
+ a = nil
+ a &&= 4
+ assert_nil a
+
+ h = {}
+ h[0] ||= 1
+ assert_equal 1, h[0]
+ h = {}
+ h[0] &&= 1
+ assert_nil h[0]
+ h = {0 => 7}
+ h[0] ||= 1
+ assert_equal 7, h[0]
+ h = {0 => 7}
+ h[0] &&= 1
+ assert_equal 1, h[0]
+ end
+
+ def test_backref
+ /a(b)(c)d/ =~ 'xyzabcdefgabcdefg'
+ assert_equal 'b', $1
+ assert_equal 'c', $2
+ assert_nil $3
+ assert_instance_of MatchData, $~
+ assert_equal 'abcd', $&
+ assert_equal 'xyz', $`
+ assert_equal 'efgabcdefg', $'
+ assert_equal 'c', $+
+
+ /(?!)/ =~ 'xyzabcdefgabcdefg'
+ assert_nil $1
+ assert_nil $2
+ assert_nil $3
+ assert_nil $~
+ assert_nil $&
+ assert_nil $`
+ assert_nil $'
+ assert_nil $+
+ end
+
+ def test_fact
+ assert_equal 306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000, fact(300)
+ end
+
+ def fact(n)
+ if n > 1
+ n * fact(n - 1)
+ else
+ 1
+ end
+ end
+
+ def test_mul
+ assert_equal 0, 2 * 0
+ assert_equal 0, 0 * 2
+ assert_equal 4, 2 * 2
+ end
+
+ class MyNum
+ def /(a)
+ a * 100
+ end
+ end
+
+ def test_div
+ assert_equal 1, 3 / 2
+ assert_equal 1.5, 3.0 / 2.0
+ assert_equal 300, MyNum.new / 3
+ end
+
+ class MyArr
+ def length
+ 'string'
+ end
+ end
+
+ def test_length
+ assert_equal 0, [].length
+ assert_equal 1, [1].length
+ assert_equal 2, [1,2].length
+ assert_equal 0, {}.length
+ assert_equal 1, {1=>1}.length
+ assert_equal 2, {1=>1, 2=>2}.length
+ assert_equal 'string', MyArr.new.length
+ end
+
+ class MyNum2
+ def %(a)
+ a * 100
+ end
+ end
+
+ def test_mod
+ assert_equal 2, 5 % 3
+ assert_equal 1.0, 3.0 % 2.0
+ assert_equal 300, MyNum2.new % 3
+ end
+
+ class MyObj
+ def [](*args)
+ args
+ end
+
+ def []=(*args)
+ args
+ end
+ end
+
+ def test_aref
+ a = [0,1]
+ assert_equal 0, a[0]
+ assert_equal 1, a[1]
+ assert_nil a[2]
+ h = {0=>0, 1=>1}
+ obj = MyObj.new
+ assert_equal 0, h[0]
+ assert_equal 1, h[1]
+ assert_nil h[2]
+ assert_equal [0], obj[0]
+ assert_equal [0,1], obj[0,1]
+ assert_equal [0,1,2], obj[0,1,2]
+ end
+
+ def test_aset
+ obj = MyObj.new
+ assert_equal 7, (obj[0] = 7)
+ assert_equal 7, (obj[0,1] = 7)
+ assert_equal 7, (obj[0,1,2] = 7)
+ end
+
+ class MyObj2
+ def attr=(*args)
+ args
+ end
+ end
+
+ def test_attr_setter
+ obj = MyObj2.new
+ assert_equal 1, (obj.attr = 1)
+ end
+
+ def test_list_expand
+ a = []
+ assert_equal [0], [0, *a]
+ a = [1]
+ assert_equal [0,1], [0, *a]
+ a = [1,2]
+ assert_equal [0,1,2], [0, *a]
+ a = [1,2,3]
+ assert_equal [0,1,2,3], [0, *a]
+ #a = [1,2,3]
+ #assert_equal [0,1,2,3,4], [0, *a, 4]
+ end
+
+end
diff --git a/trunk/test/ruby/test_proc.rb b/trunk/test/ruby/test_proc.rb
new file mode 100644
index 0000000000..ee53eeaf3a
--- /dev/null
+++ b/trunk/test/ruby/test_proc.rb
@@ -0,0 +1,312 @@
+require 'test/unit'
+
+class TestProc < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_proc
+ p1 = proc{|i| i}
+ assert_equal(2, p1.call(2))
+ assert_equal(3, p1.call(3))
+
+ p1 = proc{|i| i*2}
+ assert_equal(4, p1.call(2))
+ assert_equal(6, p1.call(3))
+
+ p2 = nil
+ x=0
+
+ proc{
+ iii=5 # nested local variable
+ p1 = proc{|i|
+ iii = i
+ }
+ p2 = proc {
+ x = iii # nested variables shared by procs
+ }
+ # scope of nested variables
+ assert(defined?(iii))
+ }.call
+ assert(!defined?(iii)) # out of scope
+
+ loop{iii=5; assert(eval("defined? iii")); break}
+ loop {
+ iii = 10
+ def self.dyna_var_check
+ loop {
+ assert(!defined?(iii))
+ break
+ }
+ end
+ dyna_var_check
+ break
+ }
+ p1.call(5)
+ p2.call
+ assert_equal(5, x)
+ end
+
+ def assert_arity(n)
+ meta = class << self; self; end
+ meta.class_eval {define_method(:foo, Proc.new)}
+ assert_equal(n, method(:foo).arity)
+ end
+
+ def test_arity
+ assert_equal(0, proc{}.arity)
+ assert_equal(0, proc{||}.arity)
+ assert_equal(1, proc{|x|}.arity)
+ assert_equal(2, proc{|x, y|}.arity)
+ assert_equal(-2, proc{|x, *y|}.arity)
+ assert_equal(-1, proc{|*x|}.arity)
+ assert_equal(-1, proc{|*|}.arity)
+ assert_equal(-3, proc{|x, *y, z|}.arity)
+ assert_equal(-4, proc{|x, *y, z, a|}.arity)
+
+ assert_arity(0) {}
+ assert_arity(0) {||}
+ assert_arity(1) {|x|}
+ assert_arity(2) {|x, y|}
+ assert_arity(-2) {|x, *y|}
+ assert_arity(-3) {|x, *y, z|}
+ assert_arity(-1) {|*x|}
+ assert_arity(-1) {|*|}
+ end
+
+ def m(x)
+ lambda { x }
+ end
+
+ def test_eq
+ a = m(1)
+ b = m(2)
+ assert_not_equal(a, b, "[ruby-dev:22592]")
+ assert_not_equal(a.call, b.call, "[ruby-dev:22592]")
+
+ assert_not_equal(proc {||}, proc {|x,y|}, "[ruby-dev:22599]")
+
+ a = lambda {|x| lambda {} }.call(1)
+ b = lambda {}
+ assert_not_equal(a, b, "[ruby-dev:22601]")
+ end
+
+ def test_block_par
+ assert_equal(10, Proc.new{|&b| b.call(10)}.call {|x| x})
+ assert_equal(12, Proc.new{|a,&b| b.call(a)}.call(12) {|x| x})
+ end
+
+ def test_safe
+ safe = $SAFE
+ c = Class.new
+ x = c.new
+
+ p = proc {
+ $SAFE += 1
+ proc {$SAFE}
+ }.call
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, p.call)
+ assert_equal(safe, $SAFE)
+
+ c.class_eval {define_method(:safe, p)}
+ assert_equal(safe, x.safe)
+ assert_equal(safe, x.method(:safe).call)
+ assert_equal(safe, x.method(:safe).to_proc.call)
+
+ p = proc {$SAFE += 1}
+ assert_equal(safe + 1, p.call)
+ assert_equal(safe, $SAFE)
+
+ c.class_eval {define_method(:inc, p)}
+ assert_equal(safe + 1, proc {x.inc; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, proc {x.method(:inc).call; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ assert_equal(safe + 1, proc {x.method(:inc).to_proc.call; $SAFE}.call)
+ assert_equal(safe, $SAFE)
+ end
+
+ def m2
+ "OK"
+ end
+
+ def block
+ method(:m2).to_proc
+ end
+
+ # [yarv-dev:777] block made by Method#to_proc
+ def test_method_to_proc
+ b = block()
+ assert_equal "OK", b.call
+ end
+
+ def test_curry
+ b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
+ assert_equal(6, b.curry[1][2][3])
+ assert_equal(6, b.curry[1, 2][3, 4])
+ assert_equal(6, b.curry(5)[1][2][3][4][5])
+ assert_equal(6, b.curry(5)[1, 2][3, 4][5])
+ assert_equal(1, b.curry(1)[1])
+
+ b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
+ assert_equal(6, b.curry[1][2][3])
+ assert_equal(10, b.curry[1, 2][3, 4])
+ assert_equal(15, b.curry(5)[1][2][3][4][5])
+ assert_equal(15, b.curry(5)[1, 2][3, 4][5])
+ assert_equal(1, b.curry(1)[1])
+
+ b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
+ assert_equal(6, b.curry[1][2][3])
+ assert_raise(ArgumentError) { b.curry[1, 2][3, 4] }
+ assert_raise(ArgumentError) { b.curry(5) }
+ assert_raise(ArgumentError) { b.curry(1) }
+
+ b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
+ assert_equal(6, b.curry[1][2][3])
+ assert_equal(10, b.curry[1, 2][3, 4])
+ assert_equal(15, b.curry(5)[1][2][3][4][5])
+ assert_equal(15, b.curry(5)[1, 2][3, 4][5])
+ assert_raise(ArgumentError) { b.curry(1) }
+
+ b = proc { :foo }
+ assert_equal(:foo, b.curry[])
+ end
+
+ def test_curry_ski_fib
+ s = proc {|f, g, x| f[x][g[x]] }.curry
+ k = proc {|x, y| x }.curry
+ i = proc {|x| x }.curry
+
+ fib = []
+ inc = proc {|x| fib[-1] += 1; x }.curry
+ ret = proc {|x| throw :end if fib.size > 10; fib << 0; x }.curry
+
+ catch(:end) do
+ s[
+ s[s[i][i]][k[i]]
+ ][
+ k[inc]
+ ][
+ s[
+ s[
+ k[s]
+ ][
+ s[k[s[k[s]]]
+ ][
+ s[s[k[s]][s[k[s[k[ret]]]][s[k[s[i]]][k]]]][k]]
+ ]
+ ][
+ k[s[k[s]][k]]
+ ]
+ ]
+ end
+
+ assert_equal(fib, [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89])
+ end
+
+ def test_curry_from_knownbug
+ a = lambda {|x, y, &b| b }
+ b = a.curry[1]
+
+ assert_equal(:ok,
+ if b.call(2){} == nil
+ :ng
+ else
+ :ok
+ end, 'moved from btest/knownbug, [ruby-core:15551]')
+ end
+
+ def test_dup_clone
+ b = proc {|x| x + "bar" }
+ class << b; attr_accessor :foo; end
+
+ bd = b.dup
+ assert_equal("foobar", bd.call("foo"))
+ assert_raise(NoMethodError) { bd.foo = :foo }
+ assert_raise(NoMethodError) { bd.foo }
+
+ bc = b.clone
+ assert_equal("foobar", bc.call("foo"))
+ bc.foo = :foo
+ assert_equal(:foo, bc.foo)
+ end
+
+ def test_binding
+ b = proc {|x, y, z| proc {}.binding }.call(1, 2, 3)
+ class << b; attr_accessor :foo; end
+
+ bd = b.dup
+ assert_equal([1, 2, 3], bd.eval("[x, y, z]"))
+ assert_raise(NoMethodError) { bd.foo = :foo }
+ assert_raise(NoMethodError) { bd.foo }
+
+ bc = b.clone
+ assert_equal([1, 2, 3], bc.eval("[x, y, z]"))
+ bc.foo = :foo
+ assert_equal(:foo, bc.foo)
+
+ b = nil
+ 1.times { x, y, z = 1, 2, 3; b = binding }
+ assert_equal([1, 2, 3], b.eval("[x, y, z]"))
+ end
+
+ def test_proc_lambda
+ assert_raise(ArgumentError) { proc }
+ assert_raise(ArgumentError) { lambda }
+
+ o = Object.new
+ def o.foo
+ b = nil
+ 1.times { b = lambda }
+ b
+ end
+ assert_equal(:foo, o.foo { :foo }.call)
+
+ def o.foo(&b)
+ b = nil
+ 1.times { b = lambda }
+ b
+ end
+ assert_equal(:foo, o.foo { :foo }.call)
+ end
+
+ def test_arity2
+ assert_equal(0, method(:proc).to_proc.arity)
+ assert_equal(-1, proc {}.curry.arity)
+ end
+
+ def test_proc_location
+ t = Thread.new { sleep }
+ assert_raise(ThreadError) { t.instance_eval { initialize { } } }
+ t.kill
+ end
+
+ def test_eq2
+ b1 = proc { }
+ b2 = b1.dup
+ assert(b1 == b2)
+ end
+
+ def test_to_proc
+ b = proc { :foo }
+ assert_equal(:foo, b.to_proc.call)
+ end
+
+ def test_localjump_error
+ o = Object.new
+ def foo; yield; end
+ exc = foo rescue $!
+ assert_nil(exc.exit_value)
+ assert_equal(:noreason, exc.reason)
+ end
+
+ def test_binding2
+ assert_raise(ArgumentError) { proc {}.curry.binding }
+ end
+end
diff --git a/trunk/test/ruby/test_process.rb b/trunk/test/ruby/test_process.rb
new file mode 100644
index 0000000000..ba933b2d56
--- /dev/null
+++ b/trunk/test/ruby/test_process.rb
@@ -0,0 +1,1007 @@
+require 'test/unit'
+require 'tmpdir'
+require 'pathname'
+require_relative 'envutil'
+
+class TestProcess < Test::Unit::TestCase
+ RUBY = EnvUtil.rubybin
+
+ def setup
+ Process.waitall
+ end
+
+ def teardown
+ Process.waitall
+ end
+
+ def write_file(filename, content)
+ File.open(filename, "w") {|f|
+ f << content
+ }
+ end
+
+ def with_tmpchdir
+ Dir.mktmpdir {|d|
+ d = Pathname.new(d).realpath.to_s
+ Dir.chdir(d) {
+ yield d
+ }
+ }
+ end
+
+ def run_in_child(str) # should be called in a temporary directory
+ write_file("test-script", str)
+ Process.wait spawn(RUBY, "test-script")
+ $?
+ end
+
+ def test_rlimit_availability
+ begin
+ Process.getrlimit(nil)
+ rescue NotImplementedError
+ assert_raise(NotImplementedError) { Process.setrlimit }
+ rescue TypeError
+ assert_raise(ArgumentError) { Process.setrlimit }
+ end
+ end
+
+ def rlimit_exist?
+ Process.getrlimit(nil)
+ rescue NotImplementedError
+ return false
+ rescue TypeError
+ return true
+ end
+
+ def test_rlimit_nofile
+ return unless rlimit_exist?
+ with_tmpchdir {
+ write_file 's', <<-"End"
+ cur_nofile, max_nofile = Process.getrlimit(Process::RLIMIT_NOFILE)
+ result = 1
+ begin
+ Process.setrlimit(Process::RLIMIT_NOFILE, 0, max_nofile)
+ rescue Errno::EINVAL
+ result = 0
+ end
+ if result == 1
+ begin
+ IO.pipe
+ rescue Errno::EMFILE
+ result = 0
+ end
+ end
+ Process.setrlimit(Process::RLIMIT_NOFILE, cur_nofile, max_nofile)
+ exit result
+ End
+ pid = spawn RUBY, "s"
+ Process.wait pid
+ assert_equal(0, $?.to_i, "#{$?}")
+ }
+ end
+
+ def test_rlimit_name
+ return unless rlimit_exist?
+ [
+ :AS, "AS",
+ :CORE, "CORE",
+ :CPU, "CPU",
+ :DATA, "DATA",
+ :FSIZE, "FSIZE",
+ :MEMLOCK, "MEMLOCK",
+ :NOFILE, "NOFILE",
+ :NPROC, "NPROC",
+ :RSS, "RSS",
+ :STACK, "STACK",
+ :SBSIZE, "SBSIZE",
+ ].each {|name|
+ if Process.const_defined? "RLIMIT_#{name}"
+ assert_nothing_raised { Process.getrlimit(name) }
+ else
+ assert_raise(ArgumentError) { Process.getrlimit(name) }
+ end
+ }
+ assert_raise(ArgumentError) { Process.getrlimit(:FOO) }
+ assert_raise(ArgumentError) { Process.getrlimit("FOO") }
+ end
+
+ def test_rlimit_value
+ return unless rlimit_exist?
+ assert_raise(ArgumentError) { Process.setrlimit(:CORE, :FOO) }
+ assert_raise(Errno::EPERM, Errno::EINVAL) { Process.setrlimit(:NOFILE, :INFINITY) }
+ assert_raise(Errno::EPERM, Errno::EINVAL) { Process.setrlimit(:NOFILE, "INFINITY") }
+ end
+
+ TRUECOMMAND = [RUBY, '-e', '']
+
+ def test_execopts_opts
+ assert_nothing_raised {
+ Process.wait Process.spawn(*TRUECOMMAND, {})
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*TRUECOMMAND, :foo => 100)
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*TRUECOMMAND, Process => 100)
+ }
+ end
+
+ def test_execopts_pgroup
+ assert_nothing_raised { system(*TRUECOMMAND, :pgroup=>false) }
+
+ io = IO.popen([RUBY, "-e", "print Process.getpgrp"])
+ assert_equal(Process.getpgrp.to_s, io.read)
+ io.close
+
+ io = IO.popen([RUBY, "-e", "print Process.getpgrp", :pgroup=>true])
+ assert_equal(io.pid.to_s, io.read)
+ io.close
+
+ assert_raise(ArgumentError) { system(*TRUECOMMAND, :pgroup=>-1) }
+ assert_raise(Errno::EPERM) { Process.wait spawn(*TRUECOMMAND, :pgroup=>2) }
+
+ io1 = IO.popen([RUBY, "-e", "print Process.getpgrp", :pgroup=>true])
+ io2 = IO.popen([RUBY, "-e", "print Process.getpgrp", :pgroup=>io1.pid])
+ assert_equal(io1.pid.to_s, io1.read)
+ assert_equal(io1.pid.to_s, io2.read)
+ Process.wait io1.pid
+ Process.wait io2.pid
+ io1.close
+ io2.close
+ end
+
+ def test_execopts_rlimit
+ return unless rlimit_exist?
+ assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_foo=>0) }
+ assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_NOFILE=>0) }
+ assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_nofile=>[]) }
+ assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_nofile=>[1,2,3]) }
+
+ max = Process.getrlimit(:CORE).last
+
+ n = max
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io|
+ assert_equal("[#{n}, #{n}]\n", io.read)
+ }
+
+ n = 0
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io|
+ assert_equal("[#{n}, #{n}]\n", io.read)
+ }
+
+ n = max
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE)", :rlimit_core=>[n]]) {|io|
+ assert_equal("[#{n}, #{n}]", io.read.chomp)
+ }
+
+ m, n = 0, max
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
+ assert_equal("[#{m}, #{n}]", io.read.chomp)
+ }
+
+ m, n = 0, 0
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
+ assert_equal("[#{m}, #{n}]", io.read.chomp)
+ }
+
+ n = max
+ IO.popen([RUBY, "-e",
+ "p Process.getrlimit(:CORE), Process.getrlimit(:CPU)",
+ :rlimit_core=>n, :rlimit_cpu=>3600]) {|io|
+ assert_equal("[#{n}, #{n}]\n[3600, 3600]", io.read.chomp)
+ }
+ end
+
+ ENVCOMMAND = [RUBY, '-e', 'ENV.each {|k,v| puts "#{k}=#{v}" }']
+
+ def test_execopts_env
+ assert_raise(ArgumentError) {
+ system({"F=O"=>"BAR"}, *TRUECOMMAND)
+ }
+
+ h = {}
+ ENV.each {|k,v| h[k] = nil unless k.upcase == "PATH" }
+ IO.popen([h, RUBY, '-e', 'puts ENV.keys.map{|e|e.upcase}']) {|io|
+ assert_equal("PATH\n", io.read)
+ }
+
+ IO.popen([{"FOO"=>"BAR"}, *ENVCOMMAND]) {|io|
+ assert_match(/^FOO=BAR$/, io.read)
+ }
+
+ with_tmpchdir {|d|
+ system({"fofo"=>"haha"}, *ENVCOMMAND, STDOUT=>"out")
+ assert_match(/^fofo=haha$/, File.read("out").chomp)
+ }
+ end
+
+ def test_execopts_unsetenv_others
+ IO.popen([*ENVCOMMAND, :unsetenv_others=>true]) {|io|
+ assert_equal("", io.read)
+ }
+ IO.popen([{"A"=>"B"}, *ENVCOMMAND, :unsetenv_others=>true]) {|io|
+ assert_equal("A=B\n", io.read)
+ }
+ end
+
+ PWD = [RUBY, '-e', 'puts Dir.pwd']
+
+ def test_execopts_chdir
+ with_tmpchdir {|d|
+ IO.popen([*PWD, :chdir => d]) {|io|
+ assert_equal(d, io.read.chomp)
+ }
+ assert_raise(Errno::ENOENT) {
+ Process.wait Process.spawn(*PWD, :chdir => "d/notexist")
+ }
+ }
+ end
+
+ UMASK = [RUBY, '-e', 'printf "%04o\n", File.umask']
+
+ def test_execopts_umask
+ IO.popen([*UMASK, :umask => 0]) {|io|
+ assert_equal("0000", io.read.chomp)
+ }
+ IO.popen([*UMASK, :umask => 0777]) {|io|
+ assert_equal("0777", io.read.chomp)
+ }
+ end
+
+ def with_pipe
+ begin
+ r, w = IO.pipe
+ yield r, w
+ ensure
+ r.close unless r.closed?
+ w.close unless w.closed?
+ end
+ end
+
+ def with_pipes(n)
+ ary = []
+ begin
+ n.times {
+ ary << IO.pipe
+ }
+ yield ary
+ ensure
+ ary.each {|r, w|
+ r.close unless r.closed?
+ w.close unless w.closed?
+ }
+ end
+ end
+
+ ECHO = lambda {|arg| [RUBY, '-e', "puts #{arg.dump}; STDOUT.flush"] }
+ SORT = [RUBY, '-e', "puts ARGF.readlines.sort"]
+ CAT = [RUBY, '-e', "IO.copy_stream STDIN, STDOUT"]
+
+ def test_execopts_redirect
+ with_tmpchdir {|d|
+ Process.wait Process.spawn(*ECHO["a"], STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644])
+ assert_equal("a", File.read("out").chomp)
+ Process.wait Process.spawn(*ECHO["0"], STDOUT=>["out", File::WRONLY|File::CREAT|File::APPEND, 0644])
+ assert_equal("a\n0\n", File.read("out"))
+ Process.wait Process.spawn(*SORT, STDIN=>["out", File::RDONLY, 0644],
+ STDOUT=>["out2", File::WRONLY|File::CREAT|File::TRUNC, 0644])
+ assert_equal("0\na\n", File.read("out2"))
+ Process.wait Process.spawn(*ECHO["b"], [STDOUT, STDERR]=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644])
+ assert_equal("b", File.read("out").chomp)
+ # problem occur with valgrind
+ #Process.wait Process.spawn(*ECHO["a"], STDOUT=>:close, STDERR=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644])
+ #p File.read("out")
+ #assert(!File.read("out").empty?) # error message such as "-e:1:in `flush': Bad file descriptor (Errno::EBADF)"
+ Process.wait Process.spawn(*ECHO["c"], STDERR=>STDOUT, STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644])
+ assert_equal("c", File.read("out").chomp)
+ File.open("out", "w") {|f|
+ Process.wait Process.spawn(*ECHO["d"], f=>STDOUT, STDOUT=>f)
+ assert_equal("d", File.read("out").chomp)
+ }
+ Process.wait Process.spawn(*ECHO["e"], STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644],
+ 3=>STDOUT, 4=>STDOUT, 5=>STDOUT, 6=>STDOUT, 7=>STDOUT)
+ assert_equal("e", File.read("out").chomp)
+ File.open("out", "w") {|f|
+ h = {STDOUT=>f, f=>STDOUT}
+ 3.upto(30) {|i| h[i] = STDOUT if f.fileno != i }
+ Process.wait Process.spawn(*ECHO["f"], h)
+ assert_equal("f", File.read("out").chomp)
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*ECHO["f"], 1=>Process)
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*ECHO["f"], [Process]=>1)
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*ECHO["f"], [1, STDOUT]=>2)
+ }
+ assert_raise(ArgumentError) {
+ Process.wait Process.spawn(*ECHO["f"], -1=>2)
+ }
+ Process.wait Process.spawn(*ECHO["hhh\nggg\n"], STDOUT=>"out")
+ assert_equal("hhh\nggg\n", File.read("out"))
+ Process.wait Process.spawn(*SORT, STDIN=>"out", STDOUT=>"out2")
+ assert_equal("ggg\nhhh\n", File.read("out2"))
+
+ assert_raise(Errno::ENOENT) {
+ Process.wait Process.spawn("non-existing-command", (3..60).to_a=>["err", File::WRONLY|File::CREAT])
+ }
+ assert_equal("", File.read("err"))
+
+ system(*ECHO["bb\naa\n"], STDOUT=>["out", "w"])
+ assert_equal("bb\naa\n", File.read("out"))
+ system(*SORT, STDIN=>["out"], STDOUT=>"out2")
+ assert_equal("aa\nbb\n", File.read("out2"))
+
+ with_pipe {|r1, w1|
+ with_pipe {|r2, w2|
+ pid = spawn(*SORT, STDIN=>r1, STDOUT=>w2, w1=>:close, r2=>:close)
+ r1.close
+ w2.close
+ w1.puts "c"
+ w1.puts "a"
+ w1.puts "b"
+ w1.close
+ assert_equal("a\nb\nc\n", r2.read)
+ Process.wait(pid)
+ }
+ }
+
+ with_pipes(5) {|pipes|
+ ios = pipes.flatten
+ h = {}
+ ios.length.times {|i| h[ios[i]] = ios[(i-1)%ios.length] }
+ h2 = h.invert
+ rios = pipes.map {|r, w| r }
+ wios = pipes.map {|r, w| w }
+ child_wfds = wios.map {|w| h2[w].fileno }
+ pid = spawn(RUBY, "-e",
+ "[#{child_wfds.join(',')}].each {|fd| IO.new(fd).puts fd }", h)
+ pipes.each {|r, w|
+ assert_equal("#{h2[w].fileno}\n", r.gets)
+ }
+ Process.wait pid;
+ }
+
+ with_pipes(5) {|pipes|
+ ios = pipes.flatten
+ h = {}
+ ios.length.times {|i| h[ios[i]] = ios[(i+1)%ios.length] }
+ h2 = h.invert
+ rios = pipes.map {|r, w| r }
+ wios = pipes.map {|r, w| w }
+ child_wfds = wios.map {|w| h2[w].fileno }
+ pid = spawn(RUBY, "-e",
+ "[#{child_wfds.join(',')}].each {|fd| IO.new(fd).puts fd }", h)
+ pipes.each {|r, w|
+ assert_equal("#{h2[w].fileno}\n", r.gets)
+ }
+ Process.wait pid;
+ }
+
+ closed_fd = nil
+ with_pipes(5) {|pipes|
+ io = pipes.last.last
+ closed_fd = io.fileno
+ }
+ assert_raise(Errno::EBADF) { Process.wait spawn(*TRUECOMMAND, closed_fd=>closed_fd) }
+
+ with_pipe {|r, w|
+ w.close_on_exec = true
+ pid = spawn(RUBY, "-e", "IO.new(#{w.fileno}).print 'a'", w=>w)
+ w.close
+ assert_equal("a", r.read)
+ Process.wait pid
+ }
+
+ system(*ECHO["funya"], :out=>"out")
+ assert_equal("funya\n", File.read("out"))
+ system(RUBY, '-e', 'STDOUT.reopen(STDERR); puts "henya"', :err=>"out")
+ assert_equal("henya\n", File.read("out"))
+ IO.popen([*CAT, :in=>"out"]) {|io|
+ assert_equal("henya\n", io.read)
+ }
+ }
+ end
+
+ def test_execopts_exec
+ with_tmpchdir {|d|
+ write_file("s", 'exec "echo aaa", STDOUT=>"foo"')
+ pid = spawn RUBY, 's'
+ Process.wait pid
+ assert_equal("aaa\n", File.read("foo"))
+ }
+ end
+
+ def test_execopts_popen
+ with_tmpchdir {|d|
+ IO.popen("#{RUBY} -e 'puts :foo'") {|io| assert_equal("foo\n", io.read) }
+ assert_raise(Errno::ENOENT) { IO.popen(["echo bar"]) {} } # assuming "echo bar" command not exist.
+ IO.popen(ECHO["baz"]) {|io| assert_equal("baz\n", io.read) }
+ assert_raise(ArgumentError) {
+ IO.popen([*ECHO["qux"], STDOUT=>STDOUT]) {|io| }
+ }
+ IO.popen([*ECHO["hoge"], STDERR=>STDOUT]) {|io|
+ assert_equal("hoge\n", io.read)
+ }
+ assert_raise(ArgumentError) {
+ IO.popen([*ECHO["fuga"], STDOUT=>"out"]) {|io| }
+ }
+ with_pipe {|r, w|
+ IO.popen([RUBY, '-e', 'IO.new(3).puts("a"); puts "b"', 3=>w]) {|io|
+ assert_equal("b\n", io.read)
+ }
+ w.close
+ assert_equal("a\n", r.read)
+ }
+ IO.popen([RUBY, '-e', "IO.new(9).puts(:b)",
+ 9=>["out2", File::WRONLY|File::CREAT|File::TRUNC]]) {|io|
+ assert_equal("", io.read)
+ }
+ assert_equal("b\n", File.read("out2"))
+ }
+ end
+
+ def test_popen_fork
+ return if /freebsd/ =~ RUBY_PLATFORM # this test freeze in FreeBSD
+ IO.popen("-") {|io|
+ if !io
+ puts "fooo"
+ else
+ assert_equal("fooo\n", io.read)
+ end
+ }
+ rescue NotImplementedError
+ end
+
+ def test_fd_inheritance
+ with_pipe {|r, w|
+ system(RUBY, '-e', 'IO.new(ARGV[0].to_i).puts(:ba)', w.fileno.to_s)
+ w.close
+ assert_equal("ba\n", r.read)
+ }
+ with_pipe {|r, w|
+ Process.wait spawn(RUBY, '-e',
+ 'IO.new(ARGV[0].to_i).puts("bi") rescue nil',
+ w.fileno.to_s)
+ w.close
+ assert_equal("", r.read)
+ }
+ with_pipe {|r, w|
+ with_tmpchdir {|d|
+ write_file("s", <<-"End")
+ exec(#{RUBY.dump}, '-e',
+ 'IO.new(ARGV[0].to_i).puts("bu") rescue nil',
+ #{w.fileno.to_s.dump})
+ End
+ Process.wait spawn(RUBY, "s", :close_others=>false)
+ w.close
+ assert_equal("bu\n", r.read)
+ }
+ }
+ with_pipe {|r, w|
+ io = IO.popen([RUBY, "-e", "STDERR.reopen(STDOUT); IO.new(#{w.fileno}).puts('me')"])
+ w.close
+ errmsg = io.read
+ assert_equal("", r.read)
+ assert_not_equal("", errmsg)
+ Process.wait
+ }
+ with_pipe {|r, w|
+ errmsg = `#{RUBY} -e "STDERR.reopen(STDOUT); IO.new(#{w.fileno}).puts(123)"`
+ w.close
+ assert_equal("", r.read)
+ assert_not_equal("", errmsg)
+ }
+ end
+
+ def test_execopts_close_others
+ with_tmpchdir {|d|
+ with_pipe {|r, w|
+ system(RUBY, '-e', 'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i).puts("ma")', w.fileno.to_s, :close_others=>true)
+ w.close
+ assert_equal("", r.read)
+ assert_not_equal("", File.read("err"))
+ File.unlink("err")
+ }
+ with_pipe {|r, w|
+ Process.wait spawn(RUBY, '-e', 'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i).puts("mi")', w.fileno.to_s, :close_others=>true)
+ w.close
+ assert_equal("", r.read)
+ assert_not_equal("", File.read("err"))
+ File.unlink("err")
+ }
+ with_pipe {|r, w|
+ Process.wait spawn(RUBY, '-e', 'IO.new(ARGV[0].to_i).puts("bi")', w.fileno.to_s, :close_others=>false)
+ w.close
+ assert_equal("bi\n", r.read)
+ }
+ with_pipe {|r, w|
+ write_file("s", <<-"End")
+ exec(#{RUBY.dump}, '-e',
+ 'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i).puts("mu")',
+ #{w.fileno.to_s.dump},
+ :close_others=>true)
+ End
+ Process.wait spawn(RUBY, "s", :close_others=>false)
+ w.close
+ assert_equal("", r.read)
+ assert_not_equal("", File.read("err"))
+ File.unlink("err")
+ }
+ with_pipe {|r, w|
+ io = IO.popen([RUBY, "-e", "STDERR.reopen(STDOUT); IO.new(#{w.fileno}).puts('me')", :close_others=>true])
+ w.close
+ errmsg = io.read
+ assert_equal("", r.read)
+ assert_not_equal("", errmsg)
+ Process.wait
+ }
+ with_pipe {|r, w|
+ io = IO.popen([RUBY, "-e", "STDERR.reopen(STDOUT); IO.new(#{w.fileno}).puts('mo')", :close_others=>false])
+ w.close
+ errmsg = io.read
+ assert_equal("mo\n", r.read)
+ assert_equal("", errmsg)
+ Process.wait
+ }
+ with_pipe {|r, w|
+ io = IO.popen([RUBY, "-e", "STDERR.reopen(STDOUT); IO.new(#{w.fileno}).puts('mo')", :close_others=>nil])
+ w.close
+ errmsg = io.read
+ assert_equal("mo\n", r.read)
+ assert_equal("", errmsg)
+ Process.wait
+ }
+
+ }
+ end
+
+ def test_execopts_redirect_self
+ with_pipe {|r, w|
+ w << "haha\n"
+ w.close
+ r.close_on_exec = true
+ IO.popen([RUBY, "-e", "print IO.new(#{r.fileno}).read", r.fileno=>r.fileno, :close_others=>false]) {|io|
+ assert_equal("haha\n", io.read)
+ }
+ }
+ end
+
+ def test_execopts_duplex_io
+ IO.popen("#{RUBY} -e ''", "r+") {|duplex|
+ assert_raise(ArgumentError) { system("#{RUBY} -e ''", duplex=>STDOUT) }
+ assert_raise(ArgumentError) { system("#{RUBY} -e ''", STDOUT=>duplex) }
+ }
+ end
+
+ def test_execopts_modification
+ h = {}
+ Process.wait spawn(*TRUECOMMAND, h)
+ assert_equal({}, h)
+
+ h = {}
+ system(*TRUECOMMAND, h)
+ assert_equal({}, h)
+
+ h = {}
+ io = IO.popen([*TRUECOMMAND, h])
+ io.close
+ assert_equal({}, h)
+ end
+
+ def test_system_noshell
+ str = "echo non existing command name which contains spaces"
+ assert_nil(system([str, str]))
+ end
+
+ def test_spawn_noshell
+ str = "echo non existing command name which contains spaces"
+ assert_raise(Errno::ENOENT) { spawn([str, str]) }
+ end
+
+ def test_popen_noshell
+ str = "echo non existing command name which contains spaces"
+ assert_raise(Errno::ENOENT) { IO.popen([str, str]) }
+ end
+
+ def test_exec_noshell
+ with_tmpchdir {|d|
+ with_pipe {|r, w|
+ write_file("s", <<-"End")
+ str = "echo non existing command name which contains spaces"
+ w = IO.new(#{w.fileno})
+ STDOUT.reopen(w)
+ STDERR.reopen(w)
+ begin
+ exec [str, str]
+ rescue Errno::ENOENT
+ w.write "Errno::ENOENT success"
+ end
+ End
+ system(RUBY, "s", :close_others=>false)
+ w.close
+ assert_equal("Errno::ENOENT success", r.read)
+ }
+ }
+ end
+
+ def test_system_wordsplit
+ with_tmpchdir {|d|
+ write_file("script", <<-'End')
+ File.open("result", "w") {|t| t << "haha pid=#{$$} ppid=#{Process.ppid}" }
+ exit 5
+ End
+ str = "#{RUBY} script"
+ ret = system(str)
+ status = $?
+ assert_equal(false, ret)
+ assert(status.exited?)
+ assert_equal(5, status.exitstatus)
+ assert_equal("haha pid=#{status.pid} ppid=#{$$}", File.read("result"))
+ }
+ end
+
+ def test_spawn_wordsplit
+ with_tmpchdir {|d|
+ write_file("script", <<-'End')
+ File.open("result", "w") {|t| t << "hihi pid=#{$$} ppid=#{Process.ppid}" }
+ exit 6
+ End
+ str = "#{RUBY} script"
+ pid = spawn(str)
+ Process.wait pid
+ status = $?
+ assert_equal(pid, status.pid)
+ assert(status.exited?)
+ assert_equal(6, status.exitstatus)
+ assert_equal("hihi pid=#{status.pid} ppid=#{$$}", File.read("result"))
+ }
+ end
+
+ def test_popen_wordsplit
+ with_tmpchdir {|d|
+ write_file("script", <<-'End')
+ print "fufu pid=#{$$} ppid=#{Process.ppid}"
+ exit 7
+ End
+ str = "#{RUBY} script"
+ io = IO.popen(str)
+ pid = io.pid
+ result = io.read
+ io.close
+ status = $?
+ assert_equal(pid, status.pid)
+ assert(status.exited?)
+ assert_equal(7, status.exitstatus)
+ assert_equal("fufu pid=#{status.pid} ppid=#{$$}", result)
+ }
+ end
+
+ def test_exec_wordsplit
+ with_tmpchdir {|d|
+ write_file("script", <<-'End')
+ File.open("result", "w") {|t|
+ if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
+ t << "hehe ppid=#{Process.ppid}"
+ else
+ t << "hehe pid=#{$$} ppid=#{Process.ppid}"
+ end
+ }
+ exit 6
+ End
+ write_file("s", <<-"End")
+ ruby = #{RUBY.dump}
+ exec "\#{ruby} script"
+ End
+ pid = spawn(RUBY, "s")
+ Process.wait pid
+ status = $?
+ assert_equal(pid, status.pid)
+ assert(status.exited?)
+ assert_equal(6, status.exitstatus)
+ if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
+ expected = "hehe ppid=#{status.pid}"
+ else
+ expected = "hehe pid=#{status.pid} ppid=#{$$}"
+ end
+ assert_equal(expected, File.read("result"))
+ }
+ end
+
+ def test_system_shell
+ with_tmpchdir {|d|
+ write_file("script1", <<-'End')
+ File.open("result1", "w") {|t| t << "taka pid=#{$$} ppid=#{Process.ppid}" }
+ exit 7
+ End
+ write_file("script2", <<-'End')
+ File.open("result2", "w") {|t| t << "taki pid=#{$$} ppid=#{Process.ppid}" }
+ exit 8
+ End
+ ret = system("#{RUBY} script1 || #{RUBY} script2")
+ status = $?
+ assert_equal(false, ret)
+ assert(status.exited?)
+ result1 = File.read("result1")
+ result2 = File.read("result2")
+ assert_match(/\Ataka pid=\d+ ppid=\d+\z/, result1)
+ assert_match(/\Ataki pid=\d+ ppid=\d+\z/, result2)
+ assert_not_equal(result1[/\d+/].to_i, status.pid)
+ }
+ end
+
+ def test_spawn_shell
+ with_tmpchdir {|d|
+ write_file("script1", <<-'End')
+ File.open("result1", "w") {|t| t << "taku pid=#{$$} ppid=#{Process.ppid}" }
+ exit 7
+ End
+ write_file("script2", <<-'End')
+ File.open("result2", "w") {|t| t << "take pid=#{$$} ppid=#{Process.ppid}" }
+ exit 8
+ End
+ pid = spawn("#{RUBY} script1 || #{RUBY} script2")
+ Process.wait pid
+ status = $?
+ assert(status.exited?)
+ assert(!status.success?)
+ result1 = File.read("result1")
+ result2 = File.read("result2")
+ assert_match(/\Ataku pid=\d+ ppid=\d+\z/, result1)
+ assert_match(/\Atake pid=\d+ ppid=\d+\z/, result2)
+ assert_not_equal(result1[/\d+/].to_i, status.pid)
+ }
+ end
+
+ def test_popen_shell
+ with_tmpchdir {|d|
+ write_file("script1", <<-'End')
+ puts "tako pid=#{$$} ppid=#{Process.ppid}"
+ exit 7
+ End
+ write_file("script2", <<-'End')
+ puts "tika pid=#{$$} ppid=#{Process.ppid}"
+ exit 8
+ End
+ io = IO.popen("#{RUBY} script1 || #{RUBY} script2")
+ result = io.read
+ io.close
+ status = $?
+ assert(status.exited?)
+ assert(!status.success?)
+ assert_match(/\Atako pid=\d+ ppid=\d+\ntika pid=\d+ ppid=\d+\n\z/, result)
+ assert_not_equal(result[/\d+/].to_i, status.pid)
+ }
+ end
+
+ def test_exec_shell
+ with_tmpchdir {|d|
+ write_file("script1", <<-'End')
+ File.open("result1", "w") {|t| t << "tiki pid=#{$$} ppid=#{Process.ppid}" }
+ exit 7
+ End
+ write_file("script2", <<-'End')
+ File.open("result2", "w") {|t| t << "tiku pid=#{$$} ppid=#{Process.ppid}" }
+ exit 8
+ End
+ write_file("s", <<-"End")
+ ruby = #{RUBY.dump}
+ exec("\#{ruby} script1 || \#{ruby} script2")
+ End
+ pid = spawn RUBY, "s"
+ Process.wait pid
+ status = $?
+ assert(status.exited?)
+ assert(!status.success?)
+ result1 = File.read("result1")
+ result2 = File.read("result2")
+ assert_match(/\Atiki pid=\d+ ppid=\d+\z/, result1)
+ assert_match(/\Atiku pid=\d+ ppid=\d+\z/, result2)
+ assert_not_equal(result1[/\d+/].to_i, status.pid)
+ }
+ end
+
+ def test_argv0
+ with_tmpchdir {|d|
+ assert_equal(false, system([RUBY, "asdfg"], "-e", "exit false"))
+ assert_equal(true, system([RUBY, "zxcvb"], "-e", "exit true"))
+
+ Process.wait spawn([RUBY, "poiu"], "-e", "exit 4")
+ assert_equal(4, $?.exitstatus)
+
+ assert_equal("1", IO.popen([[RUBY, "qwerty"], "-e", "print 1"]).read)
+ Process.wait
+
+ write_file("s", <<-"End")
+ exec([#{RUBY.dump}, "lkjh"], "-e", "exit 5")
+ End
+ pid = spawn RUBY, "s"
+ Process.wait pid
+ assert_equal(5, $?.exitstatus)
+ }
+ end
+
+ def with_stdin(filename)
+ open(filename) {|f|
+ begin
+ old = STDIN.dup
+ begin
+ STDIN.reopen(filename)
+ yield
+ ensure
+ STDIN.reopen(old)
+ end
+ ensure
+ old.close
+ end
+ }
+ end
+
+ def test_argv0_noarg
+ with_tmpchdir {|d|
+ open("t", "w") {|f| f.print "exit true" }
+ open("f", "w") {|f| f.print "exit false" }
+
+ with_stdin("t") { assert_equal(true, system([RUBY, "qaz"])) }
+ with_stdin("f") { assert_equal(false, system([RUBY, "wsx"])) }
+
+ with_stdin("t") { Process.wait spawn([RUBY, "edc"]) }
+ assert($?.success?)
+ with_stdin("f") { Process.wait spawn([RUBY, "rfv"]) }
+ assert(!$?.success?)
+
+ with_stdin("t") { IO.popen([[RUBY, "tgb"]]) {|io| assert_equal("", io.read) } }
+ assert($?.success?)
+ with_stdin("f") { IO.popen([[RUBY, "yhn"]]) {|io| assert_equal("", io.read) } }
+ assert(!$?.success?)
+
+ status = run_in_child "STDIN.reopen('t'); exec([#{RUBY.dump}, 'ujm'])"
+ assert(status.success?)
+ status = run_in_child "STDIN.reopen('f'); exec([#{RUBY.dump}, 'ik,'])"
+ assert(!status.success?)
+ }
+ end
+
+ def test_status
+ with_tmpchdir do
+ s = run_in_child("exit 1")
+ assert_equal("#<Process::Status: pid #{ s.pid } exit #{ s.exitstatus }>", s.inspect)
+
+ assert_equal(s, s)
+ assert_equal(s, s.to_i)
+
+ assert_equal(s.to_i & 0x55555555, s & 0x55555555)
+ assert_equal(s.to_i >> 1, s >> 1)
+ assert_equal(false, s.stopped?)
+ assert_equal(nil, s.stopsig)
+ end
+ end
+
+ def test_status_kill
+ return unless Process.respond_to?(:kill)
+ return unless Signal.list.include?("QUIT")
+
+ with_tmpchdir do
+ write_file("foo", "sleep 30")
+ pid = spawn(RUBY, "foo")
+ Thread.new { sleep 1; Process.kill(:SIGQUIT, pid) }
+ Process.wait(pid)
+ s = $?
+ assert_send(
+ [["#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig })>",
+ "#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig }) (core dumped)>"],
+ :include?,
+ s.inspect])
+ assert_equal(false, s.exited?)
+ assert_equal(nil, s.success?)
+ end
+ end
+
+ def test_wait_without_arg
+ with_tmpchdir do
+ write_file("foo", "sleep 0.1")
+ pid = spawn(RUBY, "foo")
+ assert_equal(pid, Process.wait)
+ end
+ end
+
+ def test_wait2
+ with_tmpchdir do
+ write_file("foo", "sleep 0.1")
+ pid = spawn(RUBY, "foo")
+ assert_equal([pid, 0], Process.wait2)
+ end
+ end
+
+ def test_waitall
+ with_tmpchdir do
+ write_file("foo", "sleep 0.1")
+ ps = (0...3).map { spawn(RUBY, "foo") }.sort
+ ss = Process.waitall.sort
+ ps.zip(ss) do |p1, (p2, s)|
+ assert_equal(p1, p2)
+ assert_equal(p1, s.pid)
+ end
+ end
+ end
+
+ def test_abort
+ with_tmpchdir do
+ s = run_in_child("abort")
+ assert_not_equal(0, s.exitstatus)
+ end
+ end
+
+ def test_sleep
+ assert_raise(ArgumentError) { sleep(1, 1) }
+ end
+
+ def test_getpgid
+ assert_kind_of(Integer, Process.getpgid(Process.ppid))
+ rescue NotImplementedError
+ end
+
+ def test_getpriority
+ assert_kind_of(Integer, Process.getpriority(Process::PRIO_PROCESS, $$))
+ rescue NameError, NotImplementedError
+ end
+
+ def test_setpriority
+ if defined? Process::PRIO_USER
+ assert_nothing_raised do
+ pr = Process.getpriority(Process::PRIO_PROCESS, $$)
+ Process.setpriority(Process::PRIO_PROCESS, $$, pr)
+ end
+ end
+ end
+
+ def test_getuid
+ assert_kind_of(Integer, Process.uid)
+ end
+
+ def test_groups
+ gs = Process.groups
+ assert_instance_of(Array, gs)
+ gs.each {|g| assert_kind_of(Integer, g) }
+ rescue NotImplementedError
+ end
+
+ def test_maxgroups
+ assert_kind_of(Integer, Process.maxgroups)
+ end
+
+ def test_geteuid
+ assert_kind_of(Integer, Process.egid)
+ end
+
+ def test_uid_re_exchangeable_p
+ r = Process::UID.re_exchangeable?
+ assert(true == r || false == r)
+ end
+
+ def test_gid_re_exchangeable_p
+ r = Process::GID.re_exchangeable?
+ assert(true == r || false == r)
+ end
+
+ def test_uid_sid_available?
+ r = Process::UID.sid_available?
+ assert(true == r || false == r)
+ end
+
+ def test_gid_sid_available?
+ r = Process::GID.sid_available?
+ assert(true == r || false == r)
+ end
+
+ def test_pst_inspect
+ assert_nothing_raised { Process::Status.allocate.inspect }
+ end
+end
diff --git a/trunk/test/ruby/test_rand.rb b/trunk/test/ruby/test_rand.rb
new file mode 100644
index 0000000000..b7d841dbba
--- /dev/null
+++ b/trunk/test/ruby/test_rand.rb
@@ -0,0 +1,167 @@
+require 'test/unit'
+
+class TestRand < Test::Unit::TestCase
+ def test_mt
+ srand(0x00000456_00000345_00000234_00000123)
+ %w(1067595299 955945823 477289528 4107218783 4228976476).each {|w|
+ assert_equal(w.to_i, rand(0x100000000))
+ }
+ end
+
+ def test_0x3fffffff
+ srand(0)
+ %w(209652396 398764591 924231285 404868288 441365315).each {|w|
+ assert_equal(w.to_i, rand(0x3fffffff))
+ }
+ end
+
+ def test_0x40000000
+ srand(0)
+ %w(209652396 398764591 924231285 404868288 441365315).each {|w|
+ assert_equal(w.to_i, rand(0x40000000))
+ }
+ end
+
+ def test_0x40000001
+ srand(0)
+ %w(209652396 398764591 924231285 441365315 192771779).each {|w|
+ assert_equal(w.to_i, rand(0x40000001))
+ }
+ end
+
+ def test_0xffffffff
+ srand(0)
+ %w(2357136044 2546248239 3071714933 3626093760 2588848963).each {|w|
+ assert_equal(w.to_i, rand(0xffffffff))
+ }
+ end
+
+ def test_0x100000000
+ srand(0)
+ %w(2357136044 2546248239 3071714933 3626093760 2588848963).each {|w|
+ assert_equal(w.to_i, rand(0x100000000))
+ }
+ end
+
+ def test_0x100000001
+ srand(0)
+ %w(2546248239 1277901399 243580376 1171049868 2051556033).each {|w|
+ assert_equal(w.to_i, rand(0x100000001))
+ }
+ end
+
+ def test_rand_0x100000000
+ srand(311702798)
+ %w(4119812344 3870378946 80324654 4294967296 410016213).each {|w|
+ assert_equal(w.to_i, rand(0x100000001))
+ }
+ end
+
+ def test_0x1000000000000
+ srand(0)
+ %w(11736396900911
+ 183025067478208
+ 197104029029115
+ 130583529618791
+ 180361239846611).each {|w|
+ assert_equal(w.to_i, rand(0x1000000000000))
+ }
+ end
+
+ def test_0x1000000000001
+ srand(0)
+ %w(187121911899765
+ 197104029029115
+ 180361239846611
+ 236336749852452
+ 208739549485656).each {|w|
+ assert_equal(w.to_i, rand(0x1000000000001))
+ }
+ end
+
+ def test_0x3fffffffffffffff
+ srand(0)
+ %w(900450186894289455
+ 3969543146641149120
+ 1895649597198586619
+ 827948490035658087
+ 3203365596207111891).each {|w|
+ assert_equal(w.to_i, rand(0x3fffffffffffffff))
+ }
+ end
+
+ def test_0x4000000000000000
+ srand(0)
+ %w(900450186894289455
+ 3969543146641149120
+ 1895649597198586619
+ 827948490035658087
+ 3203365596207111891).each {|w|
+ assert_equal(w.to_i, rand(0x4000000000000000))
+ }
+ end
+
+ def test_0x4000000000000001
+ srand(0)
+ %w(900450186894289455
+ 3969543146641149120
+ 1895649597198586619
+ 827948490035658087
+ 2279347887019741461).each {|w|
+ assert_equal(w.to_i, rand(0x4000000000000001))
+ }
+ end
+
+ def test_neg_0x10000000000
+ ws = %w(455570294424 1073054410371 790795084744 2445173525 1088503892627)
+ srand(3)
+ ws.each {|w| assert_equal(w.to_i, rand(0x10000000000)) }
+ srand(3)
+ ws.each {|w| assert_equal(w.to_i, rand(-0x10000000000)) }
+ end
+
+ def test_neg_0x10000
+ ws = %w(2732 43567 42613 52416 45891)
+ srand(0)
+ ws.each {|w| assert_equal(w.to_i, rand(0x10000)) }
+ srand(0)
+ ws.each {|w| assert_equal(w.to_i, rand(-0x10000)) }
+ end
+
+ def test_types
+ srand(0)
+ assert_equal(44, rand(100.0))
+ assert_equal(1245085576965981900420779258691, rand((2**100).to_f))
+ assert_equal(914679880601515615685077935113, rand(-(2**100).to_f))
+
+ srand(0)
+ assert_equal(997707939797331598305742933184, rand(2**100))
+ assert_in_delta(0.602763376071644, rand((2**100).coerce(0).first),
+ 0.000000000000001)
+
+ srand(0)
+ assert_in_delta(0.548813503927325, rand(nil),
+ 0.000000000000001)
+ srand(0)
+ o = Object.new
+ def o.to_i; 100; end
+ assert_equal(44, rand(o))
+ assert_equal(47, rand(o))
+ assert_equal(64, rand(o))
+ end
+
+ def test_srand
+ srand
+ assert_kind_of(Integer, rand(2))
+
+ srand(2**100)
+ %w(3258412053).each {|w|
+ assert_equal(w.to_i, rand(0x100000000))
+ }
+ end
+
+ def test_shuffle
+ srand(0)
+ assert_equal([1,4,2,5,3], [1,2,3,4,5].shuffle)
+ end
+end
diff --git a/trunk/test/ruby/test_range.rb b/trunk/test/ruby/test_range.rb
new file mode 100644
index 0000000000..81be101857
--- /dev/null
+++ b/trunk/test/ruby/test_range.rb
@@ -0,0 +1,270 @@
+require 'test/unit'
+
+class TestRange < Test::Unit::TestCase
+ def test_range_string
+ # XXX: Is this really the test of Range?
+ assert_equal([], ("a" ... "a").to_a)
+ assert_equal(["a"], ("a" .. "a").to_a)
+ assert_equal(["a"], ("a" ... "b").to_a)
+ assert_equal(["a", "b"], ("a" .. "b").to_a)
+ end
+
+ def test_evaluation_order
+ arr = [1,2]
+ r = (arr.shift)..(arr.shift)
+ assert_equal(1..2, r, "[ruby-dev:26383]")
+ end
+
+ class DuckRange
+ def initialize(b,e,excl=false)
+ @begin = b
+ @end = e
+ @excl = excl
+ end
+ attr_reader :begin, :end
+
+ def exclude_end?
+ @excl
+ end
+ end
+
+ def test_duckrange
+ assert_equal("bc", "abcd"[DuckRange.new(1,2)])
+ end
+
+ def test_min
+ assert_equal(1, (1..2).min)
+ assert_equal(nil, (2..1).min)
+ assert_equal(1, (1...2).min)
+
+ assert_equal(1.0, (1.0..2.0).min)
+ assert_equal(nil, (2.0..1.0).min)
+ assert_equal(1, (1.0...2.0).min)
+
+ assert_equal(0, (0..0).min)
+ assert_equal(nil, (0...0).min)
+ end
+
+ def test_max
+ assert_equal(2, (1..2).max)
+ assert_equal(nil, (2..1).max)
+ assert_equal(1, (1...2).max)
+
+ assert_equal(2.0, (1.0..2.0).max)
+ assert_equal(nil, (2.0..1.0).max)
+ assert_raise(TypeError) { (1.0...2.0).max }
+
+ assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)
+
+ assert_equal(0, (0..0).max)
+ assert_equal(nil, (0...0).max)
+ end
+
+ def test_initialize_twice
+ r = eval("1..2")
+ assert_raise(NameError) { r.instance_eval { initialize 3, 4 } }
+ end
+
+ def test_uninitialized_range
+ r = Range.allocate
+ s = Marshal.dump(r)
+ r = Marshal.load(s)
+ assert_nothing_raised { r.instance_eval { initialize 5, 6} }
+ end
+
+ def test_bad_value
+ assert_raise(ArgumentError) { (1 .. :a) }
+ end
+
+ def test_exclude_end
+ assert(!((0..1).exclude_end?))
+ assert((0...1).exclude_end?)
+ end
+
+ def test_eq
+ r = (0..1)
+ assert(r == r)
+ assert(r == (0..1))
+ assert(r != 0)
+ assert(r != (1..2))
+ assert(r != (0..2))
+ assert(r != (0...1))
+ end
+
+ def test_eql
+ r = (0..1)
+ assert(r.eql?(r))
+ assert(r.eql?(0..1))
+ assert(!r.eql?(0))
+ assert(!r.eql?(1..2))
+ assert(!r.eql?(0..2))
+ assert(!r.eql?(0...1))
+ end
+
+ def test_hash
+ assert((0..1).hash.is_a?(Fixnum))
+ end
+
+ def test_step
+ a = []
+ (0..10).step {|x| a << x }
+ assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)
+
+ a = []
+ (0..10).step(2) {|x| a << x }
+ assert_equal([0, 2, 4, 6, 8, 10], a)
+
+ assert_raise(ArgumentError) { (0..10).step(-1) { } }
+ assert_raise(ArgumentError) { (0..10).step(0) { } }
+
+ a = []
+ ("a" .. "z").step(2) {|x| a << x }
+ assert_equal(%w(a c e g i k m o q s u w y), a)
+
+ a = []
+ ("a" .. "z").step(2**32) {|x| a << x }
+ assert_equal(["a"], a)
+
+ a = []
+ (2**32-1 .. 2**32+1).step(2) {|x| a << x }
+ assert_equal([4294967295, 4294967297], a)
+ zero = (2**32).coerce(0).first
+ assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }
+
+ o1 = Object.new
+ o2 = Object.new
+ def o1.<=>(x); -1; end
+ def o2.<=>(x); 0; end
+ assert_raise(TypeError) { (o1..o2).step(1) { } }
+
+ class << o1; self; end.class_eval do
+ define_method(:succ) { o2 }
+ end
+ a = []
+ (o1..o2).step(1) {|x| a << x }
+ assert_equal([o1, o2], a)
+
+ a = []
+ (o1...o2).step(1) {|x| a << x }
+ assert_equal([o1], a)
+
+ assert_nothing_raised("[ruby-dev:34557]") { (0..2).step(0.5) {|x| } }
+
+ a = []
+ (0..2).step(0.5) {|x| a << x }
+ assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)
+
+ a = []
+ (0x40000000..0x40000002).step(0.5) {|x| a << x }
+ assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)
+
+ o = Object.new
+ def o.to_int() 1 end
+ assert_nothing_raised("[ruby-dev:34558]") { (0..2).step(o) {|x| } }
+ end
+
+ def test_each
+ a = []
+ (0..10).each {|x| a << x }
+ assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)
+
+ o1 = Object.new
+ o2 = Object.new
+ def o1.<=>(x); -1; end
+ def o2.<=>(x); 0; end
+ class << o1; self; end.class_eval do
+ define_method(:succ) { o2 }
+ end
+
+ r1 = (o1..o2)
+ r2 = (o1...o2)
+
+ a = []
+ r1.each {|x| a << x }
+ assert_equal([o1, o2], a)
+
+ a = []
+ r2.each {|x| a << x }
+ assert_equal([o1], a)
+
+ def o2.<=>(x); 1; end
+
+ a = []
+ r1.each {|x| a << x }
+ assert_equal([o1], a)
+
+ def o2.<=>(x); nil; end
+
+ a = []
+ r1.each {|x| a << x }
+ assert_equal([o1], a)
+
+ def o1.<=>(x); nil; end
+
+ a = []
+ r2.each {|x| a << x }
+ assert_equal([], a)
+ end
+
+ def test_begin_end
+ assert_equal(0, (0..1).begin)
+ assert_equal(1, (0..1).end)
+ end
+
+ def test_first_last
+ assert_equal([0, 1, 2], (0..10).first(3))
+ assert_equal([8, 9, 10], (0..10).last(3))
+ end
+
+ def test_to_s
+ assert_equal("0..1", (0..1).to_s)
+ assert_equal("0...1", (0...1).to_s)
+ end
+
+ def test_inspect
+ assert_equal("0..1", (0..1).inspect)
+ assert_equal("0...1", (0...1).inspect)
+ end
+
+ def test_eqq
+ assert((0..10) === 5)
+ assert(!((0..10) === 11))
+ end
+
+ def test_include
+ assert(("a".."z").include?("c"))
+ assert(!(("a".."z").include?("5")))
+ assert(("a"..."z").include?("y"))
+ assert(!(("a"..."z").include?("z")))
+ assert(!(("a".."z").include?("cc")))
+ assert((0...10).include?(5))
+ end
+
+ def test_cover
+ assert(("a".."z").cover?("c"))
+ assert(!(("a".."z").cover?("5")))
+ assert(("a"..."z").cover?("y"))
+ assert(!(("a"..."z").cover?("z")))
+ assert(("a".."z").cover?("cc"))
+ end
+
+ def test_beg_len
+ o = Object.new
+ assert_raise(TypeError) { [][o] }
+ def o.begin; -10; end
+ assert_raise(TypeError) { [][o] }
+ def o.end; 0; end
+ assert_raise(NoMethodError) { [][o] }
+ def o.exclude_end?; false; end
+ assert_nil([0][o])
+ assert_raise(RangeError) { [0][o] = 1 }
+ def o.begin; 10; end
+ def o.end; 10; end
+ assert_nil([0][o])
+ def o.begin; 0; end
+ assert_equal([0], [0][o])
+ def o.begin; 2; end
+ def o.end; 0; end
+ assert_equal([], [0, 1, 2][o])
+ end
+end
diff --git a/trunk/test/ruby/test_rational.rb b/trunk/test/ruby/test_rational.rb
new file mode 100644
index 0000000000..eb52e3e193
--- /dev/null
+++ b/trunk/test/ruby/test_rational.rb
@@ -0,0 +1,1074 @@
+require 'test/unit'
+
+class RationalSub < Rational; end
+
+class Rational_Test < Test::Unit::TestCase
+
+ def test_ratsub
+ c = RationalSub.__send__(:new, 1)
+ cc = RationalSub.__send__(:convert, 1)
+ if defined?(RationalSub::Unify)
+ assert_instance_of(Fixnum, c)
+ assert_instance_of(Fixnum, cc)
+ else
+ assert_instance_of(RationalSub, c)
+ assert_instance_of(RationalSub, cc)
+
+ c2 = c + 1
+ assert_instance_of(RationalSub, c2)
+ c2 = c - 1
+ assert_instance_of(RationalSub, c2)
+
+ c3 = c - c2
+ assert_instance_of(RationalSub, c3)
+
+ s = Marshal.dump(c)
+ c5 = Marshal.load(s)
+ assert_equal(c, c5)
+ assert_instance_of(RationalSub, c5)
+ end
+ end
+
+ def test_hash
+ assert_instance_of(Fixnum, Rational(1,2).hash)
+
+ h = {}
+ h[Rational(0)] = 0
+ h[Rational(1,1)] = 1
+ h[Rational(2,1)] = 2
+ h[Rational(3,1)] = 3
+
+ assert_equal(4, h.size)
+ assert_equal(2, h[Rational(2,1)])
+
+ h[Rational(0,1)] = 9
+ assert_equal(4, h.size)
+ end
+
+ def test_freeze
+ c = Rational(1)
+ c.freeze
+ unless defined?(Rational::Unify)
+ assert_equal(true, c.frozen?)
+ end
+ assert_instance_of(String, c.to_s)
+ end
+
+ def test_new_bang # no unify & no reduce
+ assert_instance_of(Rational, Rational.__send__(:new!, 2,1))
+ assert_equal([2,1], Rational.__send__(:new!, 2,1).
+ instance_eval{[numerator, denominator]})
+ assert_equal([2,4], Rational.__send__(:new!, 2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-2,4], Rational.__send__(:new!, -2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-2,4], Rational.__send__(:new!, 2,-4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([2,4], Rational.__send__(:new!, -2,-4).
+ instance_eval{[numerator, denominator]})
+
+ # to_i
+ assert_equal([2,1], Rational.__send__(:new!, Rational(2)).
+ instance_eval{[numerator, denominator]})
+ assert_equal([2,3], Rational.__send__(:new!, Rational(2), Rational(3)).
+ instance_eval{[numerator, denominator]})
+ assert_equal([2,3], Rational.__send__(:new!, 2, Rational(3)).
+ instance_eval{[numerator, denominator]})
+
+ assert_equal([1,1], Rational.__send__(:new!, 1.1).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-1,1], Rational.__send__(:new!, -1.1).
+ instance_eval{[numerator, denominator]})
+ assert_equal([1,1], Rational.__send__(:new!, '1').
+ instance_eval{[numerator, denominator]})
+ assert_equal([0,1], Rational.__send__(:new!, nil).
+ instance_eval{[numerator, denominator]})
+
+ assert_raise(ZeroDivisionError){Rational.__send__(:new!, 1, 0)}
+ end
+
+=begin
+ def test_reduce
+ if defined?(Rational::Unify)
+ assert_instance_of(Fixnum, Rational.__send__(:reduce, 2,1))
+ else
+ assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
+ assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
+ end
+ assert_equal([2,1], Rational.__send__(:reduce, 2,1).
+ instance_eval{[numerator, denominator]})
+ assert_equal([1,2], Rational.__send__(:reduce, 2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-1,2], Rational.__send__(:reduce, -2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-1,2], Rational.__send__(:reduce, 2,-4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([1,2], Rational.__send__(:reduce, -2,-4).
+ instance_eval{[numerator, denominator]})
+
+ assert_raise(ArgumentError){Rational.__send__(:reduce, Rational(1,2),2)}
+ assert_raise(ArgumentError){Rational.__send__(:reduce, 2,Rational(1,2))}
+ assert_raise(ArgumentError){Rational.
+ __send__(:reduce, Rational(1,2),Rational(1,2))}
+
+ assert_raise(ArgumentError){Rational.__send__(:reduce, 1.1)}
+ assert_raise(ArgumentError){Rational.__send__(:reduce, -1.1)}
+ assert_raise(ArgumentError){Rational.__send__(:reduce, '1')}
+ assert_raise(ArgumentError){Rational.__send__(:reduce, nil)}
+ end
+=end
+
+ def test_new
+ if defined?(Rational::Unify)
+ assert_instance_of(Fixnum, Rational.__send__(:new, 2,1))
+ else
+ assert_instance_of(Rational, Rational.__send__(:new, 2,1))
+ assert_equal([2,1], Rational.__send__(:new, 2,1).
+ instance_eval{[numerator, denominator]})
+ end
+ assert_equal([1,2], Rational.__send__(:new, 2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-1,2], Rational.__send__(:new, -2,4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([-1,2], Rational.__send__(:new, 2,-4).
+ instance_eval{[numerator, denominator]})
+ assert_equal([1,2], Rational.__send__(:new, -2,-4).
+ instance_eval{[numerator, denominator]})
+
+ assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),2)}
+ assert_raise(ArgumentError){Rational.__send__(:new, 2,Rational(1,2))}
+ assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),Rational(1,2))}
+
+ assert_raise(ArgumentError){Rational.__send__(:new, 1.1)}
+ assert_raise(ArgumentError){Rational.__send__(:new, -1.1)}
+ assert_raise(ArgumentError){Rational.__send__(:new, '1')}
+ assert_raise(ArgumentError){Rational.__send__(:new, nil)}
+=begin
+ assert_raise(ArgumentError){Rational.__send__(:new, Rational(1))}
+ if defined?(Complex)
+ assert_raise(ArgumentError){Rational.__send__(:new, Complex(1))}
+ end
+=end
+ end
+
+ def test_conv
+ c = Rational(0,1)
+ assert_equal(Rational.__send__(:new, 0,1), c)
+
+ c = Rational(2**32, 2**32)
+ assert_equal(Rational.__send__(:new, 2**32,2**32), c)
+ assert_equal([1,1], [c.numerator,c.denominator])
+
+ c = Rational(-2**32, 2**32)
+ assert_equal(Rational.__send__(:new, -2**32,2**32), c)
+ assert_equal([-1,1], [c.numerator,c.denominator])
+
+ c = Rational(2**32, -2**32)
+ assert_equal(Rational.__send__(:new, 2**32,-2**32), c)
+ assert_equal([-1,1], [c.numerator,c.denominator])
+
+ c = Rational(-2**32, -2**32)
+ assert_equal(Rational.__send__(:new, -2**32,-2**32), c)
+ assert_equal([1,1], [c.numerator,c.denominator])
+
+ c = Rational(Rational(1,2),2)
+ assert_equal(Rational.__send__(:new, 1,4), c)
+
+ c = Rational(2,Rational(1,2))
+ assert_equal(Rational.__send__(:new, 4), c)
+
+ c = Rational(Rational(1,2),Rational(1,2))
+ assert_equal(Rational.__send__(:new, 1), c)
+
+ assert_equal(Rational.__send__(:new, 1),Rational(1))
+ assert_equal(1.1.to_r,Rational(1.1))
+ assert_equal(Rational.__send__(:new, 1),Rational('1'))
+ assert_raise(ArgumentError){Rational(nil)}
+ end
+
+ def test_attr
+ c = Rational(4)
+
+ assert_equal(4, c.numerator)
+ assert_equal(1, c.denominator)
+
+ c = Rational(4,5)
+
+ assert_equal(4, c.numerator)
+ assert_equal(5, c.denominator)
+
+ c = Rational.__send__(:new, 4)
+
+ assert_equal(4, c.numerator)
+ assert_equal(1, c.denominator)
+
+ c = Rational.__send__(:new, 4,5)
+
+ assert_equal(4, c.numerator)
+ assert_equal(5, c.denominator)
+
+ c = Rational.__send__(:new!, 4)
+
+ assert_equal(4, c.numerator)
+ assert_equal(1, c.denominator)
+
+ c = Rational.__send__(:new!, 4,5)
+
+ assert_equal(4, c.numerator)
+ assert_equal(5, c.denominator)
+ end
+
+ def test_attr2
+ c = Rational(1)
+
+ if defined?(Rational::Unify)
+ assert_equal(true, c.scalar?)
+=begin
+ assert_equal(true, c.finite?)
+ assert_equal(false, c.infinite?)
+ assert_equal(false, c.nan?)
+ assert_equal(true, c.integer?)
+ assert_equal(false, c.float?)
+ assert_equal(true, c.rational?)
+ assert_equal(true, c.real?)
+ assert_equal(false, c.complex?)
+ assert_equal(true, c.exact?)
+ assert_equal(false, c.inexact?)
+=end
+ else
+ assert_equal(true, c.scalar?)
+=begin
+ assert_equal(true, c.finite?)
+ assert_equal(false, c.infinite?)
+ assert_equal(false, c.nan?)
+ assert_equal(false, c.integer?)
+ assert_equal(false, c.float?)
+ assert_equal(true, c.rational?)
+ assert_equal(true, c.real?)
+ assert_equal(false, c.complex?)
+ assert_equal(true, c.exact?)
+ assert_equal(false, c.inexact?)
+=end
+ end
+
+=begin
+ assert_equal(true, Rational(0).positive?)
+ assert_equal(true, Rational(1).positive?)
+ assert_equal(false, Rational(-1).positive?)
+ assert_equal(false, Rational(0).negative?)
+ assert_equal(false, Rational(1).negative?)
+ assert_equal(true, Rational(-1).negative?)
+
+ assert_equal(0, Rational(0).sign)
+ assert_equal(1, Rational(2).sign)
+ assert_equal(-1, Rational(-2).sign)
+=end
+
+ assert_equal(true, Rational(0).zero?)
+ assert_equal(true, Rational(0,1).zero?)
+ assert_equal(false, Rational(1,1).zero?)
+
+ assert_equal(nil, Rational(0).nonzero?)
+ assert_equal(nil, Rational(0,1).nonzero?)
+ assert_equal(Rational(1,1), Rational(1,1).nonzero?)
+ end
+
+ def test_uplus
+ assert_equal(Rational(1), +Rational(1))
+ assert_equal(Rational(-1), +Rational(-1))
+ assert_equal(Rational(1,1), +Rational(1,1))
+ assert_equal(Rational(-1,1), +Rational(-1,1))
+ assert_equal(Rational(-1,1), +Rational(1,-1))
+ assert_equal(Rational(1,1), +Rational(-1,-1))
+ end
+
+ def test_negate
+ assert_equal(Rational(-1), -Rational(1))
+ assert_equal(Rational(1), -Rational(-1))
+ assert_equal(Rational(-1,1), -Rational(1,1))
+ assert_equal(Rational(1,1), -Rational(-1,1))
+ assert_equal(Rational(1,1), -Rational(1,-1))
+ assert_equal(Rational(-1,1), -Rational(-1,-1))
+
+=begin
+ assert_equal(0, Rational(0).negate)
+ assert_equal(-2, Rational(2).negate)
+ assert_equal(2, Rational(-2).negate)
+=end
+ end
+
+ def test_add
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(Rational(7,6), c + c2)
+
+ assert_equal(Rational(5,2), c + 2)
+ assert_equal(2.5, c + 2.0)
+ end
+
+ def test_sub
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(Rational(-1,6), c - c2)
+
+ assert_equal(Rational(-3,2), c - 2)
+ assert_equal(-1.5, c - 2.0)
+ end
+
+ def test_mul
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(Rational(1,3), c * c2)
+
+ assert_equal(Rational(1,1), c * 2)
+ assert_equal(1.0, c * 2.0)
+ end
+
+ def test_div
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(Rational(3,4), c / c2)
+
+ assert_equal(Rational(1,4), c / 2)
+ assert_equal(0.25, c / 2.0)
+ end
+
+ def assert_eql(exp, act, *args)
+ unless Array === exp
+ exp = [exp]
+ end
+ unless Array === act
+ act = [act]
+ end
+ exp.zip(act).each do |e, a|
+ na = [e, a] + args
+ assert_equal(*na)
+ na = [e.class, a] + args
+ assert_instance_of(*na)
+ end
+ end
+
+ def test_idiv
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_eql(0, c.div(c2))
+ assert_eql(0, c.div(2))
+ assert_eql(0, c.div(2.0))
+
+ c = Rational(301,100)
+ c2 = Rational(7,5)
+
+ assert_equal(2, c.div(c2))
+ assert_equal(-3, c.div(-c2))
+ assert_equal(-3, (-c).div(c2))
+ assert_equal(2, (-c).div(-c2))
+
+ c = Rational(301,100)
+ c2 = Rational(2)
+
+ assert_equal(1, c.div(c2))
+ assert_equal(-2, c.div(-c2))
+ assert_equal(-2, (-c).div(c2))
+ assert_equal(1, (-c).div(-c2))
+
+ unless defined?(Rational::Unify)
+ c = Rational(11)
+ c2 = Rational(3)
+
+ assert_equal(3, c.div(c2))
+ assert_equal(-4, c.div(-c2))
+ assert_equal(-4, (-c).div(c2))
+ assert_equal(3, (-c).div(-c2))
+ end
+ end
+
+ def test_divmod
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_eql([0, Rational(1,2)], c.divmod(c2))
+ assert_eql([0, Rational(1,2)], c.divmod(2))
+ assert_eql([0, 0.5], c.divmod(2.0))
+
+ c = Rational(301,100)
+ c2 = Rational(7,5)
+
+ assert_equal([2, Rational(21,100)], c.divmod(c2))
+ assert_equal([-3, Rational(-119,100)], c.divmod(-c2))
+ assert_equal([-3, Rational(119,100)], (-c).divmod(c2))
+ assert_equal([2, Rational(-21,100)], (-c).divmod(-c2))
+
+ c = Rational(301,100)
+ c2 = Rational(2)
+
+ assert_equal([1, Rational(101,100)], c.divmod(c2))
+ assert_equal([-2, Rational(-99,100)], c.divmod(-c2))
+ assert_equal([-2, Rational(99,100)], (-c).divmod(c2))
+ assert_equal([1, Rational(-101,100)], (-c).divmod(-c2))
+
+ unless defined?(Rational::Unify)
+ c = Rational(11)
+ c2 = Rational(3)
+
+ assert_equal([3,2], c.divmod(c2))
+ assert_equal([-4,-1], c.divmod(-c2))
+ assert_equal([-4,1], (-c).divmod(c2))
+ assert_equal([3,-2], (-c).divmod(-c2))
+ end
+ end
+
+=begin
+ def test_quot
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_eql(0, c.quot(c2))
+ assert_eql(0, c.quot(2))
+ assert_eql(0, c.quot(2.0))
+
+ c = Rational(301,100)
+ c2 = Rational(7,5)
+
+ assert_equal(2, c.quot(c2))
+ assert_equal(-2, c.quot(-c2))
+ assert_equal(-2, (-c).quot(c2))
+ assert_equal(2, (-c).quot(-c2))
+
+ c = Rational(301,100)
+ c2 = Rational(2)
+
+ assert_equal(1, c.quot(c2))
+ assert_equal(-1, c.quot(-c2))
+ assert_equal(-1, (-c).quot(c2))
+ assert_equal(1, (-c).quot(-c2))
+
+ unless defined?(Rational::Unify)
+ c = Rational(11)
+ c2 = Rational(3)
+
+ assert_equal(3, c.quot(c2))
+ assert_equal(-3, c.quot(-c2))
+ assert_equal(-3, (-c).quot(c2))
+ assert_equal(3, (-c).quot(-c2))
+ end
+ end
+
+ def test_quotrem
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_eql([0, Rational(1,2)], c.quotrem(c2))
+ assert_eql([0, Rational(1,2)], c.quotrem(2))
+ assert_eql([0, 0.5], c.quotrem(2.0))
+
+ c = Rational(301,100)
+ c2 = Rational(7,5)
+
+ assert_equal([2, Rational(21,100)], c.quotrem(c2))
+ assert_equal([-2, Rational(21,100)], c.quotrem(-c2))
+ assert_equal([-2, Rational(-21,100)], (-c).quotrem(c2))
+ assert_equal([2, Rational(-21,100)], (-c).quotrem(-c2))
+
+ c = Rational(301,100)
+ c2 = Rational(2)
+
+ assert_equal([1, Rational(101,100)], c.quotrem(c2))
+ assert_equal([-1, Rational(101,100)], c.quotrem(-c2))
+ assert_equal([-1, Rational(-101,100)], (-c).quotrem(c2))
+ assert_equal([1, Rational(-101,100)], (-c).quotrem(-c2))
+
+ unless defined?(Rational::Unify)
+ c = Rational(11)
+ c2 = Rational(3)
+
+ assert_equal([3,2], c.quotrem(c2))
+ assert_equal([-3,2], c.quotrem(-c2))
+ assert_equal([-3,-2], (-c).quotrem(c2))
+ assert_equal([3,-2], (-c).quotrem(-c2))
+ end
+ end
+=end
+
+ def test_quo
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(Rational(3,4), c.quo(c2))
+
+ assert_equal(Rational(1,4), c.quo(2))
+ assert_equal(Rational(0.25), c.quo(2.0))
+ end
+
+ def test_fdiv
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ assert_equal(0.75, c.fdiv(c2))
+
+ assert_equal(0.25, c.fdiv(2))
+ assert_equal(0.25, c.fdiv(2.0))
+ end
+
+ def test_expt
+ c = Rational(1,2)
+ c2 = Rational(2,3)
+
+ r = c ** c2
+ assert_in_delta(0.6299, r, 0.001)
+
+ assert_equal(Rational(1,4), c ** 2)
+ assert_equal(Rational(4), c ** -2)
+ assert_equal(Rational(1,4), (-c) ** 2)
+ assert_equal(Rational(4), (-c) ** -2)
+
+ assert_equal(0.25, c ** 2.0)
+ assert_equal(4.0, c ** -2.0)
+
+ assert_equal(Rational(1,4), c ** Rational(2))
+ assert_equal(Rational(4), c ** Rational(-2))
+
+ assert_equal(Rational(1), 0 ** Rational(0))
+ assert_equal(Rational(1), Rational(0) ** 0)
+ assert_equal(Rational(1), Rational(0) ** Rational(0))
+
+ # p ** p
+ x = 2 ** Rational(2)
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ x = Rational(2) ** 2
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ x = Rational(2) ** Rational(2)
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ # -p ** p
+ x = (-2) ** Rational(2)
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ x = Rational(-2) ** 2
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ x = Rational(-2) ** Rational(2)
+ assert_equal(Rational(4), x)
+ unless defined?(Rational::Unify)
+ assert_instance_of(Rational, x)
+ end
+ assert_equal(4, x.numerator)
+ assert_equal(1, x.denominator)
+
+ # p ** -p
+ x = 2 ** Rational(-2)
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ x = Rational(2) ** -2
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ x = Rational(2) ** Rational(-2)
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ # -p ** -p
+ x = (-2) ** Rational(-2)
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ x = Rational(-2) ** -2
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ x = Rational(-2) ** Rational(-2)
+ assert_equal(Rational(1,4), x)
+ assert_instance_of(Rational, x)
+ assert_equal(1, x.numerator)
+ assert_equal(4, x.denominator)
+
+ unless defined?(Rational::Unify) # maybe bug mathn
+ assert_raise(ZeroDivisionError){0 ** -1}
+ end
+ end
+
+ def test_cmp
+ assert_equal(-1, Rational(-1) <=> Rational(0))
+ assert_equal(0, Rational(0) <=> Rational(0))
+ assert_equal(+1, Rational(+1) <=> Rational(0))
+
+ assert_equal(-1, Rational(-1) <=> 0)
+ assert_equal(0, Rational(0) <=> 0)
+ assert_equal(+1, Rational(+1) <=> 0)
+
+ assert_equal(-1, Rational(-1) <=> 0.0)
+ assert_equal(0, Rational(0) <=> 0.0)
+ assert_equal(+1, Rational(+1) <=> 0.0)
+
+ assert_equal(-1, Rational(1,2) <=> Rational(2,3))
+ assert_equal(0, Rational(2,3) <=> Rational(2,3))
+ assert_equal(+1, Rational(2,3) <=> Rational(1,2))
+
+ f = 2**30-1
+ b = 2**30
+
+ assert_equal(0, Rational(f) <=> Rational(f))
+ assert_equal(-1, Rational(f) <=> Rational(b))
+ assert_equal(+1, Rational(b) <=> Rational(f))
+ assert_equal(0, Rational(b) <=> Rational(b))
+
+ assert_equal(-1, Rational(f-1) <=> Rational(f))
+ assert_equal(+1, Rational(f) <=> Rational(f-1))
+ assert_equal(-1, Rational(b-1) <=> Rational(b))
+ assert_equal(+1, Rational(b) <=> Rational(b-1))
+
+ assert_equal(false, Rational(0) < Rational(0))
+ assert_equal(true, Rational(0) <= Rational(0))
+ assert_equal(true, Rational(0) >= Rational(0))
+ assert_equal(false, Rational(0) > Rational(0))
+ end
+
+ def test_equal
+ assert(Rational(1,1) == Rational(1))
+ assert(Rational(1,1) == Rational.__send__(:new, 1))
+ assert(Rational(1,1) == Rational.__send__(:new, 1,1))
+ assert(Rational(1,1) == Rational.__send__(:new!, 1))
+ assert(Rational(1,1) == Rational.__send__(:new!, 1,1))
+
+ assert(Rational(-1,1) == Rational(-1))
+ assert(Rational(-1,1) == Rational.__send__(:new, -1))
+ assert(Rational(-1,1) == Rational.__send__(:new, -1,1))
+ assert(Rational(-1,1) == Rational.__send__(:new!, -1))
+ assert(Rational(-1,1) == Rational.__send__(:new!, -1,1))
+
+ assert_equal(false, Rational(2,1) == Rational(1))
+ assert_equal(true, Rational(2,1) != Rational(1))
+ assert_equal(false, Rational(1) == nil)
+ assert_equal(false, Rational(1) == '')
+ end
+
+ def test_unify
+ if defined?(Rational::Unify)
+ assert_instance_of(Fixnum, Rational(1,2) + Rational(1,2))
+ assert_instance_of(Fixnum, Rational(1,2) - Rational(1,2))
+ assert_instance_of(Fixnum, Rational(1,2) * 2)
+ assert_instance_of(Fixnum, Rational(1,2) / Rational(1,2))
+ assert_instance_of(Fixnum, Rational(1,2).div(Rational(1,2)))
+ assert_instance_of(Fixnum, Rational(1,2).quo(Rational(1,2)))
+ assert_instance_of(Fixnum, Rational(1,2) ** -2)
+ end
+ end
+
+ def test_to_s
+ c = Rational(1,2)
+
+ assert_instance_of(String, c.to_s)
+ assert_equal('1/2', c.to_s)
+
+ if defined?(Rational::Unify)
+ assert_equal('0', Rational(0,2).to_s)
+ assert_equal('0', Rational(0,-2).to_s)
+ else
+ assert_equal('0/1', Rational(0,2).to_s)
+ assert_equal('0/1', Rational(0,-2).to_s)
+ end
+ assert_equal('1/2', Rational(1,2).to_s)
+ assert_equal('-1/2', Rational(-1,2).to_s)
+ assert_equal('1/2', Rational(-1,-2).to_s)
+ assert_equal('-1/2', Rational(1,-2).to_s)
+ assert_equal('1/2', Rational(-1,-2).to_s)
+ end
+
+ def test_inspect
+ c = Rational(1,2)
+
+ assert_instance_of(String, c.inspect)
+ assert_equal('(1/2)', c.inspect)
+ end
+
+ def test_marshal
+ c = Rational(1,2)
+
+ s = Marshal.dump(c)
+ c2 = Marshal.load(s)
+ assert_equal(c, c2)
+ assert_instance_of(Rational, c2)
+
+ assert_raise(ZeroDivisionError){
+ Marshal.load("\x04\bU:\rRational[\ai\x06i\x05")
+ }
+ end
+
+ def test_parse
+ assert_equal(Rational(0), ''.to_r)
+ assert_equal(Rational(0), ' '.to_r)
+ assert_equal(Rational(5), '5'.to_r)
+ assert_equal(Rational(-5), '-5'.to_r)
+ assert_equal(Rational(5,3), '5/3'.to_r)
+ assert_equal(Rational(-5,3), '-5/3'.to_r)
+# assert_equal(Rational(5,-3), '5/-3'.to_r)
+# assert_equal(Rational(-5,-3), '-5/-3'.to_r)
+
+ assert_equal(Rational(5), '5.0'.to_r)
+ assert_equal(Rational(-5), '-5.0'.to_r)
+ assert_equal(Rational(5,3), '5.0/3'.to_r)
+ assert_equal(Rational(-5,3), '-5.0/3'.to_r)
+# assert_equal(Rational(5,-3), '5.0/-3'.to_r)
+# assert_equal(Rational(-5,-3), '-5.0/-3'.to_r)
+
+ assert_equal(Rational(5), '5e0'.to_r)
+ assert_equal(Rational(-5), '-5e0'.to_r)
+ assert_equal(Rational(5,3), '5e0/3'.to_r)
+ assert_equal(Rational(-5,3), '-5e0/3'.to_r)
+# assert_equal(Rational(5,-3), '5e0/-3'.to_r)
+# assert_equal(Rational(-5,-3), '-5e0/-3'.to_r)
+
+ assert_equal(Rational(33,100), '0.33'.to_r)
+ assert_equal(Rational(-33,100), '-0.33'.to_r)
+ assert_equal(Rational(-33,100), '-0.3_3'.to_r)
+
+ assert_equal(Rational(1,2), '5e-1'.to_r)
+ assert_equal(Rational(50), '5e+1'.to_r)
+ assert_equal(Rational(1,2), '5.0e-1'.to_r)
+ assert_equal(Rational(50), '5.0e+1'.to_r)
+ assert_equal(Rational(50), '5e1'.to_r)
+ assert_equal(Rational(50), '5E1'.to_r)
+ assert_equal(Rational(500), '5e2'.to_r)
+ assert_equal(Rational(5000), '5e3'.to_r)
+ assert_equal(Rational(500000000000), '5e1_1'.to_r)
+
+ assert_equal(Rational(5), Rational('5'))
+ assert_equal(Rational(-5), Rational('-5'))
+ assert_equal(Rational(5,3), Rational('5/3'))
+ assert_equal(Rational(-5,3), Rational('-5/3'))
+# assert_equal(Rational(5,-3), Rational('5/-3'))
+# assert_equal(Rational(-5,-3), Rational('-5/-3'))
+
+ assert_equal(Rational(33,100), Rational('0.33'))
+ assert_equal(Rational(-33,100), Rational('-0.33'))
+ assert_equal(Rational(-33,100), Rational('-0.3_3'))
+
+ assert_equal(Rational(1,2), Rational('5e-1'))
+ assert_equal(Rational(50), Rational('5e1'))
+ assert_equal(Rational(50), Rational('5E1'))
+ assert_equal(Rational(500), Rational('5e2'))
+ assert_equal(Rational(5000), Rational('5e3'))
+ assert_equal(Rational(500000000000), Rational('5e1_1'))
+
+ assert_equal(Rational(5.0), Rational('5.0'))
+ assert_equal(Rational(-5.0), Rational('-5.0'))
+ assert_equal(Rational(5.0,3), Rational('5.0/3'))
+ assert_equal(Rational(-5.0,3), Rational('-5.0/3'))
+# assert_equal(Rational(5.0,-3), Rational('5.0/-3'))
+# assert_equal(Rational(-5.0,-3), Rational('-5.0/-3'))
+
+ assert_equal(Rational(0), '_'.to_r)
+ assert_equal(Rational(0), '_5'.to_r)
+ assert_equal(Rational(5), '5_'.to_r)
+ assert_equal(Rational(5), '5x'.to_r)
+ assert_equal(Rational(5), '5/_3'.to_r)
+ assert_equal(Rational(5,3), '5/3_'.to_r)
+ assert_equal(Rational(5,3), '5/3.3'.to_r)
+ assert_equal(Rational(5,3), '5/3x'.to_r)
+ assert_raise(ArgumentError){ Rational('')}
+ assert_raise(ArgumentError){ Rational('_')}
+ assert_raise(ArgumentError){ Rational('_5')}
+ assert_raise(ArgumentError){ Rational('5_')}
+ assert_raise(ArgumentError){ Rational('5x')}
+ assert_raise(ArgumentError){ Rational('5/_3')}
+ assert_raise(ArgumentError){ Rational('5/3_')}
+ assert_raise(ArgumentError){ Rational('5/3.3')}
+ assert_raise(ArgumentError){ Rational('5/3x')}
+ end
+
+=begin
+ def test_reciprocal
+ assert_equal(Rational(1,9), Rational(9,1).reciprocal)
+ assert_equal(Rational(9,1), Rational(1,9).reciprocal)
+ assert_equal(Rational(-1,9), Rational(-9,1).reciprocal)
+ assert_equal(Rational(-9,1), Rational(-1,9).reciprocal)
+ end
+=end
+
+ def test_to_i
+ assert_equal(1, Rational(3,2).to_i)
+ assert_equal(1, Integer(Rational(3,2)))
+ end
+
+ def test_to_f
+ assert_equal(1.5, Rational(3,2).to_f)
+ assert_equal(1.5, Float(Rational(3,2)))
+ end
+
+ def test_to_c
+ if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
+ if defined?(Rational::Unify)
+ assert_equal(Rational(3,2), Rational(3,2).to_c)
+ assert_equal(Rational(3,2), Complex(Rational(3,2)))
+ else
+ assert_equal(Complex(Rational(3,2)), Rational(3,2).to_c)
+ assert_equal(Complex(Rational(3,2)), Complex(Rational(3,2)))
+ end
+ end
+ end
+
+ def test_to_r
+ c = nil.to_r
+ assert_equal([0,1] , [c.numerator, c.denominator])
+
+ c = 0.to_r
+ assert_equal([0,1] , [c.numerator, c.denominator])
+
+ c = 1.to_r
+ assert_equal([1,1] , [c.numerator, c.denominator])
+
+ c = 1.1.to_r
+ assert_equal([2476979795053773, 2251799813685248],
+ [c.numerator, c.denominator])
+
+ c = Rational(1,2).to_r
+ assert_equal([1,2] , [c.numerator, c.denominator])
+
+ if defined?(Complex)
+ if Complex.instance_variable_get('@RCS_ID')
+ assert_raise(NoMethodError){Complex(1,2).to_r}
+ else
+ assert_raise(RangeError){Complex(1,2).to_r}
+ end
+ end
+ end
+
+ def test_prec
+ assert_equal(true, Rational < Precision)
+
+ c = Rational(3,2)
+
+ assert_eql(1, c.prec(Integer))
+ assert_eql(1.5, c.prec(Float))
+ assert_eql(c, c.prec(Rational))
+ end
+
+ def test_supp
+ assert_equal(true, 1.scalar?)
+ assert_equal(true, 1.1.scalar?)
+
+ if defined?(Complex)
+ assert_equal(1, 1.real)
+ assert_equal(0, 1.image)
+ assert_equal(0, 1.imag)
+
+ assert_equal(1.1, 1.1.real)
+ assert_equal(0, 1.1.image)
+ assert_equal(0, 1.1.imag)
+
+ assert_equal(0, 1.arg)
+ assert_equal(0, 1.angle)
+
+ assert_equal(0, 1.0.arg)
+ assert_equal(0, 1.0.angle)
+
+ assert_equal(Math::PI, -1.arg)
+ assert_equal(Math::PI, -1.angle)
+
+ assert_equal(Math::PI, -1.0.arg)
+ assert_equal(Math::PI, -1.0.angle)
+
+ assert_equal([1,0], 1.polar)
+ assert_equal([1, Math::PI], -1.polar)
+
+ assert_equal([1.0,0], 1.0.polar)
+ assert_equal([1.0, Math::PI], -1.0.polar)
+
+ assert_equal(1, 1.conjugate)
+ assert_equal(-1, -1.conjugate)
+ assert_equal(1, 1.conj)
+ assert_equal(-1, -1.conj)
+
+ assert_equal(1.1, 1.1.conjugate)
+ assert_equal(-1.1, -1.1.conjugate)
+ assert_equal(1.1, 1.1.conj)
+ assert_equal(-1.1, -1.1.conj)
+ end
+
+ assert_equal(1, 1.numerator)
+ assert_equal(9, 9.numerator)
+ assert_equal(1, 1.denominator)
+ assert_equal(1, 9.denominator)
+
+ assert_equal(1.0, 1.0.numerator)
+ assert_equal(9.0, 9.0.numerator)
+ assert_equal(1.0, 1.0.denominator)
+ assert_equal(1.0, 9.0.denominator)
+
+=begin
+ assert_equal(Rational(1,9), 9.reciprocal)
+ assert_equal(Rational(1,9), 9.0.reciprocal)
+ assert_equal(Rational(1,9), 9.inverse)
+ assert_equal(Rational(1,9), 9.0.inverse)
+=end
+
+ assert_equal(Rational(1,2), 1.quo(2))
+ assert_equal(Rational(5000000000), 10000000000.quo(2))
+ assert_equal(0.5, 1.0.quo(2))
+ assert_equal(Rational(1,4), Rational(1,2).quo(2))
+
+ assert_equal(0.5, 1.fdiv(2))
+ assert_equal(5000000000.0, 10000000000.fdiv(2))
+ assert_equal(0.5, 1.0.fdiv(2))
+ assert_equal(0.25, Rational(1,2).fdiv(2))
+ end
+
+=begin
+ def test_zero_div
+ assert_raise(ZeroDivisionError) { Rational(1, 0) }
+ assert_raise(ZeroDivisionError) { Rational(1, 1) / 0 }
+ end
+
+ def test_gcd
+ assert_equal(0, Rational(0, 2**100))
+ end
+
+ def test_unify2
+ f = defined?(Rational::Unify)
+ Rational.const_set(:Unify, true) unless f
+
+ assert_same(42, Rational(84, 2))
+ assert_same(1, Rational(1, 2) + Rational(1, 2))
+
+ Rational.instance_eval { remove_const(:Unify) } unless f
+ end
+
+ def test_coerce
+ r = Rational(7, 3)
+ assert_equal(Rational(42, 1), r.coerce(42).first)
+ assert_raise(TypeError) { r.coerce(Object.new) }
+
+ o = Object.new
+ def o.coerce(x); [x.numerator, x.denominator]; end
+ assert_equal(10, r + o)
+ assert_equal(4, r - o)
+ assert_equal(21, r * o)
+ assert_equal(2, r / o)
+ assert_equal(343, r ** o)
+ assert_equal(1, r <=> o)
+
+ b = 2**100
+ def b.<=>(x); 0; end rescue nil
+ assert_equal(1, r ** b)
+ b = 2**100
+ def b.**(x); -1; end rescue nil
+ assert_equal(-1, Rational(1, b)**3)
+ end
+
+ def test_modulo_remainder
+ assert_equal(Rational(1, 2), Rational(5, 2).modulo(1))
+ assert_equal(Rational(1, 2), Rational(5, 2).modulo(2))
+ assert_equal(Rational(5, 2), Rational(5, 2).modulo(3))
+ assert_equal(Rational(5, 6), Rational(5, 2).modulo(Rational(5, 3)))
+ assert_equal(Rational(1, 2), Rational(-5, 2).modulo(1))
+ assert_equal(Rational(-1, 2), Rational(5, 2).modulo(-1))
+ assert_equal(Rational(-1, 2), Rational(-5, 2).modulo(-1))
+
+ assert_equal(Rational(1, 2), Rational(5, 2).remainder(1))
+ assert_equal(Rational(1, 2), Rational(5, 2).remainder(2))
+ assert_equal(Rational(5, 2), Rational(5, 2).remainder(3))
+ assert_equal(Rational(5, 6), Rational(5, 2).remainder(Rational(5, 3)))
+ assert_equal(Rational(-1, 2), Rational(-5, 2).remainder(1))
+ assert_equal(Rational(1, 2), Rational(5, 2).remainder(-1))
+ assert_equal(Rational(-1, 2), Rational(-5, 2).remainder(-1))
+ end
+
+ def test_abs
+ assert_equal(Rational(1, 2), Rational(1, 2).abs)
+ assert_equal(Rational(1, 2), Rational(-1, 2).abs)
+ end
+
+ def test_floor_ceil_truncate_round
+ assert_equal( 2, Rational( 5, 2).floor)
+ assert_equal(-3, Rational(-5, 2).floor)
+ assert_equal( 3, Rational( 5, 2).ceil)
+ assert_equal(-2, Rational(-5, 2).ceil)
+ assert_equal( 2, Rational( 5, 2).truncate)
+ assert_equal(-2, Rational(-5, 2).truncate)
+ assert_equal( 3, Rational( 5, 2).round)
+ assert_equal(-3, Rational(-5, 2).round)
+ assert_equal( 1, Rational( 4, 3).round)
+ assert_equal(-1, Rational(-4, 3).round)
+ assert_equal( 2, Rational( 5, 3).round)
+ assert_equal(-2, Rational(-5, 3).round)
+ end
+
+ def test_convert
+ assert_equal(Rational(1, 2), Rational(Complex(1, 0), 2))
+ assert_raise(RangeError) { Rational(Complex(1, 1), 1) }
+ assert_equal(Rational(1, 2), Rational(1, Complex(2, 0)))
+ assert_raise(RangeError) { Rational(1, Complex(2, 1)) }
+ assert_equal(Rational(1, 2), Rational(0.25, 0.5))
+ assert_equal(Rational(1, 2), Rational('1', '2'))
+ end
+
+ def test_add2
+ assert_equal(Rational(2**100, 3), Rational(0, 1) + Rational(2**100, 3))
+ assert_equal(Rational(2, 3**100), Rational(0, 1) + Rational(2, 3**100))
+ end
+
+ def test_div2
+ assert_raise(ZeroDivisionError) { Rational(1, 1) / Rational(0, 1) }
+ end
+
+ def test_to_f2
+ assert_equal(1, Rational(2**5000,3).to_f.infinite?)
+ assert_equal(0, Rational(1, 2**5000).to_f)
+ end
+=end
+
+ def test_fixed_bug
+ if defined?(Rational::Unify)
+ assert_instance_of(Fixnum, Rational(1,2) ** 0) # mathn's bug
+ end
+
+ n = Float::MAX.to_i * 2
+ assert_equal(1.0, Rational(n + 2, n + 1).to_f, '[ruby-dev:33852]')
+ end
+
+ def test_known_bug
+ end
+
+end
diff --git a/trunk/test/ruby/test_rational2.rb b/trunk/test/ruby/test_rational2.rb
new file mode 100644
index 0000000000..641bfea565
--- /dev/null
+++ b/trunk/test/ruby/test_rational2.rb
@@ -0,0 +1,1360 @@
+require 'test/unit'
+
+class Rational_Test2 < Test::Unit::TestCase
+
+ def test_kumi
+ assert_equal(Rational(2, 1),
+ Rational(1, 1) + Rational(1, 1))
+ assert_equal(Rational(0, 1),
+ Rational(1, 1) - Rational(1, 1))
+ assert_equal(Rational(1, 1),
+ Rational(1, 1) * Rational(1, 1))
+ assert_equal(Rational(1, 1),
+ Rational(1, 1) / Rational(1, 1))
+ assert_equal(Rational(3, 1),
+ Rational(1, 1) + Rational(2, 1))
+ assert_equal(Rational(-1, 1),
+ Rational(1, 1) - Rational(2, 1))
+ assert_equal(Rational(2, 1),
+ Rational(1, 1) * Rational(2, 1))
+ assert_equal(Rational(1, 2),
+ Rational(1, 1) / Rational(2, 1))
+ assert_equal(Rational(4, 1),
+ Rational(1, 1) + Rational(3, 1))
+ assert_equal(Rational(-2, 1),
+ Rational(1, 1) - Rational(3, 1))
+ assert_equal(Rational(3, 1),
+ Rational(1, 1) * Rational(3, 1))
+ assert_equal(Rational(1, 3),
+ Rational(1, 1) / Rational(3, 1))
+ assert_equal(Rational(1073741790, 1),
+ Rational(1, 1) + Rational(1073741789, 1))
+ assert_equal(Rational(-1073741788, 1),
+ Rational(1, 1) - Rational(1073741789, 1))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1, 1) * Rational(1073741789, 1))
+ assert_equal(Rational(1, 1073741789),
+ Rational(1, 1) / Rational(1073741789, 1))
+ assert_equal(Rational(1073741828, 1),
+ Rational(1, 1) + Rational(1073741827, 1))
+ assert_equal(Rational(-1073741826, 1),
+ Rational(1, 1) - Rational(1073741827, 1))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1, 1) * Rational(1073741827, 1))
+ assert_equal(Rational(1, 1073741827),
+ Rational(1, 1) / Rational(1073741827, 1))
+ assert_equal(Rational(5, 3),
+ Rational(1, 1) + Rational(2, 3))
+ assert_equal(Rational(1, 3),
+ Rational(1, 1) - Rational(2, 3))
+ assert_equal(Rational(2, 3),
+ Rational(1, 1) * Rational(2, 3))
+ assert_equal(Rational(3, 2),
+ Rational(1, 1) / Rational(2, 3))
+ assert_equal(Rational(5, 2),
+ Rational(1, 1) + Rational(3, 2))
+ assert_equal(Rational(-1, 2),
+ Rational(1, 1) - Rational(3, 2))
+ assert_equal(Rational(3, 2),
+ Rational(1, 1) * Rational(3, 2))
+ assert_equal(Rational(2, 3),
+ Rational(1, 1) / Rational(3, 2))
+ assert_equal(Rational(1073741792, 1073741789),
+ Rational(1, 1) + Rational(3, 1073741789))
+ assert_equal(Rational(1073741786, 1073741789),
+ Rational(1, 1) - Rational(3, 1073741789))
+ assert_equal(Rational(3, 1073741789),
+ Rational(1, 1) * Rational(3, 1073741789))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1, 1) / Rational(3, 1073741789))
+ assert_equal(Rational(1073741792, 3),
+ Rational(1, 1) + Rational(1073741789, 3))
+ assert_equal(Rational(-1073741786, 3),
+ Rational(1, 1) - Rational(1073741789, 3))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1, 1) * Rational(1073741789, 3))
+ assert_equal(Rational(3, 1073741789),
+ Rational(1, 1) / Rational(1073741789, 3))
+ assert_equal(Rational(1073741830, 1073741827),
+ Rational(1, 1) + Rational(3, 1073741827))
+ assert_equal(Rational(1073741824, 1073741827),
+ Rational(1, 1) - Rational(3, 1073741827))
+ assert_equal(Rational(3, 1073741827),
+ Rational(1, 1) * Rational(3, 1073741827))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1, 1) / Rational(3, 1073741827))
+ assert_equal(Rational(1073741830, 3),
+ Rational(1, 1) + Rational(1073741827, 3))
+ assert_equal(Rational(-1073741824, 3),
+ Rational(1, 1) - Rational(1073741827, 3))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1, 1) * Rational(1073741827, 3))
+ assert_equal(Rational(3, 1073741827),
+ Rational(1, 1) / Rational(1073741827, 3))
+ assert_equal(Rational(2147483616, 1073741827),
+ Rational(1, 1) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(38, 1073741827),
+ Rational(1, 1) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1, 1) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1, 1) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483616, 1073741789),
+ Rational(1, 1) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(-38, 1073741789),
+ Rational(1, 1) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1, 1) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1),
+ Rational(2, 1) + Rational(1, 1))
+ assert_equal(Rational(1, 1),
+ Rational(2, 1) - Rational(1, 1))
+ assert_equal(Rational(2, 1),
+ Rational(2, 1) * Rational(1, 1))
+ assert_equal(Rational(2, 1),
+ Rational(2, 1) / Rational(1, 1))
+ assert_equal(Rational(4, 1),
+ Rational(2, 1) + Rational(2, 1))
+ assert_equal(Rational(0, 1),
+ Rational(2, 1) - Rational(2, 1))
+ assert_equal(Rational(4, 1),
+ Rational(2, 1) * Rational(2, 1))
+ assert_equal(Rational(1, 1),
+ Rational(2, 1) / Rational(2, 1))
+ assert_equal(Rational(5, 1),
+ Rational(2, 1) + Rational(3, 1))
+ assert_equal(Rational(-1, 1),
+ Rational(2, 1) - Rational(3, 1))
+ assert_equal(Rational(6, 1),
+ Rational(2, 1) * Rational(3, 1))
+ assert_equal(Rational(2, 3),
+ Rational(2, 1) / Rational(3, 1))
+ assert_equal(Rational(1073741791, 1),
+ Rational(2, 1) + Rational(1073741789, 1))
+ assert_equal(Rational(-1073741787, 1),
+ Rational(2, 1) - Rational(1073741789, 1))
+ assert_equal(Rational(2147483578, 1),
+ Rational(2, 1) * Rational(1073741789, 1))
+ assert_equal(Rational(2, 1073741789),
+ Rational(2, 1) / Rational(1073741789, 1))
+ assert_equal(Rational(1073741829, 1),
+ Rational(2, 1) + Rational(1073741827, 1))
+ assert_equal(Rational(-1073741825, 1),
+ Rational(2, 1) - Rational(1073741827, 1))
+ assert_equal(Rational(2147483654, 1),
+ Rational(2, 1) * Rational(1073741827, 1))
+ assert_equal(Rational(2, 1073741827),
+ Rational(2, 1) / Rational(1073741827, 1))
+ assert_equal(Rational(8, 3),
+ Rational(2, 1) + Rational(2, 3))
+ assert_equal(Rational(4, 3),
+ Rational(2, 1) - Rational(2, 3))
+ assert_equal(Rational(4, 3),
+ Rational(2, 1) * Rational(2, 3))
+ assert_equal(Rational(3, 1),
+ Rational(2, 1) / Rational(2, 3))
+ assert_equal(Rational(7, 2),
+ Rational(2, 1) + Rational(3, 2))
+ assert_equal(Rational(1, 2),
+ Rational(2, 1) - Rational(3, 2))
+ assert_equal(Rational(3, 1),
+ Rational(2, 1) * Rational(3, 2))
+ assert_equal(Rational(4, 3),
+ Rational(2, 1) / Rational(3, 2))
+ assert_equal(Rational(2147483581, 1073741789),
+ Rational(2, 1) + Rational(3, 1073741789))
+ assert_equal(Rational(2147483575, 1073741789),
+ Rational(2, 1) - Rational(3, 1073741789))
+ assert_equal(Rational(6, 1073741789),
+ Rational(2, 1) * Rational(3, 1073741789))
+ assert_equal(Rational(2147483578, 3),
+ Rational(2, 1) / Rational(3, 1073741789))
+ assert_equal(Rational(1073741795, 3),
+ Rational(2, 1) + Rational(1073741789, 3))
+ assert_equal(Rational(-1073741783, 3),
+ Rational(2, 1) - Rational(1073741789, 3))
+ assert_equal(Rational(2147483578, 3),
+ Rational(2, 1) * Rational(1073741789, 3))
+ assert_equal(Rational(6, 1073741789),
+ Rational(2, 1) / Rational(1073741789, 3))
+ assert_equal(Rational(2147483657, 1073741827),
+ Rational(2, 1) + Rational(3, 1073741827))
+ assert_equal(Rational(2147483651, 1073741827),
+ Rational(2, 1) - Rational(3, 1073741827))
+ assert_equal(Rational(6, 1073741827),
+ Rational(2, 1) * Rational(3, 1073741827))
+ assert_equal(Rational(2147483654, 3),
+ Rational(2, 1) / Rational(3, 1073741827))
+ assert_equal(Rational(1073741833, 3),
+ Rational(2, 1) + Rational(1073741827, 3))
+ assert_equal(Rational(-1073741821, 3),
+ Rational(2, 1) - Rational(1073741827, 3))
+ assert_equal(Rational(2147483654, 3),
+ Rational(2, 1) * Rational(1073741827, 3))
+ assert_equal(Rational(6, 1073741827),
+ Rational(2, 1) / Rational(1073741827, 3))
+ assert_equal(Rational(3221225443, 1073741827),
+ Rational(2, 1) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741865, 1073741827),
+ Rational(2, 1) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483578, 1073741827),
+ Rational(2, 1) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483654, 1073741789),
+ Rational(2, 1) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225405, 1073741789),
+ Rational(2, 1) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741751, 1073741789),
+ Rational(2, 1) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483654, 1073741789),
+ Rational(2, 1) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483578, 1073741827),
+ Rational(2, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(4, 1),
+ Rational(3, 1) + Rational(1, 1))
+ assert_equal(Rational(2, 1),
+ Rational(3, 1) - Rational(1, 1))
+ assert_equal(Rational(3, 1),
+ Rational(3, 1) * Rational(1, 1))
+ assert_equal(Rational(3, 1),
+ Rational(3, 1) / Rational(1, 1))
+ assert_equal(Rational(5, 1),
+ Rational(3, 1) + Rational(2, 1))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1) - Rational(2, 1))
+ assert_equal(Rational(6, 1),
+ Rational(3, 1) * Rational(2, 1))
+ assert_equal(Rational(3, 2),
+ Rational(3, 1) / Rational(2, 1))
+ assert_equal(Rational(6, 1),
+ Rational(3, 1) + Rational(3, 1))
+ assert_equal(Rational(0, 1),
+ Rational(3, 1) - Rational(3, 1))
+ assert_equal(Rational(9, 1),
+ Rational(3, 1) * Rational(3, 1))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1) / Rational(3, 1))
+ assert_equal(Rational(1073741792, 1),
+ Rational(3, 1) + Rational(1073741789, 1))
+ assert_equal(Rational(-1073741786, 1),
+ Rational(3, 1) - Rational(1073741789, 1))
+ assert_equal(Rational(3221225367, 1),
+ Rational(3, 1) * Rational(1073741789, 1))
+ assert_equal(Rational(3, 1073741789),
+ Rational(3, 1) / Rational(1073741789, 1))
+ assert_equal(Rational(1073741830, 1),
+ Rational(3, 1) + Rational(1073741827, 1))
+ assert_equal(Rational(-1073741824, 1),
+ Rational(3, 1) - Rational(1073741827, 1))
+ assert_equal(Rational(3221225481, 1),
+ Rational(3, 1) * Rational(1073741827, 1))
+ assert_equal(Rational(3, 1073741827),
+ Rational(3, 1) / Rational(1073741827, 1))
+ assert_equal(Rational(11, 3),
+ Rational(3, 1) + Rational(2, 3))
+ assert_equal(Rational(7, 3),
+ Rational(3, 1) - Rational(2, 3))
+ assert_equal(Rational(2, 1),
+ Rational(3, 1) * Rational(2, 3))
+ assert_equal(Rational(9, 2),
+ Rational(3, 1) / Rational(2, 3))
+ assert_equal(Rational(9, 2),
+ Rational(3, 1) + Rational(3, 2))
+ assert_equal(Rational(3, 2),
+ Rational(3, 1) - Rational(3, 2))
+ assert_equal(Rational(9, 2),
+ Rational(3, 1) * Rational(3, 2))
+ assert_equal(Rational(2, 1),
+ Rational(3, 1) / Rational(3, 2))
+ assert_equal(Rational(3221225370, 1073741789),
+ Rational(3, 1) + Rational(3, 1073741789))
+ assert_equal(Rational(3221225364, 1073741789),
+ Rational(3, 1) - Rational(3, 1073741789))
+ assert_equal(Rational(9, 1073741789),
+ Rational(3, 1) * Rational(3, 1073741789))
+ assert_equal(Rational(1073741789, 1),
+ Rational(3, 1) / Rational(3, 1073741789))
+ assert_equal(Rational(1073741798, 3),
+ Rational(3, 1) + Rational(1073741789, 3))
+ assert_equal(Rational(-1073741780, 3),
+ Rational(3, 1) - Rational(1073741789, 3))
+ assert_equal(Rational(1073741789, 1),
+ Rational(3, 1) * Rational(1073741789, 3))
+ assert_equal(Rational(9, 1073741789),
+ Rational(3, 1) / Rational(1073741789, 3))
+ assert_equal(Rational(3221225484, 1073741827),
+ Rational(3, 1) + Rational(3, 1073741827))
+ assert_equal(Rational(3221225478, 1073741827),
+ Rational(3, 1) - Rational(3, 1073741827))
+ assert_equal(Rational(9, 1073741827),
+ Rational(3, 1) * Rational(3, 1073741827))
+ assert_equal(Rational(1073741827, 1),
+ Rational(3, 1) / Rational(3, 1073741827))
+ assert_equal(Rational(1073741836, 3),
+ Rational(3, 1) + Rational(1073741827, 3))
+ assert_equal(Rational(-1073741818, 3),
+ Rational(3, 1) - Rational(1073741827, 3))
+ assert_equal(Rational(1073741827, 1),
+ Rational(3, 1) * Rational(1073741827, 3))
+ assert_equal(Rational(9, 1073741827),
+ Rational(3, 1) / Rational(1073741827, 3))
+ assert_equal(Rational(4294967270, 1073741827),
+ Rational(3, 1) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483692, 1073741827),
+ Rational(3, 1) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(3, 1) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(3, 1) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(4294967194, 1073741789),
+ Rational(3, 1) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483540, 1073741789),
+ Rational(3, 1) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(3, 1) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(3, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741790, 1),
+ Rational(1073741789, 1) + Rational(1, 1))
+ assert_equal(Rational(1073741788, 1),
+ Rational(1073741789, 1) - Rational(1, 1))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741789, 1) * Rational(1, 1))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741789, 1) / Rational(1, 1))
+ assert_equal(Rational(1073741791, 1),
+ Rational(1073741789, 1) + Rational(2, 1))
+ assert_equal(Rational(1073741787, 1),
+ Rational(1073741789, 1) - Rational(2, 1))
+ assert_equal(Rational(2147483578, 1),
+ Rational(1073741789, 1) * Rational(2, 1))
+ assert_equal(Rational(1073741789, 2),
+ Rational(1073741789, 1) / Rational(2, 1))
+ assert_equal(Rational(1073741792, 1),
+ Rational(1073741789, 1) + Rational(3, 1))
+ assert_equal(Rational(1073741786, 1),
+ Rational(1073741789, 1) - Rational(3, 1))
+ assert_equal(Rational(3221225367, 1),
+ Rational(1073741789, 1) * Rational(3, 1))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741789, 1) / Rational(3, 1))
+ assert_equal(Rational(2147483578, 1),
+ Rational(1073741789, 1) + Rational(1073741789, 1))
+ assert_equal(Rational(0, 1),
+ Rational(1073741789, 1) - Rational(1073741789, 1))
+ assert_equal(Rational(1152921429444920521, 1),
+ Rational(1073741789, 1) * Rational(1073741789, 1))
+ assert_equal(Rational(1, 1),
+ Rational(1073741789, 1) / Rational(1073741789, 1))
+ assert_equal(Rational(2147483616, 1),
+ Rational(1073741789, 1) + Rational(1073741827, 1))
+ assert_equal(Rational(-38, 1),
+ Rational(1073741789, 1) - Rational(1073741827, 1))
+ assert_equal(Rational(1152921470247108503, 1),
+ Rational(1073741789, 1) * Rational(1073741827, 1))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1073741789, 1) / Rational(1073741827, 1))
+ assert_equal(Rational(3221225369, 3),
+ Rational(1073741789, 1) + Rational(2, 3))
+ assert_equal(Rational(3221225365, 3),
+ Rational(1073741789, 1) - Rational(2, 3))
+ assert_equal(Rational(2147483578, 3),
+ Rational(1073741789, 1) * Rational(2, 3))
+ assert_equal(Rational(3221225367, 2),
+ Rational(1073741789, 1) / Rational(2, 3))
+ assert_equal(Rational(2147483581, 2),
+ Rational(1073741789, 1) + Rational(3, 2))
+ assert_equal(Rational(2147483575, 2),
+ Rational(1073741789, 1) - Rational(3, 2))
+ assert_equal(Rational(3221225367, 2),
+ Rational(1073741789, 1) * Rational(3, 2))
+ assert_equal(Rational(2147483578, 3),
+ Rational(1073741789, 1) / Rational(3, 2))
+ assert_equal(Rational(1152921429444920524, 1073741789),
+ Rational(1073741789, 1) + Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920518, 1073741789),
+ Rational(1073741789, 1) - Rational(3, 1073741789))
+ assert_equal(Rational(3, 1),
+ Rational(1073741789, 1) * Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920521, 3),
+ Rational(1073741789, 1) / Rational(3, 1073741789))
+ assert_equal(Rational(4294967156, 3),
+ Rational(1073741789, 1) + Rational(1073741789, 3))
+ assert_equal(Rational(2147483578, 3),
+ Rational(1073741789, 1) - Rational(1073741789, 3))
+ assert_equal(Rational(1152921429444920521, 3),
+ Rational(1073741789, 1) * Rational(1073741789, 3))
+ assert_equal(Rational(3, 1),
+ Rational(1073741789, 1) / Rational(1073741789, 3))
+ assert_equal(Rational(1152921470247108506, 1073741827),
+ Rational(1073741789, 1) + Rational(3, 1073741827))
+ assert_equal(Rational(1152921470247108500, 1073741827),
+ Rational(1073741789, 1) - Rational(3, 1073741827))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(1073741789, 1) * Rational(3, 1073741827))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741789, 1) / Rational(3, 1073741827))
+ assert_equal(Rational(4294967194, 3),
+ Rational(1073741789, 1) + Rational(1073741827, 3))
+ assert_equal(Rational(2147483540, 3),
+ Rational(1073741789, 1) - Rational(1073741827, 3))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741789, 1) * Rational(1073741827, 3))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(1073741789, 1) / Rational(1073741827, 3))
+ assert_equal(Rational(1152921471320850292, 1073741827),
+ Rational(1073741789, 1) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921469173366714, 1073741827),
+ Rational(1073741789, 1) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921429444920521, 1073741827),
+ Rational(1073741789, 1) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741789, 1) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921430518662348, 1073741789),
+ Rational(1073741789, 1) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921428371178694, 1073741789),
+ Rational(1073741789, 1) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741789, 1) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921429444920521, 1073741827),
+ Rational(1073741789, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741828, 1),
+ Rational(1073741827, 1) + Rational(1, 1))
+ assert_equal(Rational(1073741826, 1),
+ Rational(1073741827, 1) - Rational(1, 1))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741827, 1) * Rational(1, 1))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741827, 1) / Rational(1, 1))
+ assert_equal(Rational(1073741829, 1),
+ Rational(1073741827, 1) + Rational(2, 1))
+ assert_equal(Rational(1073741825, 1),
+ Rational(1073741827, 1) - Rational(2, 1))
+ assert_equal(Rational(2147483654, 1),
+ Rational(1073741827, 1) * Rational(2, 1))
+ assert_equal(Rational(1073741827, 2),
+ Rational(1073741827, 1) / Rational(2, 1))
+ assert_equal(Rational(1073741830, 1),
+ Rational(1073741827, 1) + Rational(3, 1))
+ assert_equal(Rational(1073741824, 1),
+ Rational(1073741827, 1) - Rational(3, 1))
+ assert_equal(Rational(3221225481, 1),
+ Rational(1073741827, 1) * Rational(3, 1))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741827, 1) / Rational(3, 1))
+ assert_equal(Rational(2147483616, 1),
+ Rational(1073741827, 1) + Rational(1073741789, 1))
+ assert_equal(Rational(38, 1),
+ Rational(1073741827, 1) - Rational(1073741789, 1))
+ assert_equal(Rational(1152921470247108503, 1),
+ Rational(1073741827, 1) * Rational(1073741789, 1))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1073741827, 1) / Rational(1073741789, 1))
+ assert_equal(Rational(2147483654, 1),
+ Rational(1073741827, 1) + Rational(1073741827, 1))
+ assert_equal(Rational(0, 1),
+ Rational(1073741827, 1) - Rational(1073741827, 1))
+ assert_equal(Rational(1152921511049297929, 1),
+ Rational(1073741827, 1) * Rational(1073741827, 1))
+ assert_equal(Rational(1, 1),
+ Rational(1073741827, 1) / Rational(1073741827, 1))
+ assert_equal(Rational(3221225483, 3),
+ Rational(1073741827, 1) + Rational(2, 3))
+ assert_equal(Rational(3221225479, 3),
+ Rational(1073741827, 1) - Rational(2, 3))
+ assert_equal(Rational(2147483654, 3),
+ Rational(1073741827, 1) * Rational(2, 3))
+ assert_equal(Rational(3221225481, 2),
+ Rational(1073741827, 1) / Rational(2, 3))
+ assert_equal(Rational(2147483657, 2),
+ Rational(1073741827, 1) + Rational(3, 2))
+ assert_equal(Rational(2147483651, 2),
+ Rational(1073741827, 1) - Rational(3, 2))
+ assert_equal(Rational(3221225481, 2),
+ Rational(1073741827, 1) * Rational(3, 2))
+ assert_equal(Rational(2147483654, 3),
+ Rational(1073741827, 1) / Rational(3, 2))
+ assert_equal(Rational(1152921470247108506, 1073741789),
+ Rational(1073741827, 1) + Rational(3, 1073741789))
+ assert_equal(Rational(1152921470247108500, 1073741789),
+ Rational(1073741827, 1) - Rational(3, 1073741789))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(1073741827, 1) * Rational(3, 1073741789))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741827, 1) / Rational(3, 1073741789))
+ assert_equal(Rational(4294967270, 3),
+ Rational(1073741827, 1) + Rational(1073741789, 3))
+ assert_equal(Rational(2147483692, 3),
+ Rational(1073741827, 1) - Rational(1073741789, 3))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741827, 1) * Rational(1073741789, 3))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(1073741827, 1) / Rational(1073741789, 3))
+ assert_equal(Rational(1152921511049297932, 1073741827),
+ Rational(1073741827, 1) + Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297926, 1073741827),
+ Rational(1073741827, 1) - Rational(3, 1073741827))
+ assert_equal(Rational(3, 1),
+ Rational(1073741827, 1) * Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297929, 3),
+ Rational(1073741827, 1) / Rational(3, 1073741827))
+ assert_equal(Rational(4294967308, 3),
+ Rational(1073741827, 1) + Rational(1073741827, 3))
+ assert_equal(Rational(2147483654, 3),
+ Rational(1073741827, 1) - Rational(1073741827, 3))
+ assert_equal(Rational(1152921511049297929, 3),
+ Rational(1073741827, 1) * Rational(1073741827, 3))
+ assert_equal(Rational(3, 1),
+ Rational(1073741827, 1) / Rational(1073741827, 3))
+ assert_equal(Rational(1152921512123039718, 1073741827),
+ Rational(1073741827, 1) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921509975556140, 1073741827),
+ Rational(1073741827, 1) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741827, 1) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921511049297929, 1073741789),
+ Rational(1073741827, 1) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921471320850330, 1073741789),
+ Rational(1073741827, 1) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921469173366676, 1073741789),
+ Rational(1073741827, 1) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921511049297929, 1073741789),
+ Rational(1073741827, 1) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741827, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(5, 3),
+ Rational(2, 3) + Rational(1, 1))
+ assert_equal(Rational(-1, 3),
+ Rational(2, 3) - Rational(1, 1))
+ assert_equal(Rational(2, 3),
+ Rational(2, 3) * Rational(1, 1))
+ assert_equal(Rational(2, 3),
+ Rational(2, 3) / Rational(1, 1))
+ assert_equal(Rational(8, 3),
+ Rational(2, 3) + Rational(2, 1))
+ assert_equal(Rational(-4, 3),
+ Rational(2, 3) - Rational(2, 1))
+ assert_equal(Rational(4, 3),
+ Rational(2, 3) * Rational(2, 1))
+ assert_equal(Rational(1, 3),
+ Rational(2, 3) / Rational(2, 1))
+ assert_equal(Rational(11, 3),
+ Rational(2, 3) + Rational(3, 1))
+ assert_equal(Rational(-7, 3),
+ Rational(2, 3) - Rational(3, 1))
+ assert_equal(Rational(2, 1),
+ Rational(2, 3) * Rational(3, 1))
+ assert_equal(Rational(2, 9),
+ Rational(2, 3) / Rational(3, 1))
+ assert_equal(Rational(3221225369, 3),
+ Rational(2, 3) + Rational(1073741789, 1))
+ assert_equal(Rational(-3221225365, 3),
+ Rational(2, 3) - Rational(1073741789, 1))
+ assert_equal(Rational(2147483578, 3),
+ Rational(2, 3) * Rational(1073741789, 1))
+ assert_equal(Rational(2, 3221225367),
+ Rational(2, 3) / Rational(1073741789, 1))
+ assert_equal(Rational(3221225483, 3),
+ Rational(2, 3) + Rational(1073741827, 1))
+ assert_equal(Rational(-3221225479, 3),
+ Rational(2, 3) - Rational(1073741827, 1))
+ assert_equal(Rational(2147483654, 3),
+ Rational(2, 3) * Rational(1073741827, 1))
+ assert_equal(Rational(2, 3221225481),
+ Rational(2, 3) / Rational(1073741827, 1))
+ assert_equal(Rational(4, 3),
+ Rational(2, 3) + Rational(2, 3))
+ assert_equal(Rational(0, 1),
+ Rational(2, 3) - Rational(2, 3))
+ assert_equal(Rational(4, 9),
+ Rational(2, 3) * Rational(2, 3))
+ assert_equal(Rational(1, 1),
+ Rational(2, 3) / Rational(2, 3))
+ assert_equal(Rational(13, 6),
+ Rational(2, 3) + Rational(3, 2))
+ assert_equal(Rational(-5, 6),
+ Rational(2, 3) - Rational(3, 2))
+ assert_equal(Rational(1, 1),
+ Rational(2, 3) * Rational(3, 2))
+ assert_equal(Rational(4, 9),
+ Rational(2, 3) / Rational(3, 2))
+ assert_equal(Rational(2147483587, 3221225367),
+ Rational(2, 3) + Rational(3, 1073741789))
+ assert_equal(Rational(2147483569, 3221225367),
+ Rational(2, 3) - Rational(3, 1073741789))
+ assert_equal(Rational(2, 1073741789),
+ Rational(2, 3) * Rational(3, 1073741789))
+ assert_equal(Rational(2147483578, 9),
+ Rational(2, 3) / Rational(3, 1073741789))
+ assert_equal(Rational(1073741791, 3),
+ Rational(2, 3) + Rational(1073741789, 3))
+ assert_equal(Rational(-357913929, 1),
+ Rational(2, 3) - Rational(1073741789, 3))
+ assert_equal(Rational(2147483578, 9),
+ Rational(2, 3) * Rational(1073741789, 3))
+ assert_equal(Rational(2, 1073741789),
+ Rational(2, 3) / Rational(1073741789, 3))
+ assert_equal(Rational(2147483663, 3221225481),
+ Rational(2, 3) + Rational(3, 1073741827))
+ assert_equal(Rational(2147483645, 3221225481),
+ Rational(2, 3) - Rational(3, 1073741827))
+ assert_equal(Rational(2, 1073741827),
+ Rational(2, 3) * Rational(3, 1073741827))
+ assert_equal(Rational(2147483654, 9),
+ Rational(2, 3) / Rational(3, 1073741827))
+ assert_equal(Rational(357913943, 1),
+ Rational(2, 3) + Rational(1073741827, 3))
+ assert_equal(Rational(-1073741825, 3),
+ Rational(2, 3) - Rational(1073741827, 3))
+ assert_equal(Rational(2147483654, 9),
+ Rational(2, 3) * Rational(1073741827, 3))
+ assert_equal(Rational(2, 1073741827),
+ Rational(2, 3) / Rational(1073741827, 3))
+ assert_equal(Rational(5368709021, 3221225481),
+ Rational(2, 3) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(-1073741713, 3221225481),
+ Rational(2, 3) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483578, 3221225481),
+ Rational(2, 3) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483654, 3221225367),
+ Rational(2, 3) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(5368709059, 3221225367),
+ Rational(2, 3) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(-1073741903, 3221225367),
+ Rational(2, 3) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483654, 3221225367),
+ Rational(2, 3) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483578, 3221225481),
+ Rational(2, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(5, 2),
+ Rational(3, 2) + Rational(1, 1))
+ assert_equal(Rational(1, 2),
+ Rational(3, 2) - Rational(1, 1))
+ assert_equal(Rational(3, 2),
+ Rational(3, 2) * Rational(1, 1))
+ assert_equal(Rational(3, 2),
+ Rational(3, 2) / Rational(1, 1))
+ assert_equal(Rational(7, 2),
+ Rational(3, 2) + Rational(2, 1))
+ assert_equal(Rational(-1, 2),
+ Rational(3, 2) - Rational(2, 1))
+ assert_equal(Rational(3, 1),
+ Rational(3, 2) * Rational(2, 1))
+ assert_equal(Rational(3, 4),
+ Rational(3, 2) / Rational(2, 1))
+ assert_equal(Rational(9, 2),
+ Rational(3, 2) + Rational(3, 1))
+ assert_equal(Rational(-3, 2),
+ Rational(3, 2) - Rational(3, 1))
+ assert_equal(Rational(9, 2),
+ Rational(3, 2) * Rational(3, 1))
+ assert_equal(Rational(1, 2),
+ Rational(3, 2) / Rational(3, 1))
+ assert_equal(Rational(2147483581, 2),
+ Rational(3, 2) + Rational(1073741789, 1))
+ assert_equal(Rational(-2147483575, 2),
+ Rational(3, 2) - Rational(1073741789, 1))
+ assert_equal(Rational(3221225367, 2),
+ Rational(3, 2) * Rational(1073741789, 1))
+ assert_equal(Rational(3, 2147483578),
+ Rational(3, 2) / Rational(1073741789, 1))
+ assert_equal(Rational(2147483657, 2),
+ Rational(3, 2) + Rational(1073741827, 1))
+ assert_equal(Rational(-2147483651, 2),
+ Rational(3, 2) - Rational(1073741827, 1))
+ assert_equal(Rational(3221225481, 2),
+ Rational(3, 2) * Rational(1073741827, 1))
+ assert_equal(Rational(3, 2147483654),
+ Rational(3, 2) / Rational(1073741827, 1))
+ assert_equal(Rational(13, 6),
+ Rational(3, 2) + Rational(2, 3))
+ assert_equal(Rational(5, 6),
+ Rational(3, 2) - Rational(2, 3))
+ assert_equal(Rational(1, 1),
+ Rational(3, 2) * Rational(2, 3))
+ assert_equal(Rational(9, 4),
+ Rational(3, 2) / Rational(2, 3))
+ assert_equal(Rational(3, 1),
+ Rational(3, 2) + Rational(3, 2))
+ assert_equal(Rational(0, 1),
+ Rational(3, 2) - Rational(3, 2))
+ assert_equal(Rational(9, 4),
+ Rational(3, 2) * Rational(3, 2))
+ assert_equal(Rational(1, 1),
+ Rational(3, 2) / Rational(3, 2))
+ assert_equal(Rational(3221225373, 2147483578),
+ Rational(3, 2) + Rational(3, 1073741789))
+ assert_equal(Rational(3221225361, 2147483578),
+ Rational(3, 2) - Rational(3, 1073741789))
+ assert_equal(Rational(9, 2147483578),
+ Rational(3, 2) * Rational(3, 1073741789))
+ assert_equal(Rational(1073741789, 2),
+ Rational(3, 2) / Rational(3, 1073741789))
+ assert_equal(Rational(2147483587, 6),
+ Rational(3, 2) + Rational(1073741789, 3))
+ assert_equal(Rational(-2147483569, 6),
+ Rational(3, 2) - Rational(1073741789, 3))
+ assert_equal(Rational(1073741789, 2),
+ Rational(3, 2) * Rational(1073741789, 3))
+ assert_equal(Rational(9, 2147483578),
+ Rational(3, 2) / Rational(1073741789, 3))
+ assert_equal(Rational(3221225487, 2147483654),
+ Rational(3, 2) + Rational(3, 1073741827))
+ assert_equal(Rational(3221225475, 2147483654),
+ Rational(3, 2) - Rational(3, 1073741827))
+ assert_equal(Rational(9, 2147483654),
+ Rational(3, 2) * Rational(3, 1073741827))
+ assert_equal(Rational(1073741827, 2),
+ Rational(3, 2) / Rational(3, 1073741827))
+ assert_equal(Rational(2147483663, 6),
+ Rational(3, 2) + Rational(1073741827, 3))
+ assert_equal(Rational(-2147483645, 6),
+ Rational(3, 2) - Rational(1073741827, 3))
+ assert_equal(Rational(1073741827, 2),
+ Rational(3, 2) * Rational(1073741827, 3))
+ assert_equal(Rational(9, 2147483654),
+ Rational(3, 2) / Rational(1073741827, 3))
+ assert_equal(Rational(5368709059, 2147483654),
+ Rational(3, 2) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741903, 2147483654),
+ Rational(3, 2) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225367, 2147483654),
+ Rational(3, 2) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225481, 2147483578),
+ Rational(3, 2) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(5368709021, 2147483578),
+ Rational(3, 2) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741713, 2147483578),
+ Rational(3, 2) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225481, 2147483578),
+ Rational(3, 2) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225367, 2147483654),
+ Rational(3, 2) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741792, 1073741789),
+ Rational(3, 1073741789) + Rational(1, 1))
+ assert_equal(Rational(-1073741786, 1073741789),
+ Rational(3, 1073741789) - Rational(1, 1))
+ assert_equal(Rational(3, 1073741789),
+ Rational(3, 1073741789) * Rational(1, 1))
+ assert_equal(Rational(3, 1073741789),
+ Rational(3, 1073741789) / Rational(1, 1))
+ assert_equal(Rational(2147483581, 1073741789),
+ Rational(3, 1073741789) + Rational(2, 1))
+ assert_equal(Rational(-2147483575, 1073741789),
+ Rational(3, 1073741789) - Rational(2, 1))
+ assert_equal(Rational(6, 1073741789),
+ Rational(3, 1073741789) * Rational(2, 1))
+ assert_equal(Rational(3, 2147483578),
+ Rational(3, 1073741789) / Rational(2, 1))
+ assert_equal(Rational(3221225370, 1073741789),
+ Rational(3, 1073741789) + Rational(3, 1))
+ assert_equal(Rational(-3221225364, 1073741789),
+ Rational(3, 1073741789) - Rational(3, 1))
+ assert_equal(Rational(9, 1073741789),
+ Rational(3, 1073741789) * Rational(3, 1))
+ assert_equal(Rational(1, 1073741789),
+ Rational(3, 1073741789) / Rational(3, 1))
+ assert_equal(Rational(1152921429444920524, 1073741789),
+ Rational(3, 1073741789) + Rational(1073741789, 1))
+ assert_equal(Rational(-1152921429444920518, 1073741789),
+ Rational(3, 1073741789) - Rational(1073741789, 1))
+ assert_equal(Rational(3, 1),
+ Rational(3, 1073741789) * Rational(1073741789, 1))
+ assert_equal(Rational(3, 1152921429444920521),
+ Rational(3, 1073741789) / Rational(1073741789, 1))
+ assert_equal(Rational(1152921470247108506, 1073741789),
+ Rational(3, 1073741789) + Rational(1073741827, 1))
+ assert_equal(Rational(-1152921470247108500, 1073741789),
+ Rational(3, 1073741789) - Rational(1073741827, 1))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(3, 1073741789) * Rational(1073741827, 1))
+ assert_equal(Rational(3, 1152921470247108503),
+ Rational(3, 1073741789) / Rational(1073741827, 1))
+ assert_equal(Rational(2147483587, 3221225367),
+ Rational(3, 1073741789) + Rational(2, 3))
+ assert_equal(Rational(-2147483569, 3221225367),
+ Rational(3, 1073741789) - Rational(2, 3))
+ assert_equal(Rational(2, 1073741789),
+ Rational(3, 1073741789) * Rational(2, 3))
+ assert_equal(Rational(9, 2147483578),
+ Rational(3, 1073741789) / Rational(2, 3))
+ assert_equal(Rational(3221225373, 2147483578),
+ Rational(3, 1073741789) + Rational(3, 2))
+ assert_equal(Rational(-3221225361, 2147483578),
+ Rational(3, 1073741789) - Rational(3, 2))
+ assert_equal(Rational(9, 2147483578),
+ Rational(3, 1073741789) * Rational(3, 2))
+ assert_equal(Rational(2, 1073741789),
+ Rational(3, 1073741789) / Rational(3, 2))
+ assert_equal(Rational(6, 1073741789),
+ Rational(3, 1073741789) + Rational(3, 1073741789))
+ assert_equal(Rational(0, 1),
+ Rational(3, 1073741789) - Rational(3, 1073741789))
+ assert_equal(Rational(9, 1152921429444920521),
+ Rational(3, 1073741789) * Rational(3, 1073741789))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1073741789) / Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920530, 3221225367),
+ Rational(3, 1073741789) + Rational(1073741789, 3))
+ assert_equal(Rational(-1152921429444920512, 3221225367),
+ Rational(3, 1073741789) - Rational(1073741789, 3))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1073741789) * Rational(1073741789, 3))
+ assert_equal(Rational(9, 1152921429444920521),
+ Rational(3, 1073741789) / Rational(1073741789, 3))
+ assert_equal(Rational(6442450848, 1152921470247108503),
+ Rational(3, 1073741789) + Rational(3, 1073741827))
+ assert_equal(Rational(114, 1152921470247108503),
+ Rational(3, 1073741789) - Rational(3, 1073741827))
+ assert_equal(Rational(9, 1152921470247108503),
+ Rational(3, 1073741789) * Rational(3, 1073741827))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(3, 1073741789) / Rational(3, 1073741827))
+ assert_equal(Rational(1152921470247108512, 3221225367),
+ Rational(3, 1073741789) + Rational(1073741827, 3))
+ assert_equal(Rational(-1152921470247108494, 3221225367),
+ Rational(3, 1073741789) - Rational(1073741827, 3))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(3, 1073741789) * Rational(1073741827, 3))
+ assert_equal(Rational(9, 1152921470247108503),
+ Rational(3, 1073741789) / Rational(1073741827, 3))
+ assert_equal(Rational(1152921432666146002, 1152921470247108503),
+ Rational(3, 1073741789) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(-1152921426223695040, 1152921470247108503),
+ Rational(3, 1073741789) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(3, 1073741827),
+ Rational(3, 1073741789) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225481, 1152921429444920521),
+ Rational(3, 1073741789) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741830, 1073741789),
+ Rational(3, 1073741789) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(-1073741824, 1073741789),
+ Rational(3, 1073741789) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225481, 1152921429444920521),
+ Rational(3, 1073741789) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1073741827),
+ Rational(3, 1073741789) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741792, 3),
+ Rational(1073741789, 3) + Rational(1, 1))
+ assert_equal(Rational(1073741786, 3),
+ Rational(1073741789, 3) - Rational(1, 1))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741789, 3) * Rational(1, 1))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741789, 3) / Rational(1, 1))
+ assert_equal(Rational(1073741795, 3),
+ Rational(1073741789, 3) + Rational(2, 1))
+ assert_equal(Rational(1073741783, 3),
+ Rational(1073741789, 3) - Rational(2, 1))
+ assert_equal(Rational(2147483578, 3),
+ Rational(1073741789, 3) * Rational(2, 1))
+ assert_equal(Rational(1073741789, 6),
+ Rational(1073741789, 3) / Rational(2, 1))
+ assert_equal(Rational(1073741798, 3),
+ Rational(1073741789, 3) + Rational(3, 1))
+ assert_equal(Rational(1073741780, 3),
+ Rational(1073741789, 3) - Rational(3, 1))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741789, 3) * Rational(3, 1))
+ assert_equal(Rational(1073741789, 9),
+ Rational(1073741789, 3) / Rational(3, 1))
+ assert_equal(Rational(4294967156, 3),
+ Rational(1073741789, 3) + Rational(1073741789, 1))
+ assert_equal(Rational(-2147483578, 3),
+ Rational(1073741789, 3) - Rational(1073741789, 1))
+ assert_equal(Rational(1152921429444920521, 3),
+ Rational(1073741789, 3) * Rational(1073741789, 1))
+ assert_equal(Rational(1, 3),
+ Rational(1073741789, 3) / Rational(1073741789, 1))
+ assert_equal(Rational(4294967270, 3),
+ Rational(1073741789, 3) + Rational(1073741827, 1))
+ assert_equal(Rational(-2147483692, 3),
+ Rational(1073741789, 3) - Rational(1073741827, 1))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741789, 3) * Rational(1073741827, 1))
+ assert_equal(Rational(1073741789, 3221225481),
+ Rational(1073741789, 3) / Rational(1073741827, 1))
+ assert_equal(Rational(1073741791, 3),
+ Rational(1073741789, 3) + Rational(2, 3))
+ assert_equal(Rational(357913929, 1),
+ Rational(1073741789, 3) - Rational(2, 3))
+ assert_equal(Rational(2147483578, 9),
+ Rational(1073741789, 3) * Rational(2, 3))
+ assert_equal(Rational(1073741789, 2),
+ Rational(1073741789, 3) / Rational(2, 3))
+ assert_equal(Rational(2147483587, 6),
+ Rational(1073741789, 3) + Rational(3, 2))
+ assert_equal(Rational(2147483569, 6),
+ Rational(1073741789, 3) - Rational(3, 2))
+ assert_equal(Rational(1073741789, 2),
+ Rational(1073741789, 3) * Rational(3, 2))
+ assert_equal(Rational(2147483578, 9),
+ Rational(1073741789, 3) / Rational(3, 2))
+ assert_equal(Rational(1152921429444920530, 3221225367),
+ Rational(1073741789, 3) + Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920512, 3221225367),
+ Rational(1073741789, 3) - Rational(3, 1073741789))
+ assert_equal(Rational(1, 1),
+ Rational(1073741789, 3) * Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920521, 9),
+ Rational(1073741789, 3) / Rational(3, 1073741789))
+ assert_equal(Rational(2147483578, 3),
+ Rational(1073741789, 3) + Rational(1073741789, 3))
+ assert_equal(Rational(0, 1),
+ Rational(1073741789, 3) - Rational(1073741789, 3))
+ assert_equal(Rational(1152921429444920521, 9),
+ Rational(1073741789, 3) * Rational(1073741789, 3))
+ assert_equal(Rational(1, 1),
+ Rational(1073741789, 3) / Rational(1073741789, 3))
+ assert_equal(Rational(1152921470247108512, 3221225481),
+ Rational(1073741789, 3) + Rational(3, 1073741827))
+ assert_equal(Rational(1152921470247108494, 3221225481),
+ Rational(1073741789, 3) - Rational(3, 1073741827))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1073741789, 3) * Rational(3, 1073741827))
+ assert_equal(Rational(1152921470247108503, 9),
+ Rational(1073741789, 3) / Rational(3, 1073741827))
+ assert_equal(Rational(715827872, 1),
+ Rational(1073741789, 3) + Rational(1073741827, 3))
+ assert_equal(Rational(-38, 3),
+ Rational(1073741789, 3) - Rational(1073741827, 3))
+ assert_equal(Rational(1152921470247108503, 9),
+ Rational(1073741789, 3) * Rational(1073741827, 3))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1073741789, 3) / Rational(1073741827, 3))
+ assert_equal(Rational(1152921473468333870, 3221225481),
+ Rational(1073741789, 3) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921467025883136, 3221225481),
+ Rational(1073741789, 3) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921429444920521, 3221225481),
+ Rational(1073741789, 3) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741789, 3) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921432666146002, 3221225367),
+ Rational(1073741789, 3) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921426223695040, 3221225367),
+ Rational(1073741789, 3) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741789, 3) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921429444920521, 3221225481),
+ Rational(1073741789, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741830, 1073741827),
+ Rational(3, 1073741827) + Rational(1, 1))
+ assert_equal(Rational(-1073741824, 1073741827),
+ Rational(3, 1073741827) - Rational(1, 1))
+ assert_equal(Rational(3, 1073741827),
+ Rational(3, 1073741827) * Rational(1, 1))
+ assert_equal(Rational(3, 1073741827),
+ Rational(3, 1073741827) / Rational(1, 1))
+ assert_equal(Rational(2147483657, 1073741827),
+ Rational(3, 1073741827) + Rational(2, 1))
+ assert_equal(Rational(-2147483651, 1073741827),
+ Rational(3, 1073741827) - Rational(2, 1))
+ assert_equal(Rational(6, 1073741827),
+ Rational(3, 1073741827) * Rational(2, 1))
+ assert_equal(Rational(3, 2147483654),
+ Rational(3, 1073741827) / Rational(2, 1))
+ assert_equal(Rational(3221225484, 1073741827),
+ Rational(3, 1073741827) + Rational(3, 1))
+ assert_equal(Rational(-3221225478, 1073741827),
+ Rational(3, 1073741827) - Rational(3, 1))
+ assert_equal(Rational(9, 1073741827),
+ Rational(3, 1073741827) * Rational(3, 1))
+ assert_equal(Rational(1, 1073741827),
+ Rational(3, 1073741827) / Rational(3, 1))
+ assert_equal(Rational(1152921470247108506, 1073741827),
+ Rational(3, 1073741827) + Rational(1073741789, 1))
+ assert_equal(Rational(-1152921470247108500, 1073741827),
+ Rational(3, 1073741827) - Rational(1073741789, 1))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(3, 1073741827) * Rational(1073741789, 1))
+ assert_equal(Rational(3, 1152921470247108503),
+ Rational(3, 1073741827) / Rational(1073741789, 1))
+ assert_equal(Rational(1152921511049297932, 1073741827),
+ Rational(3, 1073741827) + Rational(1073741827, 1))
+ assert_equal(Rational(-1152921511049297926, 1073741827),
+ Rational(3, 1073741827) - Rational(1073741827, 1))
+ assert_equal(Rational(3, 1),
+ Rational(3, 1073741827) * Rational(1073741827, 1))
+ assert_equal(Rational(3, 1152921511049297929),
+ Rational(3, 1073741827) / Rational(1073741827, 1))
+ assert_equal(Rational(2147483663, 3221225481),
+ Rational(3, 1073741827) + Rational(2, 3))
+ assert_equal(Rational(-2147483645, 3221225481),
+ Rational(3, 1073741827) - Rational(2, 3))
+ assert_equal(Rational(2, 1073741827),
+ Rational(3, 1073741827) * Rational(2, 3))
+ assert_equal(Rational(9, 2147483654),
+ Rational(3, 1073741827) / Rational(2, 3))
+ assert_equal(Rational(3221225487, 2147483654),
+ Rational(3, 1073741827) + Rational(3, 2))
+ assert_equal(Rational(-3221225475, 2147483654),
+ Rational(3, 1073741827) - Rational(3, 2))
+ assert_equal(Rational(9, 2147483654),
+ Rational(3, 1073741827) * Rational(3, 2))
+ assert_equal(Rational(2, 1073741827),
+ Rational(3, 1073741827) / Rational(3, 2))
+ assert_equal(Rational(6442450848, 1152921470247108503),
+ Rational(3, 1073741827) + Rational(3, 1073741789))
+ assert_equal(Rational(-114, 1152921470247108503),
+ Rational(3, 1073741827) - Rational(3, 1073741789))
+ assert_equal(Rational(9, 1152921470247108503),
+ Rational(3, 1073741827) * Rational(3, 1073741789))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(3, 1073741827) / Rational(3, 1073741789))
+ assert_equal(Rational(1152921470247108512, 3221225481),
+ Rational(3, 1073741827) + Rational(1073741789, 3))
+ assert_equal(Rational(-1152921470247108494, 3221225481),
+ Rational(3, 1073741827) - Rational(1073741789, 3))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(3, 1073741827) * Rational(1073741789, 3))
+ assert_equal(Rational(9, 1152921470247108503),
+ Rational(3, 1073741827) / Rational(1073741789, 3))
+ assert_equal(Rational(6, 1073741827),
+ Rational(3, 1073741827) + Rational(3, 1073741827))
+ assert_equal(Rational(0, 1),
+ Rational(3, 1073741827) - Rational(3, 1073741827))
+ assert_equal(Rational(9, 1152921511049297929),
+ Rational(3, 1073741827) * Rational(3, 1073741827))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1073741827) / Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297938, 3221225481),
+ Rational(3, 1073741827) + Rational(1073741827, 3))
+ assert_equal(Rational(-1152921511049297920, 3221225481),
+ Rational(3, 1073741827) - Rational(1073741827, 3))
+ assert_equal(Rational(1, 1),
+ Rational(3, 1073741827) * Rational(1073741827, 3))
+ assert_equal(Rational(9, 1152921511049297929),
+ Rational(3, 1073741827) / Rational(1073741827, 3))
+ assert_equal(Rational(1073741792, 1073741827),
+ Rational(3, 1073741827) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(-1073741786, 1073741827),
+ Rational(3, 1073741827) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(3221225367, 1152921511049297929),
+ Rational(3, 1073741827) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(3, 1073741789),
+ Rational(3, 1073741827) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921514270523296, 1152921470247108503),
+ Rational(3, 1073741827) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(-1152921507828072562, 1152921470247108503),
+ Rational(3, 1073741827) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1073741789),
+ Rational(3, 1073741827) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(3221225367, 1152921511049297929),
+ Rational(3, 1073741827) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741830, 3),
+ Rational(1073741827, 3) + Rational(1, 1))
+ assert_equal(Rational(1073741824, 3),
+ Rational(1073741827, 3) - Rational(1, 1))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741827, 3) * Rational(1, 1))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741827, 3) / Rational(1, 1))
+ assert_equal(Rational(1073741833, 3),
+ Rational(1073741827, 3) + Rational(2, 1))
+ assert_equal(Rational(1073741821, 3),
+ Rational(1073741827, 3) - Rational(2, 1))
+ assert_equal(Rational(2147483654, 3),
+ Rational(1073741827, 3) * Rational(2, 1))
+ assert_equal(Rational(1073741827, 6),
+ Rational(1073741827, 3) / Rational(2, 1))
+ assert_equal(Rational(1073741836, 3),
+ Rational(1073741827, 3) + Rational(3, 1))
+ assert_equal(Rational(1073741818, 3),
+ Rational(1073741827, 3) - Rational(3, 1))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741827, 3) * Rational(3, 1))
+ assert_equal(Rational(1073741827, 9),
+ Rational(1073741827, 3) / Rational(3, 1))
+ assert_equal(Rational(4294967194, 3),
+ Rational(1073741827, 3) + Rational(1073741789, 1))
+ assert_equal(Rational(-2147483540, 3),
+ Rational(1073741827, 3) - Rational(1073741789, 1))
+ assert_equal(Rational(1152921470247108503, 3),
+ Rational(1073741827, 3) * Rational(1073741789, 1))
+ assert_equal(Rational(1073741827, 3221225367),
+ Rational(1073741827, 3) / Rational(1073741789, 1))
+ assert_equal(Rational(4294967308, 3),
+ Rational(1073741827, 3) + Rational(1073741827, 1))
+ assert_equal(Rational(-2147483654, 3),
+ Rational(1073741827, 3) - Rational(1073741827, 1))
+ assert_equal(Rational(1152921511049297929, 3),
+ Rational(1073741827, 3) * Rational(1073741827, 1))
+ assert_equal(Rational(1, 3),
+ Rational(1073741827, 3) / Rational(1073741827, 1))
+ assert_equal(Rational(357913943, 1),
+ Rational(1073741827, 3) + Rational(2, 3))
+ assert_equal(Rational(1073741825, 3),
+ Rational(1073741827, 3) - Rational(2, 3))
+ assert_equal(Rational(2147483654, 9),
+ Rational(1073741827, 3) * Rational(2, 3))
+ assert_equal(Rational(1073741827, 2),
+ Rational(1073741827, 3) / Rational(2, 3))
+ assert_equal(Rational(2147483663, 6),
+ Rational(1073741827, 3) + Rational(3, 2))
+ assert_equal(Rational(2147483645, 6),
+ Rational(1073741827, 3) - Rational(3, 2))
+ assert_equal(Rational(1073741827, 2),
+ Rational(1073741827, 3) * Rational(3, 2))
+ assert_equal(Rational(2147483654, 9),
+ Rational(1073741827, 3) / Rational(3, 2))
+ assert_equal(Rational(1152921470247108512, 3221225367),
+ Rational(1073741827, 3) + Rational(3, 1073741789))
+ assert_equal(Rational(1152921470247108494, 3221225367),
+ Rational(1073741827, 3) - Rational(3, 1073741789))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1073741827, 3) * Rational(3, 1073741789))
+ assert_equal(Rational(1152921470247108503, 9),
+ Rational(1073741827, 3) / Rational(3, 1073741789))
+ assert_equal(Rational(715827872, 1),
+ Rational(1073741827, 3) + Rational(1073741789, 3))
+ assert_equal(Rational(38, 3),
+ Rational(1073741827, 3) - Rational(1073741789, 3))
+ assert_equal(Rational(1152921470247108503, 9),
+ Rational(1073741827, 3) * Rational(1073741789, 3))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1073741827, 3) / Rational(1073741789, 3))
+ assert_equal(Rational(1152921511049297938, 3221225481),
+ Rational(1073741827, 3) + Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297920, 3221225481),
+ Rational(1073741827, 3) - Rational(3, 1073741827))
+ assert_equal(Rational(1, 1),
+ Rational(1073741827, 3) * Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297929, 9),
+ Rational(1073741827, 3) / Rational(3, 1073741827))
+ assert_equal(Rational(2147483654, 3),
+ Rational(1073741827, 3) + Rational(1073741827, 3))
+ assert_equal(Rational(0, 1),
+ Rational(1073741827, 3) - Rational(1073741827, 3))
+ assert_equal(Rational(1152921511049297929, 9),
+ Rational(1073741827, 3) * Rational(1073741827, 3))
+ assert_equal(Rational(1, 1),
+ Rational(1073741827, 3) / Rational(1073741827, 3))
+ assert_equal(Rational(1152921514270523296, 3221225481),
+ Rational(1073741827, 3) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921507828072562, 3221225481),
+ Rational(1073741827, 3) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741827, 3) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921511049297929, 3221225367),
+ Rational(1073741827, 3) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921473468333984, 3221225367),
+ Rational(1073741827, 3) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921467025883022, 3221225367),
+ Rational(1073741827, 3) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921511049297929, 3221225367),
+ Rational(1073741827, 3) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741827, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483616, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(1, 1))
+ assert_equal(Rational(-38, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(1, 1))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1073741789, 1073741827) * Rational(1, 1))
+ assert_equal(Rational(1073741789, 1073741827),
+ Rational(1073741789, 1073741827) / Rational(1, 1))
+ assert_equal(Rational(3221225443, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(2, 1))
+ assert_equal(Rational(-1073741865, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(2, 1))
+ assert_equal(Rational(2147483578, 1073741827),
+ Rational(1073741789, 1073741827) * Rational(2, 1))
+ assert_equal(Rational(1073741789, 2147483654),
+ Rational(1073741789, 1073741827) / Rational(2, 1))
+ assert_equal(Rational(4294967270, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(3, 1))
+ assert_equal(Rational(-2147483692, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(3, 1))
+ assert_equal(Rational(3221225367, 1073741827),
+ Rational(1073741789, 1073741827) * Rational(3, 1))
+ assert_equal(Rational(1073741789, 3221225481),
+ Rational(1073741789, 1073741827) / Rational(3, 1))
+ assert_equal(Rational(1152921471320850292, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(1073741789, 1))
+ assert_equal(Rational(-1152921469173366714, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(1073741789, 1))
+ assert_equal(Rational(1152921429444920521, 1073741827),
+ Rational(1073741789, 1073741827) * Rational(1073741789, 1))
+ assert_equal(Rational(1, 1073741827),
+ Rational(1073741789, 1073741827) / Rational(1073741789, 1))
+ assert_equal(Rational(1152921512123039718, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(1073741827, 1))
+ assert_equal(Rational(-1152921509975556140, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(1073741827, 1))
+ assert_equal(Rational(1073741789, 1),
+ Rational(1073741789, 1073741827) * Rational(1073741827, 1))
+ assert_equal(Rational(1073741789, 1152921511049297929),
+ Rational(1073741789, 1073741827) / Rational(1073741827, 1))
+ assert_equal(Rational(5368709021, 3221225481),
+ Rational(1073741789, 1073741827) + Rational(2, 3))
+ assert_equal(Rational(1073741713, 3221225481),
+ Rational(1073741789, 1073741827) - Rational(2, 3))
+ assert_equal(Rational(2147483578, 3221225481),
+ Rational(1073741789, 1073741827) * Rational(2, 3))
+ assert_equal(Rational(3221225367, 2147483654),
+ Rational(1073741789, 1073741827) / Rational(2, 3))
+ assert_equal(Rational(5368709059, 2147483654),
+ Rational(1073741789, 1073741827) + Rational(3, 2))
+ assert_equal(Rational(-1073741903, 2147483654),
+ Rational(1073741789, 1073741827) - Rational(3, 2))
+ assert_equal(Rational(3221225367, 2147483654),
+ Rational(1073741789, 1073741827) * Rational(3, 2))
+ assert_equal(Rational(2147483578, 3221225481),
+ Rational(1073741789, 1073741827) / Rational(3, 2))
+ assert_equal(Rational(1152921432666146002, 1152921470247108503),
+ Rational(1073741789, 1073741827) + Rational(3, 1073741789))
+ assert_equal(Rational(1152921426223695040, 1152921470247108503),
+ Rational(1073741789, 1073741827) - Rational(3, 1073741789))
+ assert_equal(Rational(3, 1073741827),
+ Rational(1073741789, 1073741827) * Rational(3, 1073741789))
+ assert_equal(Rational(1152921429444920521, 3221225481),
+ Rational(1073741789, 1073741827) / Rational(3, 1073741789))
+ assert_equal(Rational(1152921473468333870, 3221225481),
+ Rational(1073741789, 1073741827) + Rational(1073741789, 3))
+ assert_equal(Rational(-1152921467025883136, 3221225481),
+ Rational(1073741789, 1073741827) - Rational(1073741789, 3))
+ assert_equal(Rational(1152921429444920521, 3221225481),
+ Rational(1073741789, 1073741827) * Rational(1073741789, 3))
+ assert_equal(Rational(3, 1073741827),
+ Rational(1073741789, 1073741827) / Rational(1073741789, 3))
+ assert_equal(Rational(1073741792, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(3, 1073741827))
+ assert_equal(Rational(1073741786, 1073741827),
+ Rational(1073741789, 1073741827) - Rational(3, 1073741827))
+ assert_equal(Rational(3221225367, 1152921511049297929),
+ Rational(1073741789, 1073741827) * Rational(3, 1073741827))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741789, 1073741827) / Rational(3, 1073741827))
+ assert_equal(Rational(1152921514270523296, 3221225481),
+ Rational(1073741789, 1073741827) + Rational(1073741827, 3))
+ assert_equal(Rational(-1152921507828072562, 3221225481),
+ Rational(1073741789, 1073741827) - Rational(1073741827, 3))
+ assert_equal(Rational(1073741789, 3),
+ Rational(1073741789, 1073741827) * Rational(1073741827, 3))
+ assert_equal(Rational(3221225367, 1152921511049297929),
+ Rational(1073741789, 1073741827) / Rational(1073741827, 3))
+ assert_equal(Rational(2147483578, 1073741827),
+ Rational(1073741789, 1073741827) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(0, 1),
+ Rational(1073741789, 1073741827) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921429444920521, 1152921511049297929),
+ Rational(1073741789, 1073741827) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1, 1),
+ Rational(1073741789, 1073741827) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(2305842940494218450, 1152921470247108503),
+ Rational(1073741789, 1073741827) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(-81604377408, 1152921470247108503),
+ Rational(1073741789, 1073741827) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1, 1),
+ Rational(1073741789, 1073741827) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921429444920521, 1152921511049297929),
+ Rational(1073741789, 1073741827) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(2147483616, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(1, 1))
+ assert_equal(Rational(38, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(1, 1))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1073741827, 1073741789) * Rational(1, 1))
+ assert_equal(Rational(1073741827, 1073741789),
+ Rational(1073741827, 1073741789) / Rational(1, 1))
+ assert_equal(Rational(3221225405, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(2, 1))
+ assert_equal(Rational(-1073741751, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(2, 1))
+ assert_equal(Rational(2147483654, 1073741789),
+ Rational(1073741827, 1073741789) * Rational(2, 1))
+ assert_equal(Rational(1073741827, 2147483578),
+ Rational(1073741827, 1073741789) / Rational(2, 1))
+ assert_equal(Rational(4294967194, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(3, 1))
+ assert_equal(Rational(-2147483540, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(3, 1))
+ assert_equal(Rational(3221225481, 1073741789),
+ Rational(1073741827, 1073741789) * Rational(3, 1))
+ assert_equal(Rational(1073741827, 3221225367),
+ Rational(1073741827, 1073741789) / Rational(3, 1))
+ assert_equal(Rational(1152921430518662348, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(1073741789, 1))
+ assert_equal(Rational(-1152921428371178694, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(1073741789, 1))
+ assert_equal(Rational(1073741827, 1),
+ Rational(1073741827, 1073741789) * Rational(1073741789, 1))
+ assert_equal(Rational(1073741827, 1152921429444920521),
+ Rational(1073741827, 1073741789) / Rational(1073741789, 1))
+ assert_equal(Rational(1152921471320850330, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(1073741827, 1))
+ assert_equal(Rational(-1152921469173366676, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(1073741827, 1))
+ assert_equal(Rational(1152921511049297929, 1073741789),
+ Rational(1073741827, 1073741789) * Rational(1073741827, 1))
+ assert_equal(Rational(1, 1073741789),
+ Rational(1073741827, 1073741789) / Rational(1073741827, 1))
+ assert_equal(Rational(5368709059, 3221225367),
+ Rational(1073741827, 1073741789) + Rational(2, 3))
+ assert_equal(Rational(1073741903, 3221225367),
+ Rational(1073741827, 1073741789) - Rational(2, 3))
+ assert_equal(Rational(2147483654, 3221225367),
+ Rational(1073741827, 1073741789) * Rational(2, 3))
+ assert_equal(Rational(3221225481, 2147483578),
+ Rational(1073741827, 1073741789) / Rational(2, 3))
+ assert_equal(Rational(5368709021, 2147483578),
+ Rational(1073741827, 1073741789) + Rational(3, 2))
+ assert_equal(Rational(-1073741713, 2147483578),
+ Rational(1073741827, 1073741789) - Rational(3, 2))
+ assert_equal(Rational(3221225481, 2147483578),
+ Rational(1073741827, 1073741789) * Rational(3, 2))
+ assert_equal(Rational(2147483654, 3221225367),
+ Rational(1073741827, 1073741789) / Rational(3, 2))
+ assert_equal(Rational(1073741830, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(3, 1073741789))
+ assert_equal(Rational(1073741824, 1073741789),
+ Rational(1073741827, 1073741789) - Rational(3, 1073741789))
+ assert_equal(Rational(3221225481, 1152921429444920521),
+ Rational(1073741827, 1073741789) * Rational(3, 1073741789))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741827, 1073741789) / Rational(3, 1073741789))
+ assert_equal(Rational(1152921432666146002, 3221225367),
+ Rational(1073741827, 1073741789) + Rational(1073741789, 3))
+ assert_equal(Rational(-1152921426223695040, 3221225367),
+ Rational(1073741827, 1073741789) - Rational(1073741789, 3))
+ assert_equal(Rational(1073741827, 3),
+ Rational(1073741827, 1073741789) * Rational(1073741789, 3))
+ assert_equal(Rational(3221225481, 1152921429444920521),
+ Rational(1073741827, 1073741789) / Rational(1073741789, 3))
+ assert_equal(Rational(1152921514270523296, 1152921470247108503),
+ Rational(1073741827, 1073741789) + Rational(3, 1073741827))
+ assert_equal(Rational(1152921507828072562, 1152921470247108503),
+ Rational(1073741827, 1073741789) - Rational(3, 1073741827))
+ assert_equal(Rational(3, 1073741789),
+ Rational(1073741827, 1073741789) * Rational(3, 1073741827))
+ assert_equal(Rational(1152921511049297929, 3221225367),
+ Rational(1073741827, 1073741789) / Rational(3, 1073741827))
+ assert_equal(Rational(1152921473468333984, 3221225367),
+ Rational(1073741827, 1073741789) + Rational(1073741827, 3))
+ assert_equal(Rational(-1152921467025883022, 3221225367),
+ Rational(1073741827, 1073741789) - Rational(1073741827, 3))
+ assert_equal(Rational(1152921511049297929, 3221225367),
+ Rational(1073741827, 1073741789) * Rational(1073741827, 3))
+ assert_equal(Rational(3, 1073741789),
+ Rational(1073741827, 1073741789) / Rational(1073741827, 3))
+ assert_equal(Rational(2305842940494218450, 1152921470247108503),
+ Rational(1073741827, 1073741789) + Rational(1073741789, 1073741827))
+ assert_equal(Rational(81604377408, 1152921470247108503),
+ Rational(1073741827, 1073741789) - Rational(1073741789, 1073741827))
+ assert_equal(Rational(1, 1),
+ Rational(1073741827, 1073741789) * Rational(1073741789, 1073741827))
+ assert_equal(Rational(1152921511049297929, 1152921429444920521),
+ Rational(1073741827, 1073741789) / Rational(1073741789, 1073741827))
+ assert_equal(Rational(2147483654, 1073741789),
+ Rational(1073741827, 1073741789) + Rational(1073741827, 1073741789))
+ assert_equal(Rational(0, 1),
+ Rational(1073741827, 1073741789) - Rational(1073741827, 1073741789))
+ assert_equal(Rational(1152921511049297929, 1152921429444920521),
+ Rational(1073741827, 1073741789) * Rational(1073741827, 1073741789))
+ assert_equal(Rational(1, 1),
+ Rational(1073741827, 1073741789) / Rational(1073741827, 1073741789))
+ end
+
+end
diff --git a/trunk/test/ruby/test_readpartial.rb b/trunk/test/ruby/test_readpartial.rb
new file mode 100644
index 0000000000..c4f9d193f2
--- /dev/null
+++ b/trunk/test/ruby/test_readpartial.rb
@@ -0,0 +1,70 @@
+require 'test/unit'
+require 'timeout'
+require 'fcntl'
+
+class TestReadPartial < Test::Unit::TestCase
+ def make_pipe
+ r, w = IO.pipe
+ begin
+ yield r, w
+ ensure
+ r.close unless r.closed?
+ w.close unless w.closed?
+ end
+ end
+
+ def pipe
+ make_pipe {|r, w|
+ yield r, w
+ }
+ return unless defined?(Fcntl::F_SETFL)
+ return unless defined?(Fcntl::F_GETFL)
+ return unless defined?(Fcntl::O_NONBLOCK)
+ make_pipe {|r, w|
+ r.fcntl(Fcntl::F_SETFL, r.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
+ yield r, w
+ }
+ end
+
+ def test_length_zero
+ pipe {|r, w|
+ assert_equal('', r.readpartial(0))
+ }
+ end
+
+ def test_closed_pipe
+ pipe {|r, w|
+ w << 'abc'
+ w.close
+ assert_equal('ab', r.readpartial(2))
+ assert_equal('c', r.readpartial(2))
+ assert_raises(EOFError) { r.readpartial(2) }
+ assert_raises(EOFError) { r.readpartial(2) }
+ }
+ end
+
+ def test_open_pipe
+ pipe {|r, w|
+ w << 'abc'
+ assert_equal('ab', r.readpartial(2))
+ assert_equal('c', r.readpartial(2))
+ assert_raises(TimeoutError) {
+ timeout(0.1) { r.readpartial(2) }
+ }
+ }
+ end
+
+ def test_with_stdio
+ pipe {|r, w|
+ w << "abc\ndef\n"
+ assert_equal("abc\n", r.gets)
+ w << "ghi\n"
+ assert_equal("de", r.readpartial(2))
+ assert_equal("f\n", r.readpartial(4096))
+ assert_equal("ghi\n", r.readpartial(4096))
+ assert_raises(TimeoutError) {
+ timeout(0.1) { r.readpartial(2) }
+ }
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_regexp.rb b/trunk/test/ruby/test_regexp.rb
new file mode 100644
index 0000000000..ad222c5483
--- /dev/null
+++ b/trunk/test/ruby/test_regexp.rb
@@ -0,0 +1,758 @@
+require 'test/unit'
+
+class TestRegexp < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_ruby_dev_24643
+ assert_nothing_raised("[ruby-dev:24643]") {
+ /(?:(?:[a]*[a])?b)*a*$/ =~ "aabaaca"
+ }
+ end
+
+ def test_ruby_talk_116455
+ assert_match(/^(\w{2,}).* ([A-Za-z\xa2\xc0-\xff]{2,}?)$/n, "Hallo Welt")
+ end
+
+ def test_ruby_dev_24887
+ assert_equal("a".gsub(/a\Z/, ""), "")
+ end
+
+ def test_yoshidam_net_20041111_1
+ s = "[\xC2\xA0-\xC3\xBE]"
+ assert_match(Regexp.new(s, nil, "u"), "\xC3\xBE")
+ end
+
+ def test_yoshidam_net_20041111_2
+ assert_raise(RegexpError) do
+ s = "[\xFF-\xFF]".force_encoding("utf-8")
+ Regexp.new(s, nil, "u")
+ end
+ end
+
+ def test_ruby_dev_31309
+ assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-'))
+ end
+
+ def test_assert_normal_exit
+ # moved from knownbug. It caused core.
+ Regexp.union("a", "a")
+ end
+
+ def test_to_s
+ assert_equal '(?-mix:\x00)', Regexp.new("\0").to_s
+ end
+
+ def test_union
+ assert_equal :ok, begin
+ Regexp.union(
+ "a",
+ Regexp.new("\xc2\xa1".force_encoding("euc-jp")),
+ Regexp.new("\xc2\xa1".force_encoding("utf-8")))
+ :ng
+ rescue ArgumentError
+ :ok
+ end
+ end
+
+ def test_named_capture
+ m = /&(?<foo>.*?);/.match("aaa &amp; yyy")
+ assert_equal("amp", m["foo"])
+ assert_equal("amp", m[:foo])
+ assert_equal(5, m.begin(:foo))
+ assert_equal(8, m.end(:foo))
+ assert_equal([5,8], m.offset(:foo))
+
+ assert_equal("aaa [amp] yyy",
+ "aaa &amp; yyy".sub(/&(?<foo>.*?);/, '[\k<foo>]'))
+
+ assert_equal('#<MatchData "&amp; y" foo:"amp">',
+ /&(?<foo>.*?); (y)/.match("aaa &amp; yyy").inspect)
+ assert_equal('#<MatchData "&amp; y" 1:"amp" 2:"y">',
+ /&(.*?); (y)/.match("aaa &amp; yyy").inspect)
+ assert_equal('#<MatchData "&amp; y" foo:"amp" bar:"y">',
+ /&(?<foo>.*?); (?<bar>y)/.match("aaa &amp; yyy").inspect)
+ assert_equal('#<MatchData "&amp; y" foo:"amp" foo:"y">',
+ /&(?<foo>.*?); (?<foo>y)/.match("aaa &amp; yyy").inspect)
+
+ /(?<id>[A-Za-z_]+)/ =~ "!abc"
+ assert_equal("abc", Regexp.last_match(:id))
+
+ /a/ =~ "b" # doesn't match.
+ assert_equal(nil, Regexp.last_match)
+ assert_equal(nil, Regexp.last_match(1))
+ assert_equal(nil, Regexp.last_match(:foo))
+
+ assert_equal(["foo", "bar"], /(?<foo>.)(?<bar>.)/.names)
+ assert_equal(["foo"], /(?<foo>.)(?<foo>.)/.names)
+ assert_equal([], /(.)(.)/.names)
+
+ assert_equal(["foo", "bar"], /(?<foo>.)(?<bar>.)/.match("ab").names)
+ assert_equal(["foo"], /(?<foo>.)(?<foo>.)/.match("ab").names)
+ assert_equal([], /(.)(.)/.match("ab").names)
+
+ assert_equal({"foo"=>[1], "bar"=>[2]},
+ /(?<foo>.)(?<bar>.)/.named_captures)
+ assert_equal({"foo"=>[1, 2]},
+ /(?<foo>.)(?<foo>.)/.named_captures)
+ assert_equal({}, /(.)(.)/.named_captures)
+
+ assert_equal("a[b]c", "abc".sub(/(?<x>[bc])/, "[\\k<x>]"))
+ end
+
+ def test_assign_named_capture
+ assert_equal("a", eval('/(?<foo>.)/ =~ "a"; foo'))
+ assert_equal("a", eval('foo = 1; /(?<foo>.)/ =~ "a"; foo'))
+ assert_equal("a", eval('1.times {|foo| /(?<foo>.)/ =~ "a"; break foo }'))
+ assert_nothing_raised { eval('/(?<Foo>.)/ =~ "a"') }
+ assert_nil(eval('/(?<Foo>.)/ =~ "a"; defined? Foo'))
+ end
+
+ def test_assign_named_capture_to_reserved_word
+ /(?<nil>.)/ =~ "a"
+ assert(!local_variables.include?(:nil), "[ruby-dev:32675]")
+ end
+
+ def test_match_regexp
+ r = /./
+ m = r.match("a")
+ assert_equal(r, m.regexp)
+ re = /foo/
+ assert_equal(re, re.match("foo").regexp)
+ end
+
+ def test_source
+ assert_equal('', //.source)
+ end
+
+ def test_inspect
+ assert_equal('//', //.inspect)
+ assert_equal('//i', //i.inspect)
+ assert_equal('/\//i', /\//i.inspect)
+ assert_equal('/\//i', /#{'/'}/i.inspect)
+ assert_equal('/\/x/i', /\/x/i.inspect)
+ assert_equal('/\x00/i', /#{"\0"}/i.inspect)
+ assert_equal("/\n/i", /#{"\n"}/i.inspect)
+ s = [0xff].pack("C")
+ assert_equal('/\/'+s+'/i', /\/#{s}/i.inspect)
+ end
+
+ def test_char_to_option
+ assert_equal("BAR", "FOOBARBAZ"[/b../i])
+ assert_equal("bar", "foobarbaz"[/ b . . /x])
+ assert_equal("bar\n", "foo\nbar\nbaz"[/b.../m])
+ assert_raise(SyntaxError) { eval('//z') }
+ end
+
+ def test_char_to_option_kcode
+ assert_equal("bar", "foobarbaz"[/b../s])
+ assert_equal("bar", "foobarbaz"[/b../e])
+ assert_equal("bar", "foobarbaz"[/b../u])
+ end
+
+ def test_to_s2
+ assert_equal('(?-mix:foo)', /(?:foo)/.to_s)
+ assert_equal('(?m-ix:foo)', /(?:foo)/m.to_s)
+ assert_equal('(?mi-x:foo)', /(?:foo)/mi.to_s)
+ assert_equal('(?mix:foo)', /(?:foo)/mix.to_s)
+ assert_equal('(?m-ix:foo)', /(?m-ix:foo)/.to_s)
+ assert_equal('(?mi-x:foo)', /(?mi-x:foo)/.to_s)
+ assert_equal('(?mix:foo)', /(?mix:foo)/.to_s)
+ assert_equal('(?mix:)', /(?mix)/.to_s)
+ assert_equal('(?-mix:(?mix:foo) )', /(?mix:foo) /.to_s)
+ end
+
+ def test_casefold_p
+ assert_equal(false, /a/.casefold?)
+ assert_equal(true, /a/i.casefold?)
+ assert_equal(false, /(?i:a)/.casefold?)
+ end
+
+ def test_options
+ assert_equal(Regexp::IGNORECASE, /a/i.options)
+ assert_equal(Regexp::EXTENDED, /a/x.options)
+ assert_equal(Regexp::MULTILINE, /a/m.options)
+ end
+
+ def test_match_init_copy
+ m = /foo/.match("foo")
+ assert_equal(/foo/, m.dup.regexp)
+ assert_raise(TypeError) do
+ m.instance_eval { initialize_copy(nil) }
+ end
+ assert_equal([0, 3], m.offset(0))
+ assert_equal(/foo/, m.dup.regexp)
+ end
+
+ def test_match_size
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ assert_equal(5, m.size)
+ end
+
+ def test_match_offset_begin_end
+ m = /(?<x>b..)/.match("foobarbaz")
+ assert_equal([3, 6], m.offset("x"))
+ assert_equal(3, m.begin("x"))
+ assert_equal(6, m.end("x"))
+ assert_raise(IndexError) { m.offset("y") }
+ assert_raise(IndexError) { m.offset(2) }
+ assert_raise(IndexError) { m.begin(2) }
+ assert_raise(IndexError) { m.end(2) }
+
+ m = /(?<x>q..)?/.match("foobarbaz")
+ assert_equal([nil, nil], m.offset("x"))
+ assert_equal(nil, m.begin("x"))
+ assert_equal(nil, m.end("x"))
+
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ assert_equal([1, 2], m.offset(1))
+ assert_equal([nil, nil], m.offset(2))
+ assert_equal([2, 3], m.offset(3))
+ end
+
+ def test_match_to_s
+ m = /(?<x>b..)/.match("foobarbaz")
+ assert_equal("bar", m.to_s)
+ end
+
+ def test_match_pre_post
+ m = /(?<x>b..)/.match("foobarbaz")
+ assert_equal("foo", m.pre_match)
+ assert_equal("baz", m.post_match)
+ end
+
+ def test_match_array
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal(["foobarbaz", "foo", "bar", "baz", nil], m.to_a)
+ end
+
+ def test_match_captures
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal(["foo", "bar", "baz", nil], m.captures)
+ end
+
+ def test_match_aref
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal("foo", m[1])
+ assert_equal(["foo", "bar", "baz"], m[1..3])
+ assert_nil(m[5])
+ assert_raise(IndexError) { m[:foo] }
+ end
+
+ def test_match_values_at
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal(["foo", "bar", "baz"], m.values_at(1, 2, 3))
+ end
+
+ def test_match_string
+ m = /(?<x>b..)/.match("foobarbaz")
+ assert_equal("foobarbaz", m.string)
+ end
+
+ def test_match_inspect
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect)
+ end
+
+ def test_initialize
+ assert_raise(ArgumentError) { Regexp.new }
+ assert_equal(/foo/, Regexp.new(/foo/, Regexp::IGNORECASE))
+ re = /foo/
+ assert_raise(SecurityError) do
+ Thread.new { $SAFE = 4; re.instance_eval { initialize(re) } }.join
+ end
+ re.taint
+ assert_raise(SecurityError) do
+ Thread.new { $SAFE = 4; re.instance_eval { initialize(re) } }.join
+ end
+
+ assert_equal(Encoding.find("ASCII-8BIT"), Regexp.new("b..", nil, "n").encoding)
+ assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
+
+ assert_raise(RegexpError) { Regexp.new(")(") }
+ end
+
+ def test_unescape
+ assert_raise(ArgumentError) { s = '\\'; /#{ s }/ }
+ assert_equal(/\177/, (s = '\177'; /#{ s }/))
+ assert_raise(ArgumentError) { s = '\u'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u{ ffffffff }'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u{ ffffff }'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u{ ffff X }'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u{ }'; /#{ s }/ }
+ assert_equal("b", "abc"[(s = '\u{0062}'; /#{ s }/)])
+ assert_equal("b", "abc"[(s = '\u0062'; /#{ s }/)])
+ assert_raise(ArgumentError) { s = '\u0'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u000X'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = "\xff" + '\u3042'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\u3042' + [0xff].pack("C"); /#{ s }/ }
+ assert_raise(SyntaxError) { s = ''; eval(%q(/\u#{ s }/)) }
+
+ assert_equal(/a/, eval(%q(s="\u0061";/#{s}/n)))
+ assert_raise(RegexpError) { s = "\u3042"; eval(%q(/#{s}/n)) }
+ assert_raise(RegexpError) { s = "\u0061"; eval(%q(/\u3042#{s}/n)) }
+ assert_raise(ArgumentError) { s1=[0xff].pack("C"); s2="\u3042"; eval(%q(/#{s1}#{s2}/)) }
+
+ assert_raise(ArgumentError) { s = '\x'; /#{ s }/ }
+
+ assert_equal("\xe1", [0x00, 0xe1, 0xff].pack("C*")[/\M-a/])
+ assert_equal("\xdc", [0x00, 0xdc, 0xff].pack("C*")[/\M-\\/])
+ assert_equal("\x8a", [0x00, 0x8a, 0xff].pack("C*")[/\M-\n/])
+ assert_equal("\x89", [0x00, 0x89, 0xff].pack("C*")[/\M-\t/])
+ assert_equal("\x8d", [0x00, 0x8d, 0xff].pack("C*")[/\M-\r/])
+ assert_equal("\x8c", [0x00, 0x8c, 0xff].pack("C*")[/\M-\f/])
+ assert_equal("\x8b", [0x00, 0x8b, 0xff].pack("C*")[/\M-\v/])
+ assert_equal("\x87", [0x00, 0x87, 0xff].pack("C*")[/\M-\a/])
+ assert_equal("\x9b", [0x00, 0x9b, 0xff].pack("C*")[/\M-\e/])
+ assert_equal("\x01", [0x00, 0x01, 0xff].pack("C*")[/\C-a/])
+
+ assert_raise(ArgumentError) { s = '\M'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\M-\M-a'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\M-\\'; /#{ s }/ }
+
+ assert_raise(ArgumentError) { s = '\C'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\c'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\C-\C-a'; /#{ s }/ }
+
+ assert_raise(ArgumentError) { s = '\M-\z'; /#{ s }/ }
+ assert_raise(ArgumentError) { s = '\M-\777'; /#{ s }/ }
+
+ assert_equal("\u3042\u3042", "\u3042\u3042"[(s = "\u3042" + %q(\xe3\x81\x82); /#{s}/)])
+ assert_raise(ArgumentError) { s = "\u3042" + %q(\xe3); /#{s}/ }
+ assert_raise(ArgumentError) { s = "\u3042" + %q(\xe3\xe3); /#{s}/ }
+ assert_raise(ArgumentError) { s = '\u3042' + [0xff].pack("C"); /#{s}/ }
+
+ assert_raise(SyntaxError) { eval("/\u3042/n") }
+
+ s = ".........."
+ 5.times { s.sub!(".", "") }
+ assert_equal(".....", s)
+ end
+
+ def test_equal
+ assert_equal(true, /abc/ == /abc/)
+ assert_equal(false, /abc/ == /abc/m)
+ assert_equal(false, /abc/ == /abd/)
+ end
+
+ def test_match
+ assert_nil(//.match(nil))
+ assert_equal("abc", /.../.match(:abc)[0])
+ assert_raise(TypeError) { /.../.match(Object.new)[0] }
+ assert_equal("bc", /../.match('abc', 1)[0])
+ assert_equal("bc", /../.match('abc', -2)[0])
+ assert_nil(/../.match("abc", -4))
+ assert_nil(/../.match("abc", 4))
+ assert_equal('\x', /../n.match("\u3042" + '\x', 1)[0])
+
+ r = nil
+ /.../.match("abc") {|m| r = m[0] }
+ assert_equal("abc", r)
+
+ $_ = "abc"; assert_equal(1, ~/bc/)
+ $_ = "abc"; assert_nil(~/d/)
+ $_ = nil; assert_nil(~/./)
+ end
+
+ def test_eqq
+ assert_equal(false, /../ === nil)
+ end
+
+ def test_quote
+ assert_equal("\xff", Regexp.quote([0xff].pack("C")))
+ assert_equal("\\ ", Regexp.quote("\ "))
+ assert_equal("\\t", Regexp.quote("\t"))
+ assert_equal("\\n", Regexp.quote("\n"))
+ assert_equal("\\r", Regexp.quote("\r"))
+ assert_equal("\\f", Regexp.quote("\f"))
+ assert_equal("\\v", Regexp.quote("\v"))
+ assert_equal("\u3042\\t", Regexp.quote("\u3042\t"))
+ assert_equal("\\t\xff", Regexp.quote("\t" + [0xff].pack("C")))
+ end
+
+ def test_try_convert
+ assert_equal(/re/, Regexp.try_convert(/re/))
+ assert_nil(Regexp.try_convert("re"))
+
+ o = Object.new
+ assert_nil(Regexp.try_convert(o))
+ def o.to_regexp() /foo/ end
+ assert_equal(/foo/, Regexp.try_convert(o))
+ end
+
+ def test_union2
+ assert_equal(/(?!)/, Regexp.union)
+ assert_equal(/foo/, Regexp.union(/foo/))
+ assert_equal(/foo/, Regexp.union([/foo/]))
+ assert_equal(/\t/, Regexp.union("\t"))
+ assert_equal(/(?-mix:\u3042)|(?-mix:\u3042)/, Regexp.union(/\u3042/, /\u3042/))
+ assert_equal("\u3041", "\u3041"[Regexp.union(/\u3042/, "\u3041")])
+ end
+
+ def test_dup
+ assert_equal(//, //.dup)
+ assert_raise(TypeError) { //.instance_eval { initialize_copy(nil) } }
+ end
+
+ def test_regsub
+ assert_equal("fooXXXbaz", "foobarbaz".sub!(/bar/, "XXX"))
+ s = [0xff].pack("C")
+ assert_equal(s, "X".sub!(/./, s))
+ assert_equal('\\' + s, "X".sub!(/./, '\\' + s))
+ assert_equal('\k', "foo".sub!(/.../, '\k'))
+ assert_raise(RuntimeError) { "foo".sub!(/(?<x>o)/, '\k<x') }
+ assert_equal('foo[bar]baz', "foobarbaz".sub!(/(b..)/, '[\0]'))
+ assert_equal('foo[foo]baz', "foobarbaz".sub!(/(b..)/, '[\`]'))
+ assert_equal('foo[baz]baz', "foobarbaz".sub!(/(b..)/, '[\\\']'))
+ assert_equal('foo[r]baz', "foobarbaz".sub!(/(b)(.)(.)/, '[\+]'))
+ assert_equal('foo[\\]baz', "foobarbaz".sub!(/(b..)/, '[\\\\]'))
+ assert_equal('foo[\z]baz', "foobarbaz".sub!(/(b..)/, '[\z]'))
+ end
+
+ def test_KCODE
+ assert_nil($KCODE)
+ assert_nothing_raised { $KCODE = nil }
+ assert_equal(false, $=)
+ assert_nothing_raised { $= = nil }
+ end
+
+ def test_match_setter
+ /foo/ =~ "foo"
+ m = $~
+ /bar/ =~ "bar"
+ $~ = m
+ assert_equal("foo", $&)
+ end
+
+ def test_last_match
+ /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal("foobarbaz", Regexp.last_match(0))
+ assert_equal("foo", Regexp.last_match(1))
+ assert_nil(Regexp.last_match(5))
+ assert_nil(Regexp.last_match(-1))
+ end
+
+ def test_getter
+ alias $__REGEXP_TEST_LASTMATCH__ $&
+ alias $__REGEXP_TEST_PREMATCH__ $`
+ alias $__REGEXP_TEST_POSTMATCH__ $'
+ alias $__REGEXP_TEST_LASTPARENMATCH__ $+
+ /(b)(.)(.)/.match("foobarbaz")
+ assert_equal("bar", $__REGEXP_TEST_LASTMATCH__)
+ assert_equal("foo", $__REGEXP_TEST_PREMATCH__)
+ assert_equal("baz", $__REGEXP_TEST_POSTMATCH__)
+ assert_equal("r", $__REGEXP_TEST_LASTPARENMATCH__)
+
+ /(...)(...)(...)/.match("foobarbaz")
+ assert_equal("baz", $+)
+ end
+
+ def test_rindex_regexp
+ assert_equal(3, "foobarbaz\u3042".rindex(/b../n, 5))
+ end
+
+ def test_taint
+ m = Thread.new do
+ "foo"[/foo/]
+ $SAFE = 4
+ /foo/.match("foo")
+ end.value
+ assert(m.tainted?)
+ end
+
+ def check(re, ss, fs = [])
+ re = Regexp.new(re) unless re.is_a?(Regexp)
+ ss = [ss] unless ss.is_a?(Array)
+ ss.each do |e, s|
+ s ||= e
+ assert_match(re, s)
+ m = re.match(s)
+ assert_equal(e, m[0])
+ end
+ fs = [fs] unless fs.is_a?(Array)
+ fs.each {|s| assert_no_match(re, s) }
+ end
+
+ def failcheck(re)
+ assert_raise(RegexpError) { /#{ re }/ }
+ end
+
+ def test_parse
+ check(/\*\+\?\{\}\|\(\)\<\>\`\'/, "*+?{}|()<>`'")
+ check(/\A\w\W\z/, %w(a. b!), %w(.. ab))
+ check(/\A.\b.\b.\B.\B.\z/, %w(a.aaa .a...), %w(aaaaa .....))
+ check(/\A\s\S\z/, [' a', "\n."], [' ', "\n\n", 'a '])
+ check(/\A\d\D\z/, '0a', %w(00 aa))
+ check(/\A\h\H\z/, %w(0g ag BH), %w(a0 af GG))
+ check(/\Afoo\Z\s\z/, "foo\n", ["foo", "foo\nbar"])
+ assert_equal(%w(a b c), "abc def".scan(/\G\w/))
+ check(/\A\u3042\z/, "\u3042", ["", "\u3043", "a"])
+ check(/\A(..)\1\z/, %w(abab ....), %w(abba aba))
+ failcheck('\1')
+ check(/\A\80\z/, "80", ["\100", ""])
+ check(/\A\77\z/, "?")
+ check(/\A\78\z/, "\7" + '8', ["\100", ""])
+ check(/\A\Qfoo\E\z/, "QfooE")
+ check(/\Aa++\z/, "aaa")
+ check('\Ax]\z', "x]")
+ check(/x#foo/x, "x", "#foo")
+ check(/\Ax#foo#{ "\n" }x\z/x, "xx", ["x", "x#foo\nx"])
+ check(/\A\p{Alpha}\z/, ["a", "z"], [".", "", ".."])
+ check(/\A\p{^Alpha}\z/, [".", "!"], ["!a", ""])
+ check(/\A\n\z/, "\n")
+ check(/\A\t\z/, "\t")
+ check(/\A\r\z/, "\r")
+ check(/\A\f\z/, "\f")
+ check(/\A\a\z/, "\007")
+ check(/\A\e\z/, "\033")
+ check(/\A\v\z/, "\v")
+ failcheck('(')
+ failcheck('(?foo)')
+ failcheck('/\p{foobarbazqux}/')
+ failcheck('/\p{foobarbazqux' + 'a' * 1000 + '}/')
+ failcheck('/[1-\w]/')
+ end
+
+ def test_exec
+ check(/A*B/, %w(B AB AAB AAAB), %w(A))
+ check(/\w*!/, %w(! a! ab! abc!), %w(abc))
+ check(/\w*\W/, %w(! a" ab# abc$), %w(abc))
+ check(/\w*\w/, %w(z az abz abcz), %w(!))
+ check(/[a-z]*\w/, %w(z az abz abcz), %w(!))
+ check(/[a-z]*\W/, %w(! a" ab# abc$), %w(A))
+ check(/((a|bb|ccc|dddd)(1|22|333|4444))/i, %w(a1 bb1 a22), %w(a2 b1))
+ check(/\u0080/, (1..4).map {|i| ["\u0080", "\u0080" * i] }, ["\u0081"])
+ check(/\u0080\u0080/, (2..4).map {|i| ["\u0080" * 2, "\u0080" * i] }, ["\u0081"])
+ check(/\u0080\u0080\u0080/, (3..4).map {|i| ["\u0080" * 3, "\u0080" * i] }, ["\u0081"])
+ check(/\u0080\u0080\u0080\u0080/, (4..4).map {|i| ["\u0080" * 4, "\u0080" * i] }, ["\u0081"])
+ check(/[^\u3042\u3043\u3044]/, %W(a b \u0080 \u3041 \u3045), %W(\u3042 \u3043 \u3044))
+ check(/a.+/m, %W(a\u0080 a\u0080\u0080 a\u0080\u0080\u0080), %W(a))
+ check(/a.+z/m, %W(a\u0080z a\u0080\u0080z a\u0080\u0080\u0080z), %W(az))
+ check(/abc\B.\Bxyz/, %w(abcXxyz abc0xyz), %w(abc|xyz abc-xyz))
+ check(/\Bxyz/, [%w(xyz abcXxyz), %w(xyz abc0xyz)], %w(abc xyz abc-xyz))
+ check(/abc\B/, [%w(abc abcXxyz), %w(abc abc0xyz)], %w(abc xyz abc-xyz))
+ failcheck('(?<foo>abc)\1')
+ check(/^(A+|B+)(?>\g<1>)*[BC]$/, %w(AC BC ABC BAC AABBC), %w(AABB))
+ check(/^(A+|B(?>\g<1>)*)[AC]$/, %w(AAAC BBBAAAAC), %w(BBBAAA))
+ check(/^()(?>\g<1>)*$/, "", "a")
+ check(/^(?>(?=a)(#{ "a" * 1000 }|))++$/, ["a" * 1000, "a" * 2000, "a" * 3000], ["", "a" * 500, "b" * 1000])
+ check(eval('/^(?:a?)?$/'), ["", "a"], ["aa"])
+ check(eval('/^(?:a+)?$/'), ["", "a", "aa"], ["ab"])
+ check(/^(?:a?)+?$/, ["", "a", "aa"], ["ab"])
+ check(/^a??[ab]/, [["a", "a"], ["a", "aa"], ["b", "b"], ["a", "ab"]], ["c"])
+ check(/^(?:a*){3,5}$/, ["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], ["b"])
+ check(/^(?:a+){3,5}$/, ["aaa", "aaaa", "aaaaa", "aaaaaa"], ["", "a", "aa", "b"])
+ end
+
+ def test_parse_look_behind
+ check(/(?<=A)B(?=C)/, [%w(B ABC)], %w(aBC ABc aBc))
+ check(/(?<!A)B(?!C)/, [%w(B aBc)], %w(ABC aBC ABc))
+ failcheck('(?<=.*)')
+ failcheck('(?<!.*)')
+ check(/(?<=A|B.)C/, [%w(C AC), %w(C BXC)], %w(C BC))
+ check(/(?<!A|B.)C/, [%w(C C), %w(C BC)], %w(AC BXC))
+ end
+
+ def test_parse_kg
+ check(/\A(.)(.)\k<1>(.)\z/, %w(abac abab ....), %w(abcd aaba xxx))
+ check(/\A(.)(.)\k<-1>(.)\z/, %w(abbc abba ....), %w(abcd aaba xxx))
+ check(/\A(?<n>.)(?<x>\g<n>){0}(?<y>\k<n+0>){0}\g<x>\g<y>\z/, "aba", "abb")
+ check(/\A(?<n>.)(?<x>\g<n>){0}(?<y>\k<n+1>){0}\g<x>\g<y>\z/, "abb", "aba")
+ check(/\A(?<x>..)\k<x>\z/, %w(abab ....), %w(abac abba xxx))
+ check(/\A(.)(..)\g<-1>\z/, "abcde", %w(.... ......))
+ failcheck('\k<x>')
+ failcheck('\k<')
+ failcheck('\k<>')
+ failcheck('\k<.>')
+ failcheck('\k<x.>')
+ failcheck('\k<1.>')
+ failcheck('\k<x')
+ failcheck('\k<x+')
+ failcheck('()\k<-2>')
+ failcheck('()\g<-2>')
+ check(/\A(?<x>.)(?<x>.)\k<x>\z/, %w(aba abb), %w(abc .. ....))
+ check(/\A(?<x>.)(?<x>.)\k<x>\z/i, %w(aba ABa abb ABb), %w(abc .. ....))
+ check(/\k\g/, "kg")
+ failcheck('(.\g<1>)')
+ failcheck('(.\g<2>)')
+ failcheck('(?=\g<1>)')
+ failcheck('((?=\g<1>))')
+ failcheck('(\g<1>|.)')
+ failcheck('(.|\g<1>)')
+ check(/(!)(?<=(a)|\g<1>)/, ["!"], %w(a))
+ check(/^(a|b\g<1>c)$/, %w(a bac bbacc bbbaccc), %w(bbac bacc))
+ check(/^(a|b\g<2>c)(B\g<1>C){0}$/, %w(a bBaCc bBbBaCcCc bBbBbBaCcCcCc), %w(bBbBaCcC BbBaCcCc))
+ check(/\A(?<n>.|X\g<n>)(?<x>\g<n>){0}(?<y>\k<n+0>){0}\g<x>\g<y>\z/, "XXaXbXXa", %w(XXabXa abb))
+ check(/\A(?<n>.|X\g<n>)(?<x>\g<n>){0}(?<y>\k<n+1>){0}\g<x>\g<y>\z/, "XaXXbXXb", %w(aXXbXb aba))
+ failcheck('(?<x>)(?<x>)(\g<x>)')
+ check(/^(?<x>foo)(bar)\k<x>/, %w(foobarfoo), %w(foobar barfoo))
+ check(/^(?<a>f)(?<a>o)(?<a>o)(?<a>b)(?<a>a)(?<a>r)(?<a>b)(?<a>a)(?<a>z)\k<a>{9}$/, %w(foobarbazfoobarbaz foobarbazbazbarfoo foobarbazzabraboof), %w(foobar barfoo))
+ end
+
+ def test_parse_curly_brace
+ check(/\A{/, ["{", ["{", "{x"]])
+ check(/\A{ /, ["{ ", ["{ ", "{ x"]])
+ check(/\A{,}\z/, "{,}")
+ check(/\A{}\z/, "{}")
+ check(/\Aa{0}+\z/, "", %w(a aa aab))
+ check(/\Aa{1}+\z/, %w(a aa), ["", "aab"])
+ check(/\Aa{1,2}b{1,2}\z/, %w(ab aab abb aabb), ["", "aaabb", "abbb"])
+ failcheck('.{100001}')
+ failcheck('.{0,100001}')
+ failcheck('.{1,0}')
+ failcheck('{0}')
+ failcheck('(?!x){0,1}')
+ end
+
+ def test_parse_comment
+ check(/\A(?#foo\)bar)\z/, "", "a")
+ failcheck('(?#')
+ end
+
+ def test_char_type
+ check(/\u3042\d/, ["\u30421", "\u30422"])
+
+ # CClassTable cache test
+ assert(/\u3042\d/.match("\u30421"))
+ assert(/\u3042\d/.match("\u30422"))
+ end
+
+ def test_char_class
+ failcheck('[]')
+ failcheck('[x')
+ check('\A[]]\z', "]", "")
+ check('\A[]\.]+\z', %w(] . ]..]), ["", "["])
+ check(/\A[\u3042]\z/, "\u3042", "\u3042aa")
+ check(/\A[\u3042\x61]+\z/, ["aa\u3042aa", "\u3042\u3042", "a"], ["", "b"])
+ check(/\A[\u3042\x61\x62]+\z/, "abab\u3042abab\u3042")
+ check(/\A[abc]+\z/, "abcba", ["", "ada"])
+ check(/\A[\w][\W]\z/, %w(a. b!), %w(.. ab))
+ check(/\A[\s][\S]\z/, [' a', "\n."], [' ', "\n\n", 'a '])
+ check(/\A[\d][\D]\z/, '0a', %w(00 aa))
+ check(/\A[\h][\H]\z/, %w(0g ag BH), %w(a0 af GG))
+ check(/\A[\p{Alpha}]\z/, ["a", "z"], [".", "", ".."])
+ check(/\A[\p{^Alpha}]\z/, [".", "!"], ["!a", ""])
+ check(/\A[\xff]\z/, "\xff", ["", "\xfe"])
+ check(/\A[\80]+\z/, "8008", ["\\80", "\100", "\1000"])
+ check(/\A[\77]+\z/, "???")
+ check(/\A[\78]+\z/, "\788\7")
+ check(/\A[\0]\z/, "\0")
+ check(/\A[[:0]]\z/, [":", "0"], ["", ":0"])
+ check(/\A[0-]\z/, ["0", "-"], "0-")
+ check('\A[a-&&\w]\z', "a", "-")
+ check('\A[--0]\z', ["-", "/", "0"], ["", "1"])
+ check('\A[\'--0]\z', %w(* + \( \) 0 ,), ["", ".", "1"])
+ check(/\A[a-b-]\z/, %w(a b -), ["", "c"])
+ check('\A[a-b-&&\w]\z', %w(a b), ["", "-"])
+ check('\A[a-b-&&\W]\z', "-", ["", "a", "b"])
+ check('\A[a-c-e]\z', %w(a b c e), %w(- d)) # is it OK?
+ check(/\A[a-f&&[^b-c]&&[^e]]\z/, %w(a d f), %w(b c e g 0))
+ check(/\A[[^b-c]&&[^e]&&a-f]\z/, %w(a d f), %w(b c e g 0))
+ check(/\A[\n\r\t]\z/, ["\n", "\r", "\t"])
+ failcheck('[9-1]')
+ end
+
+ def test_posix_bracket
+ check(/\A[[:alpha:]0]\z/, %w(0 a), %w(1 .))
+ check(/\A[[:^alpha:]0]\z/, %w(0 1 .), "a")
+ check(/\A[[:alpha\:]]\z/, %w(a l p h a :), %w(b 0 1 .))
+ check(/\A[[:alpha:foo]0]\z/, %w(0 a), %w(1 .))
+ check(/\A[[:xdigit:]&&[:alpha:]]\z/, "a", %w(g 0))
+ check('\A[[:abcdefghijklmnopqrstu:]]+\z', "[]")
+ failcheck('[[:alpha')
+ failcheck('[[:alpha:')
+ failcheck('[[:alp:]]')
+ end
+
+ def test_backward
+ assert_equal(3, "foobar".rindex(/b.r/i))
+ assert_equal(nil, "foovar".rindex(/b.r/i))
+ assert_equal(3, ("foo" + "bar" * 1000).rindex(/#{"bar"*1000}/))
+ assert_equal(4, ("foo\nbar\nbaz\n").rindex(/bar/i))
+ end
+
+ def test_uninitialized
+ assert_raise(TypeError) { Regexp.allocate.hash }
+ assert_raise(TypeError) { Regexp.allocate.eql? Regexp.allocate }
+ assert_raise(TypeError) { Regexp.allocate == Regexp.allocate }
+ assert_raise(TypeError) { Regexp.allocate =~ "" }
+ assert_equal(false, Regexp.allocate === Regexp.allocate)
+ assert_nil(~Regexp.allocate)
+ assert_raise(TypeError) { Regexp.allocate.match("") }
+ assert_raise(TypeError) { Regexp.allocate.to_s }
+ assert_match(/^#<Regexp:.*>$/, Regexp.allocate.inspect)
+ assert_raise(TypeError) { Regexp.allocate.source }
+ assert_raise(TypeError) { Regexp.allocate.casefold? }
+ assert_raise(TypeError) { Regexp.allocate.options }
+ assert_equal(Encoding.find("ASCII-8BIT"), Regexp.allocate.encoding)
+ assert_equal(false, Regexp.allocate.fixed_encoding?)
+ assert_raise(TypeError) { Regexp.allocate.names }
+ assert_raise(TypeError) { Regexp.allocate.named_captures }
+
+ assert_raise(TypeError) { MatchData.allocate.regexp }
+ assert_raise(TypeError) { MatchData.allocate.names }
+ assert_raise(TypeError) { MatchData.allocate.size }
+ assert_raise(TypeError) { MatchData.allocate.length }
+ assert_raise(TypeError) { MatchData.allocate.offset(0) }
+ assert_raise(TypeError) { MatchData.allocate.begin(0) }
+ assert_raise(TypeError) { MatchData.allocate.end(0) }
+ assert_raise(TypeError) { MatchData.allocate.to_a }
+ assert_raise(TypeError) { MatchData.allocate[:foo] }
+ assert_raise(TypeError) { MatchData.allocate.captures }
+ assert_raise(TypeError) { MatchData.allocate.values_at }
+ assert_raise(TypeError) { MatchData.allocate.pre_match }
+ assert_raise(TypeError) { MatchData.allocate.post_match }
+ assert_raise(TypeError) { MatchData.allocate.to_s }
+ assert_match(/^#<MatchData:.*>$/, MatchData.allocate.inspect)
+ assert_raise(TypeError) { MatchData.allocate.string }
+ $~ = MatchData.allocate
+ assert_raise(TypeError) { $& }
+ assert_raise(TypeError) { $` }
+ assert_raise(TypeError) { $' }
+ assert_raise(TypeError) { $+ }
+ end
+
+ def test_unicode
+ assert_match(/^\u3042{0}\p{Any}$/, "a")
+ assert_match(/^\u3042{0}\p{Any}$/, "\u3041")
+ assert_match(/^\u3042{0}\p{Any}$/, "\0")
+ assert_no_match(/^\u3042{0}\p{Any}$/, "\0\0")
+ assert_no_match(/^\u3042{0}\p{Any}$/, "")
+ assert_raise(SyntaxError) { eval('/^\u3042{0}\p{' + "\u3042" + '}$/') }
+ assert_raise(SyntaxError) { eval('/^\u3042{0}\p{' + 'a' * 1000 + '}$/') }
+ assert_raise(SyntaxError) { eval('/^\u3042{0}\p{foobarbazqux}$/') }
+ assert_match(/^(\uff21)(a)\1\2$/i, "\uff21A\uff41a")
+ assert_no_match(/^(\uff21)\1$/i, "\uff21A")
+ assert_no_match(/^(\uff41)\1$/i, "\uff41a")
+ assert_match(/^\u00df$/i, "\u00df")
+ assert_match(/^\u00df$/i, "ss")
+ #assert_match(/^(\u00df)\1$/i, "\u00dfss") # this must be bug...
+ assert_match(/^\u00df{2}$/i, "\u00dfss")
+ assert_match(/^\u00c5$/i, "\u00c5")
+ assert_match(/^\u00c5$/i, "\u00e5")
+ assert_match(/^\u00c5$/i, "\u212b")
+ assert_match(/^(\u00c5)\1\1$/i, "\u00c5\u00e5\u212b")
+ assert_match(/^\u0149$/i, "\u0149")
+ assert_match(/^\u0149$/i, "\u02bcn")
+ #assert_match(/^(\u0149)\1$/i, "\u0149\u02bcn") # this must be bug...
+ assert_match(/^\u0149{2}$/i, "\u0149\u02bcn")
+ assert_match(/^\u0390$/i, "\u0390")
+ assert_match(/^\u0390$/i, "\u03b9\u0308\u0301")
+ #assert_match(/^(\u0390)\1$/i, "\u0390\u03b9\u0308\u0301") # this must be bug...
+ assert_match(/^\u0390{2}$/i, "\u0390\u03b9\u0308\u0301")
+ assert_match(/^\ufb05$/i, "\ufb05")
+ assert_match(/^\ufb05$/i, "\ufb06")
+ assert_match(/^\ufb05$/i, "st")
+ #assert_match(/^(\ufb05)\1\1$/i, "\ufb05\ufb06st") # this must be bug...
+ assert_match(/^\ufb05{3}$/i, "\ufb05\ufb06st")
+ assert_match(/^\u03b9\u0308\u0301$/i, "\u0390")
+ assert_nothing_raised { 0x03ffffff.chr("utf-8").size }
+ assert_nothing_raised { 0x7fffffff.chr("utf-8").size }
+ end
+end
diff --git a/trunk/test/ruby/test_require.rb b/trunk/test/ruby/test_require.rb
new file mode 100644
index 0000000000..a5f453a055
--- /dev/null
+++ b/trunk/test/ruby/test_require.rb
@@ -0,0 +1,194 @@
+require 'test/unit'
+
+require 'tempfile'
+require_relative 'envutil'
+
+class TestRequire < Test::Unit::TestCase
+ def test_require_invalid_shared_object
+ t = Tempfile.new(["test_ruby_test_require", ".so"])
+ t.puts "dummy"
+ t.close
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ begin
+ require \"#{ t.path }\"
+ rescue LoadError
+ p :ok
+ end
+ INPUT
+ end
+
+ def test_require_too_long_filename
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ begin
+ require '#{ "foo/" * 10000 }foo'
+ rescue LoadError
+ p :ok
+ end
+ INPUT
+
+ assert_in_out_err(["-S", "foo/" * 10000 + "foo"], "") do |r, e|
+ assert_equal([], r)
+ assert_operator(2, :<=, e.size)
+ assert_equal("openpath: pathname too long (ignored)", e.first)
+ assert_match(/\(LoadError\)/, e.last)
+ end
+ end
+
+ def test_require_path_home
+ env_rubypath, env_home = ENV["RUBYPATH"], ENV["HOME"]
+
+ ENV["RUBYPATH"] = "~"
+ ENV["HOME"] = "/foo" * 10000
+ assert_in_out_err(%w(-S test_ruby_test_require), "", [], /^.+$/)
+
+ ENV["RUBYPATH"] = "~" + "/foo" * 10000
+ ENV["HOME"] = "/foo"
+ assert_in_out_err(%w(-S test_ruby_test_require), "", [], /^.+$/)
+
+ t = Tempfile.new(["test_ruby_test_require", ".rb"])
+ t.puts "p :ok"
+ t.close
+ ENV["RUBYPATH"] = "~"
+ ENV["HOME"], name = File.split(t.path)
+ assert_in_out_err(["-S", name], "", %w(:ok), [])
+
+ ensure
+ env_rubypath ? ENV["RUBYPATH"] = env_rubypath : ENV.delete("RUBYPATH")
+ env_home ? ENV["HOME"] = env_home : ENV.delete("HOME")
+ end
+
+ def test_define_class
+ begin
+ require "socket"
+ rescue LoadError
+ return
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ BasicSocket = 1
+ begin
+ require 'socket'
+ p :ng
+ rescue TypeError
+ p :ok
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ class BasicSocket; end
+ begin
+ require 'socket'
+ p :ng
+ rescue NameError
+ p :ok
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ class BasicSocket < IO; end
+ begin
+ require 'socket'
+ p :ok
+ rescue Exception
+ p :ng
+ end
+ INPUT
+ end
+
+ def test_define_class_under
+ begin
+ require "zlib"
+ rescue LoadError
+ return
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ module Zlib; end
+ Zlib::Error = 1
+ begin
+ require 'zlib'
+ p :ng
+ rescue TypeError
+ p :ok
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ module Zlib; end
+ class Zlib::Error; end
+ begin
+ require 'zlib'
+ p :ng
+ rescue NameError
+ p :ok
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ module Zlib; end
+ class Zlib::Error < StandardError; end
+ begin
+ require 'zlib'
+ p :ok
+ rescue Exception
+ p :ng
+ end
+ INPUT
+ end
+
+ def test_define_module
+ begin
+ require "zlib"
+ rescue LoadError
+ return
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ Zlib = 1
+ begin
+ require 'zlib'
+ p :ng
+ rescue TypeError
+ p :ok
+ end
+ INPUT
+ end
+
+ def test_define_module_under
+ begin
+ require "socket"
+ rescue LoadError
+ return
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ class BasicSocket < IO; end
+ class Socket < BasicSocket; end
+ Socket::Constants = 1
+ begin
+ require 'socket'
+ p :ng
+ rescue TypeError
+ p :ok
+ end
+ INPUT
+ end
+
+ def test_load
+ t = Tempfile.new(["test_ruby_test_require", ".rb"])
+ t.puts "module Foo; end"
+ t.puts "at_exit { p :wrap_end }"
+ t.puts "at_exit { raise 'error in at_exit test' }"
+ t.puts "p :ok"
+ t.close
+
+ assert_in_out_err([], <<-INPUT, %w(:ok :end :wrap_end), /error in at_exit test/)
+ load(#{ t.path.dump }, true)
+ GC.start
+ p :end
+ INPUT
+
+ assert_raise(ArgumentError) { at_exit }
+ end
+end
diff --git a/trunk/test/ruby/test_rubyoptions.rb b/trunk/test/ruby/test_rubyoptions.rb
new file mode 100644
index 0000000000..af4ca282ee
--- /dev/null
+++ b/trunk/test/ruby/test_rubyoptions.rb
@@ -0,0 +1,283 @@
+require 'test/unit'
+
+require 'tmpdir'
+require 'tempfile'
+require_relative 'envutil'
+
+class TestRubyOptions < Test::Unit::TestCase
+ def test_source_file
+ assert_in_out_err([], "", [], [])
+ end
+
+ def test_usage
+ assert_in_out_err(%w(-h)) do |r, e|
+ assert_operator(r.size, :<=, 24)
+ assert_equal([], e)
+ end
+
+ assert_in_out_err(%w(--help)) do |r, e|
+ assert_operator(r.size, :<=, 24)
+ assert_equal([], e)
+ end
+ end
+
+ def test_option_variables
+ assert_in_out_err(["-e", 'p [$-p, $-l, $-a]']) do |r, e|
+ assert_equal(["[false, false, false]"], r)
+ assert_equal([], e)
+ end
+
+ assert_in_out_err(%w(-p -l -a -e) + ['p [$-p, $-l, $-a]'],
+ "foo\nbar\nbaz\n") do |r, e|
+ assert_equal(
+ [ '[true, true, true]', 'foo',
+ '[true, true, true]', 'bar',
+ '[true, true, true]', 'baz' ], r)
+ assert_equal([], e)
+ end
+ end
+
+ def test_warning
+ assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), [])
+ assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), [])
+ assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(1), [])
+ assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), [])
+ end
+
+ def test_safe_level
+ assert_in_out_err(%w(-T -e) + [""], "", [],
+ /no -e allowed in tainted mode \(SecurityError\)/)
+
+ assert_in_out_err(%w(-T4 -S foo.rb), "", [],
+ /no -S allowed in tainted mode \(SecurityError\)/)
+ end
+
+ def test_debug
+ assert_in_out_err(%w(-de) + ["p $DEBUG"], "", %w(true), [])
+
+ assert_in_out_err(%w(--debug -e) + ["p $DEBUG"], "", %w(true), [])
+ end
+
+ def test_verbose
+ assert_in_out_err(%w(-vve) + [""]) do |r, e|
+ assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, r.join)
+ assert_equal RUBY_DESCRIPTION, r.join.chomp
+ assert_equal([], e)
+ end
+
+ assert_in_out_err(%w(--verbose -e) + ["p $VERBOSE"], "", %w(true), [])
+
+ assert_in_out_err(%w(--verbose), "", [], [])
+ end
+
+ def test_copyright
+ assert_in_out_err(%w(--copyright), "",
+ /^ruby - Copyright \(C\) 1993-\d+ Yukihiro Matsumoto$/, [])
+
+ assert_in_out_err(%w(--verbose -e) + ["p $VERBOSE"], "", %w(true), [])
+ end
+
+ def test_enable
+ assert_in_out_err(%w(--enable all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--enable-all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--enable=all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--enable foobarbazqux -e) + [""], "", [],
+ /unknown argument for --enable: `foobarbazqux'/)
+ assert_in_out_err(%w(--enable), "", [], /missing argument for --enable/)
+ end
+
+ def test_disable
+ assert_in_out_err(%w(--disable all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--disable-all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--disable=all -e) + [""], "", [], [])
+ assert_in_out_err(%w(--disable foobarbazqux -e) + [""], "", [],
+ /unknown argument for --disable: `foobarbazqux'/)
+ assert_in_out_err(%w(--disable), "", [], /missing argument for --disable/)
+ end
+
+ def test_kanji
+ assert_in_out_err(%w(-KU), "p '\u3042'") do |r, e|
+ assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
+ end
+ assert_in_out_err(%w(-KE -e) + [""], "", [], [])
+ assert_in_out_err(%w(-KS -e) + [""], "", [], [])
+ assert_in_out_err(%w(-KN -e) + [""], "", [], [])
+ end
+
+ def test_version
+ assert_in_out_err(%w(--version)) do |r, e|
+ assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, r.join)
+ assert_equal RUBY_DESCRIPTION, r.join.chomp
+ assert_equal([], e)
+ end
+ end
+
+ def test_eval
+ assert_in_out_err(%w(-e), "", [], /no code specified for -e \(RuntimeError\)/)
+ end
+
+ def test_require
+ require "pp"
+ assert_in_out_err(%w(-r pp -e) + ["pp 1"], "", %w(1), [])
+ assert_in_out_err(%w(-rpp -e) + ["pp 1"], "", %w(1), [])
+ rescue LoadError
+ end
+
+ def test_include
+ d = Dir.tmpdir
+ assert_in_out_err(["-I" + d, "-e", ""], "", [], [])
+ assert_in_out_err(["-I", d, "-e", ""], "", [], [])
+ end
+
+ def test_separator
+ assert_in_out_err(%w(-000 -e) + ["print gets"], "foo\nbar\0baz", %W(foo bar\0baz), [])
+
+ assert_in_out_err(%w(-0141 -e) + ["print gets"], "foo\nbar\0baz", %w(foo ba), [])
+
+ assert_in_out_err(%w(-0e) + ["print gets"], "foo\nbar\0baz", %W(foo bar\0), [])
+ end
+
+ def test_autosplit
+ assert_in_out_err(%w(-an -F: -e) + ["p $F"], "foo:bar:baz\nqux:quux:quuux\n",
+ ['["foo", "bar", "baz\n"]', '["qux", "quux", "quuux\n"]'], [])
+ end
+
+ def test_chdir
+ assert_in_out_err(%w(-C), "", [], /Can't chdir/)
+
+ assert_in_out_err(%w(-C test_ruby_test_rubyoptions_foobarbazqux), "", [], /Can't chdir/)
+
+ d = Dir.tmpdir
+ assert_in_out_err(["-C", d, "-e", "puts Dir.pwd"]) do |r, e|
+ assert(File.identical?(r.join, d))
+ assert_equal([], e)
+ end
+ end
+
+ def test_yydebug
+ assert_in_out_err(["-ye", ""]) do |r, e|
+ assert_equal([], r)
+ assert_not_equal([], e)
+ end
+
+ assert_in_out_err(%w(--yydebug -e) + [""]) do |r, e|
+ assert_equal([], r)
+ assert_not_equal([], e)
+ end
+ end
+
+ def test_encoding
+ assert_in_out_err(%w(-Eutf-8), "p '\u3042'", [], /invalid multibyte char/)
+
+ assert_in_out_err(%w(--encoding), "", [], /missing argument for --encoding/)
+
+ assert_in_out_err(%w(--encoding test_ruby_test_rubyoptions_foobarbazqux), "", [],
+ /unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/)
+
+ assert_in_out_err(%w(--encoding utf-8), "p '\u3042'", [], /invalid multibyte char/)
+ end
+
+ def test_syntax_check
+ assert_in_out_err(%w(-c -e 1+1), "", ["Syntax OK"], [])
+ end
+
+ def test_invalid_option
+ assert_in_out_err(%w(--foobarbazqux), "", [], /invalid option --foobarbazqux/)
+
+ assert_in_out_err(%W(-\r -e) + [""], "", [], [])
+
+ assert_in_out_err(%W(-\rx), "", [], /invalid option -\\x0D \(-h will show valid options\) \(RuntimeError\)/)
+
+ assert_in_out_err(%W(-\x01), "", [], /invalid option -\\x01 \(-h will show valid options\) \(RuntimeError\)/)
+
+ assert_in_out_err(%w(-Z), "", [], /invalid option -Z \(-h will show valid options\) \(RuntimeError\)/)
+ end
+
+ def test_rubyopt
+ rubyopt_orig = ENV['RUBYOPT']
+
+ ENV['RUBYOPT'] = ' - -'
+ assert_in_out_err([], "", [], [])
+
+ ENV['RUBYOPT'] = '-e "p 1"'
+ assert_in_out_err([], "", [], /invalid switch in RUBYOPT: -e \(RuntimeError\)/)
+
+ ENV['RUBYOPT'] = '-T1'
+ assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
+
+ ENV['RUBYOPT'] = '-T4'
+ assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
+
+ ENV['RUBYOPT'] = '-KN -Eus-ascii'
+ assert_in_out_err(%w(-KU -Eutf-8), "p '\u3042'") do |r, e|
+ assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
+ assert_equal([], e)
+ end
+
+ ensure
+ if rubyopt_orig
+ ENV['RUBYOPT'] = rubyopt_orig
+ else
+ ENV.delete('RUBYOPT')
+ end
+ end
+
+ def test_search
+ rubypath_orig = ENV['RUBYPATH']
+ path_orig = ENV['PATH']
+
+ t = Tempfile.new(["test_ruby_test_rubyoption", ".rb"])
+ t.puts "p 1"
+ t.close
+
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+
+ ENV['PATH'] = File.dirname(t.path)
+
+ assert_in_out_err(%w(-S) + [File.basename(t.path)], "", %w(1), [])
+
+ ENV['RUBYPATH'] = File.dirname(t.path)
+
+ assert_in_out_err(%w(-S) + [File.basename(t.path)], "", %w(1), [])
+
+ ensure
+ if rubypath_orig
+ ENV['RUBYPATH'] = rubypath_orig
+ else
+ ENV.delete('RUBYPATH')
+ end
+ if path_orig
+ ENV['PATH'] = path_orig
+ else
+ ENV.delete('PATH')
+ end
+ t.close(true) if t
+ $VERBOSE = @verbose
+ end
+
+ def test_shebang
+ assert_in_out_err([], "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux\r\np 1\r\n",
+ [], /Can't exec [\/\\]test_r_u_b_y_test_r_u_b_y_options_foobarbazqux \(fatal\)/)
+
+ assert_in_out_err([], "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux -foo -bar\r\np 1\r\n",
+ [], /Can't exec [\/\\]test_r_u_b_y_test_r_u_b_y_options_foobarbazqux \(fatal\)/)
+
+ assert_in_out_err([], "#!ruby -KU -Eutf-8\r\np \"\u3042\"\r\n") do |r, e|
+ assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
+ assert_equal([], e)
+ end
+ end
+
+ def test_sflag
+ assert_in_out_err(%w(- -abc -def=foo -ghi-jkl -- -xyz),
+ "#!ruby -s\np [$abc, $def, $ghi_jkl, $xyz]\n",
+ ['[true, "foo", true, nil]'], [])
+
+ assert_in_out_err(%w(- -#), "#!ruby -s\n", [],
+ /invalid name for global variable - -# \(NameError\)/)
+
+ assert_in_out_err(%w(- -#=foo), "#!ruby -s\n", [],
+ /invalid name for global variable - -# \(NameError\)/)
+ end
+end
diff --git a/trunk/test/ruby/test_settracefunc.rb b/trunk/test/ruby/test_settracefunc.rb
new file mode 100644
index 0000000000..c098e548b8
--- /dev/null
+++ b/trunk/test/ruby/test_settracefunc.rb
@@ -0,0 +1,184 @@
+require 'test/unit'
+
+class TestSetTraceFunc < Test::Unit::TestCase
+ def setup
+ @original_compile_option = RubyVM::InstructionSequence.compile_option
+ RubyVM::InstructionSequence.compile_option = {
+ :trace_instruction => true,
+ :specialized_instruction => false
+ }
+ end
+
+ def teardown
+ set_trace_func(nil)
+ RubyVM::InstructionSequence.compile_option = @original_compile_option
+ end
+
+ def test_c_call
+ events = []
+ eval <<-EOF.gsub(/^.*?: /, "")
+ 1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
+ 2: events << [event, lineno, mid, klass]
+ 3: })
+ 4: x = 1 + 1
+ 5: set_trace_func(nil)
+ EOF
+ assert_equal(["c-return", 3, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal(["line", 4, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 4, :+, Fixnum],
+ events.shift)
+ assert_equal(["c-return", 4, :+, Fixnum],
+ events.shift)
+ assert_equal(["line", 5, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 5, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal([], events)
+ end
+
+ def test_call
+ events = []
+ eval <<-EOF.gsub(/^.*?: /, "")
+ 1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
+ 2: events << [event, lineno, mid, klass]
+ 3: })
+ 4: def add(x, y)
+ 5: x + y
+ 6: end
+ 7: x = add(1, 1)
+ 8: set_trace_func(nil)
+ EOF
+ assert_equal(["c-return", 3, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal(["line", 4, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 4, :method_added, Module],
+ events.shift)
+ assert_equal(["c-return", 4, :method_added, Module],
+ events.shift)
+ assert_equal(["line", 7, __method__, self.class],
+ events.shift)
+ assert_equal(["call", 6, :add, self.class],
+ events.shift)
+ assert_equal(["line", 5, :add, self.class],
+ events.shift)
+ assert_equal(["c-call", 5, :+, Fixnum],
+ events.shift)
+ assert_equal(["c-return", 5, :+, Fixnum],
+ events.shift)
+ assert_equal(["return", 6, :add, self.class],
+ events.shift)
+ assert_equal(["line", 8, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 8, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal([], events)
+ end
+
+ def test_class
+ events = []
+ eval <<-EOF.gsub(/^.*?: /, "")
+ 1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
+ 2: events << [event, lineno, mid, klass]
+ 3: })
+ 4: class Foo
+ 5: def bar
+ 6: end
+ 7: end
+ 8: x = Foo.new.bar
+ 9: set_trace_func(nil)
+ EOF
+ assert_equal(["c-return", 3, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal(["line", 4, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 4, :inherited, Class],
+ events.shift)
+ assert_equal(["c-return", 4, :inherited, Class],
+ events.shift)
+ assert_equal(["class", 7, nil, nil],
+ events.shift)
+ assert_equal(["line", 5, nil, nil],
+ events.shift)
+ assert_equal(["c-call", 5, :method_added, Module],
+ events.shift)
+ assert_equal(["c-return", 5, :method_added, Module],
+ events.shift)
+ assert_equal(["end", 7, nil, nil],
+ events.shift)
+ assert_equal(["line", 8, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 8, :new, Class],
+ events.shift)
+ assert_equal(["c-call", 8, :initialize, BasicObject],
+ events.shift)
+ assert_equal(["c-return", 8, :initialize, BasicObject],
+ events.shift)
+ assert_equal(["c-return", 8, :new, Class],
+ events.shift)
+ assert_equal(["call", 6, :bar, Foo],
+ events.shift)
+ assert_equal(["return", 6, :bar, Foo],
+ events.shift)
+ assert_equal(["line", 9, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 9, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal([], events)
+ end
+
+ def test_raise
+ events = []
+ eval <<-EOF.gsub(/^.*?: /, "")
+ 1: set_trace_func(Proc.new { |event, file, lineno, mid, binding, klass|
+ 2: events << [event, lineno, mid, klass]
+ 3: })
+ 4: begin
+ 5: raise TypeError, "error"
+ 6: rescue TypeError
+ 7: end
+ 8: set_trace_func(nil)
+ EOF
+ assert_equal(["c-return", 3, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal(["line", 4, __method__, self.class],
+ events.shift)
+ assert_equal(["line", 5, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 5, :raise, Kernel],
+ events.shift)
+ assert_equal(["c-call", 5, :exception, Exception],
+ events.shift)
+ assert_equal(["c-call", 5, :initialize, Exception],
+ events.shift)
+ assert_equal(["c-return", 5, :initialize, Exception],
+ events.shift)
+ assert_equal(["c-return", 5, :exception, Exception],
+ events.shift)
+ assert_equal(["c-call", 5, :backtrace, Exception],
+ events.shift)
+ assert_equal(["c-return", 5, :backtrace, Exception],
+ events.shift)
+ assert_equal(["c-call", 5, :set_backtrace, Exception],
+ events.shift)
+ assert_equal(["c-return", 5, :set_backtrace, Exception],
+ events.shift)
+ assert_equal(["raise", 5, :test_raise, TestSetTraceFunc],
+ events.shift)
+ assert_equal(["c-call", 6, :===, Module],
+ events.shift)
+ assert_equal(["c-return", 6, :===, Module],
+ events.shift)
+ assert_equal(["line", 8, __method__, self.class],
+ events.shift)
+ assert_equal(["c-call", 8, :set_trace_func, Kernel],
+ events.shift)
+ assert_equal([], events)
+ end
+
+ def test_invalid_proc
+ assert_raise(TypeError) { set_trace_func(1) }
+ end
+end
diff --git a/trunk/test/ruby/test_signal.rb b/trunk/test/ruby/test_signal.rb
new file mode 100644
index 0000000000..0bc2078c18
--- /dev/null
+++ b/trunk/test/ruby/test_signal.rb
@@ -0,0 +1,166 @@
+require 'test/unit'
+require 'timeout'
+
+class TestSignal < Test::Unit::TestCase
+ def have_fork?
+ begin
+ Process.fork {}
+ return true
+ rescue NotImplementedError
+ return false
+ end
+ end
+
+ def test_signal
+ return unless Process.respond_to?(:kill)
+ begin
+ x = 0
+ oldtrap = Signal.trap(:INT) {|sig| x = 2 }
+ Process.kill :INT, Process.pid
+ sleep 0.1
+ assert_equal 2, x
+
+ Signal.trap(:INT) { raise "Interrupt" }
+ ex = assert_raises(RuntimeError) {
+ Process.kill :INT, Process.pid
+ sleep 0.1
+ }
+ assert_kind_of Exception, ex
+ assert_match(/Interrupt/, ex.message)
+ ensure
+ Signal.trap :INT, oldtrap if oldtrap
+ end
+ end
+
+ def test_exit_action
+ return unless have_fork? # snip this test
+ begin
+ r, w = IO.pipe
+ r0, w0 = IO.pipe
+ pid = Process.fork {
+ Signal.trap(:USR1, "EXIT")
+ w0.close
+ w.syswrite("a")
+ Thread.start { Thread.pass }
+ r0.sysread(4096)
+ }
+ r.sysread(1)
+ sleep 0.1
+ assert_nothing_raised("[ruby-dev:26128]") {
+ Process.kill(:USR1, pid)
+ begin
+ Timeout.timeout(3) {
+ Process.waitpid pid
+ }
+ rescue Timeout::Error
+ Process.kill(:TERM, pid)
+ raise
+ end
+ }
+ ensure
+ r.close
+ w.close
+ r0.close
+ w0.close
+ end
+ end
+
+ def test_invalid_signal_name
+ return unless Process.respond_to?(:kill)
+
+ assert_raise(ArgumentError) { Process.kill(:XXXXXXXXXX, $$) }
+ end
+
+ def test_signal_exception
+ assert_raise(ArgumentError) { SignalException.new }
+ assert_raise(ArgumentError) { SignalException.new(-1) }
+ assert_raise(ArgumentError) { SignalException.new(:XXXXXXXXXX) }
+ Signal.list.each do |signm, signo|
+ next if signm == "EXIT"
+ assert_equal(SignalException.new(signm).signo, signo)
+ assert_equal(SignalException.new(signm.to_sym).signo, signo)
+ assert_equal(SignalException.new(signo).signo, signo)
+ end
+ end
+
+ def test_interrupt
+ assert_raise(Interrupt) { raise Interrupt.new }
+ end
+
+ def test_signal2
+ return unless Process.respond_to?(:kill)
+ begin
+ x = false
+ oldtrap = Signal.trap(:INT) {|sig| x = true }
+ GC.start
+
+ assert_raise(ArgumentError) { Process.kill }
+
+ Timeout.timeout(10) do
+ x = false
+ Process.kill(SignalException.new(:INT).signo, $$)
+ nil until x
+
+ x = false
+ Process.kill("INT", $$)
+ nil until x
+
+ x = false
+ Process.kill("SIGINT", $$)
+ nil until x
+
+ x = false
+ o = Object.new
+ def o.to_str; "SIGINT"; end
+ Process.kill(o, $$)
+ nil until x
+ end
+
+ assert_raise(ArgumentError) { Process.kill(Object.new, $$) }
+
+ ensure
+ Signal.trap(:INT, oldtrap) if oldtrap
+ end
+ end
+
+ def test_trap
+ return unless Process.respond_to?(:kill)
+ begin
+ oldtrap = Signal.trap(:INT) {|sig| }
+
+ assert_raise(ArgumentError) { Signal.trap }
+
+ assert_raise(SecurityError) do
+ s = proc {}.taint
+ Signal.trap(:INT, s)
+ end
+
+ # FIXME!
+ Signal.trap(:INT, nil)
+ Signal.trap(:INT, "")
+ Signal.trap(:INT, "SIG_IGN")
+ Signal.trap(:INT, "IGNORE")
+
+ Signal.trap(:INT, "SIG_DFL")
+ Signal.trap(:INT, "SYSTEM_DEFAULT")
+
+ Signal.trap(:INT, "EXIT")
+
+ Signal.trap(:INT, "xxxxxx")
+ Signal.trap(:INT, "xxxx")
+
+ Signal.trap(SignalException.new(:INT).signo, "SIG_DFL")
+
+ assert_raise(ArgumentError) { Signal.trap(-1, "xxxx") }
+
+ o = Object.new
+ def o.to_str; "SIGINT"; end
+ Signal.trap(o, "SIG_DFL")
+
+ assert_raise(ArgumentError) { Signal.trap("XXXXXXXXXX", "SIG_DFL") }
+
+ ensure
+ Signal.trap(:INT, oldtrap) if oldtrap
+ end
+ end
+end
diff --git a/trunk/test/ruby/test_sleep.rb b/trunk/test/ruby/test_sleep.rb
new file mode 100644
index 0000000000..675fdc9747
--- /dev/null
+++ b/trunk/test/ruby/test_sleep.rb
@@ -0,0 +1,10 @@
+require 'test/unit'
+
+class TestSleep < Test::Unit::TestCase
+ def test_sleep_5sec
+ start = Time.now
+ sleep 5
+ slept = Time.now-start
+ assert_in_delta(5.0, slept, 0.1, "[ruby-core:18015]: longer than expected")
+ end
+end
diff --git a/trunk/test/ruby/test_sprintf.rb b/trunk/test/ruby/test_sprintf.rb
new file mode 100644
index 0000000000..cad9f5e031
--- /dev/null
+++ b/trunk/test/ruby/test_sprintf.rb
@@ -0,0 +1,273 @@
+require 'test/unit'
+
+class TestSprintf < Test::Unit::TestCase
+ def test_positional
+ assert_equal(" 00001", sprintf("%*1$.*2$3$d", 10, 5, 1))
+ end
+
+ def test_binary
+ assert_equal("0", sprintf("%b", 0))
+ assert_equal("1", sprintf("%b", 1))
+ assert_equal("10", sprintf("%b", 2))
+ assert_equal("..1", sprintf("%b", -1))
+
+ assert_equal(" 0", sprintf("%4b", 0))
+ assert_equal(" 1", sprintf("%4b", 1))
+ assert_equal(" 10", sprintf("%4b", 2))
+ assert_equal(" ..1", sprintf("%4b", -1))
+
+ assert_equal("0000", sprintf("%04b", 0))
+ assert_equal("0001", sprintf("%04b", 1))
+ assert_equal("0010", sprintf("%04b", 2))
+ assert_equal("..11", sprintf("%04b", -1))
+
+ assert_equal("0000", sprintf("%.4b", 0))
+ assert_equal("0001", sprintf("%.4b", 1))
+ assert_equal("0010", sprintf("%.4b", 2))
+ assert_equal("..11", sprintf("%.4b", -1))
+
+ assert_equal(" 0000", sprintf("%6.4b", 0))
+ assert_equal(" 0001", sprintf("%6.4b", 1))
+ assert_equal(" 0010", sprintf("%6.4b", 2))
+ assert_equal(" ..11", sprintf("%6.4b", -1))
+
+ assert_equal(" 0", sprintf("%#4b", 0))
+ assert_equal(" 0b1", sprintf("%#4b", 1))
+ assert_equal("0b10", sprintf("%#4b", 2))
+ assert_equal("0b..1", sprintf("%#4b", -1))
+
+ assert_equal("0000", sprintf("%#04b", 0))
+ assert_equal("0b01", sprintf("%#04b", 1))
+ assert_equal("0b10", sprintf("%#04b", 2))
+ assert_equal("0b..1", sprintf("%#04b", -1))
+
+ assert_equal("0000", sprintf("%#.4b", 0))
+ assert_equal("0b0001", sprintf("%#.4b", 1))
+ assert_equal("0b0010", sprintf("%#.4b", 2))
+ assert_equal("0b..11", sprintf("%#.4b", -1))
+
+ assert_equal(" 0000", sprintf("%#6.4b", 0))
+ assert_equal("0b0001", sprintf("%#6.4b", 1))
+ assert_equal("0b0010", sprintf("%#6.4b", 2))
+ assert_equal("0b..11", sprintf("%#6.4b", -1))
+
+ assert_equal("+0", sprintf("%+b", 0))
+ assert_equal("+1", sprintf("%+b", 1))
+ assert_equal("+10", sprintf("%+b", 2))
+ assert_equal("-1", sprintf("%+b", -1))
+
+ assert_equal(" +0", sprintf("%+4b", 0))
+ assert_equal(" +1", sprintf("%+4b", 1))
+ assert_equal(" +10", sprintf("%+4b", 2))
+ assert_equal(" -1", sprintf("%+4b", -1))
+
+ assert_equal("+000", sprintf("%+04b", 0))
+ assert_equal("+001", sprintf("%+04b", 1))
+ assert_equal("+010", sprintf("%+04b", 2))
+ assert_equal("-001", sprintf("%+04b", -1))
+
+ assert_equal("+0000", sprintf("%+.4b", 0))
+ assert_equal("+0001", sprintf("%+.4b", 1))
+ assert_equal("+0010", sprintf("%+.4b", 2))
+ assert_equal("-0001", sprintf("%+.4b", -1))
+
+ assert_equal(" +0000", sprintf("%+6.4b", 0))
+ assert_equal(" +0001", sprintf("%+6.4b", 1))
+ assert_equal(" +0010", sprintf("%+6.4b", 2))
+ assert_equal(" -0001", sprintf("%+6.4b", -1))
+ end
+
+ def test_nan
+ nan = 0.0 / 0.0
+ assert_equal("NaN", sprintf("%f", nan))
+ assert_equal("NaN", sprintf("%-f", nan))
+ assert_equal("+NaN", sprintf("%+f", nan))
+
+ assert_equal(" NaN", sprintf("%8f", nan))
+ assert_equal("NaN ", sprintf("%-8f", nan))
+ assert_equal(" +NaN", sprintf("%+8f", nan))
+
+ assert_equal(" NaN", sprintf("%08f", nan))
+ assert_equal("NaN ", sprintf("%-08f", nan))
+ assert_equal(" +NaN", sprintf("%+08f", nan))
+
+ assert_equal(" NaN", sprintf("% 8f", nan))
+ assert_equal(" NaN ", sprintf("%- 8f", nan))
+ assert_equal(" +NaN", sprintf("%+ 8f", nan))
+
+ assert_equal(" NaN", sprintf("% 08f", nan))
+ assert_equal(" NaN ", sprintf("%- 08f", nan))
+ assert_equal(" +NaN", sprintf("%+ 08f", nan))
+ end
+
+ def test_inf
+ inf = 1.0 / 0.0
+ assert_equal("Inf", sprintf("%f", inf))
+ assert_equal("Inf", sprintf("%-f", inf))
+ assert_equal("+Inf", sprintf("%+f", inf))
+
+ assert_equal(" Inf", sprintf("%8f", inf))
+ assert_equal("Inf ", sprintf("%-8f", inf))
+ assert_equal(" +Inf", sprintf("%+8f", inf))
+
+ assert_equal(" Inf", sprintf("%08f", inf))
+ assert_equal("Inf ", sprintf("%-08f", inf))
+ assert_equal(" +Inf", sprintf("%+08f", inf))
+
+ assert_equal(" Inf", sprintf("% 8f", inf))
+ assert_equal(" Inf ", sprintf("%- 8f", inf))
+ assert_equal(" +Inf", sprintf("%+ 8f", inf))
+
+ assert_equal(" Inf", sprintf("% 08f", inf))
+ assert_equal(" Inf ", sprintf("%- 08f", inf))
+ assert_equal(" +Inf", sprintf("%+ 08f", inf))
+
+ assert_equal("-Inf", sprintf("%f", -inf))
+ assert_equal("-Inf", sprintf("%-f", -inf))
+ assert_equal("-Inf", sprintf("%+f", -inf))
+
+ assert_equal(" -Inf", sprintf("%8f", -inf))
+ assert_equal("-Inf ", sprintf("%-8f", -inf))
+ assert_equal(" -Inf", sprintf("%+8f", -inf))
+
+ assert_equal(" -Inf", sprintf("%08f", -inf))
+ assert_equal("-Inf ", sprintf("%-08f", -inf))
+ assert_equal(" -Inf", sprintf("%+08f", -inf))
+
+ assert_equal(" -Inf", sprintf("% 8f", -inf))
+ assert_equal("-Inf ", sprintf("%- 8f", -inf))
+ assert_equal(" -Inf", sprintf("%+ 8f", -inf))
+
+ assert_equal(" -Inf", sprintf("% 08f", -inf))
+ assert_equal("-Inf ", sprintf("%- 08f", -inf))
+ assert_equal(" -Inf", sprintf("%+ 08f", -inf))
+ assert_equal('..f00000000',
+ sprintf("%x", -2**32), '[ruby-dev:32351]')
+ assert_equal("..101111111111111111111111111111111",
+ sprintf("%b", -2147483649), '[ruby-dev:32365]')
+ assert_equal(" Inf", sprintf("% e", inf), '[ruby-dev:34002]')
+ end
+
+ def test_invalid
+ # Star precision before star width:
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.**d", 5, 10, 1)}
+
+ # Precision before flags and width:
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.5+05d", 5)}
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.5 5d", 5)}
+
+ # Overriding a star width with a numeric one:
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%*1s", 5, 1)}
+
+ # Width before flags:
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%5+0d", 1)}
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%5 0d", 1)}
+
+ # Specifying width multiple times:
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%50+30+20+10+5d", 5)}
+ assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%50 30 20 10 5d", 5)}
+
+ # Specifying the precision multiple times with negative star arguments:
+ assert_raise(ArgumentError, "[ruby-core:11570]") {sprintf("%.*.*.*.*f", -1, -1, -1, 5, 1)}
+
+ # Null bytes after percent signs are removed:
+ assert_equal("%\0x hello", sprintf("%\0x hello"), "[ruby-core:11571]")
+
+ assert_raise(ArgumentError, "[ruby-core:11573]") {sprintf("%.25555555555555555555555555555555555555s", "hello")}
+
+ assert_raise(ArgumentError) { sprintf("%\1", 1) }
+ assert_raise(ArgumentError) { sprintf("%!", 1) }
+ assert_raise(ArgumentError) { sprintf("%1$1$d", 1) }
+ assert_raise(ArgumentError) { sprintf("%0%") }
+ assert_nothing_raised { sprintf("", 1) }
+ end
+
+ def test_float
+ assert_equal("36893488147419111424",
+ sprintf("%20.0f", 36893488147419107329.0))
+ assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
+ end
+
+ BSIZ = 120
+
+ def test_skip
+ assert_equal(" " * BSIZ + "1", sprintf(" " * BSIZ + "%d", 1))
+ end
+
+ def test_char
+ assert_equal("a", sprintf("%c", 97))
+ assert_equal("a", sprintf("%c", ?a))
+ assert_raise(ArgumentError) { sprintf("%c", sprintf("%c%c", ?a, ?a)) }
+ assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%c", ?a))
+ assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%-1c", ?a))
+ assert_equal(" " * BSIZ + "a", sprintf("%#{ BSIZ + 1 }c", ?a))
+ assert_equal("a" + " " * BSIZ, sprintf("%-#{ BSIZ + 1 }c", ?a))
+ end
+
+ def test_string
+ assert_equal("foo", sprintf("%s", "foo"))
+ assert_equal("fo", sprintf("%.2s", "foo"))
+ assert_equal(" " * BSIZ, sprintf("%s", " " * BSIZ))
+ assert_equal(" " * (BSIZ - 1) + "foo", sprintf("%#{ BSIZ - 1 + 3 }s", "foo"))
+ assert_equal(" " * BSIZ + "foo", sprintf("%#{ BSIZ + 3 }s", "foo"))
+ assert_equal("foo" + " " * BSIZ, sprintf("%-#{ BSIZ + 3 }s", "foo"))
+ end
+
+ def test_integer
+ assert_equal("01", sprintf("%#o", 1))
+ assert_equal("0x1", sprintf("%#x", 1))
+ assert_equal("0X1", sprintf("%#X", 1))
+ assert_equal("0b1", sprintf("%#b", 1))
+ assert_equal("0B1", sprintf("%#B", 1))
+ assert_equal("1", sprintf("%d", 1.0))
+ assert_equal("4294967296", sprintf("%d", (2**32).to_f))
+ assert_equal("-2147483648", sprintf("%d", -(2**31).to_f))
+ assert_equal("18446744073709551616", sprintf("%d", (2**64).to_f))
+ assert_equal("-9223372036854775808", sprintf("%d", -(2**63).to_f))
+ assert_equal("1", sprintf("%d", "1"))
+ o = Object.new; def o.to_int; 1; end
+ assert_equal("1", sprintf("%d", o))
+ assert_equal("+1", sprintf("%+d", 1))
+ assert_equal(" 1", sprintf("% d", 1))
+ assert_equal("..f", sprintf("%x", -1))
+ assert_equal("..7", sprintf("%o", -1))
+ one = (2**32).coerce(1).first
+ mone = (2**32).coerce(-1).first
+ assert_equal("+1", sprintf("%+d", one))
+ assert_equal(" 1", sprintf("% d", one))
+ assert_equal("..f", sprintf("%x", mone))
+ assert_equal("..7", sprintf("%o", mone))
+ assert_equal(" " * BSIZ + "1", sprintf("%#{ BSIZ + 1 }d", one))
+ assert_equal(" " * (BSIZ - 1) + "1", sprintf(" " * (BSIZ - 1) + "%d", 1))
+ end
+
+ def test_float2
+ inf = 1.0 / 0.0
+ assert_equal(" " * BSIZ + "Inf", sprintf("%#{ BSIZ + 3 }.1f", inf))
+ assert_equal("+Inf", sprintf("%+-f", inf))
+ assert_equal(" " * BSIZ + "1.0", sprintf("%#{ BSIZ + 3 }.1f", 1.0))
+ end
+
+ class T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ end
+
+ def test_star
+ assert_equal("-1 ", sprintf("%*d", -3, -1))
+ end
+
+ def test_escape
+ assert_equal("%" * BSIZ, sprintf("%%" * BSIZ))
+ end
+
+ def test_rb_sprintf
+ assert(T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.new.inspect =~ /^#<TestSprintf::T012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:0x[0-9a-f]+>$/)
+ end
+
+ def test_negative_hex
+ s1 = sprintf("%0x", -0x40000000)
+ s2 = sprintf("%0x", -0x40000001)
+ b1 = (/\.\./ =~ s1) != nil
+ b2 = (/\.\./ =~ s2) != nil
+ assert(b1 == b2, "[ruby-dev:33224]")
+ end
+end
diff --git a/trunk/test/ruby/test_sprintf_comb.rb b/trunk/test/ruby/test_sprintf_comb.rb
new file mode 100644
index 0000000000..8b2c1a7e05
--- /dev/null
+++ b/trunk/test/ruby/test_sprintf_comb.rb
@@ -0,0 +1,548 @@
+require 'test/unit'
+require_relative 'allpairs'
+
+class TestSprintfComb < Test::Unit::TestCase
+ VS = [
+ #-0x1000000000000000000000000000000000000000000000002,
+ #-0x1000000000000000000000000000000000000000000000001,
+ #-0x1000000000000000000000000000000000000000000000000,
+ #-0xffffffffffffffffffffffffffffffffffffffffffffffff,
+ #-0x1000000000000000000000002,
+ #-0x1000000000000000000000001,
+ #-0x1000000000000000000000000,
+ #-0xffffffffffffffffffffffff,
+ -0x10000000000000002,
+ -0x10000000000000001,
+ -0x10000000000000000,
+ -0xffffffffffffffff,
+ -0x4000000000000002,
+ -0x4000000000000001,
+ -0x4000000000000000,
+ -0x3fffffffffffffff,
+ -0x100000002,
+ -0x100000001,
+ -0x100000000,
+ -0xffffffff,
+ #-0xc717a08d, # 0xc717a08d * 0x524b2245 = 0x4000000000000001
+ -0x80000002,
+ -0x80000001,
+ -0x80000000,
+ -0x7fffffff,
+ #-0x524b2245,
+ -0x40000002,
+ -0x40000001,
+ -0x40000000,
+ -0x3fffffff,
+ #-0x10002,
+ #-0x10001,
+ #-0x10000,
+ #-0xffff,
+ #-0x8101, # 0x8101 * 0x7f01 = 0x40000001
+ #-0x8002,
+ #-0x8001,
+ #-0x8000,
+ #-0x7fff,
+ #-0x7f01,
+ #-65,
+ #-64,
+ #-63,
+ #-62,
+ #-33,
+ #-32,
+ #-31,
+ #-30,
+ -3,
+ -2,
+ -1,
+ 0,
+ 1,
+ 2,
+ 3,
+ #30,
+ #31,
+ #32,
+ #33,
+ #62,
+ #63,
+ #64,
+ #65,
+ #0x7f01,
+ #0x7ffe,
+ #0x7fff,
+ #0x8000,
+ #0x8001,
+ #0x8101,
+ #0xfffe,
+ #0xffff,
+ #0x10000,
+ #0x10001,
+ 0x3ffffffe,
+ 0x3fffffff,
+ 0x40000000,
+ 0x40000001,
+ #0x524b2245,
+ 0x7ffffffe,
+ 0x7fffffff,
+ 0x80000000,
+ 0x80000001,
+ #0xc717a08d,
+ 0xfffffffe,
+ 0xffffffff,
+ 0x100000000,
+ 0x100000001,
+ 0x3ffffffffffffffe,
+ 0x3fffffffffffffff,
+ 0x4000000000000000,
+ 0x4000000000000001,
+ 0xfffffffffffffffe,
+ 0xffffffffffffffff,
+ 0x10000000000000000,
+ 0x10000000000000001,
+ #0xffffffffffffffffffffffff,
+ #0x1000000000000000000000000,
+ #0x1000000000000000000000001,
+ #0xffffffffffffffffffffffffffffffffffffffffffffffff,
+ #0x1000000000000000000000000000000000000000000000000,
+ #0x1000000000000000000000000000000000000000000000001
+ ]
+ VS.reverse!
+
+ def combination(*args, &b)
+ #AllPairs.exhaustive_each(*args, &b)
+ AllPairs.each(*args, &b)
+ end
+
+ def emu_int(format, v)
+ /\A%( )?(\#)?(\+)?(-)?(0)?(\d+)?(?:\.(\d*))?(.)\z/ =~ format
+ sp = $1
+ hs = $2
+ pl = $3
+ mi = $4
+ zr = $5
+ width = $6
+ precision = $7
+ type = $8
+ width = width.to_i if width
+ precision = precision.to_i if precision
+ prefix = ''
+
+ zr = nil if precision
+
+ zr = nil if mi && zr
+
+ case type
+ when 'b'
+ radix = 2
+ digitmap = {0 => '0', 1 => '1'}
+ complement = !pl && !sp
+ prefix = '0b' if hs && v != 0
+ when 'd'
+ radix = 10
+ digitmap = {}
+ 10.times {|i| digitmap[i] = i.to_s }
+ complement = false
+ when 'o'
+ radix = 8
+ digitmap = {}
+ 8.times {|i| digitmap[i] = i.to_s }
+ complement = !pl && !sp
+ when 'X'
+ radix = 16
+ digitmap = {}
+ 16.times {|i| digitmap[i] = i.to_s(16).upcase }
+ complement = !pl && !sp
+ prefix = '0X' if hs && v != 0
+ when 'x'
+ radix = 16
+ digitmap = {}
+ 16.times {|i| digitmap[i] = i.to_s(16) }
+ complement = !pl && !sp
+ prefix = '0x' if hs && v != 0
+ else
+ raise "unexpected type: #{type.inspect}"
+ end
+
+ digits = []
+ abs = v.abs
+ sign = ''
+ while 0 < abs
+ digits << (abs % radix)
+ abs /= radix
+ end
+
+ if v < 0
+ if complement
+ digits.map! {|d| radix-1 - d }
+ carry = 1
+ digits.each_index {|i|
+ digits[i] += carry
+ carry = 0
+ if radix <= digits[i]
+ digits[i] -= radix
+ carry = 1
+ end
+ }
+ if digits.last != radix-1
+ digits << (radix-1)
+ end
+ sign = '..'
+ else
+ sign = '-'
+ end
+ else
+ if pl
+ sign = '+'
+ elsif sp
+ sign = ' '
+ end
+ end
+
+ dlen = digits.length
+ dlen += 2 if sign == '..'
+
+ if v < 0 && complement
+ d = radix - 1
+ else
+ d = 0
+ end
+ if precision
+ if dlen < precision
+ (precision - dlen).times {
+ digits << d
+ }
+ end
+ else
+ if dlen == 0
+ digits << d
+ end
+ end
+ if type == 'o' && hs
+ if digits.empty? || digits.last != d
+ digits << d
+ end
+ end
+
+ digits.reverse!
+
+ str = digits.map {|d| digitmap[d] }.join
+
+ pad = ''
+ nlen = prefix.length + sign.length + str.length
+ if width && nlen < width
+ len = width - nlen
+ if zr
+ if complement && v < 0
+ pad = digitmap[radix-1] * len
+ else
+ pad = '0' * len
+ end
+ else
+ pad = ' ' * len
+ end
+ end
+
+ if / / =~ pad
+ if sign == '..'
+ str = prefix + sign + str
+ else
+ str = sign + prefix + str
+ end
+ if mi
+ str = str + pad
+ else
+ str = pad + str
+ end
+ else
+ if sign == '..'
+ str = prefix + sign + pad + str
+ else
+ str = sign + prefix + pad + str
+ end
+ end
+
+ str
+ end
+
+ def test_format_integer
+ combination(
+ %w[b d o X x],
+ [nil, 0, 5, 20],
+ ["", ".", ".0", ".8", ".20"],
+ ['', ' '],
+ ['', '#'],
+ ['', '+'],
+ ['', '-'],
+ ['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
+ format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ VS.each {|v|
+ r = sprintf format, v
+ e = emu_int format, v
+ if true
+ assert_equal(e, r, "sprintf(#{format.dump}, #{v})")
+ else
+ if e != r
+ puts "#{e.dump}\t#{r.dump}\tsprintf(#{format.dump}, #{v})"
+ end
+ end
+ }
+ }
+ end
+
+ FLOAT_VALUES = [
+ -1e100,
+ -123456789.0,
+ -1.0,
+ -0.0,
+ 0.0,
+ 0.01,
+ 1/3.0,
+ 2/3.0,
+ 1.0,
+ 2.0,
+ 9.99999999,
+ 123456789.0,
+ 1e100,
+ Float::MAX,
+ Float::MIN,
+ Float::EPSILON,
+ 1+Float::EPSILON,
+ #1-Float::EPSILON/2,
+ 10 + Float::EPSILON*10,
+ 10 - Float::EPSILON*5,
+ 1.0/0.0,
+ -1.0/0.0,
+ 0.0/0.0,
+ ]
+
+ def split_float10(v)
+ if v == 0
+ if 1/v < 0
+ sign = -1
+ v = -v
+ else
+ sign = 1
+ end
+ else
+ if v < 0
+ sign = -1
+ v = -v
+ else
+ sign = 1
+ end
+ end
+ exp = 0
+ int = v.floor
+ v -= int
+ while v != 0
+ v *= 2
+ int *= 2
+ i = v.floor
+ v -= i
+ int += i
+ exp -= 1
+ end
+ int *= 5 ** (-exp)
+ [sign, int, exp]
+ end
+
+ def emu_e(sp, hs, pl, mi, zr, width, precision, type, v, sign, int, exp)
+ precision = 6 unless precision
+ if int == 0
+ if precision == 0 && !hs
+ result = "0#{type}+00"
+ else
+ result = "0." + "0" * precision + "#{type}+00"
+ end
+ else
+ if int < 10**precision
+ int *= 10**precision
+ exp -= precision
+ end
+ digits = int.to_s.length
+ discard = digits - (precision+1)
+ if discard != 0
+ q, r = int.divmod(10**discard)
+ if r < 10**discard / 2
+ int = q
+ exp += discard
+ elsif (q+1).to_s.length == q.to_s.length
+ int = q+1
+ exp += discard
+ else
+ discard += 1
+ q, r = int.divmod(10**discard)
+ int = q+1
+ exp += discard
+ end
+ end
+ ints = int.to_s
+ frac = ints[1..-1]
+ result = ints[0,1]
+ e = exp + frac.length
+ if precision != 0 || hs
+ result << "."
+ if precision != 0
+ result << frac
+ end
+ end
+ result << type
+ if e == 0
+ if v.abs < 1
+ result << '-00' # glibc 2.7 causes '+00'
+ else
+ result << '+00'
+ end
+ else
+ result << sprintf("%+03d", e)
+ end
+ result
+ end
+ result
+ end
+
+ def emu_f(sp, hs, pl, mi, zr, width, precision, type, sign, int, exp)
+ precision = 6 unless precision
+ if int == 0
+ if precision == 0 && !hs
+ result = '0'
+ else
+ result = '0.' + '0' * precision
+ end
+ else
+ if -precision < exp
+ int *= 10 ** (precision+exp)
+ exp = -precision
+ end
+ if exp < -precision
+ discard = -exp - precision
+ q, r = int.divmod(10**discard)
+ if 10**discard / 2 <= r
+ q += 1
+ end
+ int = q
+ exp += discard
+ end
+ result = int.to_s
+ if result.length <= precision
+ result = '0' * (precision+1 - result.length) + result
+ end
+ if precision != 0 || hs
+ if precision == 0
+ result << '.'
+ else
+ result[-precision,0] = '.'
+ end
+ end
+ end
+ result
+ end
+
+ def emu_float(format, v)
+ /\A%( )?(\#)?(\+)?(-)?(0)?(\d+)?(?:\.(\d*))?(.)\z/ =~ format
+ sp = $1
+ hs = $2
+ pl = $3
+ mi = $4
+ zr = $5
+ width = $6
+ precision = $7
+ type = $8
+ width = width.to_i if width
+ precision = precision.to_i if precision
+
+ zr = nil if mi && zr
+
+ if v.infinite?
+ sign = v < 0 ? -1 : 1
+ int = :inf
+ hs = zr = nil
+ elsif v.nan?
+ sign = 1
+ int = :nan
+ hs = zr = nil
+ else
+ sign, int, exp = split_float10(v)
+ end
+
+ if sign < 0
+ sign = '-'
+ elsif sign == 0
+ sign = ''
+ elsif pl
+ sign = '+'
+ elsif sp
+ sign = ' '
+ else
+ sign = ''
+ end
+
+ if v.nan?
+ result = 'NaN'
+ elsif v.infinite?
+ result = 'Inf'
+ else
+ case type
+ when /[eE]/
+ result = emu_e(sp, hs, pl, mi, zr, width, precision, type, v, sign, int, exp)
+ when /f/
+ result = emu_f(sp, hs, pl, mi, zr, width, precision, type, sign, int, exp)
+ when /[gG]/
+ precision = 6 unless precision
+ precision = 1 if precision == 0
+ r = emu_e(sp, hs, pl, mi, zr, width, precision-1, type.tr('gG', 'eE'), v, sign, int, exp)
+ /[eE]([+-]\d+)/ =~ r
+ e = $1.to_i
+ if e < -4 || precision <= e
+ result = r
+ else
+ result = emu_f(sp, hs, pl, mi, zr, width, precision-1-e, type, sign, int, exp)
+ end
+ result.sub!(/\.[0-9]*/) { $&.sub(/\.?0*\z/, '') } if !hs
+ else
+ raise "unexpected type: #{type}"
+ end
+ end
+
+ pad = ''
+ if width && sign.length + result.length < width
+ if zr
+ pad = '0' * (width - sign.length - result.length)
+ else
+ pad = ' ' * (width - sign.length - result.length)
+ end
+ end
+ if mi
+ sign + result + pad
+ elsif zr
+ sign + pad + result
+ else
+ pad + sign + result
+ end
+
+ end
+
+ def test_format_float
+ combination(
+ %w[e E f g G],
+ [nil, 0, 5, 20],
+ ["", ".", ".0", ".8", ".20", ".200"],
+ ['', ' '],
+ ['', '#'],
+ ['', '+'],
+ ['', '-'],
+ ['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
+ format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
+ FLOAT_VALUES.each {|v|
+ r = sprintf format, v
+ e = emu_float format, v
+ if true
+ assert_equal(e, r, "sprintf(#{format.dump}, #{'%.20g' % v})")
+ else
+ if e != r
+ puts "#{e.dump}\t#{r.dump}\tsprintf(#{format.dump}, #{'%.20g' % v})"
+ end
+ end
+ }
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_string.rb b/trunk/test/ruby/test_string.rb
new file mode 100644
index 0000000000..cd32709658
--- /dev/null
+++ b/trunk/test/ruby/test_string.rb
@@ -0,0 +1,1717 @@
+require 'test/unit'
+require_relative 'envutil'
+
+# use of $= is deprecated after 1.7.1
+def pre_1_7_1
+end
+
+class TestString < Test::Unit::TestCase
+
+ def initialize(*args)
+ @cls = String
+ @aref_re_nth = true
+ @aref_re_silent = false
+ @aref_slicebang_silent = true
+ super
+ end
+
+ def S(str)
+ @cls.new(str)
+ end
+
+ def test_s_new
+ assert_equal("RUBY", S("RUBY"))
+ end
+
+ def test_AREF # '[]'
+ assert_equal("A", S("AooBar")[0])
+ assert_equal("B", S("FooBaB")[-1])
+ assert_equal(nil, S("FooBar")[6])
+ assert_equal(nil, S("FooBar")[-7])
+
+ assert_equal(S("Foo"), S("FooBar")[0,3])
+ assert_equal(S("Bar"), S("FooBar")[-3,3])
+ assert_equal(S(""), S("FooBar")[6,2])
+ assert_equal(nil, S("FooBar")[-7,10])
+
+ assert_equal(S("Foo"), S("FooBar")[0..2])
+ assert_equal(S("Foo"), S("FooBar")[0...3])
+ assert_equal(S("Bar"), S("FooBar")[-3..-1])
+ assert_equal(S(""), S("FooBar")[6..2])
+ assert_equal(nil, S("FooBar")[-10..-7])
+
+ assert_equal(S("Foo"), S("FooBar")[/^F../])
+ assert_equal(S("Bar"), S("FooBar")[/..r$/])
+ assert_equal(nil, S("FooBar")[/xyzzy/])
+ assert_equal(nil, S("FooBar")[/plugh/])
+
+ assert_equal(S("Foo"), S("FooBar")[S("Foo")])
+ assert_equal(S("Bar"), S("FooBar")[S("Bar")])
+ assert_equal(nil, S("FooBar")[S("xyzzy")])
+ assert_equal(nil, S("FooBar")[S("plugh")])
+
+ if @aref_re_nth
+ assert_equal(S("Foo"), S("FooBar")[/([A-Z]..)([A-Z]..)/, 1])
+ assert_equal(S("Bar"), S("FooBar")[/([A-Z]..)([A-Z]..)/, 2])
+ assert_equal(nil, S("FooBar")[/([A-Z]..)([A-Z]..)/, 3])
+ assert_equal(S("Bar"), S("FooBar")[/([A-Z]..)([A-Z]..)/, -1])
+ assert_equal(S("Foo"), S("FooBar")[/([A-Z]..)([A-Z]..)/, -2])
+ assert_equal(nil, S("FooBar")[/([A-Z]..)([A-Z]..)/, -3])
+ end
+
+ o = Object.new
+ def o.to_int; 2; end
+ assert_equal("o", "foo"[o])
+
+ assert_raise(ArgumentError) { "foo"[] }
+ end
+
+ def test_ASET # '[]='
+ s = S("FooBar")
+ s[0] = S('A')
+ assert_equal(S("AooBar"), s)
+
+ s[-1]= S('B')
+ assert_equal(S("AooBaB"), s)
+ assert_raise(IndexError) { s[-7] = S("xyz") }
+ assert_equal(S("AooBaB"), s)
+ s[0] = S("ABC")
+ assert_equal(S("ABCooBaB"), s)
+
+ s = S("FooBar")
+ s[0,3] = S("A")
+ assert_equal(S("ABar"),s)
+ s[0] = S("Foo")
+ assert_equal(S("FooBar"), s)
+ s[-3,3] = S("Foo")
+ assert_equal(S("FooFoo"), s)
+ assert_raise(IndexError) { s[7,3] = S("Bar") }
+ assert_raise(IndexError) { s[-7,3] = S("Bar") }
+
+ s = S("FooBar")
+ s[0..2] = S("A")
+ assert_equal(S("ABar"), s)
+ s[1..3] = S("Foo")
+ assert_equal(S("AFoo"), s)
+ s[-4..-4] = S("Foo")
+ assert_equal(S("FooFoo"), s)
+ assert_raise(RangeError) { s[7..10] = S("Bar") }
+ assert_raise(RangeError) { s[-7..-10] = S("Bar") }
+
+ s = S("FooBar")
+ s[/^F../]= S("Bar")
+ assert_equal(S("BarBar"), s)
+ s[/..r$/] = S("Foo")
+ assert_equal(S("BarFoo"), s)
+ if @aref_re_silent
+ s[/xyzzy/] = S("None")
+ assert_equal(S("BarFoo"), s)
+ else
+ assert_raise(IndexError) { s[/xyzzy/] = S("None") }
+ end
+ if @aref_re_nth
+ s[/([A-Z]..)([A-Z]..)/, 1] = S("Foo")
+ assert_equal(S("FooFoo"), s)
+ s[/([A-Z]..)([A-Z]..)/, 2] = S("Bar")
+ assert_equal(S("FooBar"), s)
+ assert_raise(IndexError) { s[/([A-Z]..)([A-Z]..)/, 3] = "None" }
+ s[/([A-Z]..)([A-Z]..)/, -1] = S("Foo")
+ assert_equal(S("FooFoo"), s)
+ s[/([A-Z]..)([A-Z]..)/, -2] = S("Bar")
+ assert_equal(S("BarFoo"), s)
+ assert_raise(IndexError) { s[/([A-Z]..)([A-Z]..)/, -3] = "None" }
+ end
+
+ s = S("FooBar")
+ s[S("Foo")] = S("Bar")
+ assert_equal(S("BarBar"), s)
+
+ pre_1_7_1 do
+ s = S("FooBar")
+ s[S("Foo")] = S("xyz")
+ assert_equal(S("xyzBar"), s)
+
+ $= = true
+ s = S("FooBar")
+ s[S("FOO")] = S("Bar")
+ assert_equal(S("BarBar"), s)
+ s[S("FOO")] = S("xyz")
+ assert_equal(S("BarBar"), s)
+ $= = false
+ end
+
+ s = S("a string")
+ s[0..s.size] = S("another string")
+ assert_equal(S("another string"), s)
+
+ o = Object.new
+ def o.to_int; 2; end
+ s = "foo"
+ s[o] = "bar"
+ assert_equal("fobar", s)
+
+ assert_raise(ArgumentError) { "foo"[1, 2, 3] = "" }
+ end
+
+ def test_CMP # '<=>'
+ assert_equal(1, S("abcdef") <=> S("abcde"))
+ assert_equal(0, S("abcdef") <=> S("abcdef"))
+ assert_equal(-1, S("abcde") <=> S("abcdef"))
+
+ assert_equal(-1, S("ABCDEF") <=> S("abcdef"))
+
+ pre_1_7_1 do
+ $= = true
+ assert_equal(0, S("ABCDEF") <=> S("abcdef"))
+ $= = false
+ end
+
+ assert_nil("foo" <=> Object.new)
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_nil("foo" <=> o)
+
+ def o.<=>(x); nil; end
+ assert_nil("foo" <=> o)
+
+ def o.<=>(x); 1; end
+ assert_equal(-1, "foo" <=> o)
+
+ def o.<=>(x); 2**100; end
+ assert_equal(-(2**100), "foo" <=> o)
+ end
+
+ def test_EQUAL # '=='
+ assert_equal(false, S("foo") == :foo)
+ assert(S("abcdef") == S("abcdef"))
+
+ pre_1_7_1 do
+ $= = true
+ assert(S("CAT") == S('cat'))
+ assert(S("CaT") == S('cAt'))
+ $= = false
+ end
+
+ assert(S("CAT") != S('cat'))
+ assert(S("CaT") != S('cAt'))
+
+ o = Object.new
+ def o.to_str; end
+ def o.==(x); false; end
+ assert_equal(false, "foo" == o)
+ def o.==(x); true; end
+ assert_equal(true, "foo" == o)
+ end
+
+ def test_LSHIFT # '<<'
+ assert_equal(S("world!"), S("world") << 33)
+ assert_equal(S("world!"), S("world") << S('!'))
+
+ s = "a"
+ 10.times {|i|
+ s << s
+ assert_equal("a" * (2 << i), s)
+ }
+
+ s = ["foo"].pack("p")
+ l = s.size
+ s << "bar"
+ assert_equal(l + 3, s.size)
+ end
+
+ def test_MATCH # '=~'
+ assert_equal(10, S("FeeFieFoo-Fum") =~ /Fum$/)
+ assert_equal(nil, S("FeeFieFoo-Fum") =~ /FUM$/)
+
+ pre_1_7_1 do
+ $= = true
+ assert_equal(10, S("FeeFieFoo-Fum") =~ /FUM$/)
+ $= = false
+ end
+
+ o = Object.new
+ def o.=~(x); x + "bar"; end
+ assert_equal("foobar", S("foo") =~ o)
+
+ assert_raise(TypeError) { S("foo") =~ "foo" }
+ end
+
+ def test_MOD # '%'
+ assert_equal(S("00123"), S("%05d") % 123)
+ assert_equal(S("123 |00000001"), S("%-5s|%08x") % [123, 1])
+ x = S("%3s %-4s%%foo %.0s%5d %#x%c%3.1f %b %x %X %#b %#x %#X") %
+ [S("hi"),
+ 123,
+ S("never seen"),
+ 456,
+ 0,
+ ?A,
+ 3.0999,
+ 11,
+ 171,
+ 171,
+ 11,
+ 171,
+ 171]
+
+ assert_equal(S(' hi 123 %foo 456 0A3.1 1011 ab AB 0b1011 0xab 0XAB'), x)
+ end
+
+ def test_MUL # '*'
+ assert_equal(S("XXX"), S("X") * 3)
+ assert_equal(S("HOHO"), S("HO") * 2)
+ end
+
+ def test_PLUS # '+'
+ assert_equal(S("Yodel"), S("Yo") + S("del"))
+ end
+
+ def casetest(a, b, rev=false)
+ case a
+ when b
+ assert(!rev)
+ else
+ assert(rev)
+ end
+ end
+
+ def test_VERY_EQUAL # '==='
+ # assert_equal(true, S("foo") === :foo)
+ casetest(S("abcdef"), S("abcdef"))
+
+ pre_1_7_1 do
+ $= = true
+ casetest(S("CAT"), S('cat'))
+ casetest(S("CaT"), S('cAt'))
+ $= = false
+ end
+
+ casetest(S("CAT"), S('cat'), true) # Reverse the test - we don't want to
+ casetest(S("CaT"), S('cAt'), true) # find these in the case.
+ end
+
+ def test_capitalize
+ assert_equal(S("Hello"), S("hello").capitalize)
+ assert_equal(S("Hello"), S("hELLO").capitalize)
+ assert_equal(S("123abc"), S("123ABC").capitalize)
+ end
+
+ def test_capitalize!
+ a = S("hello"); a.capitalize!
+ assert_equal(S("Hello"), a)
+
+ a = S("hELLO"); a.capitalize!
+ assert_equal(S("Hello"), a)
+
+ a = S("123ABC"); a.capitalize!
+ assert_equal(S("123abc"), a)
+
+ assert_equal(nil, S("123abc").capitalize!)
+ assert_equal(S("123abc"), S("123ABC").capitalize!)
+ assert_equal(S("Abc"), S("ABC").capitalize!)
+ assert_equal(S("Abc"), S("abc").capitalize!)
+ assert_equal(nil, S("Abc").capitalize!)
+
+ a = S("hello")
+ b = a.dup
+ assert_equal(S("Hello"), a.capitalize!)
+ assert_equal(S("hello"), b)
+
+ end
+
+ def test_center
+ assert_equal(S("hello"), S("hello").center(4))
+ assert_equal(S(" hello "), S("hello").center(11))
+ end
+
+ def test_chomp
+ assert_equal(S("hello"), S("hello").chomp("\n"))
+ assert_equal(S("hello"), S("hello\n").chomp("\n"))
+ save = $/
+
+ $/ = "\n"
+
+ assert_equal(S("hello"), S("hello").chomp)
+ assert_equal(S("hello"), S("hello\n").chomp)
+
+ $/ = "!"
+ assert_equal(S("hello"), S("hello").chomp)
+ assert_equal(S("hello"), S("hello!").chomp)
+ $/ = save
+ end
+
+ def test_chomp!
+ a = S("hello")
+ a.chomp!(S("\n"))
+
+ assert_equal(S("hello"), a)
+ assert_equal(nil, a.chomp!(S("\n")))
+
+ a = S("hello\n")
+ a.chomp!(S("\n"))
+ assert_equal(S("hello"), a)
+ save = $/
+
+ $/ = "\n"
+ a = S("hello")
+ a.chomp!
+ assert_equal(S("hello"), a)
+
+ a = S("hello\n")
+ a.chomp!
+ assert_equal(S("hello"), a)
+
+ $/ = "!"
+ a = S("hello")
+ a.chomp!
+ assert_equal(S("hello"), a)
+
+ a="hello!"
+ a.chomp!
+ assert_equal(S("hello"), a)
+
+ $/ = save
+
+ a = S("hello\n")
+ b = a.dup
+ assert_equal(S("hello"), a.chomp!)
+ assert_equal(S("hello\n"), b)
+
+ s = "foo\r\n"
+ s.chomp!
+ assert_equal("foo", s)
+
+ s = "foo\r"
+ s.chomp!
+ assert_equal("foo", s)
+
+ s = "foo\r\n"
+ s.chomp!("")
+ assert_equal("foo", s)
+
+ s = "foo\r"
+ s.chomp!("")
+ assert_equal("foo\r", s)
+ end
+
+ def test_chop
+ assert_equal(S("hell"), S("hello").chop)
+ assert_equal(S("hello"), S("hello\r\n").chop)
+ assert_equal(S("hello\n"), S("hello\n\r").chop)
+ assert_equal(S(""), S("\r\n").chop)
+ assert_equal(S(""), S("").chop)
+ end
+
+ def test_chop!
+ a = S("hello").chop!
+ assert_equal(S("hell"), a)
+
+ a = S("hello\r\n").chop!
+ assert_equal(S("hello"), a)
+
+ a = S("hello\n\r").chop!
+ assert_equal(S("hello\n"), a)
+
+ a = S("\r\n").chop!
+ assert_equal(S(""), a)
+
+ a = S("").chop!
+ assert_nil(a)
+
+ a = S("hello\n")
+ b = a.dup
+ assert_equal(S("hello"), a.chop!)
+ assert_equal(S("hello\n"), b)
+ end
+
+ def test_clone
+ for taint in [ false, true ]
+ for untrust in [ false, true ]
+ for frozen in [ false, true ]
+ a = S("Cool")
+ a.taint if taint
+ a.untrust if untrust
+ a.freeze if frozen
+ b = a.clone
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert_equal(a.frozen?, b.frozen?)
+ assert_equal(a.untrusted?, b.untrusted?)
+ assert_equal(a.tainted?, b.tainted?)
+ end
+ end
+ end
+
+ null = File.exist?("/dev/null") ? "/dev/null" : "NUL" # maybe DOSISH
+ assert_equal("", File.read(null).clone, '[ruby-dev:32819] reported by Kazuhiro NISHIYAMA')
+ end
+
+ def test_concat
+ assert_equal(S("world!"), S("world").concat(33))
+ assert_equal(S("world!"), S("world").concat(S('!')))
+ end
+
+ def test_count
+ a = S("hello world")
+ assert_equal(5, a.count(S("lo")))
+ assert_equal(2, a.count(S("lo"), S("o")))
+ assert_equal(4, a.count(S("hello"), S("^l")))
+ assert_equal(4, a.count(S("ej-m")))
+ assert_equal(0, S("y").count(S("a\\-z")))
+
+ assert_raise(ArgumentError) { "foo".count }
+ end
+
+ def test_crypt
+ assert_equal(S('aaGUC/JkO9/Sc'), S("mypassword").crypt(S("aa")))
+ assert(S('aaGUC/JkO9/Sc') != S("mypassword").crypt(S("ab")))
+ end
+
+ def test_delete
+ assert_equal(S("heo"), S("hello").delete(S("l"), S("lo")))
+ assert_equal(S("he"), S("hello").delete(S("lo")))
+ assert_equal(S("hell"), S("hello").delete(S("aeiou"), S("^e")))
+ assert_equal(S("ho"), S("hello").delete(S("ej-m")))
+ end
+
+ def test_delete!
+ a = S("hello")
+ a.delete!(S("l"), S("lo"))
+ assert_equal(S("heo"), a)
+
+ a = S("hello")
+ a.delete!(S("lo"))
+ assert_equal(S("he"), a)
+
+ a = S("hello")
+ a.delete!(S("aeiou"), S("^e"))
+ assert_equal(S("hell"), a)
+
+ a = S("hello")
+ a.delete!(S("ej-m"))
+ assert_equal(S("ho"), a)
+
+ a = S("hello")
+ assert_nil(a.delete!(S("z")))
+
+ a = S("hello")
+ b = a.dup
+ a.delete!(S("lo"))
+ assert_equal(S("he"), a)
+ assert_equal(S("hello"), b)
+
+ a = S("hello")
+ a.delete!(S("^el"))
+ assert_equal(S("ell"), a)
+
+ assert_raise(ArgumentError) { S("foo").delete! }
+ end
+
+
+ def test_downcase
+ assert_equal(S("hello"), S("helLO").downcase)
+ assert_equal(S("hello"), S("hello").downcase)
+ assert_equal(S("hello"), S("HELLO").downcase)
+ assert_equal(S("abc hello 123"), S("abc HELLO 123").downcase)
+ end
+
+ def test_downcase!
+ a = S("helLO")
+ b = a.dup
+ assert_equal(S("hello"), a.downcase!)
+ assert_equal(S("hello"), a)
+ assert_equal(S("helLO"), b)
+
+ a=S("hello")
+ assert_nil(a.downcase!)
+ assert_equal(S("hello"), a)
+ end
+
+ def test_dump
+ a= S("Test") << 1 << 2 << 3 << 9 << 13 << 10
+ assert_equal(S('"Test\\x01\\x02\\x03\\t\\r\\n"'), a.dump)
+ end
+
+ def test_dup
+ for taint in [ false, true ]
+ for untrust in [ false, true ]
+ for frozen in [ false, true ]
+ a = S("hello")
+ a.taint if taint
+ a.untrust if untrust
+ a.freeze if frozen
+ b = a.dup
+
+ assert_equal(a, b)
+ assert(a.__id__ != b.__id__)
+ assert(!b.frozen?)
+ assert_equal(a.tainted?, b.tainted?)
+ assert_equal(a.untrusted?, b.untrusted?)
+ end
+ end
+ end
+ end
+
+ def test_each
+ save = $/
+ $/ = "\n"
+ res=[]
+ S("hello\nworld").lines.each {|x| res << x}
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res=[]
+ S("hello\n\n\nworld").lines(S('')).each {|x| res << x}
+ assert_equal(S("hello\n\n\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ $/ = "!"
+ res=[]
+ S("hello!world").lines.each {|x| res << x}
+ assert_equal(S("hello!"), res[0])
+ assert_equal(S("world"), res[1])
+ $/ = save
+ end
+
+ def test_each_byte
+ res = []
+ S("ABC").each_byte {|x| res << x }
+ assert_equal(65, res[0])
+ assert_equal(66, res[1])
+ assert_equal(67, res[2])
+ end
+
+ def test_each_line
+ save = $/
+ $/ = "\n"
+ res=[]
+ S("hello\nworld").lines.each {|x| res << x}
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res=[]
+ S("hello\n\n\nworld").lines(S('')).each {|x| res << x}
+ assert_equal(S("hello\n\n\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ $/ = "!"
+
+ res=[]
+ S("hello!world").lines.each {|x| res << x}
+ assert_equal(S("hello!"), res[0])
+ assert_equal(S("world"), res[1])
+
+ $/ = save
+
+ s = nil
+ "foo\nbar".each_line(nil) {|s2| s = s2 }
+ assert_equal("foo\nbar", s)
+ end
+
+ def test_empty?
+ assert(S("").empty?)
+ assert(!S("not").empty?)
+ end
+
+ def test_eql?
+ a = S("hello")
+ assert(a.eql?(S("hello")))
+ assert(a.eql?(a))
+ end
+
+ def test_gsub
+ assert_equal(S("h*ll*"), S("hello").gsub(/[aeiou]/, S('*')))
+ assert_equal(S("h<e>ll<o>"), S("hello").gsub(/([aeiou])/, S('<\1>')))
+ assert_equal(S("h e l l o "),
+ S("hello").gsub(/./) { |s| s[0].to_s + S(' ')})
+ assert_equal(S("HELL-o"),
+ S("hello").gsub(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 })
+
+ a = S("hello")
+ a.taint
+ a.untrust
+ assert(a.gsub(/./, S('X')).tainted?)
+ assert(a.gsub(/./, S('X')).untrusted?)
+
+ assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
+
+ assert_raise(ArgumentError) { "foo".gsub }
+ end
+
+ def test_gsub!
+ a = S("hello")
+ b = a.dup
+ a.gsub!(/[aeiou]/, S('*'))
+ assert_equal(S("h*ll*"), a)
+ assert_equal(S("hello"), b)
+
+ a = S("hello")
+ a.gsub!(/([aeiou])/, S('<\1>'))
+ assert_equal(S("h<e>ll<o>"), a)
+
+ a = S("hello")
+ a.gsub!(/./) { |s| s[0].to_s + S(' ')}
+ assert_equal(S("h e l l o "), a)
+
+ a = S("hello")
+ a.gsub!(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 }
+ assert_equal(S("HELL-o"), a)
+
+ r = S('X')
+ r.taint
+ r.untrust
+ a.gsub!(/./, r)
+ assert(a.tainted?)
+ assert(a.untrusted?)
+
+ a = S("hello")
+ assert_nil(a.sub!(S('X'), S('Y')))
+ end
+
+ def test_sub_hash
+ assert_equal('azc', 'abc'.sub(/b/, "b" => "z"))
+ assert_equal('ac', 'abc'.sub(/b/, {}))
+ assert_equal('a1c', 'abc'.sub(/b/, "b" => 1))
+ assert_equal('aBc', 'abc'.sub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', 'abc'.sub(/b/, "b" => '[\&]'))
+ assert_equal('aBcabc', 'abcabc'.sub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcdef', 'abcdef'.sub(/de|b/, "b" => "B", "de" => "DE"))
+ end
+
+ def test_gsub_hash
+ assert_equal('azc', 'abc'.gsub(/b/, "b" => "z"))
+ assert_equal('ac', 'abc'.gsub(/b/, {}))
+ assert_equal('a1c', 'abc'.gsub(/b/, "b" => 1))
+ assert_equal('aBc', 'abc'.gsub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', 'abc'.gsub(/b/, "b" => '[\&]'))
+ assert_equal('aBcaBc', 'abcabc'.gsub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcDEf', 'abcdef'.gsub(/de|b/, "b" => "B", "de" => "DE"))
+ end
+
+ def test_hash
+ assert_equal(S("hello").hash, S("hello").hash)
+ assert(S("hello").hash != S("helLO").hash)
+ end
+
+ def test_hash_random
+ str = 'abc'
+ a = [str.hash.to_s]
+ 3.times {
+ assert_in_out_err(["-e", "print #{str.dump}.hash"], "") do |r, e|
+ a += r
+ assert_equal([], e)
+ end
+ }
+ assert_not_equal([str.hash.to_s], a.uniq)
+ end
+
+ def test_hex
+ assert_equal(255, S("0xff").hex)
+ assert_equal(-255, S("-0xff").hex)
+ assert_equal(255, S("ff").hex)
+ assert_equal(-255, S("-ff").hex)
+ assert_equal(0, S("-ralph").hex)
+ assert_equal(-15, S("-fred").hex)
+ assert_equal(15, S("fred").hex)
+ end
+
+ def test_include?
+ assert( S("foobar").include?(?f))
+ assert( S("foobar").include?(S("foo")))
+ assert(!S("foobar").include?(S("baz")))
+ assert(!S("foobar").include?(?z))
+ end
+
+ def test_index
+ assert_equal(0, S("hello").index(?h))
+ assert_equal(1, S("hello").index(S("ell")))
+ assert_equal(2, S("hello").index(/ll./))
+
+ assert_equal(3, S("hello").index(?l, 3))
+ assert_equal(3, S("hello").index(S("l"), 3))
+ assert_equal(3, S("hello").index(/l./, 3))
+
+ assert_nil(S("hello").index(?z, 3))
+ assert_nil(S("hello").index(S("z"), 3))
+ assert_nil(S("hello").index(/z./, 3))
+
+ assert_nil(S("hello").index(?z))
+ assert_nil(S("hello").index(S("z")))
+ assert_nil(S("hello").index(/z./))
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_equal(3, "foobarbarbaz".index(o))
+ assert_raise(TypeError) { "foo".index(Object.new) }
+
+ assert_nil("foo".index(//, -100))
+ assert_nil($~)
+ end
+
+ def test_intern
+ assert_equal(:koala, S("koala").intern)
+ assert(:koala != S("Koala").intern)
+ end
+
+ def test_length
+ assert_equal(0, S("").length)
+ assert_equal(4, S("1234").length)
+ assert_equal(6, S("1234\r\n").length)
+ assert_equal(7, S("\0011234\r\n").length)
+ end
+
+ def test_ljust
+ assert_equal(S("hello"), S("hello").ljust(4))
+ assert_equal(S("hello "), S("hello").ljust(11))
+ end
+
+ def test_next
+ assert_equal(S("abd"), S("abc").next)
+ assert_equal(S("z"), S("y").next)
+ assert_equal(S("aaa"), S("zz").next)
+
+ assert_equal(S("124"), S("123").next)
+ assert_equal(S("1000"), S("999").next)
+
+ assert_equal(S("2000aaa"), S("1999zzz").next)
+ assert_equal(S("AAAAA000"), S("ZZZZ999").next)
+
+ assert_equal(S("*+"), S("**").next)
+ end
+
+ def test_next!
+ a = S("abc")
+ b = a.dup
+ assert_equal(S("abd"), a.next!)
+ assert_equal(S("abd"), a)
+ assert_equal(S("abc"), b)
+
+ a = S("y")
+ assert_equal(S("z"), a.next!)
+ assert_equal(S("z"), a)
+
+ a = S("zz")
+ assert_equal(S("aaa"), a.next!)
+ assert_equal(S("aaa"), a)
+
+ a = S("123")
+ assert_equal(S("124"), a.next!)
+ assert_equal(S("124"), a)
+
+ a = S("999")
+ assert_equal(S("1000"), a.next!)
+ assert_equal(S("1000"), a)
+
+ a = S("1999zzz")
+ assert_equal(S("2000aaa"), a.next!)
+ assert_equal(S("2000aaa"), a)
+
+ a = S("ZZZZ999")
+ assert_equal(S("AAAAA000"), a.next!)
+ assert_equal(S("AAAAA000"), a)
+
+ a = S("**")
+ assert_equal(S("*+"), a.next!)
+ assert_equal(S("*+"), a)
+ end
+
+ def test_oct
+ assert_equal(255, S("0377").oct)
+ assert_equal(255, S("377").oct)
+ assert_equal(-255, S("-0377").oct)
+ assert_equal(-255, S("-377").oct)
+ assert_equal(0, S("OO").oct)
+ assert_equal(24, S("030OO").oct)
+ end
+
+ def test_replace
+ a = S("foo")
+ assert_equal(S("f"), a.replace(S("f")))
+
+ a = S("foo")
+ assert_equal(S("foobar"), a.replace(S("foobar")))
+
+ a = S("foo")
+ a.taint
+ a.untrust
+ b = a.replace(S("xyz"))
+ assert_equal(S("xyz"), b)
+ assert(b.tainted?)
+ assert(b.untrusted?)
+
+ s = "foo" * 100
+ s2 = ("bar" * 100).dup
+ s.replace(s2)
+ assert_equal(s2, s)
+
+ s2 = ["foo"].pack("p")
+ s.replace(s2)
+ assert_equal(s2, s)
+ end
+
+ def test_reverse
+ assert_equal(S("beta"), S("ateb").reverse)
+ assert_equal(S("madamImadam"), S("madamImadam").reverse)
+
+ a=S("beta")
+ assert_equal(S("ateb"), a.reverse)
+ assert_equal(S("beta"), a)
+ end
+
+ def test_reverse!
+ a = S("beta")
+ b = a.dup
+ assert_equal(S("ateb"), a.reverse!)
+ assert_equal(S("ateb"), a)
+ assert_equal(S("beta"), b)
+
+ assert_equal(S("madamImadam"), S("madamImadam").reverse!)
+
+ a = S("madamImadam")
+ assert_equal(S("madamImadam"), a.reverse!) # ??
+ assert_equal(S("madamImadam"), a)
+ end
+
+ def test_rindex
+ assert_equal(3, S("hello").rindex(?l))
+ assert_equal(6, S("ell, hello").rindex(S("ell")))
+ assert_equal(7, S("ell, hello").rindex(/ll./))
+
+ assert_equal(3, S("hello,lo").rindex(?l, 3))
+ assert_equal(3, S("hello,lo").rindex(S("l"), 3))
+ assert_equal(3, S("hello,lo").rindex(/l./, 3))
+
+ assert_nil(S("hello").rindex(?z, 3))
+ assert_nil(S("hello").rindex(S("z"), 3))
+ assert_nil(S("hello").rindex(/z./, 3))
+
+ assert_nil(S("hello").rindex(?z))
+ assert_nil(S("hello").rindex(S("z")))
+ assert_nil(S("hello").rindex(/z./))
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_equal(6, "foobarbarbaz".rindex(o))
+ assert_raise(TypeError) { "foo".rindex(Object.new) }
+
+ assert_nil("foo".rindex(//, -100))
+ assert_nil($~)
+ end
+
+ def test_rjust
+ assert_equal(S("hello"), S("hello").rjust(4))
+ assert_equal(S(" hello"), S("hello").rjust(11))
+ end
+
+ def test_scan
+ a = S("cruel world")
+ assert_equal([S("cruel"), S("world")],a.scan(/\w+/))
+ assert_equal([S("cru"), S("el "), S("wor")],a.scan(/.../))
+ assert_equal([[S("cru")], [S("el ")], [S("wor")]],a.scan(/(...)/))
+
+ res = []
+ a.scan(/\w+/) { |w| res << w }
+ assert_equal([S("cruel"), S("world") ],res)
+
+ res = []
+ a.scan(/.../) { |w| res << w }
+ assert_equal([S("cru"), S("el "), S("wor")],res)
+
+ res = []
+ a.scan(/(...)/) { |w| res << w }
+ assert_equal([[S("cru")], [S("el ")], [S("wor")]],res)
+ end
+
+ def test_size
+ assert_equal(0, S("").size)
+ assert_equal(4, S("1234").size)
+ assert_equal(6, S("1234\r\n").size)
+ assert_equal(7, S("\0011234\r\n").size)
+ end
+
+ def test_slice
+ assert_equal(?A, S("AooBar").slice(0))
+ assert_equal(?B, S("FooBaB").slice(-1))
+ assert_nil(S("FooBar").slice(6))
+ assert_nil(S("FooBar").slice(-7))
+
+ assert_equal(S("Foo"), S("FooBar").slice(0,3))
+ assert_equal(S(S("Bar")), S("FooBar").slice(-3,3))
+ assert_nil(S("FooBar").slice(7,2)) # Maybe should be six?
+ assert_nil(S("FooBar").slice(-7,10))
+
+ assert_equal(S("Foo"), S("FooBar").slice(0..2))
+ assert_equal(S("Bar"), S("FooBar").slice(-3..-1))
+ assert_equal(S(""), S("FooBar").slice(6..2))
+ assert_nil(S("FooBar").slice(-10..-7))
+
+ assert_equal(S("Foo"), S("FooBar").slice(/^F../))
+ assert_equal(S("Bar"), S("FooBar").slice(/..r$/))
+ assert_nil(S("FooBar").slice(/xyzzy/))
+ assert_nil(S("FooBar").slice(/plugh/))
+
+ assert_equal(S("Foo"), S("FooBar").slice(S("Foo")))
+ assert_equal(S("Bar"), S("FooBar").slice(S("Bar")))
+ assert_nil(S("FooBar").slice(S("xyzzy")))
+ assert_nil(S("FooBar").slice(S("plugh")))
+ end
+
+ def test_slice!
+ a = S("AooBar")
+ b = a.dup
+ assert_equal(?A, a.slice!(0))
+ assert_equal(S("ooBar"), a)
+ assert_equal(S("AooBar"), b)
+
+ a = S("FooBar")
+ assert_equal(?r,a.slice!(-1))
+ assert_equal(S("FooBa"), a)
+
+ a = S("FooBar")
+ if @aref_slicebang_silent
+ assert_nil( a.slice!(6) )
+ else
+ assert_raise(IndexError) { a.slice!(6) }
+ end
+ assert_equal(S("FooBar"), a)
+
+ if @aref_slicebang_silent
+ assert_nil( a.slice!(-7) )
+ else
+ assert_raise(IndexError) { a.slice!(-7) }
+ end
+ assert_equal(S("FooBar"), a)
+
+ a = S("FooBar")
+ assert_equal(S("Foo"), a.slice!(0,3))
+ assert_equal(S("Bar"), a)
+
+ a = S("FooBar")
+ assert_equal(S("Bar"), a.slice!(-3,3))
+ assert_equal(S("Foo"), a)
+
+ a=S("FooBar")
+ if @aref_slicebang_silent
+ assert_nil(a.slice!(7,2)) # Maybe should be six?
+ else
+ assert_raise(IndexError) {a.slice!(7,2)} # Maybe should be six?
+ end
+ assert_equal(S("FooBar"), a)
+ if @aref_slicebang_silent
+ assert_nil(a.slice!(-7,10))
+ else
+ assert_raise(IndexError) {a.slice!(-7,10)}
+ end
+ assert_equal(S("FooBar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Foo"), a.slice!(0..2))
+ assert_equal(S("Bar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Bar"), a.slice!(-3..-1))
+ assert_equal(S("Foo"), a)
+
+ a=S("FooBar")
+ if @aref_slicebang_silent
+ assert_equal(S(""), a.slice!(6..2))
+ else
+ assert_raise(RangeError) {a.slice!(6..2)}
+ end
+ assert_equal(S("FooBar"), a)
+ if @aref_slicebang_silent
+ assert_nil(a.slice!(-10..-7))
+ else
+ assert_raise(RangeError) {a.slice!(-10..-7)}
+ end
+ assert_equal(S("FooBar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Foo"), a.slice!(/^F../))
+ assert_equal(S("Bar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Bar"), a.slice!(/..r$/))
+ assert_equal(S("Foo"), a)
+
+ a=S("FooBar")
+ if @aref_slicebang_silent
+ assert_nil(a.slice!(/xyzzy/))
+ else
+ assert_raise(IndexError) {a.slice!(/xyzzy/)}
+ end
+ assert_equal(S("FooBar"), a)
+ if @aref_slicebang_silent
+ assert_nil(a.slice!(/plugh/))
+ else
+ assert_raise(IndexError) {a.slice!(/plugh/)}
+ end
+ assert_equal(S("FooBar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Foo"), a.slice!(S("Foo")))
+ assert_equal(S("Bar"), a)
+
+ a=S("FooBar")
+ assert_equal(S("Bar"), a.slice!(S("Bar")))
+ assert_equal(S("Foo"), a)
+
+ pre_1_7_1 do
+ a=S("FooBar")
+ assert_nil(a.slice!(S("xyzzy")))
+ assert_equal(S("FooBar"), a)
+ assert_nil(a.slice!(S("plugh")))
+ assert_equal(S("FooBar"), a)
+ end
+
+ assert_raise(ArgumentError) { "foo".slice! }
+ end
+
+ def test_split
+ assert_nil($;)
+ assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split)
+ assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split(S(" ")))
+
+ assert_equal([S(" a "), S(" b "), S(" c ")], S(" a | b | c ").split(S("|")))
+
+ assert_equal([S("a"), S("b"), S("c")], S("aXXbXXcXX").split(/X./))
+
+ assert_equal([S("a"), S("b"), S("c")], S("abc").split(//))
+
+ assert_equal([S("a|b|c")], S("a|b|c").split(S('|'), 1))
+
+ assert_equal([S("a"), S("b|c")], S("a|b|c").split(S('|'), 2))
+ assert_equal([S("a"), S("b"), S("c")], S("a|b|c").split(S('|'), 3))
+
+ assert_equal([S("a"), S("b"), S("c"), S("")], S("a|b|c|").split(S('|'), -1))
+ assert_equal([S("a"), S("b"), S("c"), S(""), S("")], S("a|b|c||").split(S('|'), -1))
+
+ assert_equal([S("a"), S(""), S("b"), S("c")], S("a||b|c|").split(S('|')))
+ assert_equal([S("a"), S(""), S("b"), S("c"), S("")], S("a||b|c|").split(S('|'), -1))
+
+ assert_equal([], "".split(//, 1))
+
+ assert_equal("[2, 3]", [1,2,3].slice!(1,10000).inspect, "moved from btest/knownbug")
+
+ end
+
+ def test_squeeze
+ assert_equal(S("abc"), S("aaabbbbccc").squeeze)
+ assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" ")))
+ assert_equal(S("BxTyWz"), S("BxxxTyyyWzzzzz").squeeze(S("a-z")))
+ end
+
+ def test_squeeze!
+ a = S("aaabbbbccc")
+ b = a.dup
+ assert_equal(S("abc"), a.squeeze!)
+ assert_equal(S("abc"), a)
+ assert_equal(S("aaabbbbccc"), b)
+
+ a = S("aa bb cc")
+ assert_equal(S("aa bb cc"), a.squeeze!(S(" ")))
+ assert_equal(S("aa bb cc"), a)
+
+ a = S("BxxxTyyyWzzzzz")
+ assert_equal(S("BxTyWz"), a.squeeze!(S("a-z")))
+ assert_equal(S("BxTyWz"), a)
+
+ a=S("The quick brown fox")
+ assert_nil(a.squeeze!)
+ end
+
+ def test_strip
+ assert_equal(S("x"), S(" x ").strip)
+ assert_equal(S("x"), S(" \n\r\t x \t\r\n\n ").strip)
+ end
+
+ def test_strip!
+ a = S(" x ")
+ b = a.dup
+ assert_equal(S("x") ,a.strip!)
+ assert_equal(S("x") ,a)
+ assert_equal(S(" x "), b)
+
+ a = S(" \n\r\t x \t\r\n\n ")
+ assert_equal(S("x"), a.strip!)
+ assert_equal(S("x"), a)
+
+ a = S("x")
+ assert_nil(a.strip!)
+ assert_equal(S("x") ,a)
+ end
+
+ def test_sub
+ assert_equal(S("h*llo"), S("hello").sub(/[aeiou]/, S('*')))
+ assert_equal(S("h<e>llo"), S("hello").sub(/([aeiou])/, S('<\1>')))
+ assert_equal(S("h ello"), S("hello").sub(/./) {
+ |s| s[0].to_s + S(' ')})
+ assert_equal(S("HELL-o"), S("hello").sub(/(hell)(.)/) {
+ |s| $1.upcase + S('-') + $2
+ })
+
+ assert_equal(S("a\\aba"), S("ababa").sub(/b/, '\\'))
+ assert_equal(S("ab\\aba"), S("ababa").sub(/(b)/, '\1\\'))
+ assert_equal(S("ababa"), S("ababa").sub(/(b)/, '\1'))
+ assert_equal(S("ababa"), S("ababa").sub(/(b)/, '\\1'))
+ assert_equal(S("a\\1aba"), S("ababa").sub(/(b)/, '\\\1'))
+ assert_equal(S("a\\1aba"), S("ababa").sub(/(b)/, '\\\\1'))
+ assert_equal(S("a\\baba"), S("ababa").sub(/(b)/, '\\\\\1'))
+
+ assert_equal(S("a--ababababababababab"),
+ S("abababababababababab").sub(/(b)/, '-\9-'))
+ assert_equal(S("1-b-0"),
+ S("1b2b3b4b5b6b7b8b9b0").
+ sub(/(b).(b).(b).(b).(b).(b).(b).(b).(b)/, '-\9-'))
+ assert_equal(S("1-b-0"),
+ S("1b2b3b4b5b6b7b8b9b0").
+ sub(/(b).(b).(b).(b).(b).(b).(b).(b).(b)/, '-\\9-'))
+ assert_equal(S("1-\\9-0"),
+ S("1b2b3b4b5b6b7b8b9b0").
+ sub(/(b).(b).(b).(b).(b).(b).(b).(b).(b)/, '-\\\9-'))
+ assert_equal(S("k"),
+ S("1a2b3c4d5e6f7g8h9iAjBk").
+ sub(/.(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.)/, '\+'))
+
+ assert_equal(S("ab\\aba"), S("ababa").sub(/b/, '\&\\'))
+ assert_equal(S("ababa"), S("ababa").sub(/b/, '\&'))
+ assert_equal(S("ababa"), S("ababa").sub(/b/, '\\&'))
+ assert_equal(S("a\\&aba"), S("ababa").sub(/b/, '\\\&'))
+ assert_equal(S("a\\&aba"), S("ababa").sub(/b/, '\\\\&'))
+ assert_equal(S("a\\baba"), S("ababa").sub(/b/, '\\\\\&'))
+
+ a = S("hello")
+ a.taint
+ a.untrust
+ x = a.sub(/./, S('X'))
+ assert(x.tainted?)
+ assert(x.untrusted?)
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_equal("fooBARbaz", "foobarbaz".sub(o, "BAR"))
+
+ assert_raise(TypeError) { "foo".sub(Object.new, "") }
+
+ assert_raise(ArgumentError) { "foo".sub }
+
+ assert_raise(IndexError) { "foo"[/(?:(o$)|(x))/, 2] = 'bar' }
+
+ o = Object.new
+ def o.to_s; self; end
+ assert_match(/^foo#<Object:0x.*>baz$/, "foobarbaz".sub("bar") { o })
+ end
+
+ def test_sub!
+ a = S("hello")
+ b = a.dup
+ a.sub!(/[aeiou]/, S('*'))
+ assert_equal(S("h*llo"), a)
+ assert_equal(S("hello"), b)
+
+ a = S("hello")
+ a.sub!(/([aeiou])/, S('<\1>'))
+ assert_equal(S("h<e>llo"), a)
+
+ a = S("hello")
+ a.sub!(/./) { |s| s[0].to_s + S(' ')}
+ assert_equal(S("h ello"), a)
+
+ a = S("hello")
+ a.sub!(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 }
+ assert_equal(S("HELL-o"), a)
+
+ a=S("hello")
+ assert_nil(a.sub!(/X/, S('Y')))
+
+ r = S('X')
+ r.taint
+ r.untrust
+ a.sub!(/./, r)
+ assert(a.tainted?)
+ assert(a.untrusted?)
+ end
+
+ def test_succ
+ assert_equal(S("abd"), S("abc").succ)
+ assert_equal(S("z"), S("y").succ)
+ assert_equal(S("aaa"), S("zz").succ)
+
+ assert_equal(S("124"), S("123").succ)
+ assert_equal(S("1000"), S("999").succ)
+ assert_equal(S("2.000"), S("1.999").succ)
+
+ assert_equal(S("No.10"), S("No.9").succ)
+ assert_equal(S("2000aaa"), S("1999zzz").succ)
+ assert_equal(S("AAAAA000"), S("ZZZZ999").succ)
+ assert_equal(S("*+"), S("**").succ)
+
+ assert_equal("abce", "abcd".succ)
+ assert_equal("THX1139", "THX1138".succ)
+ assert_equal("<<koalb>>", "<<koala>>".succ)
+ assert_equal("2000aaa", "1999zzz".succ)
+ assert_equal("AAAA0000", "ZZZ9999".succ)
+ assert_equal("**+", "***".succ)
+ end
+
+ def test_succ!
+ a = S("abc")
+ b = a.dup
+ assert_equal(S("abd"), a.succ!)
+ assert_equal(S("abd"), a)
+ assert_equal(S("abc"), b)
+
+ a = S("y")
+ assert_equal(S("z"), a.succ!)
+ assert_equal(S("z"), a)
+
+ a = S("zz")
+ assert_equal(S("aaa"), a.succ!)
+ assert_equal(S("aaa"), a)
+
+ a = S("123")
+ assert_equal(S("124"), a.succ!)
+ assert_equal(S("124"), a)
+
+ a = S("999")
+ assert_equal(S("1000"), a.succ!)
+ assert_equal(S("1000"), a)
+
+ a = S("1999zzz")
+ assert_equal(S("2000aaa"), a.succ!)
+ assert_equal(S("2000aaa"), a)
+
+ a = S("ZZZZ999")
+ assert_equal(S("AAAAA000"), a.succ!)
+ assert_equal(S("AAAAA000"), a)
+
+ a = S("**")
+ assert_equal(S("*+"), a.succ!)
+ assert_equal(S("*+"), a)
+
+ a = S("No.9")
+ assert_equal(S("No.10"), a.succ!)
+ assert_equal(S("No.10"), a)
+
+ assert_equal("aaaaaaaaaaaa", "zzzzzzzzzzz".succ!)
+ assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", "zzzzzzzzzzzzzzzzzzzzzzz".succ!)
+ end
+
+ def test_sum
+ n = S("\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001")
+ assert_equal(15, n.sum)
+ n += S("\001")
+ assert_equal(16, n.sum(17))
+ n[0] = 2.chr
+ assert(15 != n.sum)
+ end
+
+ def check_sum(str, bits=16)
+ sum = 0
+ str.each_byte {|c| sum += c}
+ sum = sum & ((1 << bits) - 1) if bits != 0
+ assert_equal(sum, str.sum(bits))
+ end
+
+ def test_sum_2
+ assert_equal(0, "".sum)
+ assert_equal(294, "abc".sum)
+ check_sum("abc")
+ check_sum("\x80")
+ 0.upto(70) {|bits|
+ check_sum("xyz", bits)
+ }
+ end
+
+ def test_swapcase
+ assert_equal(S("hi&LOW"), S("HI&low").swapcase)
+ end
+
+ def test_swapcase!
+ a = S("hi&LOW")
+ b = a.dup
+ assert_equal(S("HI&low"), a.swapcase!)
+ assert_equal(S("HI&low"), a)
+ assert_equal(S("hi&LOW"), b)
+
+ a = S("$^#^%$#!!")
+ assert_nil(a.swapcase!)
+ assert_equal(S("$^#^%$#!!"), a)
+ end
+
+ def test_to_f
+ assert_equal(344.3, S("344.3").to_f)
+ assert_equal(5.9742e24, S("5.9742e24").to_f)
+ assert_equal(98.6, S("98.6 degrees").to_f)
+ assert_equal(0.0, S("degrees 100.0").to_f)
+ end
+
+ def test_to_i
+ assert_equal(1480, S("1480ft/sec").to_i)
+ assert_equal(0, S("speed of sound in water @20C = 1480ft/sec)").to_i)
+ assert_equal(0, " 0".to_i)
+ assert_equal(0, "+0".to_i)
+ assert_equal(0, "-0".to_i)
+ assert_equal(0, "--0".to_i)
+ assert_equal(16, "0x10".to_i(0))
+ assert_equal(16, "0X10".to_i(0))
+ assert_equal(2, "0b10".to_i(0))
+ assert_equal(2, "0B10".to_i(0))
+ assert_equal(8, "0o10".to_i(0))
+ assert_equal(8, "0O10".to_i(0))
+ assert_equal(10, "0d10".to_i(0))
+ assert_equal(10, "0D10".to_i(0))
+ assert_equal(8, "010".to_i(0))
+ assert_raise(ArgumentError) { "010".to_i(-10) }
+ 2.upto(36) {|radix|
+ assert_equal(radix, "10".to_i(radix))
+ assert_equal(radix**2, "100".to_i(radix))
+ }
+ assert_raise(ArgumentError) { "0".to_i(1) }
+ assert_raise(ArgumentError) { "0".to_i(37) }
+ assert_equal(0, "z".to_i(10))
+ assert_equal(12, "1_2".to_i(10))
+ assert_equal(0x40000000, "1073741824".to_i(10))
+ assert_equal(0x4000000000000000, "4611686018427387904".to_i(10))
+ assert_equal(1, "1__2".to_i(10))
+ assert_equal(1, "1_z".to_i(10))
+ end
+
+ def test_to_s
+ a = S("me")
+ assert_equal("me", a.to_s)
+ assert_equal(a.__id__, a.to_s.__id__) if @cls == String
+ end
+
+ def test_to_str
+ a = S("me")
+ assert_equal("me", a.to_s)
+ assert_equal(a.__id__, a.to_s.__id__) if @cls == String
+ end
+
+ def test_tr
+ assert_equal(S("hippo"), S("hello").tr(S("el"), S("ip")))
+ assert_equal(S("*e**o"), S("hello").tr(S("^aeiou"), S("*")))
+ assert_equal(S("hal"), S("ibm").tr(S("b-z"), S("a-z")))
+ end
+
+ def test_tr!
+ a = S("hello")
+ b = a.dup
+ assert_equal(S("hippo"), a.tr!(S("el"), S("ip")))
+ assert_equal(S("hippo"), a)
+ assert_equal(S("hello"),b)
+
+ a = S("hello")
+ assert_equal(S("*e**o"), a.tr!(S("^aeiou"), S("*")))
+ assert_equal(S("*e**o"), a)
+
+ a = S("IBM")
+ assert_equal(S("HAL"), a.tr!(S("B-Z"), S("A-Z")))
+ assert_equal(S("HAL"), a)
+
+ a = S("ibm")
+ assert_nil(a.tr!(S("B-Z"), S("A-Z")))
+ assert_equal(S("ibm"), a)
+ end
+
+ def test_tr_s
+ assert_equal(S("hypo"), S("hello").tr_s(S("el"), S("yp")))
+ assert_equal(S("h*o"), S("hello").tr_s(S("el"), S("*")))
+ end
+
+ def test_tr_s!
+ a = S("hello")
+ b = a.dup
+ assert_equal(S("hypo"), a.tr_s!(S("el"), S("yp")))
+ assert_equal(S("hypo"), a)
+ assert_equal(S("hello"), b)
+
+ a = S("hello")
+ assert_equal(S("h*o"), a.tr_s!(S("el"), S("*")))
+ assert_equal(S("h*o"), a)
+ end
+
+ def test_unpack
+ a = [S("cat"), S("wom"), S("x"), S("yy")]
+ assert_equal(a, S("catwomx yy ").unpack(S("A3A3A3A3")))
+
+ assert_equal([S("cat")], S("cat \000\000").unpack(S("A*")))
+ assert_equal([S("cwx"), S("wx"), S("x"), S("yy")],
+ S("cwx yy ").unpack(S("A3@1A3@2A3A3")))
+ assert_equal([S("cat"), S("wom"), S("x\000\000"), S("yy\000")],
+ S("catwomx\000\000yy\000").unpack(S("a3a3a3a3")))
+ assert_equal([S("cat \000\000")], S("cat \000\000").unpack(S("a*")))
+ assert_equal([S("ca")], S("catdog").unpack(S("a2")))
+
+ assert_equal([S("cat\000\000")],
+ S("cat\000\000\000\000\000dog").unpack(S("a5")))
+
+ assert_equal([S("01100001")], S("\x61").unpack(S("B8")))
+ assert_equal([S("01100001")], S("\x61").unpack(S("B*")))
+ assert_equal([S("0110000100110111")], S("\x61\x37").unpack(S("B16")))
+ assert_equal([S("01100001"), S("00110111")], S("\x61\x37").unpack(S("B8B8")))
+ assert_equal([S("0110")], S("\x60").unpack(S("B4")))
+
+ assert_equal([S("01")], S("\x40").unpack(S("B2")))
+
+ assert_equal([S("01100001")], S("\x86").unpack(S("b8")))
+ assert_equal([S("01100001")], S("\x86").unpack(S("b*")))
+
+ assert_equal([S("0110000100110111")], S("\x86\xec").unpack(S("b16")))
+ assert_equal([S("01100001"), S("00110111")], S("\x86\xec").unpack(S("b8b8")))
+
+ assert_equal([S("0110")], S("\x06").unpack(S("b4")))
+ assert_equal([S("01")], S("\x02").unpack(S("b2")))
+
+ assert_equal([ 65, 66, 67 ], S("ABC").unpack(S("C3")))
+ assert_equal([ 255, 66, 67 ], S("\377BC").unpack("C*"))
+ assert_equal([ 65, 66, 67 ], S("ABC").unpack("c3"))
+ assert_equal([ -1, 66, 67 ], S("\377BC").unpack("c*"))
+
+
+ assert_equal([S("4142"), S("0a"), S("1")], S("AB\n\x10").unpack(S("H4H2H1")))
+ assert_equal([S("1424"), S("a0"), S("2")], S("AB\n\x02").unpack(S("h4h2h1")))
+
+ assert_equal([S("abc\002defcat\001"), S(""), S("")],
+ S("abc=02def=\ncat=\n=01=\n").unpack(S("M9M3M4")))
+
+ assert_equal([S("hello\n")], S("aGVsbG8K\n").unpack(S("m")))
+
+ assert_equal([S("hello\nhello\n")], S(",:&5L;&\\*:&5L;&\\*\n").unpack(S("u")))
+
+ assert_equal([0xa9, 0x42, 0x2260], S("\xc2\xa9B\xe2\x89\xa0").unpack(S("U*")))
+
+=begin
+ skipping "Not tested:
+ D,d & double-precision float, native format\\
+ E & double-precision float, little-endian byte order\\
+ e & single-precision float, little-endian byte order\\
+ F,f & single-precision float, native format\\
+ G & double-precision float, network (big-endian) byte order\\
+ g & single-precision float, network (big-endian) byte order\\
+ I & unsigned integer\\
+ i & integer\\
+ L & unsigned long\\
+ l & long\\
+
+ m & string encoded in base64 (uuencoded)\\
+ N & long, network (big-endian) byte order\\
+ n & short, network (big-endian) byte-order\\
+ P & pointer to a structure (fixed-length string)\\
+ p & pointer to a null-terminated string\\
+ S & unsigned short\\
+ s & short\\
+ V & long, little-endian byte order\\
+ v & short, little-endian byte order\\
+ X & back up a byte\\
+ x & null byte\\
+ Z & ASCII string (null padded, count is width)\\
+"
+=end
+ end
+
+ def test_upcase
+ assert_equal(S("HELLO"), S("hello").upcase)
+ assert_equal(S("HELLO"), S("hello").upcase)
+ assert_equal(S("HELLO"), S("HELLO").upcase)
+ assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase)
+ end
+
+ def test_upcase!
+ a = S("hello")
+ b = a.dup
+ assert_equal(S("HELLO"), a.upcase!)
+ assert_equal(S("HELLO"), a)
+ assert_equal(S("hello"), b)
+
+ a = S("HELLO")
+ assert_nil(a.upcase!)
+ assert_equal(S("HELLO"), a)
+ end
+
+ def test_upto
+ a = S("aa")
+ start = S("aa")
+ count = 0
+ assert_equal(S("aa"), a.upto(S("zz")) {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(676, count)
+ end
+
+ def test_mod_check
+ assert_raise(RuntimeError) {
+ s = ""
+ s.sub!(/\A/) { s.replace "z" * 2000; "zzz" }
+ }
+ end
+
+ def test_frozen_check
+ assert_raise(RuntimeError) {
+ s = ""
+ s.sub!(/\A/) { s.freeze; "zzz" }
+ }
+ end
+
+ def test_tainted_str_new
+ a = []
+ a << a
+ s = a.inspect
+ assert(s.tainted?)
+ assert_equal("[[...]]", s)
+ end
+
+ class S2 < String
+ end
+ def test_str_new4
+ s = (0..54).to_a.join # length = 100
+ s2 = S2.new(s[10,90])
+ s3 = s2[10,80]
+ assert_equal((10..54).to_a.to_a.join, s2)
+ assert_equal((15..54).to_a.to_a.join, s3)
+ end
+
+ def test_rb_str_new4
+ s = "a" * 100
+ s2 = s[10,90]
+ assert_equal("a" * 90, s2)
+ s3 = s2[10,80]
+ assert_equal("a" * 80, s3)
+ end
+
+ class StringLike
+ def initialize(str)
+ @str = str
+ end
+
+ def to_str
+ @str
+ end
+ end
+
+ def test_rb_str_to_str
+ assert_equal("ab", "a" + StringLike.new("b"))
+ end
+
+ def test_rb_str_shared_replace
+ s = "a" * 100
+ s.succ!
+ assert_equal("a" * 99 + "b", s)
+ s = ""
+ s.succ!
+ assert_equal("", s)
+ end
+
+ def test_times
+ assert_raise(ArgumentError) { "a" * (-1) }
+ end
+
+ def test_splice!
+ l = S("1234\n234\n34\n4\n")
+ assert_equal(S("1234\n"), l.slice!(/\A.*\n/), "[ruby-dev:31665]")
+ assert_equal(S("234\n"), l.slice!(/\A.*\n/), "[ruby-dev:31665]")
+ assert_equal(S("34\n"), l.slice!(/\A.*\n/), "[ruby-dev:31665]")
+ assert_equal(S("4\n"), l.slice!(/\A.*\n/), "[ruby-dev:31665]")
+ assert_nil(l.slice!(/\A.*\n/), "[ruby-dev:31665]")
+ end
+
+ def test_end_with?
+ assert("abc".end_with?("c"))
+ end
+
+ def test_times2
+ s1 = ''
+ 100.times {|n|
+ s2 = "a" * n
+ assert_equal(s1, s2)
+ s1 << 'a'
+ }
+
+ assert_raise(ArgumentError) { "foo" * (-1) }
+ end
+
+ def test_respond_to
+ o = Object.new
+ def o.respond_to?(arg) [:to_str].include?(arg) ? nil : super end
+ def o.to_str() "" end
+ def o.==(other) "" == other end
+ assert_equal(false, "" == o)
+ end
+
+ def test_match_method
+ assert_equal("bar", "foobarbaz".match(/bar/).to_s)
+
+ o = /foo/
+ def o.match(x, y, z); x + y + z; end
+ assert_equal("foobarbaz", "foo".match(o, "bar", "baz"))
+ x = nil
+ "foo".match(o, "bar", "baz") {|y| x = y }
+ assert_equal("foobarbaz", x)
+
+ assert_raise(ArgumentError) { "foo".match }
+ end
+
+ def test_clear
+ s = "foo" * 100
+ s.clear
+ assert_equal("", s)
+ end
+
+ def test_to_s_2
+ c = Class.new(String)
+ s = c.new
+ s.replace("foo")
+ assert_equal("foo", s.to_s)
+ assert_instance_of(String, s.to_s)
+ end
+
+ def test_partition
+ assert_equal(%w(he l lo), "hello".partition(/l/))
+ assert_equal(%w(he l lo), "hello".partition("l"))
+ assert_raise(TypeError) { "hello".partition(1) }
+ end
+
+ def test_rpartition
+ assert_equal(%w(hel l o), "hello".rpartition(/l/))
+ assert_equal(%w(hel l o), "hello".rpartition("l"))
+ assert_raise(TypeError) { "hello".rpartition(1) }
+ end
+
+ def test_setter
+ assert_raise(TypeError) { $/ = 1 }
+ end
+
+ def test_to_id
+ c = Class.new
+ c.class_eval do
+ def initialize
+ @foo = :foo
+ end
+ end
+
+ assert_raise(TypeError) do
+ c.class_eval { attr 1 }
+ end
+
+ o = Object.new
+ def o.to_str; :foo; end
+ assert_raise(TypeError) do
+ c.class_eval { attr 1 }
+ end
+
+ def o.to_str; "foo"; end
+ assert_nothing_raised do
+ c.class_eval { attr o }
+ end
+ assert_equal(:foo, c.new.foo)
+ end
+
+ def test_gsub_enumerator
+ assert_normal_exit %q{"abc".gsub(/./).next}, "[ruby-dev:34828]"
+ end
+end
diff --git a/trunk/test/ruby/test_stringchar.rb b/trunk/test/ruby/test_stringchar.rb
new file mode 100644
index 0000000000..184e221211
--- /dev/null
+++ b/trunk/test/ruby/test_stringchar.rb
@@ -0,0 +1,166 @@
+require 'test/unit'
+
+class TestStringchar < Test::Unit::TestCase
+ def test_string
+ assert_equal("abcd", "abcd")
+ assert_match(/abcd/, "abcd")
+ assert("abcd" === "abcd")
+ # compile time string concatenation
+ assert_equal("abcd", "ab" "cd")
+ assert_equal("22aacd44", "#{22}aa" "cd#{44}")
+ assert_equal("22aacd445566", "#{22}aa" "cd#{44}" "55" "#{66}")
+ assert("abc" !~ /^$/)
+ assert("abc\n" !~ /^$/)
+ assert("abc" !~ /^d*$/)
+ assert_equal(3, ("abc" =~ /d*$/))
+ assert("" =~ /^$/)
+ assert("\n" =~ /^$/)
+ assert("a\n\n" =~ /^$/)
+ assert("abcabc" =~ /.*a/); assert_equal("abca", $&)
+ assert("abcabc" =~ /.*c/); assert_equal("abcabc", $&)
+ assert("abcabc" =~ /.*?a/); assert_equal("a", $&)
+ assert("abcabc" =~ /.*?c/); assert_equal("abc", $&)
+ assert(/(.|\n)*?\n(b|\n)/ =~ "a\nb\n\n"); assert_equal("a\nb", $&)
+
+ assert(/^(ab+)+b/ =~ "ababb"); assert_equal("ababb", $&)
+ assert(/^(?:ab+)+b/ =~ "ababb"); assert_equal("ababb", $&)
+ assert(/^(ab+)+/ =~ "ababb"); assert_equal("ababb", $&)
+ assert(/^(?:ab+)+/ =~ "ababb"); assert_equal("ababb", $&)
+
+ assert(/(\s+\d+){2}/ =~ " 1 2"); assert_equal(" 1 2", $&)
+ assert(/(?:\s+\d+){2}/ =~ " 1 2"); assert_equal(" 1 2", $&)
+
+ $x = <<END;
+ABCD
+ABCD
+END
+ $x.gsub!(/((.|\n)*?)B((.|\n)*?)D/m ,'\1\3')
+ assert_equal("AC\nAC\n", $x)
+
+ assert("foobar" =~ /foo(?=(bar)|(baz))/)
+ assert("foobaz" =~ /foo(?=(bar)|(baz))/)
+
+ $foo = "abc"
+ assert_equal("abc = abc", "#$foo = abc")
+ assert_equal("abc = abc", "#{$foo} = abc")
+
+ foo = "abc"
+ assert_equal("abc = abc", "#{foo} = abc")
+
+ assert_equal('-----', '-' * 5)
+ assert_equal('-', '-' * 1)
+ assert_equal('', '-' * 0)
+
+ foo = '-'
+ assert_equal('-----', foo * 5)
+ assert_equal('-', foo * 1)
+ assert_equal('', foo * 0)
+
+ $x = "a.gif"
+ assert_equal("gif", $x.sub(/.*\.([^\.]+)$/, '\1'))
+ assert_equal("b.gif", $x.sub(/.*\.([^\.]+)$/, 'b.\1'))
+ assert_equal("", $x.sub(/.*\.([^\.]+)$/, '\2'))
+ assert_equal("ab", $x.sub(/.*\.([^\.]+)$/, 'a\2b'))
+ assert_equal("<a.gif>", $x.sub(/.*\.([^\.]+)$/, '<\&>'))
+ end
+
+ def test_char
+ # character constants(assumes ASCII)
+ assert_equal(?a, "a"[0])
+ assert_equal(?a, ?a)
+ assert_equal("\1", ?\C-a)
+ assert_equal("\341", ?\M-a)
+ assert_equal("\201", ?\M-\C-a)
+ assert_equal(?A, "a".upcase![0])
+ assert_equal(?a, "A".downcase![0])
+ assert_equal("ABC", "abc".tr!("a-z", "A-Z"))
+ assert_equal("ABC", "aabbcccc".tr_s!("a-z", "A-Z"))
+ assert_equal("abc", "abcc".squeeze!("a-z"))
+ assert_equal("ad", "abcd".delete!("bc"))
+
+ $x = "abcdef"
+ $y = [ ?a, ?b, ?c, ?d, ?e, ?f ]
+ $bad = false
+ $x.each_byte {|i|
+ if i.chr != $y.shift
+ $bad = true
+ break
+ end
+ }
+ assert(!$bad)
+
+ s = "a string"
+ s[0..s.size]="another string"
+ assert_equal("another string", s)
+
+ s = <<EOS
+#{
+[1,2,3].join(",")
+}
+EOS
+ assert_equal("1,2,3\n", s)
+ assert_equal(926381, "Just".to_i(36))
+ assert_equal(-23200231779, "-another".to_i(36))
+ assert_equal("ruby", 1299022.to_s(36))
+ assert_equal("-hacker", -1045307475.to_s(36))
+ assert_equal(265419172580680477752431643787347, "Just_another_Ruby_hacker".to_i(36))
+ assert_equal("-justanotherrubyhacker", -265419172580680477752431643787347.to_s(36))
+
+ a = []
+ (0..255).each {|n|
+ ch = [n].pack("C")
+ a.push ch if /a#{Regexp.quote ch}b/x =~ "ab"
+ }
+ assert_equal(0, a.size)
+ end
+
+ def test_bang
+ s = "aBc"
+ s.upcase
+ assert_equal("aBc", s)
+ s.upcase!
+ assert_equal("ABC", s)
+
+ s = "aBc"
+ s.downcase
+ assert_equal("aBc", s)
+ s.downcase!
+ assert_equal("abc", s)
+
+ s = "aBc"
+ s.swapcase
+ assert_equal("aBc", s)
+ s.swapcase!
+ assert_equal("AbC", s)
+
+ s = "aBc"
+ s.capitalize
+ assert_equal("aBc", s)
+ s.capitalize!
+ assert_equal("Abc", s)
+
+ s = "aBc"
+ s.tr("a-z", "A-Z")
+ assert_equal("aBc", s)
+ s.tr!("a-z", "A-Z")
+ assert_equal("ABC", s)
+
+ s = "aaBBcc"
+ s.tr_s("a-z", "A-Z")
+ assert_equal("aaBBcc", s)
+ s.tr_s!("a-z", "A-Z")
+ assert_equal("ABBC", s)
+
+ s = "aaBBcc"
+ s.squeeze("a-z")
+ assert_equal("aaBBcc", s)
+ s.squeeze!("a-z")
+ assert_equal("aBBc", s)
+
+ s = "aaBBcc"
+ s.delete("a-z")
+ assert_equal("aaBBcc", s)
+ s.delete!("a-z")
+ assert_equal("BB", s)
+ end
+end
diff --git a/trunk/test/ruby/test_struct.rb b/trunk/test/ruby/test_struct.rb
new file mode 100644
index 0000000000..6c0e1f4fb2
--- /dev/null
+++ b/trunk/test/ruby/test_struct.rb
@@ -0,0 +1,215 @@
+require 'test/unit'
+
+class TestStruct < Test::Unit::TestCase
+ def test_struct
+ struct_test = Struct.new("Test", :foo, :bar)
+ assert_equal(Struct::Test, struct_test)
+
+ test = struct_test.new(1, 2)
+ assert_equal(1, test.foo)
+ assert_equal(2, test.bar)
+ assert_equal(1, test[0])
+ assert_equal(2, test[1])
+
+ a, b = test.to_a
+ assert_equal(1, a)
+ assert_equal(2, b)
+
+ test[0] = 22
+ assert_equal(22, test.foo)
+
+ test.bar = 47
+ assert_equal(47, test.bar)
+ end
+
+ # [ruby-dev:26247] more than 10 struct members causes segmentation fault
+ def test_morethan10members
+ list = %w( a b c d e f g h i j k l m n o p )
+ until list.empty?
+ c = Struct.new(* list.map {|ch| ch.intern }).new
+ list.each do |ch|
+ c.__send__(ch)
+ end
+ list.pop
+ end
+ end
+
+ def test_small_structs
+ names = [:a, :b, :c, :d]
+ 1.upto(4) {|n|
+ fields = names[0, n]
+ klass = Struct.new(*fields)
+ o = klass.new(*(0...n).to_a)
+ fields.each_with_index {|name, i|
+ assert_equal(i, o[name])
+ }
+ o = klass.new(*(0...n).to_a.reverse)
+ fields.each_with_index {|name, i|
+ assert_equal(n-i-1, o[name])
+ }
+ }
+ end
+
+ def test_inherit
+ klass = Struct.new(:a)
+ klass2 = Class.new(klass)
+ o = klass2.new(1)
+ assert_equal(1, o.a)
+ end
+
+ def test_members
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal([:a], klass.members)
+ assert_equal([:a], o.members)
+ end
+
+ def test_ref
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal(1, o[:a])
+ assert_raise(NameError) { o[:b] }
+ end
+
+ def test_modify
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_raise(SecurityError) do
+ Thread.new do
+ $SAFE = 4
+ o.a = 2
+ end.value
+ end
+ end
+
+ def test_set
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ o[:a] = 2
+ assert_equal(2, o[:a])
+ assert_raise(NameError) { o[:b] = 3 }
+ end
+
+ def test_struct_new
+ assert_raise(NameError) { Struct.new("foo") }
+ assert_nothing_raised { Struct.new("Foo") }
+ Struct.instance_eval { remove_const(:Foo) }
+ assert_nothing_raised { Struct.new(:a) { } }
+ assert_raise(RuntimeError) { Struct.new(:a) { raise } }
+
+ assert_equal([:utime, :stime, :cutime, :cstime], Process.times.members)
+ end
+
+ def test_initialize
+ klass = Struct.new(:a)
+ assert_raise(ArgumentError) { klass.new(1, 2) }
+ end
+
+ def test_each
+ klass = Struct.new(:a, :b)
+ o = klass.new(1, 2)
+ assert_equal([1, 2], o.each.to_a)
+ end
+
+ def test_each_pair
+ klass = Struct.new(:a, :b)
+ o = klass.new(1, 2)
+ assert_equal([[:a, 1], [:b, 2]], o.each_pair.to_a)
+ end
+
+ def test_inspect
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal("#<struct a=1>", o.inspect)
+ o.a = o
+ assert(o.inspect =~ /^#<struct a=#<struct #<.*?>:...>>$/)
+
+ Struct.new("Foo", :a)
+ o = Struct::Foo.new(1)
+ assert_equal("#<struct Struct::Foo a=1>", o.inspect)
+ Struct.instance_eval { remove_const(:Foo) }
+
+ klass = Struct.new(:a, :b)
+ o = klass.new(1, 2)
+ assert_equal("#<struct a=1, b=2>", o.inspect)
+
+ klass = Struct.new(:@a)
+ o = klass.new(1)
+ assert_equal("#<struct :@a=1>", o.inspect)
+ end
+
+ def test_init_copy
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal(o, o.dup)
+ end
+
+ def test_aref
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal(1, o[0])
+ assert_raise(IndexError) { o[-2] }
+ assert_raise(IndexError) { o[1] }
+ end
+
+ def test_aset
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ o[0] = 2
+ assert_equal(2, o[:a])
+ assert_raise(IndexError) { o[-2] = 3 }
+ assert_raise(IndexError) { o[1] = 3 }
+ end
+
+ def test_values_at
+ klass = Struct.new(:a, :b, :c, :d, :e, :f)
+ o = klass.new(1, 2, 3, 4, 5, 6)
+ assert_equal([2, 4, 6], o.values_at(1, 3, 5))
+ assert_equal([2, 3, 4, 3, 4, 5], o.values_at(1..3, 2...5))
+ end
+
+ def test_select
+ klass = Struct.new(:a, :b, :c, :d, :e, :f)
+ o = klass.new(1, 2, 3, 4, 5, 6)
+ assert_equal([1, 3, 5], o.select {|v| v % 2 != 0 })
+ assert_raise(ArgumentError) { o.select(1) }
+ end
+
+ def test_equal
+ klass1 = Struct.new(:a)
+ klass2 = Struct.new(:a, :b)
+ o1 = klass1.new(1)
+ o2 = klass1.new(1)
+ o3 = klass2.new(1)
+ assert(o1.==(o2))
+ assert(o1 != o3)
+ end
+
+ def test_hash
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert(o.hash.is_a?(Fixnum))
+ end
+
+ def test_eql
+ klass1 = Struct.new(:a)
+ klass2 = Struct.new(:a, :b)
+ o1 = klass1.new(1)
+ o2 = klass1.new(1)
+ o3 = klass2.new(1)
+ assert(o1.eql?(o2))
+ assert(!(o1.eql?(o3)))
+ end
+
+ def test_size
+ klass = Struct.new(:a)
+ o = klass.new(1)
+ assert_equal(1, o.size)
+ end
+
+ def test_error
+ assert_raise(TypeError){
+ Struct.new(0)
+ }
+ end
+end
diff --git a/trunk/test/ruby/test_super.rb b/trunk/test/ruby/test_super.rb
new file mode 100644
index 0000000000..5e93074e2d
--- /dev/null
+++ b/trunk/test/ruby/test_super.rb
@@ -0,0 +1,134 @@
+require 'test/unit'
+
+class TestSuper < Test::Unit::TestCase
+ class Base
+ def single(a) a end
+ def double(a, b) [a,b] end
+ def array(*a) a end
+ def optional(a = 0) a end
+ end
+ class Single1 < Base
+ def single(*) super end
+ end
+ class Single2 < Base
+ def single(a,*) super end
+ end
+ class Double1 < Base
+ def double(*) super end
+ end
+ class Double2 < Base
+ def double(a,*) super end
+ end
+ class Double3 < Base
+ def double(a,b,*) super end
+ end
+ class Array1 < Base
+ def array(*) super end
+ end
+ class Array2 < Base
+ def array(a,*) super end
+ end
+ class Array3 < Base
+ def array(a,b,*) super end
+ end
+ class Array4 < Base
+ def array(a,b,c,*) super end
+ end
+ class Optional1 < Base
+ def optional(a = 1) super end
+ end
+ class Optional2 < Base
+ def optional(a, b = 1) super end
+ end
+ class Optional3 < Base
+ def single(a = 1) super end
+ end
+ class Optional4 < Base
+ def array(a = 1, *) super end
+ end
+ class Optional5 < Base
+ def array(a = 1, b = 2, *) super end
+ end
+
+ def test_single1
+ assert_equal(1, Single1.new.single(1))
+ end
+ def test_single2
+ assert_equal(1, Single2.new.single(1))
+ end
+ def test_double1
+ assert_equal([1, 2], Double1.new.double(1, 2))
+ end
+ def test_double2
+ assert_equal([1, 2], Double2.new.double(1, 2))
+ end
+ def test_double3
+ assert_equal([1, 2], Double3.new.double(1, 2))
+ end
+ def test_array1
+ assert_equal([], Array1.new.array())
+ assert_equal([1], Array1.new.array(1))
+ end
+ def test_array2
+ assert_equal([1], Array2.new.array(1))
+ assert_equal([1,2], Array2.new.array(1, 2))
+ end
+ def test_array3
+ assert_equal([1,2], Array3.new.array(1, 2))
+ assert_equal([1,2,3], Array3.new.array(1, 2, 3))
+ end
+ def test_array4
+ assert_equal([1,2,3], Array4.new.array(1, 2, 3))
+ assert_equal([1,2,3,4], Array4.new.array(1, 2, 3, 4))
+ end
+ def test_optional1
+ assert_equal(9, Optional1.new.optional(9))
+ assert_equal(1, Optional1.new.optional)
+ end
+ def test_optional2
+ assert_raise(ArgumentError) do
+ # call Base#optional with 2 arguments; the 2nd arg is supplied
+ assert_equal(9, Optional2.new.optional(9))
+ end
+ assert_raise(ArgumentError) do
+ # call Base#optional with 2 arguments
+ assert_equal(9, Optional2.new.optional(9, 2))
+ end
+ end
+ def test_optional3
+ assert_equal(9, Optional3.new.single(9))
+ # call Base#single with 1 argument; the arg is supplied
+ assert_equal(1, Optional3.new.single)
+ end
+ def test_optional4
+ assert_equal([1], Optional4.new.array)
+ assert_equal([9], Optional4.new.array(9))
+ assert_equal([9, 8], Optional4.new.array(9, 8))
+ end
+ def test_optional5
+ assert_equal([1, 2], Optional5.new.array)
+ assert_equal([9, 2], Optional5.new.array(9))
+ assert_equal([9, 8], Optional5.new.array(9, 8))
+ assert_equal([9, 8, 7], Optional5.new.array(9, 8, 7))
+ end
+
+ class A
+ def tt(aa)
+ "A#tt"
+ end
+
+ def uu(a)
+ class << self
+ define_method(:tt) do |sym|
+ super(sym)
+ end
+ end
+ end
+ end
+
+ def test_define_method
+ a = A.new
+ a.uu(12)
+ assert_equal("A#tt", a.tt(12), "[ruby-core:3856]")
+ end
+end
diff --git a/trunk/test/ruby/test_symbol.rb b/trunk/test/ruby/test_symbol.rb
new file mode 100644
index 0000000000..a19a78e605
--- /dev/null
+++ b/trunk/test/ruby/test_symbol.rb
@@ -0,0 +1,135 @@
+require 'test/unit'
+
+class TestSymbol < Test::Unit::TestCase
+ # [ruby-core:3573]
+
+ def assert_eval_inspected(sym)
+ n = sym.inspect
+ assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(n))}
+ end
+
+ def test_inspect_invalid
+ # 2) Symbol#inspect sometimes returns invalid symbol representations:
+ assert_eval_inspected(:"!")
+ assert_eval_inspected(:"=")
+ assert_eval_inspected(:"0")
+ assert_eval_inspected(:"$1")
+ assert_eval_inspected(:"@1")
+ assert_eval_inspected(:"@@1")
+ assert_eval_inspected(:"@")
+ assert_eval_inspected(:"@@")
+ end
+
+ def assert_inspect_evaled(n)
+ assert_nothing_raised(SyntaxError) {assert_equal(n, eval(n).inspect)}
+ end
+
+ def test_inspect_suboptimal
+ # 3) Symbol#inspect sometimes returns suboptimal symbol representations:
+ assert_inspect_evaled(':foo')
+ assert_inspect_evaled(':foo!')
+ assert_inspect_evaled(':bar?')
+ assert_inspect_evaled(':<<')
+ assert_inspect_evaled(':>>')
+ assert_inspect_evaled(':<=')
+ assert_inspect_evaled(':>=')
+ assert_inspect_evaled(':=~')
+ assert_inspect_evaled(':==')
+ assert_inspect_evaled(':===')
+ assert_raise(SyntaxError) {eval ':='}
+ assert_inspect_evaled(':*')
+ assert_inspect_evaled(':**')
+ assert_raise(SyntaxError) {eval ':***'}
+ assert_inspect_evaled(':+')
+ assert_inspect_evaled(':-')
+ assert_inspect_evaled(':+@')
+ assert_inspect_evaled(':-@')
+ assert_inspect_evaled(':|')
+ assert_inspect_evaled(':^')
+ assert_inspect_evaled(':&')
+ assert_inspect_evaled(':/')
+ assert_inspect_evaled(':%')
+ assert_inspect_evaled(':~')
+ assert_inspect_evaled(':`')
+ assert_inspect_evaled(':[]')
+ assert_inspect_evaled(':[]=')
+ assert_raise(SyntaxError) {eval ':||'}
+ assert_raise(SyntaxError) {eval ':&&'}
+ assert_raise(SyntaxError) {eval ':['}
+ end
+
+ def test_inspect_dollar
+ # 4) :$- always treats next character literally:
+ sym = "$-".intern
+ assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(':$-'))}
+ assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(":$-\n"))}
+ assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(":$- "))}
+ assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(":$-#"))}
+ assert_raise(SyntaxError) {eval ':$-('}
+ end
+
+ def test_inspect_number
+ # 5) Inconsistency between :$0 and :$1? The first one is valid, but the
+ # latter isn't.
+ assert_inspect_evaled(':$0')
+ assert_inspect_evaled(':$1')
+ end
+
+ def test_to_proc
+ assert_equal %w(1 2 3), (1..3).map(&:to_s)
+ [
+ [],
+ [1],
+ [1, 2],
+ [1, [2, 3]],
+ ].each do |ary|
+ ary_id = ary.object_id
+ assert_equal ary_id, :object_id.to_proc.call(ary)
+ ary_ids = ary.collect{|x| x.object_id }
+ assert_equal ary_ids, ary.collect(&:object_id)
+ end
+ end
+
+ def test_call
+ o = Object.new
+ def o.foo(x, y); x + y; end
+
+ assert_equal(3, :foo.to_proc.call(o, 1, 2))
+ assert_raise(ArgumentError) { :foo.to_proc.call }
+ end
+
+ def test_succ
+ assert_equal(:fop, :foo.succ)
+ end
+
+ def test_cmp
+ assert_equal(0, :FoO <=> :FoO)
+ assert_equal(-1, :FoO <=> :fOO)
+ assert_equal(1, :fOO <=> :FoO)
+ assert_nil(:foo <=> "foo")
+ end
+
+ def test_casecmp
+ assert_equal(0, :FoO.casecmp(:fOO))
+ assert_equal(1, :FoO.casecmp(:BaR))
+ assert_equal(-1, :baR.casecmp(:FoO))
+ assert_nil(:foo.casecmp("foo"))
+ end
+
+ def test_length
+ assert_equal(3, :FoO.length)
+ assert_equal(3, :FoO.size)
+ end
+
+ def test_empty
+ assert_equal(false, :FoO.empty?)
+ assert_equal(true, :"".empty?)
+ end
+
+ def test_case
+ assert_equal(:FOO, :FoO.upcase)
+ assert_equal(:foo, :FoO.downcase)
+ assert_equal(:Foo, :foo.capitalize)
+ assert_equal(:fOo, :FoO.swapcase)
+ end
+end
diff --git a/trunk/test/ruby/test_system.rb b/trunk/test/ruby/test_system.rb
new file mode 100644
index 0000000000..ec8aca74cb
--- /dev/null
+++ b/trunk/test/ruby/test_system.rb
@@ -0,0 +1,76 @@
+require 'test/unit'
+require 'tmpdir'
+require_relative 'envutil'
+
+class TestSystem < Test::Unit::TestCase
+ def valid_syntax?(code, fname)
+ code.force_encoding("ascii-8bit")
+ code = code.sub(/\A(?:\s*\#.*$)*(\n)?/n) {
+ "#$&#{"\n" if $1 && !$2}BEGIN{return true}\n"
+ }
+ eval(code, nil, fname, 0)
+ end
+
+ def test_system
+ ruby = EnvUtil.rubybin
+ assert_equal("foobar\n", `echo foobar`)
+ assert_equal('foobar', `#{ruby} -e 'print "foobar"'`)
+
+ Dir.mktmpdir("ruby_script_tmp") {|tmpdir|
+ tmpfilename = "#{tmpdir}/ruby_script_tmp.#{$$}"
+
+ tmp = open(tmpfilename, "w")
+ tmp.print "print $zzz\n";
+ tmp.close
+
+ assert_equal('true', `#{ruby} -s #{tmpfilename} -zzz`)
+ assert_equal('555', `#{ruby} -s #{tmpfilename} -zzz=555`)
+
+ tmp = open(tmpfilename, "w")
+ tmp.print "#! /usr/local/bin/ruby -s\n";
+ tmp.print "print $zzz\n";
+ tmp.close
+
+ assert_equal('678', `#{ruby} #{tmpfilename} -zzz=678`)
+
+ tmp = open(tmpfilename, "w")
+ tmp.print "this is a leading junk\n";
+ tmp.print "#! /usr/local/bin/ruby -s\n";
+ tmp.print "print $zzz\n";
+ tmp.print "__END__\n";
+ tmp.print "this is a trailing junk\n";
+ tmp.close
+
+ assert_equal('', `#{ruby} -x #{tmpfilename}`)
+ assert_equal('555', `#{ruby} -x #{tmpfilename} -zzz=555`)
+
+ tmp = open(tmpfilename, "w")
+ for i in 1..5
+ tmp.print i, "\n"
+ end
+ tmp.close
+
+ `#{ruby} -i.bak -pe '$_.sub!(/^[0-9]+$/){$&.to_i * 5}' #{tmpfilename}`
+ tmp = open(tmpfilename, "r")
+ while tmp.gets
+ assert_equal(0, $_.to_i % 5)
+ end
+ tmp.close
+
+ File.unlink tmpfilename or `/bin/rm -f "#{tmpfilename}"`
+ File.unlink "#{tmpfilename}.bak" or `/bin/rm -f "#{tmpfilename}.bak"`
+ }
+ end
+
+ def test_syntax
+ assert_nothing_raised(Exception) do
+ for script in Dir[File.expand_path("../../../{lib,sample,ext}/**/*.rb", __FILE__)]
+ valid_syntax? IO::read(script), script
+ end
+ end
+ end
+
+ def test_empty_evstr
+ assert_equal("", eval('"#{}"', nil, __FILE__, __LINE__), "[ruby-dev:25113]")
+ end
+end
diff --git a/trunk/test/ruby/test_thread.rb b/trunk/test/ruby/test_thread.rb
new file mode 100644
index 0000000000..cd99cdc401
--- /dev/null
+++ b/trunk/test/ruby/test_thread.rb
@@ -0,0 +1,507 @@
+require 'test/unit'
+require 'thread'
+require_relative 'envutil'
+
+class TestThread < Test::Unit::TestCase
+ class Thread < ::Thread
+ Threads = []
+ def self.new(*)
+ th = super
+ th.abort_on_exception = true
+ Threads << th
+ th
+ end
+ end
+
+ def setup
+ Thread::Threads.clear
+ end
+
+ def teardown
+ Thread::Threads.each do |t|
+ t.kill if t.alive?
+ begin
+ t.join
+ rescue Exception
+ end
+ end
+ end
+
+ def test_mutex_synchronize
+ m = Mutex.new
+ r = 0
+ max = 100
+ (1..max).map{
+ Thread.new{
+ i=0
+ while i<max*max
+ i+=1
+ m.synchronize{
+ r += 1
+ }
+ end
+ }
+ }.each{|e|
+ e.join
+ }
+ assert_equal(max * max * max, r)
+ end
+
+ def test_condvar
+ mutex = Mutex.new
+ condvar = ConditionVariable.new
+ result = []
+ mutex.synchronize do
+ t = Thread.new do
+ mutex.synchronize do
+ result << 1
+ condvar.signal
+ end
+ end
+
+ result << 0
+ condvar.wait(mutex)
+ result << 2
+ t.join
+ end
+ assert_equal([0, 1, 2], result)
+ end
+
+ def test_condvar_wait_not_owner
+ mutex = Mutex.new
+ condvar = ConditionVariable.new
+
+ assert_raises(ThreadError) { condvar.wait(mutex) }
+ end
+
+ def test_condvar_wait_exception_handling
+ # Calling wait in the only thread running should raise a ThreadError of
+ # 'stopping only thread'
+ mutex = Mutex.new
+ condvar = ConditionVariable.new
+
+ locked = false
+ thread = Thread.new do
+ Thread.current.abort_on_exception = false
+ mutex.synchronize do
+ begin
+ condvar.wait(mutex)
+ rescue Exception
+ locked = mutex.locked?
+ raise
+ end
+ end
+ end
+
+ until thread.stop?
+ sleep(0.1)
+ end
+
+ thread.raise Interrupt, "interrupt a dead condition variable"
+ assert_raises(Interrupt) { thread.value }
+ assert(locked)
+ end
+
+ def test_local_barrier
+ dir = File.dirname(__FILE__)
+ lbtest = File.join(dir, "lbtest.rb")
+ $:.unshift File.join(File.dirname(dir), 'ruby')
+ require 'envutil'
+ $:.shift
+ 10.times {
+ result = `#{EnvUtil.rubybin} #{lbtest}`
+ assert(!$?.coredump?, '[ruby-dev:30653]')
+ assert_equal("exit.", result[/.*\Z/], '[ruby-dev:30653]')
+ }
+ end
+
+ def test_priority
+ c1 = c2 = 0
+ t1 = Thread.new { loop { c1 += 1 } }
+ t1.priority = -1
+ t2 = Thread.new { loop { c2 += 1 } }
+ t2.priority = -3
+ assert_equal(-1, t1.priority)
+ assert_equal(-3, t2.priority)
+ sleep 0.5
+ t1.kill
+ t2.kill
+ assert(c1 > c2 * 1.5, "[ruby-dev:33124]")
+ end
+
+ def test_new
+ assert_raise(ThreadError) do
+ Thread.new
+ end
+
+ t1 = Thread.new { sleep }
+ assert_raise(ThreadError) do
+ t1.instance_eval { initialize { } }
+ end
+
+ t2 = Thread.new(&method(:sleep).to_proc)
+ assert_raise(ThreadError) do
+ t2.instance_eval { initialize { } }
+ end
+
+ ensure
+ t1.kill if t1
+ t2.kill if t2
+ end
+
+ def test_join
+ t = Thread.new { sleep }
+ assert_nil(t.join(0.5))
+
+ ensure
+ t.kill if t
+ end
+
+ def test_join2
+ t1 = Thread.new { sleep(1.5) }
+ t2 = Thread.new do
+ t1.join(1)
+ end
+ t3 = Thread.new do
+ sleep 0.5
+ t1.join
+ end
+ assert_nil(t2.value)
+ assert_equal(t1, t3.value)
+
+ ensure
+ t1.kill if t1
+ t2.kill if t2
+ t3.kill if t3
+ end
+
+ def test_kill_main_thread
+ assert_in_out_err([], <<-INPUT, %w(1), [])
+ p 1
+ Thread.kill Thread.current
+ p 2
+ INPUT
+ end
+
+ def test_exit
+ s = 0
+ Thread.new do
+ s += 1
+ Thread.exit
+ s += 2
+ end.join
+ assert_equal(1, s)
+ end
+
+ def test_wakeup
+ s = 0
+ t = Thread.new do
+ s += 1
+ Thread.stop
+ s += 1
+ end
+ sleep 0.5
+ assert_equal(1, s)
+ t.wakeup
+ sleep 0.5
+ assert_equal(2, s)
+ assert_raise(ThreadError) { t.wakeup }
+
+ ensure
+ t.kill if t
+ end
+
+ def test_stop
+ assert_in_out_err([], <<-INPUT, %w(2), [])
+ begin
+ Thread.stop
+ p 1
+ rescue ThreadError
+ p 2
+ end
+ INPUT
+ end
+
+ def test_list
+ assert_in_out_err([], <<-INPUT) do |r, e|
+ t1 = Thread.new { sleep }
+ Thread.pass
+ t2 = Thread.new { loop { } }
+ t3 = Thread.new { }.join
+ p [Thread.current, t1, t2].sort_by {|t| t.object_id }
+ p Thread.list.sort_by {|t| t.object_id }
+ INPUT
+ assert_equal(r.first, r.last)
+ assert_equal([], e)
+ end
+ end
+
+ def test_main
+ assert_in_out_err([], <<-INPUT, %w(true false), [])
+ p Thread.main == Thread.current
+ Thread.new { p Thread.main == Thread.current }.join
+ INPUT
+ end
+
+ def test_abort_on_exception
+ assert_in_out_err([], <<-INPUT, %w(false 1), [])
+ p Thread.abort_on_exception
+ begin
+ Thread.new { raise }
+ sleep 0.5
+ p 1
+ rescue
+ p 2
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(true 2), [])
+ Thread.abort_on_exception = true
+ p Thread.abort_on_exception
+ begin
+ Thread.new { raise }
+ sleep 0.5
+ p 1
+ rescue
+ p 2
+ end
+ INPUT
+
+ assert_in_out_err(%w(-d), <<-INPUT, %w(false 2), /.+/)
+ p Thread.abort_on_exception
+ begin
+ Thread.new { raise }
+ sleep 0.5
+ p 1
+ rescue
+ p 2
+ end
+ INPUT
+
+ assert_in_out_err([], <<-INPUT, %w(false true 2), [])
+ p Thread.abort_on_exception
+ begin
+ t = Thread.new { sleep 0.5; raise }
+ t.abort_on_exception = true
+ p t.abort_on_exception
+ sleep 1
+ p 1
+ rescue
+ p 2
+ end
+ INPUT
+ end
+
+ def test_status_and_stop_p
+ a = ::Thread.new { raise("die now") }
+ b = Thread.new { Thread.stop }
+ c = Thread.new { Thread.exit }
+ d = Thread.new { sleep }
+ e = Thread.current
+ sleep 0.5
+
+ assert_equal(nil, a.status)
+ assert(a.stop?)
+
+ assert_equal("sleep", b.status)
+ assert(b.stop?)
+
+ assert_equal(false, c.status)
+ assert_match(/^#<TestThread::Thread:.* dead>$/, c.inspect)
+ assert(c.stop?)
+
+ d.kill
+ assert_equal("aborting", d.status)
+ assert(!d.stop?)
+
+ assert_equal("run", e.status)
+ assert(!e.stop?)
+
+ ensure
+ a.kill if a
+ b.kill if b
+ c.kill if c
+ d.kill if d
+ end
+
+ def test_safe_level
+ t = Thread.new { $SAFE = 3; sleep }
+ sleep 0.5
+ assert_equal(0, Thread.current.safe_level)
+ assert_equal(3, t.safe_level)
+
+ ensure
+ t.kill if t
+ end
+
+ def test_thread_local
+ t = Thread.new { sleep }
+
+ assert_equal(false, t.key?(:foo))
+
+ t["foo"] = "foo"
+ t["bar"] = "bar"
+ t["baz"] = "baz"
+
+ assert_equal(true, t.key?(:foo))
+ assert_equal(true, t.key?("foo"))
+ assert_equal(false, t.key?(:qux))
+ assert_equal(false, t.key?("qux"))
+
+ assert_equal([:foo, :bar, :baz], t.keys)
+
+ ensure
+ t.kill if t
+ end
+
+ def test_thread_local_security
+ t = Thread.new { sleep }
+
+ assert_raise(SecurityError) do
+ Thread.new { $SAFE = 4; t[:foo] }.join
+ end
+
+ assert_raise(SecurityError) do
+ Thread.new { $SAFE = 4; t[:foo] = :baz }.join
+ end
+
+ assert_raise(RuntimeError) do
+ Thread.new do
+ Thread.current[:foo] = :bar
+ Thread.current.freeze
+ Thread.current[:foo] = :baz
+ end.join
+ end
+ end
+
+ def test_select_wait
+ assert_nil(IO.select(nil, nil, nil, 1))
+ t = Thread.new do
+ IO.select(nil, nil, nil, nil)
+ end
+ sleep 0.5
+ t.kill
+ end
+
+ def test_mutex_deadlock
+ m = Mutex.new
+ m.synchronize do
+ assert_raise(ThreadError) do
+ m.synchronize do
+ assert(false)
+ end
+ end
+ end
+ end
+
+ def test_mutex_interrupt
+ m = Mutex.new
+ m.lock
+ t = Thread.new do
+ m.lock
+ :foo
+ end
+ sleep 0.5
+ t.kill
+ assert_nil(t.value)
+ end
+
+ def test_mutex_illegal_unlock
+ m = Mutex.new
+ m.lock
+ assert_raise(ThreadError) do
+ Thread.new do
+ m.unlock
+ end.join
+ end
+ end
+
+ def test_mutex_fifo_like_lock
+ m1 = Mutex.new
+ m2 = Mutex.new
+ m1.lock
+ m2.lock
+ m1.unlock
+ m2.unlock
+ assert_equal(false, m1.locked?)
+ assert_equal(false, m2.locked?)
+
+ m3 = Mutex.new
+ m1.lock
+ m2.lock
+ m3.lock
+ m1.unlock
+ m2.unlock
+ m3.unlock
+ assert_equal(false, m1.locked?)
+ assert_equal(false, m2.locked?)
+ assert_equal(false, m3.locked?)
+ end
+
+ def test_recursive_error
+ o = Object.new
+ def o.inspect
+ Thread.current[:__recursive_key__][:inspect] = nil
+ super
+ end
+ assert_raise(TypeError) { [o].inspect }
+ end
+end
+
+class TestThreadGroup < Test::Unit::TestCase
+ def test_thread_init
+ thgrp = ThreadGroup.new
+ Thread.new{
+ thgrp.add(Thread.current)
+ assert_equal(thgrp, Thread.new{sleep 1}.group)
+ }.join
+ end
+
+ def test_frozen_thgroup
+ thgrp = ThreadGroup.new
+
+ t = Thread.new{1}
+ Thread.new{
+ thgrp.add(Thread.current)
+ thgrp.freeze
+ assert_raise(ThreadError) do
+ Thread.new{1}.join
+ end
+ assert_raise(ThreadError) do
+ thgrp.add(t)
+ end
+ assert_raise(ThreadError) do
+ ThreadGroup.new.add Thread.current
+ end
+ }.join
+ t.join
+ end
+
+ def test_enclosed_thgroup
+ thgrp = ThreadGroup.new
+ assert_equal(false, thgrp.enclosed?)
+
+ t = Thread.new{1}
+ Thread.new{
+ thgrp.add(Thread.current)
+ thgrp.enclose
+ assert_equal(true, thgrp.enclosed?)
+ assert_nothing_raised do
+ Thread.new{1}.join
+ end
+ assert_raise(ThreadError) do
+ thgrp.add t
+ end
+ assert_raise(ThreadError) do
+ ThreadGroup.new.add Thread.current
+ end
+ }.join
+ t.join
+ end
+
+ def test_uninitialized
+ c = Class.new(Thread)
+ c.class_eval { def initialize; end }
+ assert_raise(ThreadError) { c.new.start }
+ end
+end
diff --git a/trunk/test/ruby/test_time.rb b/trunk/test/ruby/test_time.rb
new file mode 100644
index 0000000000..87516e10c4
--- /dev/null
+++ b/trunk/test/ruby/test_time.rb
@@ -0,0 +1,394 @@
+require 'test/unit'
+require 'rational'
+require 'timeout'
+
+class TestTime < Test::Unit::TestCase
+ def test_time_add()
+ assert_equal(Time.utc(2000, 3, 21, 3, 30) + 3 * 3600,
+ Time.utc(2000, 3, 21, 6, 30))
+ assert_equal(Time.utc(2000, 3, 21, 3, 30) + (-3 * 3600),
+ Time.utc(2000, 3, 21, 0, 30))
+ assert_equal(0, (Time.at(1.1) + 0.9).usec)
+ end
+
+ def test_time_subt()
+ assert_equal(Time.utc(2000, 3, 21, 3, 30) - 3 * 3600,
+ Time.utc(2000, 3, 21, 0, 30))
+ assert_equal(Time.utc(2000, 3, 21, 3, 30) - (-3 * 3600),
+ Time.utc(2000, 3, 21, 6, 30))
+ assert_equal(900000, (Time.at(1.1) - 0.2).usec)
+ end
+
+ def test_time_time()
+ assert_equal(Time.utc(2000, 3, 21, 3, 30) \
+ -Time.utc(2000, 3, 21, 0, 30), 3*3600)
+ assert_equal(Time.utc(2000, 3, 21, 0, 30) \
+ -Time.utc(2000, 3, 21, 3, 30), -3*3600)
+ end
+
+ def negative_time_t?
+ begin
+ Time.at(-1)
+ true
+ rescue ArgumentError
+ false
+ end
+ end
+
+ def test_timegm
+ if negative_time_t?
+ assert_equal(-0x80000000, Time.utc(1901, 12, 13, 20, 45, 52).tv_sec)
+ assert_equal(-2, Time.utc(1969, 12, 31, 23, 59, 58).tv_sec)
+ assert_equal(-1, Time.utc(1969, 12, 31, 23, 59, 59).tv_sec)
+ end
+
+ assert_equal(0, Time.utc(1970, 1, 1, 0, 0, 0).tv_sec) # the Epoch
+ assert_equal(1, Time.utc(1970, 1, 1, 0, 0, 1).tv_sec)
+ assert_equal(31535999, Time.utc(1970, 12, 31, 23, 59, 59).tv_sec)
+ assert_equal(31536000, Time.utc(1971, 1, 1, 0, 0, 0).tv_sec)
+ assert_equal(78796799, Time.utc(1972, 6, 30, 23, 59, 59).tv_sec)
+
+ # 1972-06-30T23:59:60Z is the first leap second.
+ if Time.utc(1972, 7, 1, 0, 0, 0) - Time.utc(1972, 6, 30, 23, 59, 59) == 1
+ # no leap second.
+ assert_equal(78796800, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec)
+ assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec)
+ assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
+ assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec)
+ else
+ # leap seconds supported.
+ assert_equal(2, Time.utc(1972, 7, 1, 0, 0, 0) - Time.utc(1972, 6, 30, 23, 59, 59))
+ assert_equal(78796800, Time.utc(1972, 6, 30, 23, 59, 60).tv_sec)
+ assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec)
+ assert_equal(78796802, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec)
+ assert_equal(946684822, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
+ end
+ end
+
+ def test_strtime
+ t = nil
+ assert_nothing_raised { t = Time.utc("2000", "1", "2" , "3", "4", "5") }
+ assert_equal(Time.utc(2000,1,2,3,4,5), t)
+ end
+
+ def test_huge_difference
+ if negative_time_t?
+ assert_equal(Time.at(-0x80000000), Time.at(0x7fffffff) - 0xffffffff, "[ruby-dev:22619]")
+ assert_equal(Time.at(-0x80000000), Time.at(0x7fffffff) + (-0xffffffff))
+ assert_equal(Time.at(0x7fffffff), Time.at(-0x80000000) + 0xffffffff, "[ruby-dev:22619]")
+ assert_equal(Time.at(0x7fffffff), Time.at(-0x80000000) - (-0xffffffff))
+ end
+ end
+
+ def test_big_minus
+ begin
+ bigtime0 = Time.at(2**60)
+ bigtime1 = Time.at(2**60+1)
+ rescue RangeError
+ return
+ end
+ assert_equal(1.0, bigtime1 - bigtime0)
+ end
+
+ def test_at
+ assert_equal(100000, Time.at(0.1).usec)
+ assert_equal(10000, Time.at(0.01).usec)
+ assert_equal(1000, Time.at(0.001).usec)
+ assert_equal(100, Time.at(0.0001).usec)
+ assert_equal(10, Time.at(0.00001).usec)
+ assert_equal(1, Time.at(0.000001).usec)
+ assert_equal(100000000, Time.at(0.1).nsec)
+ assert_equal(10000000, Time.at(0.01).nsec)
+ assert_equal(1000000, Time.at(0.001).nsec)
+ assert_equal(100000, Time.at(0.0001).nsec)
+ assert_equal(10000, Time.at(0.00001).nsec)
+ assert_equal(1000, Time.at(0.000001).nsec)
+ assert_equal(100, Time.at(0.0000001).nsec)
+ assert_equal(10, Time.at(0.00000001).nsec)
+ assert_equal(1, Time.at(0.000000001).nsec)
+ assert_equal(0, Time.at(1e-10).nsec)
+ assert_equal(0, Time.at(4e-10).nsec)
+ assert_equal(1, Time.at(6e-10).nsec)
+ assert_equal(1, Time.at(14e-10).nsec)
+ assert_equal(2, Time.at(16e-10).nsec)
+ if negative_time_t?
+ assert_equal(0, Time.at(-1e-10).nsec)
+ assert_equal(0, Time.at(-4e-10).nsec)
+ assert_equal(999999999, Time.at(-6e-10).nsec)
+ assert_equal(999999999, Time.at(-14e-10).nsec)
+ assert_equal(999999998, Time.at(-16e-10).nsec)
+ end
+ end
+
+ def test_at2
+ assert_equal(100, Time.at(0, 0.1).nsec)
+ assert_equal(10, Time.at(0, 0.01).nsec)
+ assert_equal(1, Time.at(0, 0.001).nsec)
+ end
+
+ def test_at_rational
+ assert_equal(1, Time.at(Rational(1,1) / 1000000000).nsec)
+ assert_equal(1, Time.at(1167609600 + Rational(1,1) / 1000000000).nsec)
+ end
+
+ def test_utc_subsecond
+ assert_equal(100000, Time.utc(2007,1,1,0,0,1.1).usec)
+ assert_equal(100000, Time.utc(2007,1,1,0,0,Rational(11,10)).usec)
+ end
+
+ def test_eq_nsec
+ assert_equal(Time.at(0, 0.123), Time.at(0, 0.123))
+ assert_not_equal(Time.at(0, 0.123), Time.at(0, 0.124))
+ end
+
+ def assert_marshal_roundtrip(t)
+ iv_names = t.instance_variables
+ iv_vals1 = iv_names.map {|n| t.instance_variable_get n }
+ m = Marshal.dump(t)
+ t2 = Marshal.load(m)
+ iv_vals2 = iv_names.map {|n| t2.instance_variable_get n }
+ assert_equal(t, t2)
+ assert_equal(iv_vals1, iv_vals2)
+ t2
+ end
+
+ def test_marshal_nsec
+ assert_marshal_roundtrip(Time.at(0, 0.123))
+ assert_marshal_roundtrip(Time.at(0, 0.120))
+ end
+
+ def test_marshal_ivar
+ t = Time.at(123456789, 987654.321)
+ t.instance_eval { @var = 135 }
+ assert_marshal_roundtrip(t)
+ assert_marshal_roundtrip(Marshal.load(Marshal.dump(t)))
+ end
+
+ # Sat Jan 01 00:00:00 UTC 2000
+ T2000 = Time.at(946684800).gmtime
+
+ def test_security_error
+ assert_raise(SecurityError) do
+ Thread.new do
+ t = Time.gm(2000)
+ $SAFE = 4
+ t.localtime
+ end.join
+ end
+ end
+
+ def test_at3
+ assert_equal(T2000, Time.at(T2000))
+ assert_raise(RangeError) do
+ Time.at(2**31-1, 1_000_000)
+ Time.at(2**63-1, 1_000_000)
+ end
+ assert_raise(RangeError) do
+ Time.at(-2**31, -1_000_000)
+ Time.at(-2**63, -1_000_000)
+ end
+ end
+
+ def test_utc_or_local
+ assert_equal(T2000, Time.gm(2000))
+ assert_equal(T2000, Time.gm(0, 0, 0, 1, 1, 2000, :foo, :bar, false, :baz))
+ assert_equal(T2000, Time.gm(0))
+ assert_equal(T2000, Time.gm(100))
+ assert_equal(T2000, Time.gm(2000, "jan"))
+ assert_equal(T2000, Time.gm(2000, "1"))
+ assert_equal(T2000, Time.gm(2000, 1, 1, 0, 0, 0, 0))
+ assert_equal(T2000, Time.gm(2000, 1, 1, 0, 0, 0, "0"))
+ assert_equal(T2000, Time.gm(2000, 1, 1, 0, 0, "0", :foo, :foo))
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, -1, :foo, :foo) }
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, -1.0, :foo, :foo) }
+ assert_raise(RangeError) do
+ Time.gm(2000, 1, 1, 0, 0, 10_000_000_000_000_000_001.0, :foo, :foo)
+ end
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, -(2**31), :foo, :foo) }
+ o = Object.new
+ def o.divmod(x); nil; end
+ assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ def o.divmod(x); [-1, 0]; end
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ assert_raise(ArgumentError) { Time.gm(2000, 13) }
+
+ t = Time.local(2000)
+ assert_equal(t.gmt_offset, T2000 - t)
+ end
+
+ def test_time_interval
+ m = Mutex.new.lock
+ assert_nothing_raised {
+ Timeout.timeout(10) {
+ m.sleep(0)
+ }
+ }
+ assert_raise(ArgumentError) { m.sleep(-1) }
+ end
+
+ def test_to_f
+ assert_equal(946684800.0, T2000.to_f)
+ end
+
+ def test_cmp
+ assert_equal(-1, T2000 <=> Time.gm(2001))
+ assert_equal(1, T2000 <=> Time.gm(1999))
+ assert_nil(T2000 <=> 0)
+ end
+
+ def test_eql
+ assert(T2000.eql?(T2000))
+ assert(!T2000.eql?(Time.gm(2001)))
+ end
+
+ def test_utc_p
+ assert(Time.gm(2000).gmt?)
+ assert(!Time.local(2000).gmt?)
+ assert(!Time.at(0).gmt?)
+ end
+
+ def test_hash
+ assert_kind_of(Integer, T2000.hash)
+ end
+
+ def test_init_copy
+ assert_equal(T2000, T2000.dup)
+ assert_raise(TypeError) do
+ T2000.instance_eval { initialize_copy(nil) }
+ end
+ end
+
+ def test_localtime_gmtime
+ assert_nothing_raised do
+ t = Time.gm(2000)
+ assert(t.gmt?)
+ t.localtime
+ assert(!t.gmt?)
+ t.localtime
+ assert(!t.gmt?)
+ t.gmtime
+ assert(t.gmt?)
+ t.gmtime
+ assert(t.gmt?)
+ end
+
+ t1 = Time.gm(2000)
+ t2 = t1.getlocal
+ assert_equal(t1, t2)
+ t1.localtime
+ assert_equal(t1, t2)
+ assert_equal(t1.gmt?, t2.gmt?)
+
+ t1 = Time.local(2000)
+ t2 = t1.getgm
+ assert_equal(t1, t2)
+ t1.gmtime
+ assert_equal(t1, t2)
+ assert_equal(t1.gmt?, t2.gmt?)
+ end
+
+ def test_asctime
+ assert_equal("Sat Jan 1 00:00:00 2000", T2000.asctime)
+ assert_kind_of(String, Time.at(0).asctime)
+ end
+
+ def test_to_s
+ assert_equal("2000-01-01 00:00:00 UTC", T2000.to_s)
+ assert_kind_of(String, Time.at(946684800).getlocal.to_s)
+ assert_equal(Time.at(946684800).getlocal.to_s, Time.at(946684800).to_s)
+ end
+
+ def test_plus_minus_succ
+ # assert_raise(RangeError) { T2000 + 10000000000 }
+ # assert_raise(RangeError) T2000 - 3094168449 }
+ # assert_raise(RangeError) { T2000 + 1200798848 }
+ assert_raise(TypeError) { T2000 + Time.now }
+ assert_equal(T2000 + 1, T2000.succ)
+ end
+
+ def test_readers
+ assert_equal(0, T2000.sec)
+ assert_equal(0, T2000.min)
+ assert_equal(0, T2000.hour)
+ assert_equal(1, T2000.mday)
+ assert_equal(1, T2000.mon)
+ assert_equal(2000, T2000.year)
+ assert_equal(6, T2000.wday)
+ assert_equal(1, T2000.yday)
+ assert_equal(false, T2000.isdst)
+ assert_equal("UTC", T2000.zone)
+ assert_equal(0, T2000.gmt_offset)
+ assert(!T2000.sunday?)
+ assert(!T2000.monday?)
+ assert(!T2000.tuesday?)
+ assert(!T2000.wednesday?)
+ assert(!T2000.thursday?)
+ assert(!T2000.friday?)
+ assert(T2000.saturday?)
+ assert_equal([0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], T2000.to_a)
+
+ t = Time.at(946684800).getlocal
+ assert_equal(t.sec, Time.at(946684800).sec)
+ assert_equal(t.min, Time.at(946684800).min)
+ assert_equal(t.hour, Time.at(946684800).hour)
+ assert_equal(t.mday, Time.at(946684800).mday)
+ assert_equal(t.mon, Time.at(946684800).mon)
+ assert_equal(t.year, Time.at(946684800).year)
+ assert_equal(t.wday, Time.at(946684800).wday)
+ assert_equal(t.yday, Time.at(946684800).yday)
+ assert_equal(t.isdst, Time.at(946684800).isdst)
+ assert_equal(t.zone, Time.at(946684800).zone)
+ assert_equal(t.gmt_offset, Time.at(946684800).gmt_offset)
+ assert_equal(t.sunday?, Time.at(946684800).sunday?)
+ assert_equal(t.monday?, Time.at(946684800).monday?)
+ assert_equal(t.tuesday?, Time.at(946684800).tuesday?)
+ assert_equal(t.wednesday?, Time.at(946684800).wednesday?)
+ assert_equal(t.thursday?, Time.at(946684800).thursday?)
+ assert_equal(t.friday?, Time.at(946684800).friday?)
+ assert_equal(t.saturday?, Time.at(946684800).saturday?)
+ assert_equal(t.to_a, Time.at(946684800).to_a)
+ end
+
+ def test_strftime
+ t = Time.at(946684800).getlocal
+ assert_equal("Sat", T2000.strftime("%a"))
+ assert_equal("Saturday", T2000.strftime("%A"))
+ assert_equal("Jan", T2000.strftime("%b"))
+ assert_equal("January", T2000.strftime("%B"))
+ assert_kind_of(String, T2000.strftime("%c"))
+ assert_equal("01", T2000.strftime("%d"))
+ assert_equal("00", T2000.strftime("%H"))
+ assert_equal("12", T2000.strftime("%I"))
+ assert_equal("001", T2000.strftime("%j"))
+ assert_equal("01", T2000.strftime("%m"))
+ assert_equal("00", T2000.strftime("%M"))
+ assert_equal("AM", T2000.strftime("%p"))
+ assert_equal("00", T2000.strftime("%S"))
+ assert_equal("00", T2000.strftime("%U"))
+ assert_equal("00", T2000.strftime("%W"))
+ assert_equal("6", T2000.strftime("%w"))
+ assert_equal("01/01/00", T2000.strftime("%x"))
+ assert_equal("00:00:00", T2000.strftime("%X"))
+ assert_equal("00", T2000.strftime("%y"))
+ assert_equal("2000", T2000.strftime("%Y"))
+ assert_equal("UTC", T2000.strftime("%Z"))
+ assert_equal("%", T2000.strftime("%%"))
+
+ assert_equal("", T2000.strftime(""))
+ assert_equal("foo\0bar\x0000\x0000\x0000", T2000.strftime("foo\0bar\0%H\0%M\0%S"))
+ assert_equal("foo" * 1000, T2000.strftime("foo" * 1000))
+
+ assert_equal("Sat", Time.at(946684800).strftime("%a"))
+
+ t = Time.at(946684800, 123456.789)
+ assert_equal("123", t.strftime("%3N"))
+ assert_equal("123456", t.strftime("%6N"))
+ assert_equal("123456789", t.strftime("%9N"))
+ assert_equal("1234567890", t.strftime("%10N"))
+ assert_equal("", t.strftime("%0N"))
+ assert_equal("000", t.strftime("%3S"))
+
+ t = Time.mktime(2001, 10, 1)
+ assert_equal("2001-10-01", t.strftime("%F"))
+ end
+end
diff --git a/trunk/test/ruby/test_trace.rb b/trunk/test/ruby/test_trace.rb
new file mode 100644
index 0000000000..48294c9694
--- /dev/null
+++ b/trunk/test/ruby/test_trace.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+
+class TestTrace < Test::Unit::TestCase
+ def test_trace
+ $x = 1234
+ $y = 0
+ trace_var :$x, proc{$y = $x}
+ $x = 40414
+ assert_equal($x, $y)
+
+ untrace_var :$x
+ $x = 19660208
+ assert_not_equal($x, $y)
+
+ trace_var :$x, proc{$x *= 2}
+ $x = 5
+ assert_equal(10, $x)
+
+ untrace_var :$x
+ end
+
+ def test_trace_tainted_proc
+ $x = 1234
+ s = proc { $y = :foo }
+ trace_var :$x, s
+ s.taint
+ $x = 42
+ assert_equal(:foo, $y)
+ ensure
+ untrace_var :$x
+ end
+
+ def test_trace_proc_that_raises_exception
+ $x = 1234
+ trace_var :$x, proc { raise }
+ assert_raise(RuntimeError) { $x = 42 }
+ ensure
+ untrace_var :$x
+ end
+
+ def test_trace_string
+ $x = 1234
+ trace_var :$x, "$y = :bar"
+ $x = 42
+ assert_equal(:bar, $y)
+ ensure
+ untrace_var :$x
+ end
+end
diff --git a/trunk/test/ruby/test_transcode.rb b/trunk/test/ruby/test_transcode.rb
new file mode 100644
index 0000000000..fd673a96c0
--- /dev/null
+++ b/trunk/test/ruby/test_transcode.rb
@@ -0,0 +1,398 @@
+# -*- encoding: ASCII-8BIT -*- # make sure this runs in binary mode
+# some of the comments are in UTF-8
+
+require 'test/unit'
+class TestTranscode < Test::Unit::TestCase
+ def setup_really_needed? # trick to create all the necessary encodings
+ all_encodings = [ 'ISO-8859-1', 'ISO-8859-2',
+ 'ISO-8859-3', 'ISO-8859-4',
+ 'ISO-8859-5', 'ISO-8859-6',
+ 'ISO-8859-7', 'ISO-8859-8',
+ 'ISO-8859-9', 'ISO-8859-10',
+ 'ISO-8859-11', 'ISO-8859-13',
+ 'ISO-8859-14', 'ISO-8859-15',
+ 'UTF-16BE'
+ ]
+ all_encodings.each do |enc|
+ 'abc'.encode(enc, 'UTF-8')
+ end
+ end
+
+ def test_errors
+ assert_raise(ArgumentError) { 'abc'.encode }
+ assert_raise(ArgumentError) { 'abc'.encode! }
+ assert_raise(Encoding::NoConverter) { 'abc'.encode('foo', 'bar') }
+ assert_raise(Encoding::NoConverter) { 'abc'.encode!('foo', 'bar') }
+ assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode('foo') }
+ assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode!('foo') }
+ assert_raise(Encoding::ConversionUndefined) { "\x80".encode('utf-8','ASCII-8BIT') }
+ assert_raise(Encoding::InvalidByteSequence) { "\x80".encode('utf-8','US-ASCII') }
+ assert_raise(Encoding::ConversionUndefined) { "\xA5".encode('utf-8','iso-8859-3') }
+ end
+
+ def test_arguments
+ assert_equal('abc', 'abc'.force_encoding('utf-8').encode('iso-8859-1'))
+ # check that encoding is kept when no conversion is done
+ assert_equal('abc'.force_encoding('Shift_JIS'), 'abc'.force_encoding('Shift_JIS').encode('Shift_JIS'))
+ assert_equal('abc'.force_encoding('Shift_JIS'), 'abc'.force_encoding('Shift_JIS').encode!('Shift_JIS'))
+ # assert that encoding is correctly set
+ assert_equal("D\u00FCrst".encoding, "D\xFCrst".force_encoding('iso-8859-1').encode('utf-8').encoding)
+ # check that Encoding can be used as parameter
+ assert_equal("D\u00FCrst", "D\xFCrst".encode('utf-8', Encoding.find('ISO-8859-1')))
+ assert_equal("D\u00FCrst", "D\xFCrst".encode(Encoding.find('utf-8'), 'ISO-8859-1'))
+ assert_equal("D\u00FCrst", "D\xFCrst".encode(Encoding.find('utf-8'), Encoding.find('ISO-8859-1')))
+ end
+
+ def test_length
+ assert_equal("\u20AC"*20, ("\xA4"*20).encode('utf-8', 'iso-8859-15'))
+ assert_equal("\u20AC"*20, ("\xA4"*20).encode!('utf-8', 'iso-8859-15'))
+ assert_equal("\u20AC"*2000, ("\xA4"*2000).encode('utf-8', 'iso-8859-15'))
+ assert_equal("\u20AC"*2000, ("\xA4"*2000).encode!('utf-8', 'iso-8859-15'))
+ assert_equal("\u20AC"*200000, ("\xA4"*200000).encode('utf-8', 'iso-8859-15'))
+ assert_equal("\u20AC"*200000, ("\xA4"*200000).encode!('utf-8', 'iso-8859-15'))
+ end
+
+ def check_both_ways(utf8, raw, encoding)
+ assert_equal(utf8.force_encoding('utf-8'), raw.encode('utf-8', encoding))
+ assert_equal(raw.force_encoding(encoding), utf8.encode(encoding, 'utf-8'))
+ end
+
+ def test_encodings
+ check_both_ways("\u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D",
+ "\x82\xdc\x82\xc2\x82\xe0\x82\xc6 \x82\xe4\x82\xab\x82\xd0\x82\xeb", 'shift_jis') # ã¾ã¤ã‚‚㨠ゆãã²ã‚
+ check_both_ways("\u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D",
+ "\xa4\xde\xa4\xc4\xa4\xe2\xa4\xc8 \xa4\xe6\xa4\xad\xa4\xd2\xa4\xed", 'euc-jp')
+ check_both_ways("\u677E\u672C\u884C\u5F18", "\x8f\xbc\x96\x7b\x8d\x73\x8d\x4f", 'shift_jis') # æ¾æœ¬è¡Œå¼˜
+ check_both_ways("\u677E\u672C\u884C\u5F18", "\xbe\xbe\xcb\xdc\xb9\xd4\xb9\xb0", 'euc-jp')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-1') # Dürst
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-2')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-3')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-4')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-9')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-10')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-13')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-14')
+ check_both_ways("D\u00FCrst", "D\xFCrst", 'iso-8859-15')
+ check_both_ways("r\u00E9sum\u00E9", "r\xE9sum\xE9", 'iso-8859-1') # résumé
+ check_both_ways("\u0065\u006C\u0151\u00ED\u0072\u00E1\u0073", "el\xF5\xEDr\xE1s", 'iso-8859-2') # előírás
+ check_both_ways("\u043F\u0435\u0440\u0435\u0432\u043E\u0434",
+ "\xDF\xD5\xE0\xD5\xD2\xDE\xD4", 'iso-8859-5') # перевод
+ check_both_ways("\u0643\u062A\u0628", "\xE3\xCA\xC8", 'iso-8859-6') # كتب
+ check_both_ways("\u65E5\u8A18", "\x93\xFA\x8BL", 'shift_jis') # 日記
+ check_both_ways("\u65E5\u8A18", "\xC6\xFC\xB5\xAD", 'euc-jp')
+ check_both_ways("\uC560\uC778\uAD6C\uD568\u0020\u6734\uC9C0\uC778",
+ "\xBE\xD6\xC0\xCE\xB1\xB8\xC7\xD4\x20\xDA\xD3\xC1\xF6\xC0\xCE", 'euc-kr') # ì• ì¸êµ¬í•¨ 朴지ì¸
+ check_both_ways("\uC544\uD58F\uD58F\u0020\uB620\uBC29\uD6BD\uB2D8\u0020\uC0AC\uB791\uD716",
+ "\xBE\xC6\xC1\x64\xC1\x64\x20\x8C\x63\xB9\xE6\xC4\x4F\xB4\xD4\x20\xBB\xE7\xB6\xFB\xC5\x42", 'cp949') # ì•„í–í– ë˜ ë°©íš½ë‹˜ 사랑휖
+ end
+
+ def test_twostep
+ assert_equal("D\xFCrst".force_encoding('iso-8859-2'), "D\xFCrst".encode('iso-8859-2', 'iso-8859-1'))
+ end
+
+ def test_ascii_range
+ encodings = [
+ 'US-ASCII', 'ASCII-8BIT',
+ 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3',
+ 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6',
+ 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9',
+ 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-13',
+ 'ISO-8859-14', 'ISO-8859-15',
+ 'EUC-JP', 'SHIFT_JIS', 'EUC-KR'
+ ]
+ all_ascii = (0..127).to_a.pack 'C*'
+ encodings.each do |enc|
+ test_start = all_ascii
+ assert_equal(test_start, test_start.encode('UTF-8',enc).encode(enc).force_encoding('ASCII-8BIT'))
+ end
+ end
+
+ def test_all_bytes
+ encodings_8859 = [
+ 'ISO-8859-1', 'ISO-8859-2',
+ #'ISO-8859-3', # not all bytes used
+ 'ISO-8859-4', 'ISO-8859-5',
+ #'ISO-8859-6', # not all bytes used
+ #'ISO-8859-7', # not all bytes used
+ #'ISO-8859-8', # not all bytes used
+ 'ISO-8859-9', 'ISO-8859-10',
+ #'ISO-8859-11', # not all bytes used
+ #'ISO-8859-12', # not available
+ 'ISO-8859-13','ISO-8859-14','ISO-8859-15',
+ #'ISO-8859-16', # not available
+ ]
+ all_bytes = (0..255).to_a.pack 'C*'
+ encodings_8859.each do |enc|
+ test_start = all_bytes
+ assert_equal(test_start, test_start.encode('UTF-8',enc).encode(enc).force_encoding('ASCII-8BIT'))
+ end
+ end
+
+ def check_utf_16_both_ways(utf8, raw)
+ copy = raw.dup
+ 0.step(copy.length-1, 2) { |i| copy[i+1], copy[i] = copy[i], copy[i+1] }
+ check_both_ways(utf8, raw, 'utf-16be')
+ check_both_ways(utf8, copy, 'utf-16le')
+ end
+
+ def test_utf_16
+ check_utf_16_both_ways("abc", "\x00a\x00b\x00c")
+ check_utf_16_both_ways("\u00E9", "\x00\xE9");
+ check_utf_16_both_ways("\u00E9\u0070\u00E9\u0065", "\x00\xE9\x00\x70\x00\xE9\x00\x65") # épée
+ check_utf_16_both_ways("\u677E\u672C\u884C\u5F18", "\x67\x7E\x67\x2C\x88\x4C\x5F\x18") # æ¾æœ¬è¡Œå¼˜
+ check_utf_16_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\x97\x52\x5C\x71\x5B\x66\x96\x62\x59\x27\x5B\x66") # é’山学院大学
+ check_utf_16_both_ways("Martin D\u00FCrst", "\x00M\x00a\x00r\x00t\x00i\x00n\x00 \x00D\x00\xFC\x00r\x00s\x00t") # Martin Dürst
+ # BMP
+ check_utf_16_both_ways("\u0000", "\x00\x00")
+ check_utf_16_both_ways("\u007F", "\x00\x7F")
+ check_utf_16_both_ways("\u0080", "\x00\x80")
+ check_utf_16_both_ways("\u0555", "\x05\x55")
+ check_utf_16_both_ways("\u04AA", "\x04\xAA")
+ check_utf_16_both_ways("\u0333", "\x03\x33")
+ check_utf_16_both_ways("\u04CC", "\x04\xCC")
+ check_utf_16_both_ways("\u00F0", "\x00\xF0")
+ check_utf_16_both_ways("\u070F", "\x07\x0F")
+ check_utf_16_both_ways("\u07FF", "\x07\xFF")
+ check_utf_16_both_ways("\u0800", "\x08\x00")
+ check_utf_16_both_ways("\uD7FF", "\xD7\xFF")
+ check_utf_16_both_ways("\uE000", "\xE0\x00")
+ check_utf_16_both_ways("\uFFFF", "\xFF\xFF")
+ check_utf_16_both_ways("\u5555", "\x55\x55")
+ check_utf_16_both_ways("\uAAAA", "\xAA\xAA")
+ check_utf_16_both_ways("\u3333", "\x33\x33")
+ check_utf_16_both_ways("\uCCCC", "\xCC\xCC")
+ check_utf_16_both_ways("\uF0F0", "\xF0\xF0")
+ check_utf_16_both_ways("\u0F0F", "\x0F\x0F")
+ check_utf_16_both_ways("\uFF00", "\xFF\x00")
+ check_utf_16_both_ways("\u00FF", "\x00\xFF")
+ # outer planes
+ check_utf_16_both_ways("\u{10000}", "\xD8\x00\xDC\x00")
+ check_utf_16_both_ways("\u{FFFFF}", "\xDB\xBF\xDF\xFF")
+ check_utf_16_both_ways("\u{100000}", "\xDB\xC0\xDC\x00")
+ check_utf_16_both_ways("\u{10FFFF}", "\xDB\xFF\xDF\xFF")
+ check_utf_16_both_ways("\u{105555}", "\xDB\xD5\xDD\x55")
+ check_utf_16_both_ways("\u{55555}", "\xD9\x15\xDD\x55")
+ check_utf_16_both_ways("\u{AAAAA}", "\xDA\x6A\xDE\xAA")
+ check_utf_16_both_ways("\u{33333}", "\xD8\x8C\xDF\x33")
+ check_utf_16_both_ways("\u{CCCCC}", "\xDA\xF3\xDC\xCC")
+ check_utf_16_both_ways("\u{8F0F0}", "\xD9\xFC\xDC\xF0")
+ check_utf_16_both_ways("\u{F0F0F}", "\xDB\x83\xDF\x0F")
+ check_utf_16_both_ways("\u{8FF00}", "\xD9\xFF\xDF\x00")
+ check_utf_16_both_ways("\u{F00FF}", "\xDB\x80\xDC\xFF")
+ end
+
+ def check_utf_32_both_ways(utf8, raw)
+ copy = raw.dup
+ 0.step(copy.length-1, 4) do |i|
+ copy[i+3], copy[i+2], copy[i+1], copy[i] = copy[i], copy[i+1], copy[i+2], copy[i+3]
+ end
+ check_both_ways(utf8, raw, 'utf-32be')
+ #check_both_ways(utf8, copy, 'utf-32le')
+ end
+
+ def test_utf_32
+ check_utf_32_both_ways("abc", "\x00\x00\x00a\x00\x00\x00b\x00\x00\x00c")
+ check_utf_32_both_ways("\u00E9", "\x00\x00\x00\xE9");
+ check_utf_32_both_ways("\u00E9\u0070\u00E9\u0065",
+ "\x00\x00\x00\xE9\x00\x00\x00\x70\x00\x00\x00\xE9\x00\x00\x00\x65") # épée
+ check_utf_32_both_ways("\u677E\u672C\u884C\u5F18",
+ "\x00\x00\x67\x7E\x00\x00\x67\x2C\x00\x00\x88\x4C\x00\x00\x5F\x18") # æ¾æœ¬è¡Œå¼˜
+ check_utf_32_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66",
+ "\x00\x00\x97\x52\x00\x00\x5C\x71\x00\x00\x5B\x66\x00\x00\x96\x62\x00\x00\x59\x27\x00\x00\x5B\x66") # é’山学院大学
+ check_utf_32_both_ways("Martin D\u00FCrst",
+ "\x00\x00\x00M\x00\x00\x00a\x00\x00\x00r\x00\x00\x00t\x00\x00\x00i\x00\x00\x00n\x00\x00\x00 \x00\x00\x00D\x00\x00\x00\xFC\x00\x00\x00r\x00\x00\x00s\x00\x00\x00t") # Martin Dürst
+ # BMP
+ check_utf_32_both_ways("\u0000", "\x00\x00\x00\x00")
+ check_utf_32_both_ways("\u007F", "\x00\x00\x00\x7F")
+ check_utf_32_both_ways("\u0080", "\x00\x00\x00\x80")
+ check_utf_32_both_ways("\u0555", "\x00\x00\x05\x55")
+ check_utf_32_both_ways("\u04AA", "\x00\x00\x04\xAA")
+ check_utf_32_both_ways("\u0333", "\x00\x00\x03\x33")
+ check_utf_32_both_ways("\u04CC", "\x00\x00\x04\xCC")
+ check_utf_32_both_ways("\u00F0", "\x00\x00\x00\xF0")
+ check_utf_32_both_ways("\u070F", "\x00\x00\x07\x0F")
+ check_utf_32_both_ways("\u07FF", "\x00\x00\x07\xFF")
+ check_utf_32_both_ways("\u0800", "\x00\x00\x08\x00")
+ check_utf_32_both_ways("\uD7FF", "\x00\x00\xD7\xFF")
+ check_utf_32_both_ways("\uE000", "\x00\x00\xE0\x00")
+ check_utf_32_both_ways("\uFFFF", "\x00\x00\xFF\xFF")
+ check_utf_32_both_ways("\u5555", "\x00\x00\x55\x55")
+ check_utf_32_both_ways("\uAAAA", "\x00\x00\xAA\xAA")
+ check_utf_32_both_ways("\u3333", "\x00\x00\x33\x33")
+ check_utf_32_both_ways("\uCCCC", "\x00\x00\xCC\xCC")
+ check_utf_32_both_ways("\uF0F0", "\x00\x00\xF0\xF0")
+ check_utf_32_both_ways("\u0F0F", "\x00\x00\x0F\x0F")
+ check_utf_32_both_ways("\uFF00", "\x00\x00\xFF\x00")
+ check_utf_32_both_ways("\u00FF", "\x00\x00\x00\xFF")
+ # outer planes
+ check_utf_32_both_ways("\u{10000}", "\x00\x01\x00\x00")
+ check_utf_32_both_ways("\u{FFFFF}", "\x00\x0F\xFF\xFF")
+ check_utf_32_both_ways("\u{100000}","\x00\x10\x00\x00")
+ check_utf_32_both_ways("\u{10FFFF}","\x00\x10\xFF\xFF")
+ check_utf_32_both_ways("\u{105555}","\x00\x10\x55\x55")
+ check_utf_32_both_ways("\u{55555}", "\x00\x05\x55\x55")
+ check_utf_32_both_ways("\u{AAAAA}", "\x00\x0A\xAA\xAA")
+ check_utf_32_both_ways("\u{33333}", "\x00\x03\x33\x33")
+ check_utf_32_both_ways("\u{CCCCC}", "\x00\x0C\xCC\xCC")
+ check_utf_32_both_ways("\u{8F0F0}", "\x00\x08\xF0\xF0")
+ check_utf_32_both_ways("\u{F0F0F}", "\x00\x0F\x0F\x0F")
+ check_utf_32_both_ways("\u{8FF00}", "\x00\x08\xFF\x00")
+ check_utf_32_both_ways("\u{F00FF}", "\x00\x0F\x00\xFF")
+ end
+
+ def test_invalid_ignore
+ # arguments only
+ assert_nothing_raised { 'abc'.encode('utf-8', invalid: :ignore) }
+ # check handling of UTF-8 ill-formed subsequences
+ assert_equal("\x00\x41\x00\x3E\x00\x42".force_encoding('UTF-16BE'),
+ "\x41\xC2\x3E\x42".encode('UTF-16BE', 'UTF-8', invalid: :ignore))
+ assert_equal("\x00\x41\x00\xF1\x00\x42".force_encoding('UTF-16BE'),
+ "\x41\xC2\xC3\xB1\x42".encode('UTF-16BE', 'UTF-8', invalid: :ignore))
+ assert_equal("\x00\x42".force_encoding('UTF-16BE'),
+ "\xF0\x80\x80\x42".encode('UTF-16BE', 'UTF-8', invalid: :ignore))
+ assert_equal(''.force_encoding('UTF-16BE'),
+ "\x82\xAB".encode('UTF-16BE', 'UTF-8', invalid: :ignore))
+
+ assert_equal("\e$B!!\e(B".force_encoding("ISO-2022-JP"),
+ "\xA1\xA1\xFF".encode("ISO-2022-JP", "EUC-JP", invalid: :ignore))
+ assert_equal("\e$B\x24\x22\x24\x24\e(B".force_encoding("ISO-2022-JP"),
+ "\xA4\xA2\xFF\xA4\xA4".encode("ISO-2022-JP", "EUC-JP", invalid: :ignore))
+ assert_equal("\e$B\x24\x22\x24\x24\e(B".force_encoding("ISO-2022-JP"),
+ "\xA4\xA2\xFF\xFF\xA4\xA4".encode("ISO-2022-JP", "EUC-JP", invalid: :ignore))
+ end
+
+ def test_invalid_replace
+ # arguments only
+ assert_nothing_raised { 'abc'.encode('UTF-8', invalid: :replace) }
+ assert_equal("\xEF\xBF\xBD".force_encoding("UTF-8"),
+ "\x80".encode("UTF-8", "UTF-16BE", invalid: :replace))
+ assert_equal("\xFF\xFD".force_encoding("UTF-16BE"),
+ "\x80".encode("UTF-16BE", "UTF-8", invalid: :replace))
+ assert_equal("\xFD\xFF".force_encoding("UTF-16LE"),
+ "\x80".encode("UTF-16LE", "UTF-8", invalid: :replace))
+ assert_equal("\x00\x00\xFF\xFD".force_encoding("UTF-32BE"),
+ "\x80".encode("UTF-32BE", "UTF-8", invalid: :replace))
+ assert_equal("\xFD\xFF\x00\x00".force_encoding("UTF-32LE"),
+ "\x80".encode("UTF-32LE", "UTF-8", invalid: :replace))
+
+ assert_equal("\uFFFD!",
+ "\xdc\x00\x00!".encode("utf-8", "utf-16be", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\xd8\x00\x00!".encode("utf-8", "utf-16be", :invalid=>:replace))
+
+ assert_equal("\uFFFD!",
+ "\x00\xdc!\x00".encode("utf-8", "utf-16le", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\x00\xd8!\x00".encode("utf-8", "utf-16le", :invalid=>:replace))
+
+ assert_equal("\uFFFD!",
+ "\x01\x00\x00\x00\x00\x00\x00!".encode("utf-8", "utf-32be", :invalid=>:replace), "[ruby-dev:35726]")
+ assert_equal("\uFFFD!",
+ "\x00\xff\x00\x00\x00\x00\x00!".encode("utf-8", "utf-32be", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\x00\x00\xd8\x00\x00\x00\x00!".encode("utf-8", "utf-32be", :invalid=>:replace))
+
+ assert_equal("\uFFFD!",
+ "\x00\x00\x00\xff!\x00\x00\x00".encode("utf-8", "utf-32le", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\x00\x00\xff\x00!\x00\x00\x00".encode("utf-8", "utf-32le", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\x00\xd8\x00\x00!\x00\x00\x00".encode("utf-8", "utf-32le", :invalid=>:replace))
+
+ assert_equal("\uFFFD!",
+ "\xff!".encode("utf-8", "euc-jp", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\xa1!".encode("utf-8", "euc-jp", :invalid=>:replace))
+ assert_equal("\uFFFD!",
+ "\x8f\xa1!".encode("utf-8", "euc-jp", :invalid=>:replace))
+
+ assert_equal("?",
+ "\xdc\x00".encode("EUC-JP", "UTF-16BE", :invalid=>:replace), "[ruby-dev:35776]")
+ assert_equal("ab?cd?ef",
+ "\0a\0b\xdc\x00\0c\0d\xdf\x00\0e\0f".encode("EUC-JP", "UTF-16BE", :invalid=>:replace))
+
+ assert_equal("\e$B!!\e(B?".force_encoding("ISO-2022-JP"),
+ "\xA1\xA1\xFF".encode("ISO-2022-JP", "EUC-JP", invalid: :replace))
+ assert_equal("\e$B\x24\x22\e(B?\e$B\x24\x24\e(B".force_encoding("ISO-2022-JP"),
+ "\xA4\xA2\xFF\xA4\xA4".encode("ISO-2022-JP", "EUC-JP", invalid: :replace))
+ assert_equal("\e$B\x24\x22\e(B??\e$B\x24\x24\e(B".force_encoding("ISO-2022-JP"),
+ "\xA4\xA2\xFF\xFF\xA4\xA4".encode("ISO-2022-JP", "EUC-JP", invalid: :replace))
+ end
+
+ def test_undef_replace
+ assert_equal("?", "\u20AC".encode("EUC-JP", :undef=>:replace), "[ruby-dev:35709]")
+ end
+
+ def test_shift_jis
+ check_both_ways("\u3000", "\x81\x40", 'shift_jis') # full-width space
+ check_both_ways("\u00D7", "\x81\x7E", 'shift_jis') # ×
+ check_both_ways("\u00F7", "\x81\x80", 'shift_jis') # ÷
+ check_both_ways("\u25C7", "\x81\x9E", 'shift_jis') # â—‡
+ check_both_ways("\u25C6", "\x81\x9F", 'shift_jis') # â—†
+ check_both_ways("\u25EF", "\x81\xFC", 'shift_jis') # â—¯
+ check_both_ways("\u6A97", "\x9F\x40", 'shift_jis') # 檗
+ check_both_ways("\u6BEF", "\x9F\x7E", 'shift_jis') # 毯
+ check_both_ways("\u9EBE", "\x9F\x80", 'shift_jis') # 麾
+ check_both_ways("\u6CBE", "\x9F\x9E", 'shift_jis') # æ²¾
+ check_both_ways("\u6CBA", "\x9F\x9F", 'shift_jis') # 沺
+ check_both_ways("\u6ECC", "\x9F\xFC", 'shift_jis') # 滌
+ check_both_ways("\u6F3E", "\xE0\x40", 'shift_jis') # æ¼¾
+ check_both_ways("\u70DD", "\xE0\x7E", 'shift_jis') # çƒ
+ check_both_ways("\u70D9", "\xE0\x80", 'shift_jis') # 烙
+ check_both_ways("\u71FC", "\xE0\x9E", 'shift_jis') # 燼
+ check_both_ways("\u71F9", "\xE0\x9F", 'shift_jis') # 燹
+ check_both_ways("\u73F1", "\xE0\xFC", 'shift_jis') # ç±
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
+ check_both_ways("\u9ADC", "\xFC\x40", 'shift_jis') # 髜
+ assert_raise(Encoding::ConversionUndefined) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xFC\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefined) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
+ check_both_ways("\u677E\u672C\u884C\u5F18", "\x8f\xbc\x96\x7b\x8d\x73\x8d\x4f", 'shift_jis') # æ¾æœ¬è¡Œå¼˜
+ check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\x90\xC2\x8E\x52\x8A\x77\x89\x40\x91\xE5\x8A\x77", 'shift_jis') # é’山学院大学
+ check_both_ways("\u795E\u6797\u7FA9\u535A", "\x90\x5F\x97\xD1\x8B\x60\x94\x8E", 'shift_jis') # 神林義åš
+ end
+
+ def test_iso_2022_jp
+ assert_raise(Encoding::InvalidByteSequence) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x0e".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x80".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::ConversionUndefined) { "\u9299".encode("iso-2022-jp") }
+ assert_raise(Encoding::ConversionUndefined) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequence) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_equal("\xA1\xA1".force_encoding("euc-jp"),
+ "\e$B!!\e(B".encode("EUC-JP", "ISO-2022-JP"))
+ assert_equal("\e$B!!\e(B".force_encoding("ISO-2022-JP"),
+ "\xA1\xA1".encode("ISO-2022-JP", "EUC-JP"))
+ end
+
+ def test_iso_2022_jp_1
+ # check_both_ways("\u9299", "\x1b$(Dd!\x1b(B", "iso-2022-jp-1") # JIS X 0212 区68 点01 銙
+ end
+
+ def test_unicode_public_review_issue_121 # see http://www.unicode.org/review/pr-121.html
+ # assert_equal("\x00\x61\xFF\xFD\x00\x62".force_encoding('UTF-16BE'),
+ # "\x61\xF1\x80\x80\xE1\x80\xC2\x62".encode('UTF-16BE', 'UTF-8', invalid: :replace)) # option 1
+ assert_equal("\x00\x61\xFF\xFD\xFF\xFD\xFF\xFD\x00\x62".force_encoding('UTF-16BE'),
+ "\x61\xF1\x80\x80\xE1\x80\xC2\x62".encode('UTF-16BE', 'UTF-8', invalid: :replace)) # option 2
+ assert_equal("\x61\x00\xFD\xFF\xFD\xFF\xFD\xFF\x62\x00".force_encoding('UTF-16LE'),
+ "\x61\xF1\x80\x80\xE1\x80\xC2\x62".encode('UTF-16LE', 'UTF-8', invalid: :replace)) # option 2
+ # assert_equal("\x00\x61\xFF\xFD\xFF\xFD\xFF\xFD\xFF\xFD\xFF\xFD\xFF\xFD\x00\x62".force_encoding('UTF-16BE'),
+ # "\x61\xF1\x80\x80\xE1\x80\xC2\x62".encode('UTF-16BE', 'UTF-8', invalid: :replace)) # option 3
+ end
+end
diff --git a/trunk/test/ruby/test_unicode_escape.rb b/trunk/test/ruby/test_unicode_escape.rb
new file mode 100644
index 0000000000..e86489ec5c
--- /dev/null
+++ b/trunk/test/ruby/test_unicode_escape.rb
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+
+require 'test/unit'
+
+class TestUnicodeEscape < Test::Unit::TestCase
+ def test_basic
+ assert_equal('Matz - æ¾æœ¬è¡Œå¼˜',
+ "Matz - \u677E\u672C\u884C\u5F18")
+ assert_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚',
+ "Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D")
+ assert_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚',
+ "Matz - \u{307E}\u{3064}\u{3082}\u{3068} \u{3086}\u{304D}\u{3072}\u{308D}")
+ assert_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚',
+ "Matz - \u{307E 3064 3082 3068 20 3086 304D 3072 308D}")
+ assert_equal("Aoyama Gakuin University - \xE9\x9D\x92\xE5\xB1\xB1\xE5\xAD\xA6\xE9\x99\xA2\xE5\xA4\xA7\xE5\xAD\xA6",
+ "Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66")
+ assert_equal('Aoyama Gakuin University - é’山学院大学',
+ "Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66")
+ assert_equal('é’山学院大学', "\u9752\u5C71\u5B66\u9662\u5927\u5B66")
+ assert_equal("Martin D\xC3\xBCrst", "Martin D\u00FCrst")
+ assert_equal('Martin Dürst', "Martin D\u00FCrst")
+ assert_equal('ü', "\u00FC")
+ assert_equal("Martin D\xC3\xBCrst", "Martin D\u{FC}rst")
+ assert_equal('Martin Dürst', "Martin D\u{FC}rst")
+ assert_equal('ü', "\u{FC}")
+ assert_equal('ü', %Q|\u{FC}|)
+ assert_equal('ü', %W{\u{FC}}[0])
+
+ # \u escapes in here documents
+ assert_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚', <<EOS.chop)
+Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D
+EOS
+
+ assert_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚', <<"EOS".chop)
+Matz - \u{307E 3064 3082 3068} \u{3086 304D 3072 308D}
+EOS
+ assert_not_equal('Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚', <<'EOS'.chop)
+Matz - \u{307E 3064 3082 3068} \u{3086 304D 3072 308D}
+EOS
+
+ # single-quoted things don't expand \u
+ assert_not_equal('ü', '\u{FC}')
+ assert_not_equal('ü', %q|\u{FC}|)
+ assert_not_equal('ü', %w{\u{FC}}[0])
+ assert_equal('\u00fc', "\\" + "u00fc")
+
+ # \u in %x strings
+ assert_match(/^("?)A\1$/, `echo "\u0041"`) #"
+ assert_match(/^("?)A\1$/, %x{echo "\u0041"}) #"
+ assert_match(/^("?)ü\1$/, `echo "\u{FC}"`.force_encoding("utf-8")) #"
+
+ # \u in quoted symbols
+ assert_equal(:A, :"\u0041")
+ assert_equal(:a, :"\u0061")
+ assert_equal(:ã¾, :ã¾)
+ assert_equal(:ü, :ü)
+ assert_equal(:"\u{41}", :"\u0041")
+ assert_equal(:ü, :"\u{fc}")
+
+ # the NUL character is not allowed in symbols
+ assert_raise(SyntaxError) { eval %q(:"\u{0}")}
+ assert_raise(SyntaxError) { eval %q(:"\u0000")}
+ assert_raise(SyntaxError) { eval %q(:"\u{fc 0 0041}")}
+ assert_raise(SyntaxError) { eval %q(:"\x00")}
+ assert_raise(SyntaxError) { eval %q(:"\0")}
+ end
+
+ def test_regexp
+
+ # Compare regexps to regexps
+ assert_not_equal(/Yukihiro Matsumoto - æ¾æœ¬è¡Œå¼˜/,
+ /Yukihiro Matsumoto - \u677E\u672C\u884C\u5F18/)
+ assert_not_equal(/Yukihiro Matsumoto - æ¾æœ¬è¡Œå¼˜/,
+ /Yukihiro Matsumoto - \u{677E 672C 884C 5F18}/)
+ assert_not_equal(/Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚/,
+ /Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D/)
+ assert_not_equal(/Aoyama Gakuin University - é’山学院大学/,
+ /Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66/)
+ assert_not_equal(/é’山学院大学/, /\u9752\u5C71\u5B66\u9662\u5927\u5B66/)
+ assert_not_equal(/Martin Dürst/, /Martin D\u00FCrst/)
+ assert_not_equal(/ü/, /\u00FC/)
+ assert_not_equal(/Martin Dürst/, /Martin D\u{FC}rst/)
+ assert_not_equal(/ü/, /\u{FC}/)
+ assert_not_equal(/ü/, %r{\u{FC}})
+ assert_not_equal(/ü/i, %r{\u00FC}i)
+
+ assert_equal('Yukihiro Matsumoto - \u677E\u672C\u884C\u5F18',
+ /Yukihiro Matsumoto - \u677E\u672C\u884C\u5F18/.source)
+ assert_equal('Yukihiro Matsumoto - \u{677E 672C 884C 5F18}',
+ /Yukihiro Matsumoto - \u{677E 672C 884C 5F18}/.source)
+ assert_equal('Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D',
+ /Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D/.source)
+ assert_equal('Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66',
+ /Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66/.source)
+ assert_equal('\u9752\u5C71\u5B66\u9662\u5927\u5B66',
+ /\u9752\u5C71\u5B66\u9662\u5927\u5B66/.source)
+ assert_equal('Martin D\u00FCrst', /Martin D\u00FCrst/.source)
+ assert_equal('\u00FC', /\u00FC/.source)
+ assert_equal('Martin D\u{FC}rst', /Martin D\u{FC}rst/.source)
+ assert_equal('\u{FC}', /\u{FC}/.source)
+ assert_equal('\u{FC}', %r{\u{FC}}.source)
+ assert_equal('\u00FC', %r{\u00FC}i.source)
+
+ # match strings to regexps
+ assert_equal(0, "Yukihiro Matsumoto - æ¾æœ¬è¡Œå¼˜" =~ /Yukihiro Matsumoto - \u677E\u672C\u884C\u5F18/)
+ assert_equal(0, "Yukihiro Matsumoto - \u677E\u672C\u884C\u5F18" =~ /Yukihiro Matsumoto - \u677E\u672C\u884C/)
+ assert_equal(0, "Yukihiro Matsumoto - æ¾æœ¬è¡Œå¼˜" =~ /Yukihiro Matsumoto - \u{677E 672C 884C 5F18}/)
+ assert_equal(0, %Q{Yukihiro Matsumoto - \u{677E 672C 884C 5F18}} =~ /Yukihiro Matsumoto - \u{677E 672C 884C 5F18}/)
+ assert_equal(0, "Matz - ã¾ã¤ã‚‚㨠ゆãã²ã‚" =~ /Matz - \u307E\u3064\u3082\u3068 \u3086\u304D\u3072\u308D/)
+ assert_equal(0, "Aoyama Gakuin University - é’山学院大学" =~ /Aoyama Gakuin University - \u9752\u5C71\u5B66\u9662\u5927\u5B66/)
+ assert_equal(0, "é’山学院大学" =~ /\u9752\u5C71\u5B66\u9662\u5927\u5B66/)
+ assert_equal(0, "Martin Dürst" =~ /Martin D\u00FCrst/)
+ assert_equal(0, "ü" =~ /\u00FC/)
+ assert_equal(0, "Martin Dürst" =~ /Martin D\u{FC}rst/)
+ assert_equal(0, "ü" =~ %r{\u{FC}})
+ assert_equal(0, "ü" =~ %r{\u00FC}i)
+
+ # Flip order of the two operands
+ assert_equal(0, /Martin D\u00FCrst/ =~ "Martin Dürst")
+ assert_equal(4, /\u00FC/ =~ "testü")
+ assert_equal(3, /Martin D\u{FC}rst/ =~ "fooMartin Dürstbar")
+ assert_equal(3, %r{\u{FC}} =~ "fooübar")
+
+ # Put \u in strings, literal character in regexp
+ assert_equal(0, "Martin D\u00FCrst" =~ /Martin Dürst/)
+ assert_equal(4, "test\u00FC" =~ /ü/)
+ assert_equal(3, "fooMartin D\u{FC}rstbar" =~ /Martin Dürst/)
+ assert_equal(3, %Q{foo\u{FC}bar} =~ %r<ü>)
+
+ assert_match(eval('/\u{2a}/'), "*")
+ assert_raise(SyntaxError) { eval('/\u{6666}/n') }
+ assert_raise(SyntaxError) { eval('/\u{6666}/e') }
+ assert_raise(SyntaxError) { eval('/\u{6666}/s') }
+ assert_nothing_raised { eval('/\u{6666}/u') }
+ end
+
+ def test_dynamic_regexp
+ assert_match(Regexp.new("Martin D\\u{FC}rst"), "Martin Dürst")
+ end
+
+ def test_syntax_variants
+ # all hex digits
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89AB\uCDEF")
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89AB\uCDEF")
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89ab\ucdef")
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89ab\ucdef")
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89aB\uCdEf")
+ assert_equal("\xC4\xA3\xE4\x95\xA7\xE8\xA6\xAB\xEC\xB7\xAF", "\u0123\u4567\u89aB\ucDEF")
+ end
+
+ def test_fulton
+ # examples from Hal Fulton's book (second edition), chapter 4
+ # precomposed e'pe'e
+ assert_equal('épée', "\u00E9\u0070\u00E9\u0065")
+ assert_equal('épée', "\u00E9p\u00E9e")
+ assert_equal("\xC3\xA9\x70\xC3\xA9\x65", "\u00E9\u0070\u00E9\u0065")
+ assert_equal("\xC3\xA9\x70\xC3\xA9\x65", "\u00E9p\u00E9e")
+ # decomposed e'pe'e
+ assert_equal('eÌpeÌe', "\u0065\u0301\u0070\u0065\u0301\u0065")
+ assert_equal('eÌpeÌe', "e\u0301pe\u0301e")
+ assert_equal("\x65\xCC\x81\x70\x65\xCC\x81\x65", "\u0065\u0301\u0070\u0065\u0301\u0065")
+ assert_equal("\x65\xCC\x81\x70\x65\xCC\x81\x65", "e\u0301pe\u0301e")
+ # combinations of NFC/D, NFKC/D
+ assert_equal('öffnen', "\u00F6\u0066\u0066\u006E\u0065\u006E")
+ assert_equal("\xC3\xB6ffnen", "\u00F6\u0066\u0066\u006E\u0065\u006E")
+ assert_equal('öffnen', "\u00F6ffnen")
+ assert_equal("\xC3\xB6ffnen", "\u00F6ffnen")
+ assert_equal('öffnen', "\u006F\u0308\u0066\u0066\u006E\u0065\u006E")
+ assert_equal("\x6F\xCC\x88ffnen", "\u006F\u0308\u0066\u0066\u006E\u0065\u006E")
+ assert_equal('öffnen', "o\u0308ffnen")
+ assert_equal("\x6F\xCC\x88ffnen", "o\u0308ffnen")
+ assert_equal('öffnen', "\u00F6\uFB00\u006E\u0065\u006E")
+ assert_equal("\xC3\xB6\xEF\xAC\x80nen", "\u00F6\uFB00\u006E\u0065\u006E")
+ assert_equal('öffnen', "\u00F6\uFB00nen")
+ assert_equal("\xC3\xB6\xEF\xAC\x80nen", "\u00F6\uFB00nen")
+ assert_equal('öffnen', "\u006F\u0308\uFB00\u006E\u0065\u006E")
+ assert_equal("\x6F\xCC\x88\xEF\xAC\x80nen", "\u006F\u0308\uFB00\u006E\u0065\u006E")
+ assert_equal('öffnen', "o\u0308\uFB00nen")
+ assert_equal("\x6F\xCC\x88\xEF\xAC\x80nen", "o\u0308\uFB00nen")
+ # German sharp s (sz)
+ assert_equal('Straße', "\u0053\u0074\u0072\u0061\u00DF\u0065")
+ assert_equal("\x53\x74\x72\x61\xC3\x9F\x65", "\u0053\u0074\u0072\u0061\u00DF\u0065")
+ assert_equal('Straße', "Stra\u00DFe")
+ assert_equal("\x53\x74\x72\x61\xC3\x9F\x65", "Stra\u00DFe")
+ assert_equal('Straße', "\u{53}\u{74}\u{72}\u{61}\u{DF}\u{65}")
+ assert_equal("\x53\x74\x72\x61\xC3\x9F\x65", "\u{53}\u{74}\u{72}\u{61}\u{DF}\u{65}")
+ assert_equal("\x53\x74\x72\x61\xC3\x9F\x65", "\u{53 74 72 61 DF 65}")
+ assert_equal('Straße', "Stra\u{DF}e")
+ assert_equal("\x53\x74\x72\x61\xC3\x9F\x65", "Stra\u{DF}e")
+ end
+
+ def test_edge_cases
+ # start and end of each outer plane
+ assert_equal("\xF4\x8F\xBF\xBF", "\u{10FFFF}")
+ assert_equal("\xF4\x80\x80\x80", "\u{100000}")
+ assert_equal("\xF3\xBF\xBF\xBF", "\u{FFFFF}")
+ assert_equal("\xF3\xB0\x80\x80", "\u{F0000}")
+ assert_equal("\xF3\xAF\xBF\xBF", "\u{EFFFF}")
+ assert_equal("\xF3\xA0\x80\x80", "\u{E0000}")
+ assert_equal("\xF3\x9F\xBF\xBF", "\u{DFFFF}")
+ assert_equal("\xF3\x90\x80\x80", "\u{D0000}")
+ assert_equal("\xF3\x8F\xBF\xBF", "\u{CFFFF}")
+ assert_equal("\xF3\x80\x80\x80", "\u{C0000}")
+ assert_equal("\xF2\xBF\xBF\xBF", "\u{BFFFF}")
+ assert_equal("\xF2\xB0\x80\x80", "\u{B0000}")
+ assert_equal("\xF2\xAF\xBF\xBF", "\u{AFFFF}")
+ assert_equal("\xF2\xA0\x80\x80", "\u{A0000}")
+ assert_equal("\xF2\x9F\xBF\xBF", "\u{9FFFF}")
+ assert_equal("\xF2\x90\x80\x80", "\u{90000}")
+ assert_equal("\xF2\x8F\xBF\xBF", "\u{8FFFF}")
+ assert_equal("\xF2\x80\x80\x80", "\u{80000}")
+ assert_equal("\xF1\xBF\xBF\xBF", "\u{7FFFF}")
+ assert_equal("\xF1\xB0\x80\x80", "\u{70000}")
+ assert_equal("\xF1\xAF\xBF\xBF", "\u{6FFFF}")
+ assert_equal("\xF1\xA0\x80\x80", "\u{60000}")
+ assert_equal("\xF1\x9F\xBF\xBF", "\u{5FFFF}")
+ assert_equal("\xF1\x90\x80\x80", "\u{50000}")
+ assert_equal("\xF1\x8F\xBF\xBF", "\u{4FFFF}")
+ assert_equal("\xF1\x80\x80\x80", "\u{40000}")
+ assert_equal("\xF0\xBF\xBF\xBF", "\u{3FFFF}")
+ assert_equal("\xF0\xB0\x80\x80", "\u{30000}")
+ assert_equal("\xF0\xAF\xBF\xBF", "\u{2FFFF}")
+ assert_equal("\xF0\xA0\x80\x80", "\u{20000}")
+ assert_equal("\xF0\x9F\xBF\xBF", "\u{1FFFF}")
+ assert_equal("\xF0\x90\x80\x80", "\u{10000}")
+ # BMP
+ assert_equal("\xEF\xBF\xBF", "\uFFFF")
+ assert_equal("\xEE\x80\x80", "\uE000")
+ assert_equal("\xED\x9F\xBF", "\uD7FF")
+ assert_equal("\xE0\xA0\x80", "\u0800")
+ assert_equal("\xDF\xBF", "\u07FF")
+ assert_equal("\xC2\x80", "\u0080")
+ assert_equal("\x7F", "\u007F")
+ assert_equal("\x00", "\u0000")
+ end
+
+ def test_chars
+ assert_equal(?\u0041, ?A)
+ assert_equal(?\u{79}, ?\x79)
+ assert_equal(?\u{0}, ?\000)
+ assert_equal(?\u0000, ?\000)
+ end
+
+ # Tests to make sure that disallowed cases fail
+ def test_fail
+ assert_raise(SyntaxError) { eval %q("\uabc") } # too short
+ assert_raise(SyntaxError) { eval %q("\uab") } # too short
+ assert_raise(SyntaxError) { eval %q("\ua") } # too short
+ assert_raise(SyntaxError) { eval %q("\u") } # too short
+ assert_raise(SyntaxError) { eval %q("\u{110000}") } # too high
+ assert_raise(SyntaxError) { eval %q("\u{abcdeff}") } # too long
+ assert_raise(SyntaxError) { eval %q("\ughij") } # bad hex digits
+ assert_raise(SyntaxError) { eval %q("\u{ghij}") } # bad hex digits
+
+ assert_raise(SyntaxError) { eval %q("\u{123 456 }")} # extra space
+ assert_raise(SyntaxError) { eval %q("\u{ 123 456}")} # extra space
+ assert_raise(SyntaxError) { eval %q("\u{123 456}")} # extra space
+
+# The utf-8 encoding object currently does not object to codepoints
+# in the surrogate blocks, so these do not raise an error.
+# assert_raise(SyntaxError) { "\uD800" } # surrogate block
+# assert_raise(SyntaxError) { "\uDCBA" } # surrogate block
+# assert_raise(SyntaxError) { "\uDFFF" } # surrogate block
+# assert_raise(SyntaxError) { "\uD847\uDD9A" } # surrogate pair
+
+ end
+end
diff --git a/trunk/test/ruby/test_variable.rb b/trunk/test/ruby/test_variable.rb
new file mode 100644
index 0000000000..53cd151585
--- /dev/null
+++ b/trunk/test/ruby/test_variable.rb
@@ -0,0 +1,83 @@
+require 'test/unit'
+require_relative 'envutil'
+
+class TestVariable < Test::Unit::TestCase
+ class Gods
+ @@rule = "Uranus"
+ def ruler0
+ @@rule
+ end
+
+ def self.ruler1 # <= per method definition style
+ @@rule
+ end
+ class << self # <= multiple method definition style
+ def ruler2
+ @@rule
+ end
+ end
+ end
+
+ module Olympians
+ @@rule ="Zeus"
+ def ruler3
+ @@rule
+ end
+ end
+
+ class Titans < Gods
+ @@rule = "Cronus" # modifies @@rule in Gods
+ include Olympians
+ def ruler4
+ @@rule
+ end
+ end
+
+ def test_variable
+ assert_instance_of(Fixnum, $$)
+
+ # read-only variable
+ assert_raises(NameError) do
+ $$ = 5
+ end
+
+ foobar = "foobar"
+ $_ = foobar
+ assert_equal(foobar, $_)
+
+ assert_equal("Cronus", Gods.new.ruler0)
+ assert_equal("Cronus", Gods.ruler1)
+ assert_equal("Cronus", Gods.ruler2)
+ assert_equal("Cronus", Titans.ruler1)
+ assert_equal("Cronus", Titans.ruler2)
+ atlas = Titans.new
+ assert_equal("Cronus", atlas.ruler0)
+ assert_equal("Zeus", atlas.ruler3)
+ assert_equal("Cronus", atlas.ruler4)
+ end
+
+ def test_local_variables
+ lvar = 1
+ assert_instance_of(Symbol, local_variables[0], "[ruby-dev:34008]")
+ end
+
+ def test_local_variables2
+ x = 1
+ proc do |y|
+ assert_equal([:x, :y], local_variables.sort)
+ end.call
+ end
+
+ def test_local_variables3
+ x = 1
+ proc do |y|
+ 1.times do |z|
+ assert_equal([:x, :y, :z], local_variables.sort)
+ end
+ end.call
+ end
+
+ def test_global_variable_0
+ assert_in_out_err(["-e", "$0='t'*1000;print $0"], "", /\At+\z/, [])
+ end
+end
diff --git a/trunk/test/ruby/test_whileuntil.rb b/trunk/test/ruby/test_whileuntil.rb
new file mode 100644
index 0000000000..df5bda450d
--- /dev/null
+++ b/trunk/test/ruby/test_whileuntil.rb
@@ -0,0 +1,82 @@
+require 'test/unit'
+require 'tmpdir'
+
+class TestWhileuntil < Test::Unit::TestCase
+ def test_while
+ Dir.mktmpdir("ruby_while_tmp") {|tmpdir|
+ tmpfilename = "#{tmpdir}/ruby_while_tmp.#{$$}"
+
+ tmp = open(tmpfilename, "w")
+ tmp.print "tvi925\n";
+ tmp.print "tvi920\n";
+ tmp.print "vt100\n";
+ tmp.print "Amiga\n";
+ tmp.print "paper\n";
+ tmp.close
+
+ tmp = open(tmpfilename, "r")
+ assert_instance_of(File, tmp)
+
+ while line = tmp.gets()
+ break if /vt100/ =~ line
+ end
+
+ assert(!tmp.eof?)
+ assert_match(/vt100/, line)
+ tmp.close
+
+ tmp = open(tmpfilename, "r")
+ while line = tmp.gets()
+ next if /vt100/ =~ line
+ assert_no_match(/vt100/, line)
+ end
+ assert(tmp.eof?)
+ assert_no_match(/vt100/, line)
+ tmp.close
+
+ tmp = open(tmpfilename, "r")
+ while line = tmp.gets()
+ lastline = line
+ line = line.gsub(/vt100/, 'VT100')
+ if lastline != line
+ line.gsub!('VT100', 'Vt100')
+ redo
+ end
+ assert_no_match(/vt100/, line)
+ assert_no_match(/VT100/, line)
+ end
+ assert(tmp.eof?)
+ tmp.close
+
+ sum=0
+ for i in 1..10
+ sum += i
+ i -= 1
+ if i > 0
+ redo
+ end
+ end
+ assert_equal(220, sum)
+
+ tmp = open(tmpfilename, "r")
+ while line = tmp.gets()
+ break if 3
+ assert_no_match(/vt100/, line)
+ assert_no_match(/Amiga/, line)
+ assert_no_match(/paper/, line)
+ end
+ tmp.close
+
+ File.unlink tmpfilename or `/bin/rm -f "#{tmpfilename}"`
+ assert(!File.exist?(tmpfilename))
+ }
+ end
+
+ def test_until
+ i = 0
+ until i>4
+ i+=1
+ end
+ assert(i>4)
+ end
+end
diff --git a/trunk/test/ruby/test_yield.rb b/trunk/test/ruby/test_yield.rb
new file mode 100644
index 0000000000..452c17b141
--- /dev/null
+++ b/trunk/test/ruby/test_yield.rb
@@ -0,0 +1,355 @@
+require 'test/unit'
+
+class TestRubyYield < Test::Unit::TestCase
+
+ def test_ary_each
+ ary = [1]
+ ary.each {|a, b, c, d| assert_equal [1,nil,nil,nil], [a,b,c,d] }
+ ary.each {|a, b, c| assert_equal [1,nil,nil], [a,b,c] }
+ ary.each {|a, b| assert_equal [1,nil], [a,b] }
+ ary.each {|a| assert_equal 1, a }
+ end
+
+ def test_hash_each
+ h = {:a => 1}
+ h.each do |k, v|
+ assert_equal :a, k
+ assert_equal 1, v
+ end
+ h.each do |kv|
+ assert_equal [:a, 1], kv
+ end
+ end
+
+ def test_yield_0
+ assert_equal 1, iter0 { 1 }
+ assert_equal 2, iter0 { 2 }
+ end
+
+ def iter0
+ yield
+ end
+
+ def test_yield_1
+ iter1([]) {|a, b| assert_equal [nil,nil], [a, b] }
+ iter1([1]) {|a, b| assert_equal [1,nil], [a, b] }
+ iter1([1, 2]) {|a, b| assert_equal [1,2], [a,b] }
+ iter1([1, 2, 3]) {|a, b| assert_equal [1,2], [a,b] }
+
+ iter1([]) {|a| assert_equal [], a }
+ iter1([1]) {|a| assert_equal [1], a }
+ iter1([1, 2]) {|a| assert_equal [1,2], a }
+ iter1([1, 2, 3]) {|a| assert_equal [1,2,3], a }
+ end
+
+ def iter1(args)
+ yield args
+ end
+
+ def test_yield2
+ def iter2_1() yield 1, *[2, 3] end
+ iter2_1 {|a, b, c| assert_equal [1,2,3], [a,b,c] }
+ def iter2_2() yield 1, *[] end
+ iter2_2 {|a, b, c| assert_equal [1,nil,nil], [a,b,c] }
+ def iter2_3() yield 1, *[2] end
+ iter2_3 {|a, b, c| assert_equal [1,2,nil], [a,b,c] }
+ end
+
+ def test_yield_nested
+ [[1, [2, 3]]].each {|a, (b, c)|
+ assert_equal [1,2,3], [a,b,c]
+ }
+ [[1, [2, 3]]].map {|a, (b, c)|
+ assert_equal [1,2,3], [a,b,c]
+ }
+ end
+
+ def test_with_enum
+ obj = Object
+ def obj.each
+ yield(*[])
+ end
+ obj.each{|*v| assert_equal([], [], '[ruby-dev:32392]')}
+ obj.to_enum.each{|*v| assert_equal([], [], '[ruby-dev:32392]')}
+ end
+end
+
+require_relative 'sentence'
+class TestRubyYieldGen < Test::Unit::TestCase
+ Syntax = {
+ :exp => [["0"],
+ ["nil"],
+ ["false"],
+ ["[]"],
+ ["[",:exps,"]"]],
+ :exps => [[:exp],
+ [:exp,",",:exps]],
+ :opt_block_param => [[],
+ [:block_param_def]],
+ :block_param_def => [['|', '|'],
+ ['|', :block_param, '|']],
+ :block_param => [[:f_arg, ",", :f_rest_arg, :opt_f_block_arg],
+ [:f_arg, ","],
+ [:f_arg, ',', :f_rest_arg, ",", :f_arg, :opt_f_block_arg],
+ [:f_arg, :opt_f_block_arg],
+ [:f_rest_arg, :opt_f_block_arg],
+ [:f_rest_arg, ',', :f_arg, :opt_f_block_arg],
+ [:f_block_arg]],
+ :f_arg => [[:f_arg_item],
+ [:f_arg, ',', :f_arg_item]],
+ :f_rest_arg => [['*', "var"],
+ ['*']],
+ :opt_f_block_arg => [[',', :f_block_arg],
+ []],
+ :f_block_arg => [['&', 'var']],
+ :f_arg_item => [[:f_norm_arg],
+ ['(', :f_margs, ')']],
+ :f_margs => [[:f_marg_list],
+ [:f_marg_list, ',', '*', :f_norm_arg],
+ [:f_marg_list, ',', '*', :f_norm_arg, ',', :f_marg_list],
+ [:f_marg_list, ',', '*'],
+ [:f_marg_list, ',', '*', ',', :f_marg_list],
+ [ '*', :f_norm_arg],
+ [ '*', :f_norm_arg, ',', :f_marg_list],
+ [ '*'],
+ [ '*', ',', :f_marg_list]],
+ :f_marg_list => [[:f_marg],
+ [:f_marg_list, ',', :f_marg]],
+ :f_marg => [[:f_norm_arg],
+ ['(', :f_margs, ')']],
+ :f_norm_arg => [['var']],
+
+ :command_args => [[:open_args]],
+ :open_args => [[' ',:call_args],
+ ['(', ')'],
+ ['(', :call_args2, ')']],
+ :call_args => [[:command],
+ [ :args, :opt_block_arg],
+ [ :assocs, :opt_block_arg],
+ [ :args, ',', :assocs, :opt_block_arg],
+ [ :block_arg]],
+ :call_args2 => [[:arg, ',', :args, :opt_block_arg],
+ [:arg, ',', :block_arg],
+ [ :assocs, :opt_block_arg],
+ [:arg, ',', :assocs, :opt_block_arg],
+ [:arg, ',', :args, ',', :assocs, :opt_block_arg],
+ [ :block_arg]],
+
+ :command_args_noblock => [[:open_args_noblock]],
+ :open_args_noblock => [[' ',:call_args_noblock],
+ ['(', ')'],
+ ['(', :call_args2_noblock, ')']],
+ :call_args_noblock => [[:command],
+ [ :args],
+ [ :assocs],
+ [ :args, ',', :assocs]],
+ :call_args2_noblock => [[:arg, ',', :args],
+ [ :assocs],
+ [:arg, ',', :assocs],
+ [:arg, ',', :args, ',', :assocs]],
+
+ :command => [],
+ :args => [[:arg],
+ ["*",:arg],
+ [:args,",",:arg],
+ [:args,",","*",:arg]],
+ :arg => [[:exp]],
+ :assocs => [[:assoc],
+ [:assocs, ',', :assoc]],
+ :assoc => [[:arg, '=>', :arg],
+ ['label', ':', :arg]],
+ :opt_block_arg => [[',', :block_arg],
+ []],
+ :block_arg => [['&', :arg]],
+ #:test => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']]
+ :test_proc => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']],
+ :test_lambda => [['def m() yield', :command_args_noblock, ' end; r = m(&lambda {', :block_param_def, 'vars', '}); undef m; r']],
+ :test_enum => [['o = Object.new; def o.each() yield', :command_args_noblock, ' end; r1 = r2 = nil; o.each {|*x| r1 = x }; o.to_enum.each {|*x| r2 = x }; [r1, r2]']]
+ }
+
+ def rename_var(obj)
+ vars = []
+ r = obj.subst('var') {
+ var = "v#{vars.length}"
+ vars << var
+ var
+ }
+ return r, vars
+ end
+
+ def split_by_comma(ary)
+ return [] if ary.empty?
+ result = [[]]
+ ary.each {|e|
+ if e == ','
+ result << []
+ else
+ result.last << e
+ end
+ }
+ result
+ end
+
+ def emu_return_args(*vs)
+ vs
+ end
+
+ def emu_eval_args(args)
+ if args.last == []
+ args = args[0...-1]
+ end
+ code = "emu_return_args #{args.map {|a| a.join('') }.join(",")}"
+ eval code
+ end
+
+ def emu_bind_single(arg, param, result_binding)
+ #p [:emu_bind_single, arg, param]
+ if param.length == 1 && String === param[0] && /\A[a-z0-9]+\z/ =~ param[0]
+ result_binding[param[0]] = arg
+ elsif param.length == 1 && Array === param[0] && param[0][0] == '(' && param[0][-1] == ')'
+ arg = [arg] unless Array === arg
+ emu_bind_params(arg, split_by_comma(param[0][1...-1]), false, result_binding)
+ else
+ raise "unexpected param: #{param.inspect}"
+ end
+ result_binding
+ end
+
+ def emu_bind_params(args, params, islambda, result_binding={})
+ #p [:emu_bind_params, args, params]
+ if params.last == [] # extra comma
+ params.pop
+ end
+
+ star_index = nil
+ params.each_with_index {|par, i|
+ star_index = i if par[0] == '*'
+ }
+
+ if islambda
+ if star_index
+ if args.length < params.length - 1
+ throw :emuerror, ArgumentError
+ end
+ else
+ if args.length != params.length
+ throw :emuerror, ArgumentError
+ end
+ end
+ end
+
+ # TRICK #2 : adjust mismatch on number of arguments
+ if star_index
+ pre_params = params[0...star_index]
+ rest_param = params[star_index]
+ post_params = params[(star_index+1)..-1]
+ pre_params.each {|par| emu_bind_single(args.shift, par, result_binding) }
+ if post_params.length <= args.length
+ post_params.reverse_each {|par| emu_bind_single(args.pop, par, result_binding) }
+ else
+ post_params.each {|par| emu_bind_single(args.shift, par, result_binding) }
+ end
+ if rest_param != ['*']
+ emu_bind_single(args, rest_param[1..-1], result_binding)
+ end
+ else
+ params.each_with_index {|par, i|
+ emu_bind_single(args[i], par, result_binding)
+ }
+ end
+
+ #p [args, params, result_binding]
+
+ result_binding
+ end
+
+ def emu_bind(t, islambda)
+ #puts
+ #p t
+ command_args_noblock = t[1]
+ block_param_def = t[3]
+ command_args_noblock = command_args_noblock.expand {|a| !(a[0] == '[' && a[-1] == ']') }
+ block_param_def = block_param_def.expand {|a| !(a[0] == '(' && a[-1] == ')') }
+
+ if command_args_noblock.to_a[0] == ' '
+ args = command_args_noblock.to_a[1..-1]
+ elsif command_args_noblock.to_a[0] == '(' && command_args_noblock.to_a[-1] == ')'
+ args = command_args_noblock.to_a[1...-1]
+ else
+ raise "unexpected command_args_noblock: #{command_args_noblock.inspect}"
+ end
+ args = emu_eval_args(split_by_comma(args))
+
+ params = block_param_def.to_a[1...-1]
+ params = split_by_comma(params)
+
+ #p [:emu0, args, params]
+
+ result_binding = {}
+
+ if params.last && params.last[0] == '&'
+ result_binding[params.last[1]] = nil
+ params.pop
+ end
+
+ if !islambda
+ # TRICK #1 : single array argument is expanded if there are two or more params.
+ # * block parameter is not counted.
+ # * extra comma after single param forces the expansion.
+ if args.length == 1 && Array === args[0] && 1 < params.length
+ args = args[0]
+ end
+ end
+
+ emu_bind_params(args, params, islambda, result_binding)
+ #p result_binding
+ result_binding
+ end
+
+ def emu(t, vars, islambda)
+ catch(:emuerror) {
+ emu_binding = emu_bind(t, islambda)
+ vars.map {|var| emu_binding.fetch(var, "NOVAL") }
+ }
+ end
+
+ def check_nofork(t, islambda=false)
+ t, vars = rename_var(t)
+ t = t.subst('vars') { " [#{vars.join(",")}]" }
+ emu_values = emu(t, vars, islambda)
+ s = t.to_s
+ #print "#{s}\t\t"
+ #STDOUT.flush
+ begin
+ eval_values = eval(s)
+ rescue ArgumentError
+ eval_values = ArgumentError
+ end
+ #success = emu_values == eval_values ? 'succ' : 'fail'
+ #puts "eval:#{vs_ev.inspect[1...-1].delete(' ')}\temu:#{vs_emu.inspect[1...-1].delete(' ')}\t#{success}"
+ assert_equal(emu_values, eval_values, s)
+ end
+
+ def test_yield
+ syntax = Sentence.expand_syntax(Syntax)
+ Sentence.each(syntax, :test_proc, 4) {|t|
+ check_nofork(t)
+ }
+ end
+
+ def test_yield_lambda
+ syntax = Sentence.expand_syntax(Syntax)
+ Sentence.each(syntax, :test_lambda, 4) {|t|
+ check_nofork(t, true)
+ }
+ end
+
+ def test_yield_enum
+ syntax = Sentence.expand_syntax(Syntax)
+ Sentence.each(syntax, :test_enum, 4) {|t|
+ r1, r2 = eval(t.to_s)
+ assert_equal(r1, r2, "#{t}")
+ }
+ end
+
+end
diff --git a/trunk/test/ruby/ut_eof.rb b/trunk/test/ruby/ut_eof.rb
new file mode 100644
index 0000000000..b7219ddb51
--- /dev/null
+++ b/trunk/test/ruby/ut_eof.rb
@@ -0,0 +1,128 @@
+require 'test/unit'
+
+module TestEOF
+ def test_eof_0
+ open_file("") {|f|
+ assert_equal("", f.read(0))
+ assert_equal("", f.read(0))
+ assert_equal("", f.read)
+ assert_equal("", f.read(0))
+ assert_equal("", f.read(0))
+ }
+ open_file("") {|f|
+ assert_nil(f.read(1))
+ assert_equal("", f.read)
+ assert_nil(f.read(1))
+ }
+ open_file("") {|f|
+ s = "x"
+ assert_equal("", f.read(nil, s))
+ assert_equal("", s)
+ }
+ open_file("") {|f|
+ s = "x"
+ assert_nil(f.read(10, s))
+ assert_equal("", s)
+ }
+ end
+
+ def test_eof_0_rw
+ return unless respond_to? :open_file_rw
+ open_file_rw("") {|f|
+ assert_equal("", f.read)
+ assert_equal("", f.read)
+ assert_equal(0, f.syswrite(""))
+ assert_equal("", f.read)
+ }
+ end
+
+ def test_eof_1
+ open_file("a") {|f|
+ assert_equal("", f.read(0))
+ assert_equal("a", f.read(1))
+ assert_equal("" , f.read(0))
+ assert_equal("" , f.read(0))
+ assert_equal("", f.read)
+ assert_equal("", f.read(0))
+ assert_equal("", f.read(0))
+ }
+ open_file("a") {|f|
+ assert_equal("a", f.read(1))
+ assert_nil(f.read(1))
+ }
+ open_file("a") {|f|
+ assert_equal("a", f.read(2))
+ assert_nil(f.read(1))
+ assert_equal("", f.read)
+ assert_nil(f.read(1))
+ }
+ open_file("a") {|f|
+ assert_equal("a", f.read)
+ assert_nil(f.read(1))
+ assert_equal("", f.read)
+ assert_nil(f.read(1))
+ }
+ open_file("a") {|f|
+ assert_equal("a", f.read(2))
+ assert_equal("", f.read)
+ assert_equal("", f.read)
+ }
+ open_file("a") {|f|
+ assert_equal("a", f.read)
+ assert_equal("", f.read(0))
+ }
+ open_file("a") {|f|
+ s = "x"
+ assert_equal("a", f.read(nil, s))
+ assert_equal("a", s)
+ }
+ open_file("a") {|f|
+ s = "x"
+ assert_equal("a", f.read(10, s))
+ assert_equal("a", s)
+ }
+ end
+
+ def test_eof_2
+ open_file("") {|f|
+ assert_equal("", f.read)
+ assert(f.eof?)
+ }
+ end
+
+ def test_eof_3
+ open_file("") {|f|
+ assert(f.eof?)
+ }
+ end
+
+ module Seek
+ def open_file_seek(content, pos)
+ open_file(content) do |f|
+ f.seek(pos)
+ yield f
+ end
+ end
+
+ def test_eof_0_seek
+ open_file_seek("", 10) {|f|
+ assert_equal(10, f.pos)
+ assert_equal("", f.read(0))
+ assert_equal("", f.read)
+ assert_equal("", f.read(0))
+ assert_equal("", f.read)
+ }
+ end
+
+ def test_eof_1_seek
+ open_file_seek("a", 10) {|f|
+ assert_equal("", f.read)
+ assert_equal("", f.read)
+ }
+ open_file_seek("a", 1) {|f|
+ assert_equal("", f.read)
+ assert_equal("", f.read)
+ }
+ end
+ end
+end
diff --git a/trunk/test/rubygems/bogussources.rb b/trunk/test/rubygems/bogussources.rb
new file mode 100644
index 0000000000..008e3a1de5
--- /dev/null
+++ b/trunk/test/rubygems/bogussources.rb
@@ -0,0 +1,8 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'rubygems'
+Gem.use_paths("test/mock/gems")
diff --git a/trunk/test/rubygems/data/gem-private_key.pem b/trunk/test/rubygems/data/gem-private_key.pem
new file mode 100644
index 0000000000..3e4be4cd9a
--- /dev/null
+++ b/trunk/test/rubygems/data/gem-private_key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAz0tTOtsJuHDKAEXrQx0f6DUEzBEUTSLR1fk0iEHsY9rDCQxm
+sw5Bf2UnVhdD03B4/XzIK+pat2CMQc37/vLIBuVgS7g/fzatGiM0m5rAHtycr0XU
+8Ek6zjx4iSv70OLjybY+/utHCEc838awGDMCFR21jYxgATPVwqAIyasvwbKh/Vhw
+uErFPqT9G8BKTHsaX+H+ADIRH001OmWkjB6EyjF05114kNMa0+2C7daV9hoBL3md
+hCt6zOGcapl/9LkGxhcNEUB/So16V1ZQldg9macGyWktyNTSfctlF+f8okAmicG3
+XIwaW8UTmjFCmvDs/h1R/uKpe2IOHz87n29d2QIDAQABAoIBAQCR6n/nyg+JmTtX
+/d+hGns/RTLfQpZ7xarXZ9gmoeD4WSE42VXhbIOGXXnXDAFecKl6Jb/xycGZm4if
+OZPM3rEWyZeDNWrc7WvkHiwF7GSYVMqmRg2iJqoSSla+mAtl+pBFiNfHMW6K0Tp0
+erOyFRW+L2+A9/MMZaRun6AP9URkn0jz2kwmMFf+6szmzVn6fPFzZDRI+hEeaDmi
+LBzSrfrddrIBX+xGEoBj6RmfnKBCSUVSSxOauYjd4mVjVYxvMH4SV1hXDUS5GPl5
+MbCiBb7bpNIg/8ljMoRrQiqk0XwwS7MaCqPtMhUtpSmC/zSjAfmoN7AOc/Xh69cQ
+OCMNZH9BAoGBAPBlsuuU6fg0gVTKDdR12jHx03uRRt8/nPxHnpJkZCIh9XKh1LtY
+bkumi9HZpp3mzDiaGg/rwfCwNckKx8NLhICLgkric6ClrKftxTu6C8tBAb5YDi6u
+74KYnV8lMY/unzBtIloPgM3uluS292POmrWZpKwhvHLD71MewzMor5HFAoGBANy/
+mwsBs8i3Gzk8Twjq8effhPpE7kpxhC7bhwmjX3q41EjQWDT8M6xb1P9dRSsCIebi
+kqP1yhl27dJpA8r5WqE/z89xhBvObAGRv41eXxOI0LaH2k5lJQrUeSC+51dy+BEB
+T3GXD4C5ezZHQ8Wz/oL73uikrfhD+AqOZT2YbMEFAoGBAJvWEWpOGm3f+4bvhI+Z
+5lxCG4oa3wqRvj58XvsfQRovUWGCLtlTtgwsZq8enLf3iaOXohV4Czzvva4Z4u1i
+4v5BcbEBo1scixRBOn5BWKvl9C9j/a2dkX3jWQD4p2xaj69gz8f6DNFyPTb+tNhq
+cjgO5YUASZ1MDrSfWIKteULRAoGAZkZv8x2KyofrmQ0UITGZerDYz4t4TA1kDMGx
+QwnqhtVzpXjCJWpkFotFmDsCfPaz9mErR8PtKvcrIL1/AF+fWe5Sve3+I1P0PpXk
+hf8fVdGhwbAXuRKrouTmagGI9b9Sp65PvHUcvasyJufFwqeuV8mScX87CzeSiHGI
+/ozMdnECgYEAq4+losrhe0DEmiC9zVPvwRXjbSixDsSJxHfOcqIsZqhUgBiZ4TJD
+SrkuukrMZib6BAD+PtCJS1TBbJyyvL3QecizhHSIh3ZnT0HnaRPatLEYmU65+3kE
+kTqL4ik92bJnnWowy677sydl1lzBJDVa9ZlTs7BFSd8y/0DZaUxGg2I=
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/test/rubygems/data/gem-public_cert.pem b/trunk/test/rubygems/data/gem-public_cert.pem
new file mode 100644
index 0000000000..885bf7f369
--- /dev/null
+++ b/trunk/test/rubygems/data/gem-public_cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMREwDwYDVQQDDAhydWJ5
+Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZFgNj
+b20wHhcNMDcwODAyMDMyNTQyWhcNMDgwODAxMDMyNTQyWjBBMREwDwYDVQQDDAhy
+dWJ5Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZ
+FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPS1M62wm4cMoA
+RetDHR/oNQTMERRNItHV+TSIQexj2sMJDGazDkF/ZSdWF0PTcHj9fMgr6lq3YIxB
+zfv+8sgG5WBLuD9/Nq0aIzSbmsAe3JyvRdTwSTrOPHiJK/vQ4uPJtj7+60cIRzzf
+xrAYMwIVHbWNjGABM9XCoAjJqy/BsqH9WHC4SsU+pP0bwEpMexpf4f4AMhEfTTU6
+ZaSMHoTKMXTnXXiQ0xrT7YLt1pX2GgEveZ2EK3rM4ZxqmX/0uQbGFw0RQH9KjXpX
+VlCV2D2ZpwbJaS3I1NJ9y2UX5/yiQCaJwbdcjBpbxROaMUKa8Oz+HVH+4ql7Yg4f
+Pzufb13ZAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBRYTAoj4cn8CWZMHFnHGQgoO5jyFTANBgkqhkiG9w0BAQUFAAOCAQEATRrJC05l
+dOmx67Sy3bU+AVXkOr7B9nn2Myqo9uSIAncPoElN6aHr/Q8wOOjtok4r0JcHPe1e
+eotDCZUE1Jkl13Tpv26rOfOOUHtGlyAIAtpsUGOraaJkSut4WKLr1/KckyAAEtgP
+c13A0s0mEiWFRuYxIdEi54561pTT2qQBE/DUPGoYD5rUg9XYAlSovMMwG99Oca7L
+cI6vCymr1bzzddExoywBNOy0fbBT62I3ICBGbH5yOVVKVmlxeo2Zp10FCj0kDrnq
+OuMJSDr5I2XPYqoC+W4YSbwn55o2jGIUX1lOq2Hvj4tFgSxlnJZn0tUhBfR3gSOn
+IFnrqu8PlZsLFw==
+-----END CERTIFICATE-----
diff --git a/trunk/test/rubygems/fake_certlib/openssl.rb b/trunk/test/rubygems/fake_certlib/openssl.rb
new file mode 100644
index 0000000000..948110f078
--- /dev/null
+++ b/trunk/test/rubygems/fake_certlib/openssl.rb
@@ -0,0 +1,7 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+fail LoadError, "no such file to load -- openssl"
diff --git a/trunk/test/rubygems/functional.rb b/trunk/test/rubygems/functional.rb
new file mode 100644
index 0000000000..4838167324
--- /dev/null
+++ b/trunk/test/rubygems/functional.rb
@@ -0,0 +1,95 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require 'rubygems'
+require 'test/insure_session'
+require 'rubygems/format'
+require 'rubygems/command_manager'
+
+class FunctionalTest < Test::Unit::TestCase
+ def setup
+ @gem_path = File.expand_path("bin/gem")
+ lib_path = File.expand_path("lib")
+ @ruby_options = "-I#{lib_path} -I."
+ @verbose = false
+ end
+
+ def test_gem_help_options
+ gem_nossl 'help options'
+ assert_match(/Usage:/, @out, @err)
+ assert_status
+ end
+
+ def test_gem_help_commands
+ gem_nossl 'help commands'
+ assert_match(/gem install/, @out)
+ assert_status
+ end
+
+ def test_gem_no_args_shows_help
+ gem_nossl
+ assert_match(/Usage:/, @out)
+ assert_status 1
+ end
+
+ # This test is disabled because of the insanely long time it takes
+ # to time out.
+ def xtest_bogus_source_hoses_up_remote_install_but_gem_command_gives_decent_error_message
+ @ruby_options << " -rtest/bogussources"
+ gem_nossl "install asdf --remote"
+ assert_match(/error/im, @err)
+ assert_status 1
+ end
+
+ def test_all_command_helps
+ mgr = Gem::CommandManager.new
+ mgr.command_names.each do |cmdname|
+ gem_nossl "help #{cmdname}"
+ assert_match(/Usage: gem #{cmdname}/, @out,
+ "should see help for #{cmdname}")
+ end
+ end
+
+ # :section: Help Methods
+
+ # Run a gem command without the SSL library.
+ def gem_nossl(options="")
+ old_options = @ruby_options.dup
+ @ruby_options << " -Itest/fake_certlib"
+ gem(options)
+ ensure
+ @ruby_options = old_options
+ end
+
+ # Run a gem command with the SSL library.
+ def gem_withssl(options="")
+ gem(options)
+ end
+
+ # Run a gem command for the functional test.
+ def gem(options="")
+ shell = Session::Shell.new
+ options = options + " --config-file missing_file" if options !~ /--config-file/
+ command = "#{Gem.ruby} #{@ruby_options} #{@gem_path} #{options}"
+ puts "\n\nCOMMAND: [#{command}]" if @verbose
+ @out, @err = shell.execute command
+ @status = shell.exit_status
+ puts "STATUS: [#{@status}]" if @verbose
+ puts "OUTPUT: [#{@out}]" if @verbose
+ puts "ERROR: [#{@err}]" if @verbose
+ puts "PWD: [#{Dir.pwd}]" if @verbose
+ shell.close
+ end
+
+ private
+
+ def assert_status(expected_status=0)
+ assert_equal expected_status, @status
+ end
+
+end
diff --git a/trunk/test/rubygems/gem_installer_test_case.rb b/trunk/test/rubygems/gem_installer_test_case.rb
new file mode 100644
index 0000000000..0d684eb1eb
--- /dev/null
+++ b/trunk/test/rubygems/gem_installer_test_case.rb
@@ -0,0 +1,86 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/installer'
+
+class Gem::Installer
+ attr_accessor :gem_dir
+
+ attr_writer :format
+ attr_writer :gem_home
+ attr_writer :env_shebang
+ attr_writer :ignore_dependencies
+ attr_writer :format_executable
+ attr_writer :security_policy
+ attr_writer :spec
+ attr_writer :wrappers
+end
+
+class GemInstallerTestCase < RubyGemTestCase
+
+ def setup
+ super
+
+ @spec = quick_gem "a"
+ @gem = File.join @tempdir, "#{@spec.full_name}.gem"
+
+ util_build_gem @spec
+ FileUtils.mv File.join(@gemhome, 'cache', "#{@spec.full_name}.gem"),
+ @tempdir
+
+ @installer = Gem::Installer.new @gem
+ @installer.gem_dir = util_gem_dir
+ @installer.gem_home = @gemhome
+ @installer.spec = @spec
+ end
+
+ def util_gem_bindir(version = '2')
+ File.join util_gem_dir(version), "bin"
+ end
+
+ def util_gem_dir(version = '2')
+ File.join @gemhome, "gems", "a-#{version}" # HACK
+ end
+
+ def util_inst_bindir
+ File.join @gemhome, "bin"
+ end
+
+ def util_make_exec(version = '2', shebang = "#!/usr/bin/ruby")
+ @spec.executables = ["my_exec"]
+
+ FileUtils.mkdir_p util_gem_bindir(version)
+ exec_file = @installer.formatted_program_filename "my_exec"
+ exec_path = File.join util_gem_bindir(version), exec_file
+ File.open exec_path, 'w' do |f|
+ f.puts shebang
+ end
+ end
+
+ def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic
+ @spec.files = File.join('lib', 'code.rb')
+ @spec.executables << 'executable'
+ @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
+
+ Dir.chdir @tempdir do
+ FileUtils.mkdir_p 'bin'
+ FileUtils.mkdir_p 'lib'
+ FileUtils.mkdir_p File.join('ext', 'a')
+ File.open File.join('bin', 'executable'), 'w' do |f| f.puts '1' end
+ File.open File.join('lib', 'code.rb'), 'w' do |f| f.puts '1' end
+ File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f|
+ f << <<-EOF
+ File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end
+ EOF
+ end
+
+ use_ui ui do
+ FileUtils.rm @gem
+ Gem::Builder.new(@spec).build
+ end
+ end
+
+ @installer = Gem::Installer.new @gem
+ end
+
+end
+
diff --git a/trunk/test/rubygems/gem_package_tar_test_case.rb b/trunk/test/rubygems/gem_package_tar_test_case.rb
new file mode 100644
index 0000000000..756b30ef27
--- /dev/null
+++ b/trunk/test/rubygems/gem_package_tar_test_case.rb
@@ -0,0 +1,146 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+
+class File
+
+ # straight from setup.rb
+ def self.dir?(path)
+ # for corrupted windows stat()
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
+ end
+
+ def self.read_b(name)
+ File.open(name, "rb") { |f| f.read }
+ end
+
+end
+
+class TarTestCase < RubyGemTestCase
+
+ def ASCIIZ(str, length)
+ str + "\0" * (length - str.length)
+ end
+
+ def SP(s)
+ s + " "
+ end
+
+ def SP_Z(s)
+ s + " \0"
+ end
+
+ def Z(s)
+ s + "\0"
+ end
+
+ def assert_headers_equal(expected, actual)
+ expected = expected.to_s unless String === expected
+ actual = actual.to_s unless String === actual
+
+ fields = %w[
+ name 100
+ mode 8
+ uid 8
+ gid 8
+ size 12
+ mtime 12
+ checksum 8
+ typeflag 1
+ linkname 100
+ magic 6
+ version 2
+ uname 32
+ gname 32
+ devmajor 8
+ devminor 8
+ prefix 155
+ ]
+
+ offset = 0
+
+ until fields.empty? do
+ name = fields.shift
+ length = fields.shift.to_i
+
+ if name == "checksum" then
+ chksum_off = offset
+ offset += length
+ next
+ end
+
+ assert_equal expected[offset, length], actual[offset, length],
+ "Field #{name} of the tar header differs."
+
+ offset += length
+ end
+
+ assert_equal expected[chksum_off, 8], actual[chksum_off, 8]
+ end
+
+ def calc_checksum(header)
+ sum = header.unpack("C*").inject{|s,a| s + a}
+ SP(Z(to_oct(sum, 6)))
+ end
+
+ def header(type, fname, dname, length, mode, checksum = nil)
+ checksum ||= " " * 8
+
+ arr = [ # struct tarfile_entry_posix
+ ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled)
+ Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null
+ Z(to_oct(0, 7)), # char uid[8]; ditto
+ Z(to_oct(0, 7)), # char gid[8]; ditto
+ Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null
+ Z(to_oct(0, 11)), # char mtime[12]; 0 padded, octal, null
+ checksum, # char checksum[8]; 0 padded, octal, null, space
+ type, # char typeflag[1]; file: "0" dir: "5"
+ "\0" * 100, # char linkname[100]; ASCII + (Z unless filled)
+ "ustar\0", # char magic[6]; "ustar\0"
+ "00", # char version[2]; "00"
+ ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ
+ ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ
+ Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null
+ Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null
+ ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled)
+ ]
+
+ format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155"
+ h = if RUBY_VERSION >= "1.9" then
+ arr.join
+ else
+ arr = arr.join("").split(//).map{|x| x[0]}
+ arr.pack format
+ end
+ ret = h + "\0" * (512 - h.size)
+ assert_equal(512, ret.size)
+ ret
+ end
+
+ def tar_dir_header(name, prefix, mode)
+ h = header("5", name, prefix, 0, mode)
+ checksum = calc_checksum(h)
+ header("5", name, prefix, 0, mode, checksum)
+ end
+
+ def tar_file_header(fname, dname, mode, length)
+ h = header("0", fname, dname, length, mode)
+ checksum = calc_checksum(h)
+ header("0", fname, dname, length, mode, checksum)
+ end
+
+ def to_oct(n, pad_size)
+ "%0#{pad_size}o" % n
+ end
+
+ def util_entry(tar)
+ io = TempIO.new tar
+ header = Gem::Package::TarHeader.from io
+ entry = Gem::Package::TarReader::Entry.new header, io
+ end
+
+ def util_dir_entry
+ util_entry tar_dir_header("foo", "bar", 0)
+ end
+
+end
+
diff --git a/trunk/test/rubygems/gemutilities.rb b/trunk/test/rubygems/gemutilities.rb
new file mode 100644
index 0000000000..0ab2c5272c
--- /dev/null
+++ b/trunk/test/rubygems/gemutilities.rb
@@ -0,0 +1,441 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+at_exit { $SAFE = 1 }
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+
+require 'fileutils'
+require 'test/unit'
+require 'tmpdir'
+require 'uri'
+require 'rubygems/package'
+require 'rubygems/test_utilities'
+
+require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
+
+module Gem
+ def self.source_index=(si)
+ @@source_index = si
+ end
+
+ def self.win_platform=(val)
+ @@win_platform = val
+ end
+
+ module DefaultUserInteraction
+ @ui = MockGemUi.new
+ end
+end
+
+class RubyGemTestCase < Test::Unit::TestCase
+
+ include Gem::DefaultUserInteraction
+
+ undef_method :default_test if instance_methods.include? 'default_test' or
+ instance_methods.include? :default_test
+
+ def setup
+ super
+
+ @ui = MockGemUi.new
+ tmpdir = nil
+ Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp
+ @tempdir = File.join tmpdir, "test_rubygems_#{$$}"
+ @tempdir.untaint
+ @gemhome = File.join @tempdir, "gemhome"
+ @gemcache = File.join(@gemhome, "source_cache")
+ @usrcache = File.join(@gemhome, ".gem", "user_cache")
+ @latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
+ @userhome = File.join @tempdir, 'userhome'
+
+ ENV['HOME'] = @userhome
+ Gem.instance_variable_set :@user_home, nil
+
+ FileUtils.mkdir_p @gemhome
+ FileUtils.mkdir_p @userhome
+
+ ENV['GEMCACHE'] = @usrcache
+ Gem.use_paths(@gemhome)
+ Gem.loaded_specs.clear
+
+ Gem.configuration.verbose = true
+ Gem.configuration.update_sources = true
+
+ @gem_repo = "http://gems.example.com/"
+ @uri = URI.parse @gem_repo
+ Gem.sources.replace [@gem_repo]
+
+ Gem::SpecFetcher.fetcher = nil
+
+ @orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
+ Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:RUBY_INSTALL_NAME]
+
+ @orig_arch = Gem::ConfigMap[:arch]
+
+ if win_platform?
+ util_set_arch 'i386-mswin32'
+ else
+ util_set_arch 'i686-darwin8.10.1'
+ end
+
+ @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
+
+ @private_key = File.expand_path File.join(File.dirname(__FILE__),
+ 'private_key.pem')
+ @public_cert = File.expand_path File.join(File.dirname(__FILE__),
+ 'public_cert.pem')
+ end
+
+ def teardown
+ Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY
+ Gem::ConfigMap[:arch] = @orig_arch
+
+ if defined? Gem::RemoteFetcher then
+ Gem::RemoteFetcher.fetcher = nil
+ end
+
+ FileUtils.rm_rf @tempdir
+
+ ENV.delete 'GEMCACHE'
+ ENV.delete 'GEM_HOME'
+ ENV.delete 'GEM_PATH'
+
+ Gem.clear_paths
+ end
+
+ def install_gem gem
+ require 'rubygems/installer'
+
+ use_ui MockGemUi.new do
+ Dir.chdir @tempdir do
+ Gem::Builder.new(gem).build
+ end
+ end
+
+ gem = File.join(@tempdir, "#{gem.full_name}.gem").untaint
+ Gem::Installer.new(gem, :wrappers => true).install
+ end
+
+ def prep_cache_files(lc)
+ @usr_si ||= Gem::SourceIndex.new
+ @usr_sice ||= Gem::SourceInfoCacheEntry.new @usr_si, 0
+
+ @sys_si ||= Gem::SourceIndex.new
+ @sys_sice ||= Gem::SourceInfoCacheEntry.new @sys_si, 0
+
+ latest_si = Gem::SourceIndex.new
+ latest_si.add_specs(*@sys_si.latest_specs)
+ latest_sys_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
+
+ latest_si = Gem::SourceIndex.new
+ latest_si.add_specs(*@usr_si.latest_specs)
+ latest_usr_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
+
+ [ [lc.system_cache_file, @sys_sice],
+ [lc.latest_system_cache_file, latest_sys_sice],
+ [lc.user_cache_file, @usr_sice],
+ [lc.latest_user_cache_file, latest_usr_sice],
+ ].each do |filename, data|
+ FileUtils.mkdir_p File.dirname(filename).untaint
+
+ open filename.dup.untaint, 'wb' do |f|
+ f.write Marshal.dump({ @gem_repo => data })
+ end
+ end
+ end
+
+ def read_cache(path)
+ open path.dup.untaint, 'rb' do |io|
+ Marshal.load io.read
+ end
+ end
+
+ def read_binary(path)
+ Gem.read_binary path
+ end
+
+ def write_file(path)
+ path = File.join(@gemhome, path)
+ dir = File.dirname path
+ FileUtils.mkdir_p dir
+
+ open path, 'wb' do |io|
+ yield io
+ end
+
+ path
+ end
+
+ def quick_gem(gemname, version='2')
+ require 'rubygems/specification'
+
+ spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = gemname
+ s.version = version
+ s.author = 'A User'
+ s.email = 'example@example.com'
+ s.homepage = 'http://example.com'
+ s.has_rdoc = true
+ s.summary = "this is a summary"
+ s.description = "This is a test description"
+
+ yield(s) if block_given?
+ end
+
+ path = File.join "specifications", "#{spec.full_name}.gemspec"
+ written_path = write_file path do |io|
+ io.write(spec.to_ruby)
+ end
+
+ spec.loaded_from = written_path
+
+ Gem.source_index.add_spec spec
+
+ return spec
+ end
+
+ def util_build_gem(spec)
+ dir = File.join(@gemhome, 'gems', spec.full_name)
+ FileUtils.mkdir_p dir
+
+ Dir.chdir dir do
+ spec.files.each do |file|
+ next if File.exist? file
+ FileUtils.mkdir_p File.dirname(file)
+ File.open file, 'w' do |fp| fp.puts "# #{file}" end
+ end
+
+ use_ui MockGemUi.new do
+ Gem::Builder.new(spec).build
+ end
+
+ FileUtils.mv "#{spec.full_name}.gem",
+ File.join(@gemhome, 'cache', "#{spec.original_name}.gem")
+ end
+ end
+
+ def util_clear_gems
+ FileUtils.rm_r File.join(@gemhome, 'gems')
+ FileUtils.rm_r File.join(@gemhome, 'specifications')
+ Gem.source_index.refresh!
+ end
+
+ def util_gem(name, version, &block)
+ spec = quick_gem(name, version, &block)
+
+ util_build_gem spec
+
+ cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ FileUtils.mv File.join(@gemhome, 'cache', "#{spec.original_name}.gem"),
+ cache_file
+ FileUtils.rm File.join(@gemhome, 'specifications',
+ "#{spec.full_name}.gemspec")
+
+ spec.loaded_from = nil
+ spec.loaded = false
+
+ [spec, cache_file]
+ end
+
+ def util_gzip(data)
+ out = StringIO.new
+
+ Zlib::GzipWriter.wrap out do |io|
+ io.write data
+ end
+
+ out.string
+ end
+
+ def util_make_gems
+ init = proc do |s|
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ end
+
+ @a1 = quick_gem('a', '1', &init)
+ @a2 = quick_gem('a', '2', &init)
+ @a_evil9 = quick_gem('a_evil', '9', &init)
+ @b2 = quick_gem('b', '2', &init)
+ @c1_2 = quick_gem('c', '1.2', &init)
+ @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ s.platform = Gem::Platform.new 'i386-linux'
+ s.instance_variable_set :@original_platform, 'i386-linux'
+ end
+
+ write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) do end
+ write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) do end
+ write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) do end
+ write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) do end
+ write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) do end
+
+ [@a1, @a2, @a_evil9, @b2, @c1_2, @pl1].each { |spec| util_build_gem spec }
+
+ FileUtils.rm_r File.join(@gemhome, 'gems', @pl1.original_name)
+
+ Gem.source_index = nil
+ end
+
+ ##
+ # Set the platform to +arch+
+
+ def util_set_arch(arch)
+ Gem::ConfigMap[:arch] = arch
+ platform = Gem::Platform.new arch
+
+ Gem.instance_variable_set :@platforms, nil
+ Gem::Platform.instance_variable_set :@local, nil
+
+ platform
+ end
+
+ def util_setup_fake_fetcher
+ require 'zlib'
+ require 'socket'
+ require 'rubygems/remote_fetcher'
+
+ @fetcher = Gem::FakeFetcher.new
+
+ util_make_gems
+
+ @all_gems = [@a1, @a2, @a_evil9, @b2, @c1_2].sort
+ @all_gem_names = @all_gems.map { |gem| gem.full_name }
+
+ gem_names = [@a1.full_name, @a2.full_name, @b2.full_name]
+ @gem_names = gem_names.sort.join("\n")
+
+ @source_index = Gem::SourceIndex.new
+ @source_index.add_spec @a1
+ @source_index.add_spec @a2
+ @source_index.add_spec @a_evil9
+ @source_index.add_spec @c1_2
+
+ Gem::RemoteFetcher.fetcher = @fetcher
+ end
+
+ def util_setup_source_info_cache(*specs)
+ require 'rubygems/source_info_cache'
+ require 'rubygems/source_info_cache_entry'
+
+ specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
+ si = Gem::SourceIndex.new specs
+
+ sice = Gem::SourceInfoCacheEntry.new si, 0
+ sic = Gem::SourceInfoCache.new
+
+ sic.set_cache_data( { @gem_repo => sice } )
+ sic.update
+ sic.write_cache
+ sic.reset_cache_data
+
+ Gem::SourceInfoCache.instance_variable_set :@cache, sic
+
+ si
+ end
+
+ def util_setup_spec_fetcher(*specs)
+ specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
+ si = Gem::SourceIndex.new specs
+
+ spec_fetcher = Gem::SpecFetcher.fetcher
+
+ spec_fetcher.specs[@uri] = []
+ si.gems.sort_by { |_, spec| spec }.each do |_, spec|
+ spec_tuple = [spec.name, spec.version, spec.original_platform]
+ spec_fetcher.specs[@uri] << spec_tuple
+ end
+
+ spec_fetcher.latest_specs[@uri] = []
+ si.latest_specs.sort.each do |spec|
+ spec_tuple = [spec.name, spec.version, spec.original_platform]
+ spec_fetcher.latest_specs[@uri] << spec_tuple
+ end
+
+ si.gems.sort_by { |_,spec| spec }.each do |_, spec|
+ path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
+ data = Marshal.dump spec
+ data_deflate = Zlib::Deflate.deflate data
+ @fetcher.data[path] = data_deflate
+ end
+
+ si
+ end
+
+ def util_zip(data)
+ Zlib::Deflate.deflate data
+ end
+
+ def self.win_platform?
+ Gem.win_platform?
+ end
+
+ def win_platform?
+ Gem.win_platform?
+ end
+
+ # NOTE Allow tests to use a random (but controlled) port number instead of
+ # a hardcoded one. This helps CI tools when running parallels builds on
+ # the same builder slave.
+ def self.process_based_port
+ @@process_based_port ||= 8000 + $$ % 1000
+ end
+
+ def process_based_port
+ self.class.process_based_port
+ end
+
+ def build_rake_in
+ gem_ruby = Gem.ruby
+ ruby = @@ruby
+ Gem.module_eval {@ruby = ruby}
+ env_rake = ENV["rake"]
+ ENV["rake"] = @@rake
+ yield @@rake
+ ensure
+ Gem.module_eval {@ruby = gem_ruby}
+ if env_rake
+ ENV["rake"] = env_rake
+ else
+ ENV.delete("rake")
+ end
+ end
+
+ def self.rubybin
+ if ruby = ENV["RUBY"]
+ return ruby
+ end
+ ruby = "ruby"
+ rubyexe = ruby+".exe"
+ 3.times do
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if File.exist? rubyexe and File.executable? rubyexe
+ return File.expand_path(rubyexe)
+ end
+ ruby = File.join("..", ruby)
+ end
+ begin
+ require "rbconfig"
+ File.join(
+ RbConfig::CONFIG["bindir"],
+ RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
+ )
+ rescue LoadError
+ "ruby"
+ end
+ end
+
+ @@ruby = rubybin
+ @@rake = ENV["rake"] || (@@ruby + " " + File.expand_path("../../../bin/rake", __FILE__))
+
+end
+
diff --git a/trunk/test/rubygems/insure_session.rb b/trunk/test/rubygems/insure_session.rb
new file mode 100644
index 0000000000..e56f9abcb8
--- /dev/null
+++ b/trunk/test/rubygems/insure_session.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'rubygems'
+
+def install_session
+ path_to_gem = File.join("redist", "session.gem")
+ begin
+ Gem::Installer.new(path_to_gem).install
+ rescue Errno::EACCES => ex
+ puts
+ puts "*****************************************************************"
+ puts "Unable to install Gem 'Session'."
+ puts "Reason: #{ex.message}"
+ puts "Try running:"
+ puts
+ puts " gem -Li #{path_to_gem}"
+ puts
+ puts "with the appropriate admin privileges."
+ puts "*****************************************************************"
+ puts
+ exit
+ end
+ gem 'session'
+end
+
+begin
+ require 'session'
+rescue LoadError => e
+ puts
+ puts "Required Gem 'Session' missing."
+ puts "We can attempt to install from the RubyGems Distribution,"
+ puts "but installation may require admin privileges on your system."
+ puts
+ print "Install now from RubyGems distribution? [Yn]"
+ answer = gets
+ if(answer =~ /^y/i || answer =~ /^[^a-zA-Z0-9]$/) then
+ install_session
+ puts
+ puts "Retry running the functional tests."
+ exit(0)
+ else
+ puts "Test cancelled...quitting"
+ exit(1)
+ end
+end
diff --git a/trunk/test/rubygems/mockgemui.rb b/trunk/test/rubygems/mockgemui.rb
new file mode 100644
index 0000000000..95a95fbf98
--- /dev/null
+++ b/trunk/test/rubygems/mockgemui.rb
@@ -0,0 +1,43 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'stringio'
+require 'rubygems/user_interaction'
+
+class MockGemUi < Gem::StreamUI
+ class TermError < RuntimeError; end
+
+ def initialize(input="")
+ super(StringIO.new(input), StringIO.new, StringIO.new)
+ @terminated = false
+ end
+
+ def input
+ @ins.string
+ end
+
+ def output
+ @outs.string
+ end
+
+ def error
+ @errs.string
+ end
+
+ def terminated?
+ @terminated
+ end
+
+ def terminate_interaction(status=0)
+ @terminated = true
+
+ raise TermError
+ end
+
+end
+
diff --git a/trunk/test/rubygems/private_key.pem b/trunk/test/rubygems/private_key.pem
new file mode 100644
index 0000000000..95b3dc76d8
--- /dev/null
+++ b/trunk/test/rubygems/private_key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAm24C6xixiAxO+i1f3L8XRMwrmLkt6BvT60mZ7g8HsklH3af7
+KNHA6vo/G6sujs2UsNO4HY8BTEneiVOXXWQlcsJ+Z5wEPlIu4zFueAmLefx+n9lE
+ulNIUDoyUenKX4spoMRnX8k4lXL05ho/6JFq0JdDY2DmAaQ4vvTz5mh9kZiybtHQ
+fzcpbA51uY+sjdQRCPDHyUUfh0SmWJlLYMwcBdVeCiGUPBLi+iP5x1btO4uiJK6Q
+IMaV1H3SUCYtKGQKl7qwFd8k8ZBcHYOtmK61tupg3vqWQc0em6SxPj5lws8+1MVK
+twBNIDx24jF4ntxBRNKMZ7FN5SHbobAgDYkPAQIDAQABAoIBAGQilgK8X/PUajVH
+clEXU3hhSV0VQHwfIYKeYms6h6zXBVPKW0dLC0zXeDztJgueasMZQ67XaPCrTpGO
+px/l2zJ6F1HM8/bqn4aDXDY9f/xRLYryQRMBgL8fHzgitNylHWaT4j2Vt7yg2SI9
+mxrMRNKqASJPVR+Nm3l6+n9gpjVb99wEucWplPPHI6KhXLYPZOqSwt+zaH5roz3k
+UQmMs0Bs4hF1SzVl0n+KNoXHOwswVrmBWXgWvm2OhnwY2e26jfejc8toJc/ShAJ7
+C9exnrdimcgEKbd22Sum4G00CDYhcrG5LHHqkgwifcAEVctrvBZBZHGgpxlO8a8U
+eF2Vr7kCgYEAykdrBlzp7Fn9xzUInBQ3NXTTYAq51lpuJdmHQmPuTSY0buoHkd9f
+xbUCZ2qR9QAesrx4hI0qGLetc8IOKDoWx2rPepCCvO3Kx61o1SB5fAvBue03qVoq
+HqACX3Uk24Em8zAz9xuP13ETH/wU7sUbUxRHMCre6ZDmlxn4g5l+Nl8CgYEAxLVl
+22yBx0dfRr3UsHY9rxll2gIlnfnYfiJzq8wetzt/TfztRV5ILz7FyWqL5d7IoqkA
+fT2V4HAasRJASnKohwJe7z5M/H2ExwkGNFvY+jefb2CoUl5WouK9AlhbqBk3zmHi
+sY5GqQkAp/kHMntEin+sErJw6mkgAGdser3a9p8CgYEAqi31w++tunRnxw4+RRnY
+7Pdx0k6T1NxV6TAe1ONAHNY0rM/mOHqml65W7GzDiU1lhlh8SIB/VzZJDqfHw15D
+xdh94A7uf0bMILwrA4wDyTIW9Xa3Kpq57vQNqwPiU25QN69pOM+Ob+IpBfLOJafc
++kOINOUMj5Kh/aQS6Zzci58CgYEAk24dlFKEBjbRCvU2FrfYTYcsljPru7ZJc2gg
+588J6m0WYf5CWy5pzbcviGFpzvSlzXv7GOLylQ+QgcxbETFUbDPzsT4xd0AgJwj1
+dIKuYgMUZOa94VZBer2TydEtiRS1heJJhKhM/1329u4nXceTvHYqIq1JAfeee48I
+eAoZtaMCgYBz1FjWFQnMTD5nmyPEEZneoBPAR5+9jwOps+IYOoHtazoMFszzd0qo
+JZW3Ihn9KRrVSxfFApKS/ZwjiZ+tJUk7DE/v/0l0sszefY7s8b0pL1lpeZSoL71e
+QoG1WLXUiDV3BRlmyOAF1h3p12KRTLgwubN51ajECwcs3QwE+ZT8Gg==
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/test/rubygems/public_cert.pem b/trunk/test/rubygems/public_cert.pem
new file mode 100644
index 0000000000..9b7c3d8e98
--- /dev/null
+++ b/trunk/test/rubygems/public_cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
+YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
+ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
+cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
+FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
+LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
+U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
+Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
+mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
+g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
+sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
+kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
+bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
+DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
+UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
+14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
+x52qPcexcYZR7w==
+-----END CERTIFICATE-----
diff --git a/trunk/test/rubygems/simple_gem.rb b/trunk/test/rubygems/simple_gem.rb
new file mode 100644
index 0000000000..a6f14bc3c7
--- /dev/null
+++ b/trunk/test/rubygems/simple_gem.rb
@@ -0,0 +1,72 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+ SIMPLE_GEM = <<-GEMDATA
+ MD5SUM = "e3701f9db765a2358aef94c40ded71c8"
+ if $0 == __FILE__
+ require 'optparse'
+
+ options = {}
+ ARGV.options do |opts|
+ opts.on_tail("--help", "show this message") {puts opts; exit}
+ opts.on('--dir=DIRNAME', "Installation directory for the Gem") {|options[:directory]|}
+ opts.on('--force', "Force Gem to intall, bypassing dependency checks") {|options[:force]|}
+ opts.on('--gen-rdoc', "Generate RDoc documentation for the Gem") {|options[:gen_rdoc]|}
+ opts.parse!
+ end
+
+ require 'rubygems'
+ @directory = options[:directory] || Gem.dir
+ @force = options[:force]
+
+ gem = Gem::Installer.new(__FILE__).install(@force, @directory)
+ if options[:gen_rdoc]
+ Gem::DocManager.new(gem).generate_rdoc
+ end
+end
+
+__END__
+--- !ruby/object:Gem::Specification
+rubygems_version: "1.0"
+name: testing
+version: !ruby/object:Gem::Version
+ version: 1.2.3
+date: 2004-03-18 22:01:52.859121 -05:00
+platform:
+summary: This exercise the gem testing stuff.
+require_paths:
+ - lib
+files:
+ - lib/foo.rb
+ - lib/test
+ - lib/test.rb
+ - lib/test/wow.rb
+autorequire: test
+test_suite_file: foo
+requirements:
+ - a computer processor
+---
+-
+ size: 109
+ mode: 420
+ path: lib/foo.rb
+-
+ size: 0
+ mode: 420
+ path: lib/test.rb
+-
+ size: 15
+ mode: 420
+ path: lib/test/wow.rb
+---
+eJwVjDEKgDAUQ/eeIpsKguhY3ARPoHMp9quF0mL7e39/h5DwQpLpqz4TOqbC
+U42eO6WuYEvBntIhECuaaX1KqXXLmy2kAEc32szExK+PjyBAlpTZyK0N/Twu
+g1CKTjX9BGAj1w==
+---
+eJwDAAAAAAE=
+---
+eJwrKC0pVlAvzy9XyE3MU+cCACwiBP4=
+ GEMDATA
diff --git a/trunk/test/rubygems/test_config.rb b/trunk/test/rubygems/test_config.rb
new file mode 100644
index 0000000000..0568996c4a
--- /dev/null
+++ b/trunk/test/rubygems/test_config.rb
@@ -0,0 +1,21 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rbconfig'
+require 'rubygems'
+
+class TestConfig < RubyGemTestCase
+
+ def test_datadir
+ datadir = Config::CONFIG['datadir']
+ assert_equal "#{datadir}/xyz", Config.datadir('xyz')
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem.rb b/trunk/test/rubygems/test_gem.rb
new file mode 100644
index 0000000000..c26eeb573d
--- /dev/null
+++ b/trunk/test/rubygems/test_gem.rb
@@ -0,0 +1,449 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems'
+require 'rubygems/gem_openssl'
+require 'rubygems/installer'
+require 'pathname'
+require 'tmpdir'
+
+class TestGem < RubyGemTestCase
+
+ def setup
+ super
+
+ @additional = %w[a b].map { |d| File.join @tempdir, d }
+ @default_dir_re = %r|/[Rr]uby/[Gg]ems/[0-9.]+|
+ end
+
+ def test_self_all_load_paths
+ util_make_gems
+
+ expected = [
+ File.join(@gemhome, *%W[gems #{@a1.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@a2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]),
+ ]
+
+ assert_equal expected, Gem.all_load_paths.sort
+ end
+
+ def test_self_available?
+ util_make_gems
+ assert(Gem.available?("a"))
+ assert(Gem.available?("a", "1"))
+ assert(Gem.available?("a", ">1"))
+ assert(!Gem.available?("monkeys"))
+ end
+
+ def test_self_bindir
+ assert_equal File.join(@gemhome, 'bin'), Gem.bindir
+ assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir)
+ assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Pathname.new(Gem.dir))
+ end
+
+ def test_self_bindir_default_dir
+ default = Gem.default_dir
+ bindir = (defined? RUBY_FRAMEWORK_VERSION) ? '/usr/bin' : Config::CONFIG['bindir']
+ assert_equal bindir, Gem.bindir(default)
+ assert_equal bindir, Gem.bindir(Pathname.new(default))
+ end
+
+ def test_self_clear_paths
+ Gem.dir
+ Gem.path
+ searcher = Gem.searcher
+ source_index = Gem.source_index
+
+ Gem.clear_paths
+
+ assert_equal nil, Gem.instance_variable_get(:@gem_home)
+ assert_equal nil, Gem.instance_variable_get(:@gem_path)
+ assert_not_equal searcher, Gem.searcher
+ assert_not_equal source_index.object_id, Gem.source_index.object_id
+ end
+
+ def test_self_configuration
+ expected = Gem::ConfigFile.new []
+ Gem.configuration = nil
+
+ assert_equal expected, Gem.configuration
+ end
+
+ def test_self_datadir
+ foo = nil
+
+ Dir.chdir @tempdir do
+ FileUtils.mkdir_p 'data'
+ File.open File.join('data', 'foo.txt'), 'w' do |fp|
+ fp.puts 'blah'
+ end
+
+ foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end
+ install_gem foo
+ end
+
+ Gem.source_index = nil
+
+ gem 'foo'
+
+ expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo'
+
+ assert_equal expected, Gem.datadir('foo')
+ end
+
+ def test_self_datadir_nonexistent_package
+ assert_nil Gem.datadir('xyzzy')
+ end
+
+ def test_self_default_dir
+ assert_match @default_dir_re, Gem.default_dir
+ end
+
+ def test_self_default_exec_format
+ orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
+ orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
+ Gem::ConfigMap[:BASERUBY] = 'ruby'
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'ruby'
+
+ assert_equal '%s', Gem.default_exec_format
+ ensure
+ Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
+ end
+
+ def test_self_default_exec_format_18
+ orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
+ orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
+ Gem::ConfigMap[:BASERUBY] = 'ruby'
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'ruby18'
+
+ assert_equal '%s18', Gem.default_exec_format
+ ensure
+ Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
+ end
+
+ def test_self_default_exec_format_jruby
+ orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
+ orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
+ Gem::ConfigMap[:BASERUBY] = 'ruby'
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'jruby'
+
+ assert_equal 'j%s', Gem.default_exec_format
+ ensure
+ Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
+ Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
+ end
+
+ def test_self_default_sources
+ assert_equal %w[http://gems.rubyforge.org/], Gem.default_sources
+ end
+
+ def test_self_dir
+ assert_equal @gemhome, Gem.dir
+
+ Gem::DIRECTORIES.each do |filename|
+ assert File.directory?(File.join(Gem.dir, filename)),
+ "expected #{filename} to exist"
+ end
+ end
+
+ def test_self_ensure_gem_directories
+ FileUtils.rm_r @gemhome
+ Gem.use_paths @gemhome
+
+ Gem.ensure_gem_subdirectories @gemhome
+
+ assert File.directory?(File.join(@gemhome, "cache"))
+ end
+
+ def test_self_ensure_gem_directories_missing_parents
+ gemdir = File.join @tempdir, 'a/b/c/gemdir'
+ FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil
+ assert !File.exist?(File.join(@tempdir, 'a')),
+ "manually remove #{File.join @tempdir, 'a'}, tests are broken"
+ Gem.use_paths gemdir
+
+ Gem.ensure_gem_subdirectories gemdir
+
+ assert File.directory?("#{gemdir}/cache")
+ end
+
+ unless win_platform? then # only for FS that support write protection
+ def test_self_ensure_gem_directories_write_protected
+ gemdir = File.join @tempdir, "egd"
+ FileUtils.rm_r gemdir rescue nil
+ assert !File.exist?(gemdir), "manually remove #{gemdir}, tests are broken"
+ FileUtils.mkdir_p gemdir
+ FileUtils.chmod 0400, gemdir
+ Gem.use_paths gemdir
+
+ Gem.ensure_gem_subdirectories gemdir
+
+ assert !File.exist?("#{gemdir}/cache")
+ ensure
+ FileUtils.chmod 0600, gemdir
+ end
+
+ def test_self_ensure_gem_directories_write_protected_parents
+ parent = File.join(@tempdir, "egd")
+ gemdir = "#{parent}/a/b/c"
+
+ FileUtils.rm_r parent rescue nil
+ assert !File.exist?(parent), "manually remove #{parent}, tests are broken"
+ FileUtils.mkdir_p parent
+ FileUtils.chmod 0400, parent
+ Gem.use_paths(gemdir)
+
+ Gem.ensure_gem_subdirectories gemdir
+
+ assert !File.exist?("#{gemdir}/cache")
+ ensure
+ FileUtils.chmod 0600, parent
+ end
+ end
+
+ def test_ensure_ssl_available
+ orig_Gem_ssl_available = Gem.ssl_available?
+
+ Gem.ssl_available = true
+ assert_nothing_raised do Gem.ensure_ssl_available end
+
+ Gem.ssl_available = false
+ e = assert_raise Gem::Exception do Gem.ensure_ssl_available end
+ assert_equal 'SSL is not installed on this system', e.message
+ ensure
+ Gem.ssl_available = orig_Gem_ssl_available
+ end
+
+ def test_self_latest_load_paths
+ util_make_gems
+
+ expected = [
+ File.join(@gemhome, *%W[gems #{@a2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
+ File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]),
+ ]
+
+ assert_equal expected, Gem.latest_load_paths.sort
+ end
+
+ def test_self_loaded_specs
+ foo = quick_gem 'foo'
+ install_gem foo
+ Gem.source_index = nil
+
+ Gem.activate 'foo'
+
+ assert_equal true, Gem.loaded_specs.keys.include?('foo')
+ end
+
+ def test_self_path
+ assert_equal [Gem.dir], Gem.path
+ end
+
+ def test_self_path_default
+ if defined? APPLE_GEM_HOME
+ orig_APPLE_GEM_HOME = APPLE_GEM_HOME
+ Object.send :remove_const, :APPLE_GEM_HOME
+ end
+ Gem.instance_variable_set :@gem_path, nil
+
+ assert_equal [Gem.default_path, Gem.dir].flatten, Gem.path
+ ensure
+ Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME
+ end
+
+ unless win_platform?
+ def test_self_path_APPLE_GEM_HOME
+ Gem.clear_paths
+ Dir.mktmpdir("apple_gem_home") {|d|
+ Gem.const_set :APPLE_GEM_HOME, d
+ assert Gem.path.include?(d)
+ }
+ ensure
+ Gem.send :remove_const, :APPLE_GEM_HOME
+ end
+
+ def test_self_path_APPLE_GEM_HOME_GEM_PATH
+ Gem.clear_paths
+ ENV['GEM_PATH'] = @gemhome
+ Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
+
+ assert !Gem.path.include?('/tmp/apple_gem_home')
+ ensure
+ Gem.send :remove_const, :APPLE_GEM_HOME
+ end
+ end
+
+ def test_self_path_ENV_PATH
+ Gem.send :set_paths, nil
+ path_count = Gem.path.size
+ Gem.clear_paths
+
+ ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+
+ assert_equal @additional, Gem.path[0,2]
+
+ assert_equal path_count + @additional.size, Gem.path.size,
+ "extra path components: #{Gem.path[2..-1].inspect}"
+ assert_match Gem.dir, Gem.path.last
+ end
+
+ def test_self_path_duplicate
+ Gem.clear_paths
+ util_ensure_gem_dirs
+ dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')]
+
+ ENV['GEM_HOME'] = @gemhome
+ ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR
+
+ assert_equal @gemhome, Gem.dir
+
+ paths = [Gem.dir]
+ assert_equal @additional + paths, Gem.path
+ end
+
+ def test_self_path_overlap
+ Gem.clear_paths
+
+ util_ensure_gem_dirs
+ ENV['GEM_HOME'] = @gemhome
+ ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+
+ assert_equal @gemhome, Gem.dir
+
+ paths = [Gem.dir]
+ assert_equal @additional + paths, Gem.path
+ end
+
+ def test_self_platforms
+ assert_equal [Gem::Platform::RUBY, Gem::Platform.local], Gem.platforms
+ end
+
+ def test_self_prefix
+ file_name = File.expand_path __FILE__
+
+ prefix = File.dirname File.dirname(file_name)
+ prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+ assert_equal prefix, Gem.prefix
+ end
+
+ def test_self_prefix_libdir
+ orig_libdir = Gem::ConfigMap[:libdir]
+
+ file_name = File.expand_path __FILE__
+ prefix = File.dirname File.dirname(file_name)
+ prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+ Gem::ConfigMap[:libdir] = prefix
+
+ assert_nil Gem.prefix
+ ensure
+ Gem::ConfigMap[:libdir] = orig_libdir
+ end
+
+ def test_self_prefix_sitelibdir
+ orig_sitelibdir = Gem::ConfigMap[:sitelibdir]
+
+ file_name = File.expand_path __FILE__
+ prefix = File.dirname File.dirname(file_name)
+ prefix = File.dirname prefix if File.basename(prefix) == 'test'
+
+ Gem::ConfigMap[:sitelibdir] = prefix
+
+ assert_nil Gem.prefix
+ ensure
+ Gem::ConfigMap[:sitelibdir] = orig_sitelibdir
+ end
+
+ def test_self_refresh
+ util_make_gems
+
+ a1_spec = File.join @gemhome, "specifications", "#{@a1.full_name}.gemspec"
+
+ FileUtils.mv a1_spec, @tempdir
+
+ assert !Gem.source_index.gems.include?(@a1.full_name)
+
+ FileUtils.mv File.join(@tempdir, "#{@a1.full_name}.gemspec"), a1_spec
+
+ Gem.refresh
+
+ assert Gem.source_index.gems.include?(@a1.full_name)
+ assert_equal nil, Gem.instance_variable_get(:@searcher)
+ end
+
+ def test_self_required_location
+ util_make_gems
+
+ assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]),
+ Gem.required_location("c", "code.rb")
+ assert_equal File.join(@tempdir, *%w[gemhome gems a-1 lib code.rb]),
+ Gem.required_location("a", "code.rb", "< 2")
+ assert_equal File.join(@tempdir, *%w[gemhome gems a-2 lib code.rb]),
+ Gem.required_location("a", "code.rb", "= 2")
+ end
+
+ def test_self_ruby_version
+ version = RUBY_VERSION.dup
+ version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
+
+ assert_equal Gem::Version.new(version), Gem.ruby_version
+ end
+
+ def test_self_searcher
+ assert_kind_of Gem::GemPathSearcher, Gem.searcher
+ end
+
+ def test_self_source_index
+ assert_kind_of Gem::SourceIndex, Gem.source_index
+ end
+
+ def test_self_sources
+ assert_equal %w[http://gems.example.com/], Gem.sources
+ end
+
+ def test_ssl_available_eh
+ orig_Gem_ssl_available = Gem.ssl_available?
+
+ Gem.ssl_available = true
+ assert_equal true, Gem.ssl_available?
+
+ Gem.ssl_available = false
+ assert_equal false, Gem.ssl_available?
+ ensure
+ Gem.ssl_available = orig_Gem_ssl_available
+ end
+
+ def test_self_use_paths
+ util_ensure_gem_dirs
+
+ Gem.use_paths @gemhome, @additional
+
+ assert_equal @gemhome, Gem.dir
+ assert_equal @additional + [Gem.dir], Gem.path
+ end
+
+ def test_self_user_home
+ if ENV['HOME'] then
+ assert_equal ENV['HOME'], Gem.user_home
+ else
+ assert true, 'count this test'
+ end
+ end
+
+ def util_ensure_gem_dirs
+ Gem.ensure_gem_subdirectories @gemhome
+ @additional.each do |dir|
+ Gem.ensure_gem_subdirectories @gemhome
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_builder.rb b/trunk/test/rubygems/test_gem_builder.rb
new file mode 100644
index 0000000000..31a0d71880
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_builder.rb
@@ -0,0 +1,34 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/builder'
+
+class TestGemBuilder < RubyGemTestCase
+
+ def test_build
+ builder = Gem::Builder.new quick_gem('a')
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ builder.build
+ end
+ end
+
+ assert_match %r|Successfully built RubyGem\n Name: a|, @ui.output
+ end
+
+ def test_build_validates
+ builder = Gem::Builder.new Gem::Specification.new
+
+ assert_raises Gem::InvalidSpecificationException do
+ builder.build
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_command.rb b/trunk/test/rubygems/test_gem_command.rb
new file mode 100644
index 0000000000..9ed57b3692
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_command.rb
@@ -0,0 +1,196 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command'
+
+class Gem::Command
+ public :parser
+end
+
+class TestGemCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @xopt = nil
+
+ Gem::Command.common_options.clear
+ Gem::Command.common_options << [
+ ['-x', '--exe', 'Execute'], lambda do |*a|
+ @xopt = true
+ end
+ ]
+
+ @cmd_name = 'doit'
+ @cmd = Gem::Command.new @cmd_name, 'summary'
+ end
+
+ def test_self_add_specific_extra_args
+ added_args = %w[--all]
+ @cmd.add_option '--all' do |v,o| end
+
+ Gem::Command.add_specific_extra_args @cmd_name, added_args
+
+ assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name)
+
+ h = @cmd.add_extra_args []
+
+ assert_equal added_args, h
+ end
+
+ def test_self_add_specific_extra_args_unknown
+ added_args = %w[--definitely_not_there]
+
+ Gem::Command.add_specific_extra_args @cmd_name, added_args
+
+ assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name)
+
+ h = @cmd.add_extra_args []
+
+ assert_equal [], h
+ end
+
+ def test_add_option_overlapping_common_and_local_options
+ @cmd.add_option('-x', '--zip', 'BAD!') do end
+ @cmd.add_option('-z', '--exe', 'BAD!') do end
+ @cmd.add_option('-x', '--exe', 'BAD!') do end
+
+ assert_match %r|-x, --zip|, @cmd.parser.to_s
+ assert_match %r|-z, --exe|, @cmd.parser.to_s
+ assert_no_match %r|-x, --exe|, @cmd.parser.to_s
+ end
+
+ def test_basic_accessors
+ assert_equal "doit", @cmd.command
+ assert_equal "gem doit", @cmd.program_name
+ assert_equal "summary", @cmd.summary
+ end
+
+ def test_common_option_in_class
+ assert Array === Gem::Command.common_options
+ end
+
+ def test_defaults
+ @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ options[:help] = value
+ end
+
+ @cmd.defaults = { :help => true }
+
+ @cmd.when_invoked do |options|
+ assert options[:help], "Help options should default true"
+ end
+
+ use_ui @ui do
+ @cmd.invoke
+ end
+
+ assert_match %r|Usage: gem doit|, @ui.output
+ end
+
+ def test_invoke
+ done = false
+ @cmd.when_invoked { done = true }
+
+ use_ui @ui do
+ @cmd.invoke
+ end
+
+ assert done
+ end
+
+ def test_invode_with_bad_options
+ use_ui @ui do
+ @cmd.when_invoked do true end
+
+ ex = assert_raise(OptionParser::InvalidOption) do
+ @cmd.invoke('-zzz')
+ end
+
+ assert_match(/invalid option:/, ex.message)
+ end
+ end
+
+ def test_invoke_with_common_options
+ @cmd.when_invoked do true end
+
+ use_ui @ui do
+ @cmd.invoke "-x"
+ end
+
+ assert @xopt, "Should have done xopt"
+ end
+
+ # Returning false from the command handler invokes the usage output.
+ def test_invoke_with_help
+ done = false
+
+ use_ui @ui do
+ @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ options[:help] = true
+ done = true
+ end
+
+ @cmd.invoke('--help')
+
+ assert done
+ end
+
+ assert_match(/Usage/, @ui.output)
+ assert_match(/gem doit/, @ui.output)
+ assert_match(/\[options\]/, @ui.output)
+ assert_match(/-h/, @ui.output)
+ assert_match(/--help \[COMMAND\]/, @ui.output)
+ assert_match(/Get help on COMMAND/, @ui.output)
+ assert_match(/-x/, @ui.output)
+ assert_match(/--exe/, @ui.output)
+ assert_match(/Execute/, @ui.output)
+ assert_match(/Common Options:/, @ui.output)
+ end
+
+ def test_invoke_with_options
+ @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ options[:help] = true
+ end
+
+ @cmd.when_invoked do |opts|
+ assert opts[:help]
+ end
+
+ use_ui @ui do
+ @cmd.invoke '-h'
+ end
+
+ assert_match %r|Usage: gem doit|, @ui.output
+ end
+
+ def test_option_recognition
+ @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ options[:help] = true
+ end
+ @cmd.add_option('-f', '--file FILE', 'File option') do |value, options|
+ options[:help] = true
+ end
+ assert @cmd.handles?(['-x'])
+ assert @cmd.handles?(['-h'])
+ assert @cmd.handles?(['-h', 'command'])
+ assert @cmd.handles?(['--help', 'command'])
+ assert @cmd.handles?(['-f', 'filename'])
+ assert @cmd.handles?(['--file=filename'])
+ assert ! @cmd.handles?(['-z'])
+ assert ! @cmd.handles?(['-f'])
+ assert ! @cmd.handles?(['--toothpaste'])
+
+ args = ['-h', 'command']
+ @cmd.handles?(args)
+ assert_equal ['-h', 'command'], args
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_command_manager.rb b/trunk/test/rubygems/test_gem_command_manager.rb
new file mode 100644
index 0000000000..ee58e89844
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_command_manager.rb
@@ -0,0 +1,213 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command_manager'
+
+class InterruptCommand < Gem::Command
+
+ def initialize
+ super('interrupt', 'Raises an Interrupt Exception', {})
+ end
+
+ def execute
+ raise Interrupt, "Interrupt exception"
+ end
+
+end
+
+class TestGemCommandManager < RubyGemTestCase
+
+ def setup
+ super
+
+ @command_manager = Gem::CommandManager.new
+ end
+
+ def test_run_interrupt
+ use_ui @ui do
+ @command_manager.register_command :interrupt
+ assert_raises MockGemUi::TermError do
+ @command_manager.run 'interrupt'
+ end
+ assert_equal '', ui.output
+ assert_equal "ERROR: Interrupted\n", ui.error
+ end
+ end
+
+ def test_process_args_bad_arg
+ use_ui @ui do
+ assert_raises(MockGemUi::TermError) {
+ @command_manager.process_args("--bad-arg")
+ }
+ end
+
+ assert_match(/invalid option: --bad-arg/i, @ui.error)
+ end
+
+ def test_process_args_install
+ #capture all install options
+ use_ui @ui do
+ check_options = nil
+ @command_manager['install'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("install")
+ assert_equal false, check_options[:test]
+ assert_equal true, check_options[:generate_rdoc]
+ assert_equal false, check_options[:force]
+ assert_equal :both, check_options[:domain]
+ assert_equal true, check_options[:wrappers]
+ assert_equal Gem::Requirement.default, check_options[:version]
+ assert_equal nil, check_options[:install_dir]
+ assert_equal nil, check_options[:bin_dir]
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args(
+ "install --force --test --local --rdoc --install-dir . --version 3.0 --no-wrapper --bindir . ")
+ assert_equal true, check_options[:test]
+ assert_equal true, check_options[:generate_rdoc]
+ assert_equal true, check_options[:force]
+ assert_equal :local, check_options[:domain]
+ assert_equal false, check_options[:wrappers]
+ assert_equal Gem::Requirement.new('3.0'), check_options[:version]
+ assert_equal Dir.pwd, check_options[:install_dir]
+ assert_equal Dir.pwd, check_options[:bin_dir]
+
+ #check remote domain
+ check_options = nil
+ @command_manager.process_args("install --remote")
+ assert_equal :remote, check_options[:domain]
+
+ #check both domain
+ check_options = nil
+ @command_manager.process_args("install --both")
+ assert_equal :both, check_options[:domain]
+
+ #check both domain
+ check_options = nil
+ @command_manager.process_args("install --both")
+ assert_equal :both, check_options[:domain]
+ end
+ end
+
+ def test_process_args_uninstall
+ #capture all uninstall options
+ check_options = nil
+ @command_manager['uninstall'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("uninstall")
+ assert_equal Gem::Requirement.default, check_options[:version]
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args("uninstall foobar --version 3.0")
+ assert_equal "foobar", check_options[:args].first
+ assert_equal Gem::Requirement.new('3.0'), check_options[:version]
+ end
+
+ def test_process_args_check
+ #capture all check options
+ check_options = nil
+ @command_manager['check'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("check")
+ assert_equal false, check_options[:verify]
+ assert_equal false, check_options[:alien]
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args("check --verify foobar --alien")
+ assert_equal "foobar", check_options[:verify]
+ assert_equal true, check_options[:alien]
+ end
+
+ def test_process_args_build
+ #capture all build options
+ check_options = nil
+ @command_manager['build'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("build")
+ #NOTE: Currently no defaults
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args("build foobar.rb")
+ assert_equal 'foobar.rb', check_options[:args].first
+ end
+
+ def test_process_args_query
+ #capture all query options
+ check_options = nil
+ @command_manager['query'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("query")
+ assert_equal(//, check_options[:name])
+ assert_equal :local, check_options[:domain]
+ assert_equal false, check_options[:details]
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args("query --name foobar --local --details")
+ assert_equal(/foobar/i, check_options[:name])
+ assert_equal :local, check_options[:domain]
+ assert_equal true, check_options[:details]
+
+ #remote domain
+ check_options = nil
+ @command_manager.process_args("query --remote")
+ assert_equal :remote, check_options[:domain]
+
+ #both (local/remote) domains
+ check_options = nil
+ @command_manager.process_args("query --both")
+ assert_equal :both, check_options[:domain]
+ end
+
+ def test_process_args_update
+ #capture all update options
+ check_options = nil
+ @command_manager['update'].when_invoked do |options|
+ check_options = options
+ true
+ end
+
+ #check defaults
+ @command_manager.process_args("update")
+ assert_equal true, check_options[:generate_rdoc]
+
+ #check settings
+ check_options = nil
+ @command_manager.process_args("update --force --test --rdoc --install-dir .")
+ assert_equal true, check_options[:test]
+ assert_equal true, check_options[:generate_rdoc]
+ assert_equal true, check_options[:force]
+ assert_equal Dir.pwd, check_options[:install_dir]
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_build_command.rb b/trunk/test/rubygems/test_gem_commands_build_command.rb
new file mode 100644
index 0000000000..a49b6777bd
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_build_command.rb
@@ -0,0 +1,75 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/build_command'
+require 'rubygems/format'
+
+class TestGemCommandsBuildCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @gem = quick_gem 'some_gem' do |s|
+ s.rubyforge_project = 'example'
+ end
+
+ @cmd = Gem::Commands::BuildCommand.new
+ end
+
+ def test_execute
+ gemspec_file = File.join(@tempdir, "#{@gem.full_name}.gemspec")
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ util_test_build_gem @gem, gemspec_file
+ end
+
+ def test_execute_yaml
+ gemspec_file = File.join(@tempdir, "#{@gem.full_name}.gemspec")
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_yaml
+ end
+
+ util_test_build_gem @gem, gemspec_file
+ end
+
+ def test_execute_bad_gem
+ @cmd.options[:args] = %w[some_gem]
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal '', @ui.output
+ assert_equal "ERROR: Gemspec file not found: some_gem\n", @ui.error
+ end
+
+ def util_test_build_gem(gem, gemspec_file)
+ @cmd.options[:args] = [gemspec_file]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: some_gem", output.shift
+ assert_equal " Version: 2", output.shift
+ assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal [], output
+ assert_equal '', @ui.error
+
+ gem_file = File.join @tempdir, "#{gem.full_name}.gem"
+ assert File.exist?(gem_file)
+
+ spec = Gem::Format.from_file_by_path(gem_file).spec
+
+ assert_equal "some_gem", spec.name
+ assert_equal "this is a summary", spec.summary
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_cert_command.rb b/trunk/test/rubygems/test_gem_commands_cert_command.rb
new file mode 100644
index 0000000000..79e3e72158
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_cert_command.rb
@@ -0,0 +1,126 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+
+require 'rubygems/commands/cert_command'
+
+unless defined? OpenSSL then
+ warn "`gem cert` tests are being skipped, module OpenSSL not found"
+end
+
+class TestGemCommandsCertCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @orig_security_trust_dir = Gem::Security::OPT[:trust_dir]
+ Gem::Security::OPT[:trust_dir] = @tempdir
+
+ @cmd = Gem::Commands::CertCommand.new
+
+ root = File.expand_path(File.dirname(__FILE__))
+
+ FileUtils.cp File.join(root, 'data', 'gem-private_key.pem'), @tempdir
+ FileUtils.cp File.join(root, 'data', 'gem-public_cert.pem'), @tempdir
+
+ @cert_file_name = File.join @tempdir, 'gem-public_cert.pem'
+ @pkey_file_name = File.join @tempdir, 'gem-private_key.pem'
+ end
+
+ def teardown
+ Gem::Security::OPT[:trust_dir] = @orig_security_trust_dir
+
+ super
+ end
+
+ def test_execute_add
+ use_ui @ui do
+ @cmd.send :handle_options, %W[--add #{@cert_file_name}]
+ end
+
+ assert_equal "Added '/CN=rubygems/DC=example/DC=com'\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_build
+ FileUtils.rm @cert_file_name
+ FileUtils.rm @pkey_file_name
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.send :handle_options, %W[--build nobody@example.com]
+ end
+ end
+
+ output = @ui.output.split "\n"
+
+ assert_equal 'Public Cert: gem-public_cert.pem', output.shift
+ assert_equal 'Private Key: gem-private_key.pem', output.shift
+ assert_equal 'Don\'t forget to move the key file to somewhere private...',
+ output.shift
+ assert_equal [], output
+
+ assert_equal '', @ui.error
+
+ assert File.exist?(File.join(@tempdir, 'gem-private_key.pem'))
+ assert File.exist?(File.join(@tempdir, 'gem-public_cert.pem'))
+ end
+
+ def test_execute_certificate
+ use_ui @ui do
+ @cmd.send :handle_options, %W[--certificate #{@cert_file_name}]
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal File.read(@cert_file_name),
+ Gem::Security::OPT[:issuer_cert].to_s
+ end
+
+ def test_execute_list
+ use_ui @ui do
+ @cmd.send :handle_options, %W[--list]
+ end
+
+ assert_equal "/CN=rubygems/DC=example/DC=com\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_private_key
+ use_ui @ui do
+ @cmd.send :handle_options, %W[--private-key #{@pkey_file_name}]
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal File.read(@pkey_file_name),
+ Gem::Security::OPT[:issuer_key].to_s
+ end
+
+ def test_execute_remove
+ use_ui @ui do
+ @cmd.send :handle_options, %W[--remove rubygems]
+ end
+
+ assert_equal "Removed '/CN=rubygems/DC=example/DC=com'\n", @ui.output
+ assert_equal '', @ui.error
+
+ assert !File.exist?(@cert_file_name)
+ end
+
+ def test_execute_sign
+ use_ui @ui do
+ @cmd.send :handle_options, %W[
+ -K #{@pkey_file_name} -C #{@cert_file_name} --sign #{@cert_file_name}
+ ]
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+
+ # HACK this test sucks
+ end
+
+end if defined? OpenSSL
+
diff --git a/trunk/test/rubygems/test_gem_commands_check_command.rb b/trunk/test/rubygems/test_gem_commands_check_command.rb
new file mode 100644
index 0000000000..eea7cc5cfa
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_check_command.rb
@@ -0,0 +1,25 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/check_command'
+
+class TestGemCommandsCheckCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::CheckCommand.new
+ end
+
+ def test_initialize
+ assert_equal "check", @cmd.command
+ assert_equal "gem check", @cmd.program_name
+ assert_match(/Check/, @cmd.summary)
+ end
+
+end
diff --git a/trunk/test/rubygems/test_gem_commands_contents_command.rb b/trunk/test/rubygems/test_gem_commands_contents_command.rb
new file mode 100644
index 0000000000..cdb89673da
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_contents_command.rb
@@ -0,0 +1,92 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/contents_command'
+
+class TestGemCommandsContentsCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::ContentsCommand.new
+ end
+
+ def test_execute
+ @cmd.options[:args] = %w[foo]
+ quick_gem 'foo' do |gem|
+ gem.files = %w[lib/foo.rb Rakefile]
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|lib/foo\.rb|, @ui.output
+ assert_match %r|Rakefile|, @ui.output
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_bad_gem
+ @cmd.options[:args] = %w[foo]
+
+ assert_raise MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match %r|Unable to find gem 'foo' in default gem paths|, @ui.output
+ assert_match %r|Directories searched:|, @ui.output
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_exact_match
+ @cmd.options[:args] = %w[foo]
+ quick_gem 'foo' do |gem|
+ gem.files = %w[lib/foo.rb Rakefile]
+ end
+
+ quick_gem 'foo_bar' do |gem|
+ gem.files = %w[lib/foo_bar.rb Rakefile]
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|lib/foo\.rb|, @ui.output
+ assert_match %r|Rakefile|, @ui.output
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_lib_only
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:lib_only] = true
+
+ quick_gem 'foo' do |gem|
+ gem.files = %w[lib/foo.rb Rakefile]
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|lib/foo\.rb|, @ui.output
+ assert_no_match %r|Rakefile|, @ui.output
+
+ assert_equal "", @ui.error
+ end
+
+ def test_handle_options
+ assert_equal false, @cmd.options[:lib_only]
+ assert_equal [], @cmd.options[:specdirs]
+ assert_equal nil, @cmd.options[:version]
+
+ @cmd.send :handle_options, %w[-l -s foo --version 0.0.2]
+
+ assert_equal true, @cmd.options[:lib_only]
+ assert_equal %w[foo], @cmd.options[:specdirs]
+ assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_dependency_command.rb b/trunk/test/rubygems/test_gem_commands_dependency_command.rb
new file mode 100644
index 0000000000..e143110a71
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_dependency_command.rb
@@ -0,0 +1,227 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/dependency_command'
+
+class TestGemCommandsDependencyCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::DependencyCommand.new
+ @cmd.options[:domain] = :local
+
+ util_setup_fake_fetcher
+ end
+
+ def test_execute
+ quick_gem 'foo' do |gem|
+ gem.add_dependency 'bar', '> 1'
+ end
+
+ Gem.source_index = nil
+
+ @cmd.options[:args] = %w[foo]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_no_args
+ Gem.source_index = nil
+
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+Gem a-1
+
+Gem a-2
+
+Gem a_evil-9
+
+Gem b-2
+
+Gem c-1.2
+
+Gem pl-1-x86-linux
+
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_no_match
+ @cmd.options[:args] = %w[foo]
+
+ assert_raise MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal "No gems found matching foo (>= 0)\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_pipe_format
+ quick_gem 'foo' do |gem|
+ gem.add_dependency 'bar', '> 1'
+ end
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:pipe_format] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "bar --version '> 1'\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_regexp
+ Gem.source_index = nil
+
+ @cmd.options[:args] = %w[/[ab]/]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+Gem a-1
+
+Gem a-2
+
+Gem a_evil-9
+
+Gem b-2
+
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_reverse
+ quick_gem 'foo' do |gem|
+ gem.add_dependency 'bar', '> 1'
+ end
+
+ quick_gem 'baz' do |gem|
+ gem.add_dependency 'foo'
+ end
+
+ Gem.source_index = nil
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:reverse_dependencies] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+Gem foo-2
+ bar (> 1, runtime)
+ Used by
+ baz-2 (foo (>= 0, runtime))
+
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_reverse_remote
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:reverse_dependencies] = true
+ @cmd.options[:domain] = :remote
+
+ assert_raise MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ expected = <<-EOF
+ERROR: Only reverse dependencies for local gems are supported.
+ EOF
+
+ assert_equal '', @ui.output
+ assert_equal expected, @ui.error
+ end
+
+ def test_execute_remote
+ foo = quick_gem 'foo' do |gem|
+ gem.add_dependency 'bar', '> 1'
+ end
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ util_setup_spec_fetcher foo
+
+ FileUtils.rm File.join(@gemhome, 'specifications',
+ "#{foo.full_name}.gemspec")
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:domain] = :remote
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_remote_legacy
+ foo = quick_gem 'foo' do |gem|
+ gem.add_dependency 'bar', '> 1'
+ end
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ Gem::SpecFetcher.fetcher = nil
+ si = util_setup_source_info_cache foo
+
+ @fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
+ si.dump
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+
+ FileUtils.rm File.join(@gemhome, 'specifications',
+ "#{foo.full_name}.gemspec")
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:domain] = :remote
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
+
+ expected = <<-EOF
+WARNING: RubyGems 1.2+ index not found for:
+\t#{@gem_repo}
+
+RubyGems will revert to legacy indexes degrading performance.
+ EOF
+
+ assert_equal expected, @ui.error
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_environment_command.rb b/trunk/test/rubygems/test_gem_commands_environment_command.rb
new file mode 100644
index 0000000000..78246b0301
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_environment_command.rb
@@ -0,0 +1,134 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/environment_command'
+
+class TestGemCommandsEnvironmentCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::EnvironmentCommand.new
+ end
+
+ def test_execute
+ orig_sources = Gem.sources.dup
+ Gem.sources.replace %w[http://gems.example.com]
+
+ @cmd.send :handle_options, %w[]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|RUBYGEMS VERSION: (\d\.)+\d|, @ui.output
+ assert_match %r|RUBY VERSION: \d\.\d\.\d \(.*\) \[.*\]|, @ui.output
+ assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|,
+ @ui.output
+ assert_match %r|RUBYGEMS PREFIX: |, @ui.output
+ assert_match %r|RUBY EXECUTABLE:.*#{Gem::ConfigMap[:RUBY_INSTALL_NAME]}|,
+ @ui.output
+ assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
+ assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
+ assert_match %r|- #{Gem::Platform.local}|, @ui.output
+ assert_match %r|GEM PATHS:|, @ui.output
+ assert_match %r|- #{Regexp.escape @gemhome}|, @ui.output
+ assert_match %r|GEM CONFIGURATION:|, @ui.output
+ assert_match %r|:verbose => |, @ui.output
+ assert_match %r|REMOTE SOURCES:|, @ui.output
+ assert_equal '', @ui.error
+
+ ensure
+ Gem.sources.replace orig_sources
+ end
+
+ def test_execute_gemdir
+ @cmd.send :handle_options, %w[gemdir]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{@gemhome}\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_gempath
+ @cmd.send :handle_options, %w[gempath]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{@gemhome}\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_gempath_multiple
+ Gem.clear_paths
+ path = [@gemhome, "#{@gemhome}2"].join File::PATH_SEPARATOR
+ ENV['GEM_PATH'] = path
+
+ @cmd.send :handle_options, %w[gempath]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{Gem.path.join File::PATH_SEPARATOR}\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_packageversion
+ @cmd.send :handle_options, %w[packageversion]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{Gem::RubyGemsPackageVersion}\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_remotesources
+ orig_sources = Gem.sources.dup
+ Gem.sources.replace %w[http://gems.example.com]
+
+ @cmd.send :handle_options, %w[remotesources]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "http://gems.example.com\n", @ui.output
+ assert_equal '', @ui.error
+
+ ensure
+ Gem.sources.replace orig_sources
+ end
+
+ def test_execute_unknown
+ @cmd.send :handle_options, %w[unknown]
+
+ assert_raise Gem::CommandLineError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_version
+ @cmd.send :handle_options, %w[version]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{Gem::RubyGemsVersion}\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_fetch_command.rb b/trunk/test/rubygems/test_gem_commands_fetch_command.rb
new file mode 100644
index 0000000000..eaa13595b7
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_fetch_command.rb
@@ -0,0 +1,55 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+require 'rubygems/security'
+require 'rubygems/commands/fetch_command'
+
+class TestGemCommandsFetchCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::FetchCommand.new
+ end
+
+ def test_execute
+ util_setup_fake_fetcher
+ util_setup_spec_fetcher @a2
+
+ @fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
+ File.read(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
+
+ @cmd.options[:args] = [@a2.name]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, "#{@a2.full_name}.gem")),
+ "#{@a2.full_name} fetched"
+ end
+
+ def test_execute_legacy
+ util_setup_fake_fetcher
+ util_setup_source_info_cache @a2
+
+ @fetcher.data["#{@gem_repo}yaml"] = ''
+ @fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
+ File.read(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
+
+ @cmd.options[:args] = [@a2.name]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, "#{@a2.full_name}.gem")),
+ "#{@a2.full_name} fetched"
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_generate_index_command.rb b/trunk/test/rubygems/test_gem_commands_generate_index_command.rb
new file mode 100644
index 0000000000..548197841b
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_generate_index_command.rb
@@ -0,0 +1,32 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/indexer'
+require 'rubygems/commands/generate_index_command'
+
+class TestGemCommandsGenerateIndexCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::GenerateIndexCommand.new
+ @cmd.options[:directory] = @gemhome
+ end
+
+ def test_execute
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ yaml = File.join @gemhome, 'yaml'
+ yaml_z = File.join @gemhome, 'yaml.Z'
+ quick_index = File.join @gemhome, 'quick', 'index'
+ quick_index_rz = File.join @gemhome, 'quick', 'index.rz'
+
+ assert File.exist?(yaml), yaml
+ assert File.exist?(yaml_z), yaml_z
+ assert File.exist?(quick_index), quick_index
+ assert File.exist?(quick_index_rz), quick_index_rz
+ end
+
+end if ''.respond_to? :to_xs
+
diff --git a/trunk/test/rubygems/test_gem_commands_install_command.rb b/trunk/test/rubygems/test_gem_commands_install_command.rb
new file mode 100644
index 0000000000..ef04072b93
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_install_command.rb
@@ -0,0 +1,166 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/install_command'
+
+class TestGemCommandsInstallCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::InstallCommand.new
+ @cmd.options[:generate_rdoc] = false
+ @cmd.options[:generate_ri] = false
+ end
+
+ def test_execute_include_dependencies
+ @cmd.options[:include_dependencies] = true
+ @cmd.options[:args] = []
+
+ assert_raise Gem::CommandLineError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal "INFO: `gem install -y` is now default and will be removed",
+ output.shift
+ assert_equal "INFO: use --ignore-dependencies to install only the gems you list",
+ output.shift
+ assert output.empty?, output.inspect
+ end
+
+ def test_execute_local
+ util_setup_fake_fetcher
+ @cmd.options[:domain] = :local
+
+ FileUtils.mv File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"),
+ File.join(@tempdir)
+
+ @cmd.options[:args] = [@a2.name]
+
+ use_ui @ui do
+ orig_dir = Dir.pwd
+ begin
+ Dir.chdir @tempdir
+ e = assert_raises Gem::SystemExitException do
+ @cmd.execute
+ end
+ assert_equal 0, e.exit_code
+ ensure
+ Dir.chdir orig_dir
+ end
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "1 gem installed", out.shift
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_local_missing
+ util_setup_fake_fetcher
+ @cmd.options[:domain] = :local
+
+ @cmd.options[:args] = %w[no_such_gem]
+
+ use_ui @ui do
+ e = assert_raises Gem::SystemExitException do
+ @cmd.execute
+ end
+ assert_equal 2, e.exit_code
+ end
+
+ # HACK no repository was checked
+ assert_equal "ERROR: could not find gem no_such_gem locally or in a repository\n",
+ @ui.error
+ end
+
+ def test_execute_no_gem
+ @cmd.options[:args] = %w[]
+
+ assert_raise Gem::CommandLineError do
+ @cmd.execute
+ end
+ end
+
+ def test_execute_nonexistent
+ util_setup_fake_fetcher
+ util_setup_spec_fetcher
+
+ @cmd.options[:args] = %w[nonexistent]
+
+ use_ui @ui do
+ e = assert_raises Gem::SystemExitException do
+ @cmd.execute
+ end
+ assert_equal 2, e.exit_code
+ end
+
+ assert_equal "ERROR: could not find gem nonexistent locally or in a repository\n",
+ @ui.error
+ end
+
+ def test_execute_remote
+ @cmd.options[:generate_rdoc] = true
+ @cmd.options[:generate_ri] = true
+
+ util_setup_fake_fetcher
+ util_setup_spec_fetcher @a2
+
+ @fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
+ read_binary(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
+
+ @cmd.options[:args] = [@a2.name]
+
+ use_ui @ui do
+ e = assert_raises Gem::SystemExitException do
+ @cmd.execute
+ end
+ assert_equal 0, e.exit_code
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "1 gem installed", out.shift
+ assert_equal "Installing ri documentation for #{@a2.full_name}...",
+ out.shift
+ assert_equal "Installing RDoc documentation for #{@a2.full_name}...",
+ out.shift
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_two
+ util_setup_fake_fetcher
+ @cmd.options[:domain] = :local
+
+ FileUtils.mv File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"),
+ File.join(@tempdir)
+
+ FileUtils.mv File.join(@gemhome, 'cache', "#{@b2.full_name}.gem"),
+ File.join(@tempdir)
+
+ @cmd.options[:args] = [@a2.name, @b2.name]
+
+ use_ui @ui do
+ orig_dir = Dir.pwd
+ begin
+ Dir.chdir @tempdir
+ e = assert_raises Gem::SystemExitException do
+ @cmd.execute
+ end
+ assert_equal 0, e.exit_code
+ ensure
+ Dir.chdir orig_dir
+ end
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "Successfully installed #{@b2.full_name}", out.shift
+ assert_equal "2 gems installed", out.shift
+ assert out.empty?, out.inspect
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_mirror_command.rb b/trunk/test/rubygems/test_gem_commands_mirror_command.rb
new file mode 100644
index 0000000000..359ba5481e
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_mirror_command.rb
@@ -0,0 +1,61 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/indexer'
+require 'rubygems/commands/mirror_command'
+
+class TestGemCommandsMirrorCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::MirrorCommand.new
+ end
+
+ def test_execute
+ util_make_gems
+
+ gems_dir = File.join @tempdir, 'gems'
+ mirror = File.join @tempdir, 'mirror'
+
+ FileUtils.mkdir_p gems_dir
+ FileUtils.mkdir_p mirror
+
+ Dir[File.join(@gemhome, 'cache', '*.gem')].each do |gem|
+ FileUtils.mv gem, gems_dir
+ end
+
+ use_ui @ui do
+ Gem::Indexer.new(@tempdir).generate_index
+ end
+
+ orig_HOME = ENV['HOME']
+ ENV['HOME'] = @tempdir
+ Gem.instance_variable_set :@user_home, nil
+
+ File.open File.join(Gem.user_home, '.gemmirrorrc'), 'w' do |fp|
+ fp.puts "---"
+ # tempdir could be a drive+path (under windows)
+ if @tempdir.match(/[a-z]:/i)
+ fp.puts "- from: file:///#{@tempdir}"
+ else
+ fp.puts "- from: file://#{@tempdir}"
+ end
+ fp.puts " to: #{mirror}"
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert File.exist?(File.join(mirror, 'gems', "#{@a1.full_name}.gem"))
+ assert File.exist?(File.join(mirror, 'gems', "#{@a2.full_name}.gem"))
+ assert File.exist?(File.join(mirror, 'gems', "#{@b2.full_name}.gem"))
+ assert File.exist?(File.join(mirror, 'gems', "#{@c1_2.full_name}.gem"))
+ assert File.exist?(File.join(mirror, "Marshal.#{@marshal_version}"))
+ ensure
+ orig_HOME.nil? ? ENV.delete('HOME') : ENV['HOME'] = orig_HOME
+ Gem.instance_variable_set :@user_home, nil
+ end
+
+end if ''.respond_to? :to_xs
+
diff --git a/trunk/test/rubygems/test_gem_commands_outdated_command.rb b/trunk/test/rubygems/test_gem_commands_outdated_command.rb
new file mode 100644
index 0000000000..a6668c01fc
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_outdated_command.rb
@@ -0,0 +1,43 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/outdated_command'
+
+class TestGemCommandsOutdatedCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::OutdatedCommand.new
+ end
+
+ def test_initialize
+ assert @cmd.handles?(%W[--platform #{Gem::Platform.local}])
+ end
+
+ def test_execute
+ local_01 = quick_gem 'foo', '0.1'
+ local_02 = quick_gem 'foo', '0.2'
+ remote_10 = quick_gem 'foo', '1.0'
+ remote_20 = quick_gem 'foo', '2.0'
+
+ remote_spec_file = File.join @gemhome, 'specifications',
+ remote_10.full_name + ".gemspec"
+ FileUtils.rm remote_spec_file
+
+ remote_spec_file = File.join @gemhome, 'specifications',
+ remote_20.full_name + ".gemspec"
+ FileUtils.rm remote_spec_file
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ util_setup_spec_fetcher remote_10, remote_20
+
+ use_ui @ui do @cmd.execute end
+
+ assert_equal "foo (0.2 < 2.0)\n", @ui.output
+ assert_equal "", @ui.error
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_pristine_command.rb b/trunk/test/rubygems/test_gem_commands_pristine_command.rb
new file mode 100644
index 0000000000..d5d2d7f339
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_pristine_command.rb
@@ -0,0 +1,109 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/pristine_command'
+
+class TestGemCommandsPristineCommand < RubyGemTestCase
+
+ def setup
+ super
+ @cmd = Gem::Commands::PristineCommand.new
+ end
+
+ def test_execute
+ a = quick_gem 'a' do |s| s.executables = %w[foo] end
+ FileUtils.mkdir_p File.join(@tempdir, 'bin')
+ File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ end
+
+ install_gem a
+
+ foo_path = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
+
+ File.open foo_path, 'w' do |io|
+ io.puts 'I changed it!'
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#!/usr/bin/ruby\n", File.read(foo_path), foo_path
+
+ out = @ui.output.split "\n"
+
+ assert_equal "Restoring gem(s) to pristine condition...", out.shift
+ assert_equal "Restored #{a.full_name}", out.shift
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_all
+ a = quick_gem 'a' do |s| s.executables = %w[foo] end
+ FileUtils.mkdir_p File.join(@tempdir, 'bin')
+ File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ end
+
+ install_gem a
+
+ gem_bin = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
+
+ FileUtils.rm gem_bin
+
+ @cmd.handle_options %w[--all]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert File.exist?(gem_bin)
+
+ out = @ui.output.split "\n"
+
+ assert_equal "Restoring gem(s) to pristine condition...", out.shift
+ assert_equal "Restored #{a.full_name}", out.shift
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_missing_cache_gem
+ a = quick_gem 'a' do |s| s.executables = %w[foo] end
+ FileUtils.mkdir_p File.join(@tempdir, 'bin')
+ File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ end
+
+ install_gem a
+
+ FileUtils.rm File.join(@gemhome, 'cache', "#{a.full_name}.gem")
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+
+ assert_equal "Restoring gem\(s\) to pristine condition...", out.shift
+ assert out.empty?, out.inspect
+
+ assert_equal "ERROR: Cached gem for #{a.full_name} not found, use `gem install` to restore\n",
+ @ui.error
+ end
+
+ def test_execute_no_gem
+ @cmd.options[:args] = %w[]
+
+ e = assert_raise Gem::CommandLineError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match %r|specify a gem name|, e.message
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_query_command.rb b/trunk/test/rubygems/test_gem_commands_query_command.rb
new file mode 100644
index 0000000000..1b65fc7633
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_query_command.rb
@@ -0,0 +1,288 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/query_command'
+
+class TestGemCommandsQueryCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::QueryCommand.new
+
+ util_setup_fake_fetcher
+
+ @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+ raise Gem::RemoteFetcher::FetchError
+ end
+ end
+
+ def test_execute
+ @cmd.handle_options %w[-r]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_all
+ a1_name = @a1.full_name
+ a2_name = @a2.full_name
+
+ @cmd.handle_options %w[-r --all]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2, 1)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_details
+ @a2.summary = 'This is a lot of text. ' * 4
+ @a2.authors = ['Abraham Lincoln', 'Hirohito']
+ @a2.homepage = 'http://a.example.com/'
+ @a2.rubyforge_project = 'rubygems'
+
+ @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+ @cmd.handle_options %w[-r -d]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+ Authors: Abraham Lincoln, Hirohito
+ Rubyforge: http://rubyforge.org/projects/rubygems
+ Homepage: http://a.example.com/
+
+ This is a lot of text. This is a lot of text. This is a lot of text.
+ This is a lot of text.
+
+pl (1)
+ Author: A User
+ Homepage: http://example.com
+
+ this is a summary
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_installed
+ @cmd.handle_options %w[-n c --installed]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal 0, e.exit_code
+
+ assert_equal "true\n", @ui.output
+
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_installed_no_name
+ @cmd.handle_options %w[--installed]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal '', @ui.output
+ assert_equal "ERROR: You must specify a gem name\n", @ui.error
+
+ assert_equal 4, e.exit_code
+ end
+
+ def test_execute_installed_not_installed
+ @cmd.handle_options %w[-n not_installed --installed]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal "false\n", @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal 1, e.exit_code
+ end
+
+ def test_execute_installed_version
+ @cmd.handle_options %w[-n c --installed --version 1.2]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal "true\n", @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal 0, e.exit_code
+ end
+
+ def test_execute_installed_version_not_installed
+ @cmd.handle_options %w[-n c --installed --version 2]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal "false\n", @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal 1, e.exit_code
+ end
+
+ def test_execute_legacy
+ Gem::SpecFetcher.fetcher = nil
+ si = util_setup_source_info_cache @a1, @a2, @pl1
+
+ @fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
+ si.dump
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+
+ @cmd.handle_options %w[-r]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+
+ expected = <<-EOF
+WARNING: RubyGems 1.2+ index not found for:
+\t#{@gem_repo}
+
+RubyGems will revert to legacy indexes degrading performance.
+ EOF
+
+ assert_equal expected, @ui.error
+ end
+
+ def test_execute_local_details
+ @a2.summary = 'This is a lot of text. ' * 4
+ @a2.authors = ['Abraham Lincoln', 'Hirohito']
+ @a2.homepage = 'http://a.example.com/'
+ @a2.rubyforge_project = 'rubygems'
+
+ @cmd.handle_options %w[--local --details]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** LOCAL GEMS ***
+
+a (2, 1)
+ Author: A User
+ Homepage: http://example.com
+ Installed at (2): #{@gemhome}
+ (1): #{@gemhome}
+
+ this is a summary
+
+a_evil (9)
+ Author: A User
+ Homepage: http://example.com
+ Installed at: #{@gemhome}
+
+ this is a summary
+
+b (2)
+ Author: A User
+ Homepage: http://example.com
+ Installed at: #{@gemhome}
+
+ this is a summary
+
+c (1.2)
+ Author: A User
+ Homepage: http://example.com
+ Installed at: #{@gemhome}
+
+ this is a summary
+
+pl (1)
+ Author: A User
+ Homepage: http://example.com
+ Installed at: #{@gemhome}
+
+ this is a summary
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_no_versions
+ @cmd.handle_options %w[-r --no-versions]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a
+pl
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_server_command.rb b/trunk/test/rubygems/test_gem_commands_server_command.rb
new file mode 100644
index 0000000000..2985b036d8
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_server_command.rb
@@ -0,0 +1,27 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/server_command'
+
+class TestGemCommandsServerCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::ServerCommand.new
+ end
+
+ def test_handle_options
+ @cmd.send :handle_options, %w[-p 8808 --no-daemon]
+
+ assert_equal false, @cmd.options[:daemon]
+ assert_equal @gemhome, @cmd.options[:gemdir]
+ assert_equal 8808, @cmd.options[:port]
+
+ @cmd.send :handle_options, %w[-p 9999 -d /nonexistent --daemon]
+
+ assert_equal true, @cmd.options[:daemon]
+ assert_equal File.expand_path('/nonexistent'), @cmd.options[:gemdir]
+ assert_equal 9999, @cmd.options[:port]
+ end
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_sources_command.rb b/trunk/test/rubygems/test_gem_commands_sources_command.rb
new file mode 100644
index 0000000000..623c732e50
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_sources_command.rb
@@ -0,0 +1,275 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/sources_command'
+
+class TestGemCommandsSourcesCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::SourcesCommand.new
+
+ @new_repo = "http://beta-gems.example.com"
+ end
+
+ def test_execute
+ util_setup_spec_fetcher
+ @cmd.handle_options []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+*** CURRENT SOURCES ***
+
+#{@gem_repo}
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_add
+ util_setup_fake_fetcher
+
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+
+ specs = si.map do |_, spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ specs_dump_gz = StringIO.new
+ Zlib::GzipWriter.wrap specs_dump_gz do |io|
+ Marshal.dump specs, io
+ end
+
+ @fetcher.data["#{@new_repo}/specs.#{@marshal_version}.gz"] =
+ specs_dump_gz.string
+
+ @cmd.handle_options %W[--add #{@new_repo}]
+
+ util_setup_spec_fetcher
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal [@gem_repo, @new_repo], Gem.sources
+
+ expected = <<-EOF
+#{@new_repo} added to sources
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_add_nonexistent_source
+ util_setup_fake_fetcher
+
+ uri = "http://beta-gems.example.com/specs.#{@marshal_version}.gz"
+ @fetcher.data[uri] = proc do
+ raise Gem::RemoteFetcher::FetchError.new('it died', uri)
+ end
+
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ @cmd.handle_options %w[--add http://beta-gems.example.com]
+
+ util_setup_spec_fetcher
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+Error fetching http://beta-gems.example.com:
+\tit died (#{uri})
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_add_bad_uri
+ @cmd.handle_options %w[--add beta-gems.example.com]
+
+ util_setup_spec_fetcher
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal [@gem_repo], Gem.sources
+
+ expected = <<-EOF
+beta-gems.example.com is not a URI
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_add_legacy
+ util_setup_fake_fetcher
+ util_setup_source_info_cache
+
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+
+ @fetcher.data["#{@new_repo}/yaml"] = ''
+
+ @cmd.handle_options %W[--add #{@new_repo}]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal [@gem_repo], Gem.sources
+
+ expected = <<-EOF
+WARNING: RubyGems 1.2+ index not found for:
+\t#{@new_repo}
+
+Will cause RubyGems to revert to legacy indexes, degrading performance.
+ EOF
+
+ assert_equal "#{@new_repo} added to sources\n", @ui.output
+ assert_equal expected, @ui.error
+ end
+
+ def test_execute_clear_all
+ @cmd.handle_options %w[--clear-all]
+
+ util_setup_source_info_cache
+
+ cache = Gem::SourceInfoCache.cache
+ cache.update
+ cache.write_cache
+
+ assert File.exist?(cache.system_cache_file),
+ 'system cache file'
+ assert File.exist?(cache.latest_system_cache_file),
+ 'latest system cache file'
+
+ util_setup_spec_fetcher
+
+ fetcher = Gem::SpecFetcher.fetcher
+
+ # HACK figure out how to force directory creation via fetcher
+ #assert File.directory?(fetcher.dir), 'cache dir exists'
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+*** Removed specs cache ***
+*** Removed user source cache ***
+*** Removed latest user source cache ***
+*** Removed system source cache ***
+*** Removed latest system source cache ***
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+
+ assert !File.exist?(cache.system_cache_file),
+ 'system cache file'
+ assert !File.exist?(cache.latest_system_cache_file),
+ 'latest system cache file'
+
+ assert !File.exist?(fetcher.dir), 'cache dir removed'
+ end
+
+ def test_execute_remove
+ @cmd.handle_options %W[--remove #{@gem_repo}]
+
+ util_setup_spec_fetcher
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = "#{@gem_repo} removed from sources\n"
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_remove_no_network
+ @cmd.handle_options %W[--remove #{@gem_repo}]
+
+ util_setup_fake_fetcher
+
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+ raise Gem::RemoteFetcher::FetchError
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = "#{@gem_repo} removed from sources\n"
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_update
+ @cmd.handle_options %w[--update]
+
+ util_setup_fake_fetcher
+ source_index = util_setup_spec_fetcher @a1
+
+ specs = source_index.map do |name, spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
+ util_gzip Marshal.dump(specs)
+
+ latest_specs = source_index.latest_specs.map do |spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+ util_gzip Marshal.dump(latest_specs)
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "source cache successfully updated\n", @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_update_legacy
+ @cmd.handle_options %w[--update]
+
+ util_setup_fake_fetcher
+ util_setup_source_info_cache
+ Gem::SourceInfoCache.reset
+
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ @fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+Bulk updating Gem source index for: #{@gem_repo}
+source cache successfully updated
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_specification_command.rb b/trunk/test/rubygems/test_gem_commands_specification_command.rb
new file mode 100644
index 0000000000..7ac0429f32
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_specification_command.rb
@@ -0,0 +1,97 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/specification_command'
+
+class TestGemCommandsSpecificationCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::SpecificationCommand.new
+ end
+
+ def test_execute
+ foo = quick_gem 'foo'
+ Gem.source_index.add_spec foo
+
+ @cmd.options[:args] = %w[foo]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|Gem::Specification|, @ui.output
+ assert_match %r|name: foo|, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_all
+ foo1 = quick_gem 'foo', '0.0.1'
+ foo2 = quick_gem 'foo', '0.0.2'
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:all] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|Gem::Specification|, @ui.output
+ assert_match %r|name: foo|, @ui.output
+ assert_match %r|version: 0.0.1|, @ui.output
+ assert_match %r|version: 0.0.2|, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_bad_name
+ @cmd.options[:args] = %w[foo]
+
+ assert_raise MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal '', @ui.output
+ assert_equal "ERROR: Unknown gem 'foo'\n", @ui.error
+ end
+
+ def test_execute_exact_match
+ foo = quick_gem 'foo'
+ foo_bar = quick_gem 'foo_bar'
+
+ @cmd.options[:args] = %w[foo]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|Gem::Specification|, @ui.output
+ assert_match %r|name: foo|, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_remote
+ foo = quick_gem 'foo'
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ util_setup_spec_fetcher foo
+
+ FileUtils.rm File.join(@gemhome, 'specifications',
+ "#{foo.full_name}.gemspec")
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:domain] = :remote
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output
+ assert_match %r|name: foo|, @ui.output
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_stale_command.rb b/trunk/test/rubygems/test_gem_commands_stale_command.rb
new file mode 100644
index 0000000000..6f66c854a5
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_stale_command.rb
@@ -0,0 +1,39 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/stale_command'
+
+class TestGemCommandsStaleCommand < RubyGemTestCase
+
+ def setup
+ super
+ @cmd = Gem::Commands::StaleCommand.new
+ end
+
+ def test_execute_sorts
+ files = %w[lib/foo_bar.rb Rakefile]
+ foo_bar = quick_gem 'foo_bar' do |gem|
+ gem.files = files
+ end
+ bar_baz = quick_gem 'bar_baz' do |gem|
+ gem.files = files
+ end
+
+ files.each do |file|
+ filename = bar_baz.full_gem_path + "/#{file}"
+ FileUtils.mkdir_p(File.dirname(filename))
+ FileUtils.touch(filename, :mtime => Time.now)
+
+ filename = foo_bar.full_gem_path + "/#{file}"
+ FileUtils.mkdir_p(File.dirname(filename))
+ FileUtils.touch(filename, :mtime => Time.now - 86400)
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+ lines = @ui.output.split("\n")
+ assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first)
+ assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first)
+ end
+
+end
diff --git a/trunk/test/rubygems/test_gem_commands_unpack_command.rb b/trunk/test/rubygems/test_gem_commands_unpack_command.rb
new file mode 100644
index 0000000000..3a62a914a4
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_unpack_command.rb
@@ -0,0 +1,115 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/unpack_command'
+
+class TestGemCommandsUnpackCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ Dir.chdir @tempdir do
+ @cmd = Gem::Commands::UnpackCommand.new
+ end
+ end
+
+ def test_execute
+ util_make_gems
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, 'a-2'))
+ end
+
+ def test_execute_gem_path
+ util_make_gems
+
+ Gem.clear_paths
+
+ gemhome2 = File.join @tempdir, 'gemhome2'
+
+ Gem.send :set_paths, [gemhome2, @gemhome].join(File::PATH_SEPARATOR)
+ Gem.send :set_home, gemhome2
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, 'a-2'))
+ end
+
+ def test_execute_gem_path_missing
+ util_make_gems
+
+ Gem.clear_paths
+
+ gemhome2 = File.join @tempdir, 'gemhome2'
+
+ Gem.send :set_paths, [gemhome2, @gemhome].join(File::PATH_SEPARATOR)
+ Gem.send :set_home, gemhome2
+
+ @cmd.options[:args] = %w[z]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert_equal '', @ui.output
+ end
+
+ def test_execute_with_target_option
+ util_make_gems
+
+ target = 'with_target'
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:target] = target
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, target, 'a-2'))
+ end
+
+ def test_execute_exact_match
+ foo_spec = quick_gem 'foo'
+ foo_bar_spec = quick_gem 'foo_bar'
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ Gem::Builder.new(foo_spec).build
+ Gem::Builder.new(foo_bar_spec).build
+ end
+ end
+
+ foo_path = File.join(@tempdir, "#{foo_spec.full_name}.gem")
+ foo_bar_path = File.join(@tempdir, "#{foo_bar_spec.full_name}.gem")
+ Gem::Installer.new(foo_path).install
+ Gem::Installer.new(foo_bar_path).install
+
+ @cmd.options[:args] = %w[foo]
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+
+ assert File.exist?(File.join(@tempdir, foo_spec.full_name))
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_commands_update_command.rb b/trunk/test/rubygems/test_gem_commands_update_command.rb
new file mode 100644
index 0000000000..11da1f8a83
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_commands_update_command.rb
@@ -0,0 +1,165 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/update_command'
+
+class TestGemCommandsUpdateCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::UpdateCommand.new
+
+ util_setup_fake_fetcher
+
+ @a1_path = File.join @gemhome, 'cache', "#{@a1.full_name}.gem"
+ @a2_path = File.join @gemhome, 'cache', "#{@a2.full_name}.gem"
+
+ util_setup_spec_fetcher @a1, @a2
+
+ @fetcher.data["#{@gem_repo}gems/#{@a1.full_name}.gem"] =
+ read_binary @a1_path
+ @fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
+ read_binary @a2_path
+ end
+
+ def test_execute
+ util_clear_gems
+
+ Gem::Installer.new(@a1_path).install
+
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Updating #{@a2.name}", out.shift
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "Gems updated: #{@a2.name}", out.shift
+
+ assert out.empty?, out.inspect
+ end
+
+ # before:
+ # a1 -> c1.2
+ # after:
+ # a2 -> b2 # new dependency
+ # a2 -> c2
+
+ def test_execute_dependencies
+ @a1.add_dependency 'c', '1.2'
+
+ @c2 = quick_gem 'c', '2' do |s|
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ end
+
+ @a2.add_dependency 'c', '2'
+ @a2.add_dependency 'b', '2'
+
+ @b2_path = File.join @gemhome, 'cache', "#{@b2.full_name}.gem"
+ @c1_2_path = File.join @gemhome, 'cache', "#{@c1_2.full_name}.gem"
+ @c2_path = File.join @gemhome, 'cache', "#{@c2.full_name}.gem"
+
+ @source_index = Gem::SourceIndex.new
+ @source_index.add_spec @a1
+ @source_index.add_spec @a2
+ @source_index.add_spec @b2
+ @source_index.add_spec @c1_2
+ @source_index.add_spec @c2
+
+ util_build_gem @a1
+ util_build_gem @a2
+ util_build_gem @c2
+
+ @fetcher.data["#{@gem_repo}gems/#{@a1.full_name}.gem"] = read_binary @a1_path
+ @fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] = read_binary @a2_path
+ @fetcher.data["#{@gem_repo}gems/#{@b2.full_name}.gem"] = read_binary @b2_path
+ @fetcher.data["#{@gem_repo}gems/#{@c1_2.full_name}.gem"] =
+ read_binary @c1_2_path
+ @fetcher.data["#{@gem_repo}gems/#{@c2.full_name}.gem"] = read_binary @c2_path
+
+ util_setup_spec_fetcher @a1, @a2, @b2, @c1_2, @c2
+ util_clear_gems
+
+ Gem::Installer.new(@c1_2_path).install
+ Gem::Installer.new(@a1_path).install
+
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Updating #{@a2.name}", out.shift
+ assert_equal "Successfully installed #{@c2.full_name}", out.shift
+ assert_equal "Successfully installed #{@b2.full_name}", out.shift
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "Gems updated: #{@c2.name}, #{@b2.name}, #{@a2.name}",
+ out.shift
+
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_named
+ util_clear_gems
+
+ Gem::Installer.new(@a1_path).install
+
+ @cmd.options[:args] = [@a1.name]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Updating #{@a2.name}", out.shift
+ assert_equal "Successfully installed #{@a2.full_name}", out.shift
+ assert_equal "Gems updated: #{@a2.name}", out.shift
+
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_named_up_to_date
+ util_clear_gems
+
+ Gem::Installer.new(@a2_path).install
+
+ @cmd.options[:args] = [@a2.name]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Nothing to update", out.shift
+
+ assert out.empty?, out.inspect
+ end
+
+ def test_execute_up_to_date
+ util_clear_gems
+
+ Gem::Installer.new(@a2_path).install
+
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Nothing to update", out.shift
+
+ assert out.empty?, out.inspect
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_config_file.rb b/trunk/test/rubygems/test_gem_config_file.rb
new file mode 100644
index 0000000000..06321d4e7c
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_config_file.rb
@@ -0,0 +1,276 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/config_file'
+
+class TestGemConfigFile < RubyGemTestCase
+
+ def setup
+ super
+
+ @temp_conf = File.join @tempdir, '.gemrc'
+
+ @cfg_args = %W[--config-file #{@temp_conf}]
+
+ @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+ File.join(@tempdir, 'system-gemrc')
+ Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
+ Gem::ConfigFile::PLATFORM_DEFAULTS.clear
+
+ util_config_file
+ end
+
+ def teardown
+ Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
+ Gem::ConfigFile::PLATFORM_DEFAULTS.clear
+ Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+ @orig_SYSTEM_WIDE_CONFIG_FILE
+
+ super
+ end
+
+ def test_initialize
+ assert_equal @temp_conf, @cfg.config_file_name
+
+ assert_equal false, @cfg.backtrace
+ assert_equal true, @cfg.update_sources
+ assert_equal false, @cfg.benchmark
+ assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold
+ assert_equal true, @cfg.verbose
+ assert_equal [@gem_repo], Gem.sources
+
+ File.open @temp_conf, 'w' do |fp|
+ fp.puts ":backtrace: true"
+ fp.puts ":update_sources: false"
+ fp.puts ":benchmark: true"
+ fp.puts ":bulk_threshold: 10"
+ fp.puts ":verbose: false"
+ fp.puts ":sources:"
+ fp.puts " - http://more-gems.example.com"
+ fp.puts "install: --wrappers"
+ end
+
+ util_config_file
+
+ assert_equal true, @cfg.backtrace
+ assert_equal true, @cfg.benchmark
+ assert_equal 10, @cfg.bulk_threshold
+ assert_equal false, @cfg.verbose
+ assert_equal false, @cfg.update_sources
+ assert_equal %w[http://more-gems.example.com], Gem.sources
+ assert_equal '--wrappers', @cfg[:install]
+ end
+
+ def test_initialize_handle_arguments_config_file
+ util_config_file %W[--config-file #{@temp_conf}]
+
+ assert_equal @temp_conf, @cfg.config_file_name
+ end
+
+ def test_initialize_handle_arguments_config_file_with_other_params
+ util_config_file %W[--config-file #{@temp_conf} --backtrace]
+
+ assert_equal @temp_conf, @cfg.config_file_name
+ end
+
+ def test_initialize_handle_arguments_config_file_equals
+ util_config_file %W[--config-file=#{@temp_conf}]
+
+ assert_equal @temp_conf, @cfg.config_file_name
+ end
+
+ def test_initialize_operating_system_override
+ Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS[:bulk_threshold] = 1
+ Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS['install'] = '--no-env-shebang'
+
+ Gem::ConfigFile::PLATFORM_DEFAULTS[:bulk_threshold] = 2
+
+ util_config_file
+
+ assert_equal 2, @cfg.bulk_threshold
+ assert_equal '--no-env-shebang', @cfg[:install]
+ end
+
+ def test_initialize_platform_override
+ Gem::ConfigFile::PLATFORM_DEFAULTS[:bulk_threshold] = 2
+ Gem::ConfigFile::PLATFORM_DEFAULTS['install'] = '--no-env-shebang'
+
+ File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
+ fp.puts ":bulk_threshold: 3"
+ end
+
+ util_config_file
+
+ assert_equal 3, @cfg.bulk_threshold
+ assert_equal '--no-env-shebang', @cfg[:install]
+ end
+
+ def test_initialize_system_wide_override
+ File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
+ fp.puts ":backtrace: false"
+ fp.puts ":bulk_threshold: 2048"
+ end
+
+ File.open @temp_conf, 'w' do |fp|
+ fp.puts ":backtrace: true"
+ end
+
+ util_config_file
+
+ assert_equal 2048, @cfg.bulk_threshold
+ assert_equal true, @cfg.backtrace
+ end
+
+ def test_handle_arguments
+ args = %w[--backtrace --bunch --of --args here]
+
+ @cfg.handle_arguments args
+
+ assert_equal %w[--bunch --of --args here], @cfg.args
+ end
+
+ def test_handle_arguments_backtrace
+ assert_equal false, @cfg.backtrace
+
+ args = %w[--backtrace]
+
+ @cfg.handle_arguments args
+
+ assert_equal true, @cfg.backtrace
+ end
+
+ def test_handle_arguments_benchmark
+ assert_equal false, @cfg.benchmark
+
+ args = %w[--benchmark]
+
+ @cfg.handle_arguments args
+
+ assert_equal true, @cfg.benchmark
+ end
+
+ def test_handle_arguments_debug
+ old_dollar_DEBUG = $DEBUG
+ assert_equal false, $DEBUG
+
+ args = %w[--debug]
+
+ @cfg.handle_arguments args
+
+ assert_equal true, $DEBUG
+ ensure
+ $DEBUG = old_dollar_DEBUG
+ end
+
+ def test_handle_arguments_override
+ File.open @temp_conf, 'w' do |fp|
+ fp.puts ":benchmark: false"
+ end
+
+ util_config_file %W[--benchmark --config-file=#{@temp_conf}]
+
+ assert_equal true, @cfg.benchmark
+ end
+
+ def test_handle_arguments_traceback
+ assert_equal false, @cfg.backtrace
+
+ args = %w[--traceback]
+
+ @cfg.handle_arguments args
+
+ assert_equal true, @cfg.backtrace
+ end
+
+ def test_really_verbose
+ assert_equal false, @cfg.really_verbose
+
+ @cfg.verbose = true
+
+ assert_equal false, @cfg.really_verbose
+
+ @cfg.verbose = 1
+
+ assert_equal true, @cfg.really_verbose
+ end
+
+ def test_write
+ @cfg.backtrace = true
+ @cfg.benchmark = true
+ @cfg.update_sources = false
+ @cfg.bulk_threshold = 10
+ @cfg.verbose = false
+ Gem.sources.replace %w[http://more-gems.example.com]
+ @cfg[:install] = '--wrappers'
+
+ @cfg.write
+
+ util_config_file
+
+ # These should not be written out to the config file.
+ assert_equal false, @cfg.backtrace, 'backtrace'
+ assert_equal false, @cfg.benchmark, 'benchmark'
+ assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold,
+ 'bulk_threshold'
+ assert_equal true, @cfg.update_sources, 'update_sources'
+ assert_equal true, @cfg.verbose, 'verbose'
+
+ assert_equal '--wrappers', @cfg[:install], 'install'
+
+ # this should be written out to the config file.
+ assert_equal %w[http://more-gems.example.com], Gem.sources
+ end
+
+ def test_write_from_hash
+ File.open @temp_conf, 'w' do |fp|
+ fp.puts ":backtrace: true"
+ fp.puts ":benchmark: true"
+ fp.puts ":bulk_threshold: 10"
+ fp.puts ":update_sources: false"
+ fp.puts ":verbose: false"
+ fp.puts ":sources:"
+ fp.puts " - http://more-gems.example.com"
+ fp.puts "install: --wrappers"
+ end
+
+ util_config_file
+
+ @cfg.backtrace = :junk
+ @cfg.benchmark = :junk
+ @cfg.update_sources = :junk
+ @cfg.bulk_threshold = 20
+ @cfg.verbose = :junk
+ Gem.sources.replace %w[http://even-more-gems.example.com]
+ @cfg[:install] = '--wrappers --no-rdoc'
+
+ @cfg.write
+
+ util_config_file
+
+ # These should not be written out to the config file
+ assert_equal true, @cfg.backtrace, 'backtrace'
+ assert_equal true, @cfg.benchmark, 'benchmark'
+ assert_equal 10, @cfg.bulk_threshold, 'bulk_threshold'
+ assert_equal false, @cfg.update_sources, 'update_sources'
+ assert_equal false, @cfg.verbose, 'verbose'
+
+ assert_equal '--wrappers --no-rdoc', @cfg[:install], 'install'
+
+ assert_equal %w[http://even-more-gems.example.com], Gem.sources
+ end
+
+ def util_config_file(args = @cfg_args)
+ @cfg = Gem::ConfigFile.new args
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_dependency.rb b/trunk/test/rubygems/test_gem_dependency.rb
new file mode 100644
index 0000000000..315c49d6ce
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_dependency.rb
@@ -0,0 +1,140 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/version'
+
+class TestGemDependency < RubyGemTestCase
+
+ def setup
+ super
+
+ @pkg1_0 = Gem::Dependency.new 'pkg', ['> 1.0']
+ @pkg1_1 = Gem::Dependency.new 'pkg', ['> 1.1']
+
+ @oth1_0 = Gem::Dependency.new 'other', ['> 1.0']
+
+ @r1_0 = Gem::Requirement.new ['> 1.0']
+ end
+
+ def test_initialize
+ assert_equal "pkg", @pkg1_0.name
+ assert_equal @r1_0, @pkg1_0.version_requirements
+ end
+
+ def test_initialize_double
+ dep = Gem::Dependency.new("pkg", ["> 1.0", "< 2.0"])
+
+ assert_equal Gem::Requirement.new(["> 1.0", "< 2.0"]),
+ dep.version_requirements
+ end
+
+ def test_initialize_empty
+ dep = Gem::Dependency.new("pkg", [])
+ req = @r1_0
+
+ req.instance_eval do
+ @version = ">= 1.0"
+ @op = ">="
+ @nums = [1,0]
+ @requirements = nil
+ end
+
+ dep.instance_eval do
+ @version_requirement = req
+ @version_requirements = nil
+ end
+
+ assert_equal Gem::Requirement.new([">= 1.0"]), dep.version_requirements
+ end
+
+ def test_initialize_version
+ dep = Gem::Dependency.new 'pkg', Gem::Version.new('2')
+
+ assert_equal 'pkg', dep.name
+
+ assert_equal Gem::Requirement.new('= 2'), dep.version_requirements
+ end
+
+ def test_initialize_with_type
+ dep = Gem::Dependency.new("pkg", [], :development)
+ assert_equal(:development, dep.type)
+ end
+
+ def test_type_is_runtime_by_default
+ assert_equal(:runtime, Gem::Dependency.new("pkg", []).type)
+ end
+
+ def test_type_is_restricted
+ assert_raise(ArgumentError) do
+ Gem::Dependency.new("pkg", [:sometimes])
+ end
+ end
+
+ def test_equals2
+ assert_equal @pkg1_0, @pkg1_0.dup
+ assert_equal @pkg1_0.dup, @pkg1_0
+
+ assert_not_equal @pkg1_0, @pkg1_1, "requirements different"
+ assert_not_equal @pkg1_1, @pkg1_0, "requirements different"
+
+ assert_not_equal @pkg1_0, @oth1_0, "names different"
+ assert_not_equal @oth1_0, @pkg1_0, "names different"
+
+ assert_not_equal @pkg1_0, Object.new
+ assert_not_equal Object.new, @pkg1_0
+ end
+
+ def test_equals2_type
+ runtime = Gem::Dependency.new("pkg", [])
+ development = Gem::Dependency.new("pkg", [], :development)
+
+ assert_not_equal(runtime, development)
+ end
+
+ def test_equals_tilde
+ def dep(name, version)
+ Gem::Dependency.new name, version
+ end
+
+ a0 = dep 'a', '0'
+ a1 = dep 'a', '1'
+ b0 = dep 'b', '0'
+
+ pa0 = dep 'a', '>= 0'
+ pa0r = dep(/a/, '>= 0')
+ pab0r = dep(/a|b/, '>= 0')
+
+ assert((a0 =~ a0), 'match self')
+ assert((pa0 =~ a0), 'match version exact')
+ assert((pa0 =~ a1), 'match version')
+ assert((pa0r =~ a0), 'match regex simple')
+ assert((pab0r =~ a0), 'match regex complex')
+
+ assert(!(pa0r =~ b0), 'fail match regex')
+ assert(!(pa0r =~ Object.new), 'fail match Object')
+ end
+
+ def test_hash
+ assert_equal @pkg1_0.hash, @pkg1_0.dup.hash
+ assert_equal @pkg1_0.dup.hash, @pkg1_0.hash
+
+ assert_not_equal @pkg1_0.hash, @pkg1_1.hash, "requirements different"
+ assert_not_equal @pkg1_1.hash, @pkg1_0.hash, "requirements different"
+
+ assert_not_equal @pkg1_0.hash, @oth1_0.hash, "names different"
+ assert_not_equal @oth1_0.hash, @pkg1_0.hash, "names different"
+ end
+
+ def test_hash_type
+ runtime = Gem::Dependency.new("pkg", [])
+ development = Gem::Dependency.new("pkg", [], :development)
+
+ assert_not_equal(runtime.hash, development.hash)
+ end
+end
+
diff --git a/trunk/test/rubygems/test_gem_dependency_installer.rb b/trunk/test/rubygems/test_gem_dependency_installer.rb
new file mode 100644
index 0000000000..10e7fdfbda
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_dependency_installer.rb
@@ -0,0 +1,637 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/dependency_installer'
+
+class TestGemDependencyInstaller < RubyGemTestCase
+
+ def setup
+ super
+
+ @gems_dir = File.join @tempdir, 'gems'
+ @cache_dir = File.join @gemhome, 'cache'
+ FileUtils.mkdir @gems_dir
+
+ write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ end
+ @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
+ @aa1, @aa1_gem = util_gem 'aa', '1'
+
+ @b1, @b1_gem = util_gem 'b', '1' do |s|
+ s.add_dependency 'a'
+ s.add_development_dependency 'aa'
+ end
+
+ @d1, @d1_gem = util_gem 'd', '1'
+ @d2, @d2_gem = util_gem 'd', '2'
+
+ @x1_m, @x1_m_gem = util_gem 'x', '1' do |s|
+ s.platform = Gem::Platform.new %w[cpu my_platform 1]
+ end
+
+ @x1_o, @x1_o_gem = util_gem 'x', '1' do |s|
+ s.platform = Gem::Platform.new %w[cpu other_platform 1]
+ end
+
+ @w1, @w1_gem = util_gem 'w', '1' do |s| s.add_dependency 'x' end
+
+ @y1, @y1_gem = util_gem 'y', '1'
+ @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s|
+ s.platform = Gem::Platform.new %w[cpu my_platform 1]
+ end
+
+ @z1, @z1_gem = util_gem 'z', '1' do |s| s.add_dependency 'y' end
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ si = util_setup_spec_fetcher @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
+ @y1_1_p, @z1
+
+ util_clear_gems
+ end
+
+ def test_install
+ FileUtils.mv @a1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'a'
+ end
+
+ assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
+ Gem::SourceIndex.from_installed_gems
+
+ assert_equal [@a1], inst.installed_gems
+ end
+
+ def test_install_all_dependencies
+ e1, e1_gem = util_gem 'e', '1' do |s|
+ s.add_dependency 'b'
+ end
+
+ util_clear_gems
+
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ FileUtils.mv e1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :ignore_dependencies => true
+ inst.install 'b'
+ end
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'e'
+ end
+
+ assert_equal %w[e-1 a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_cache_dir
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
+ inst.install 'b'
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+
+ assert File.exist?(File.join(@tempdir, 'cache', "#{@a1.full_name}.gem"))
+ assert File.exist?(File.join(@tempdir, 'cache', "#{@b1.full_name}.gem"))
+ end
+
+ def test_install_dependencies_satisfied
+ a2, a2_gem = util_gem 'a', '2'
+
+ FileUtils.rm_rf File.join(@gemhome, 'gems')
+ Gem.source_index.refresh!
+
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv a2_gem, @tempdir # not in index
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'a-2'
+ end
+
+ FileUtils.rm File.join(@tempdir, "#{a2.full_name}.gem")
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'b'
+ end
+
+ installed = Gem::SourceIndex.from_installed_gems.map { |n,s| s.full_name }
+
+ assert_equal %w[a-2 b-1], installed.sort
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_dependency
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'b'
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_dependency_development
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @aa1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new(:development => true)
+ inst.install 'b'
+ end
+
+ assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_dependency_existing
+ Gem::Installer.new(@a1_gem).install
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'b'
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_dependency_old
+ e1, e1_gem = util_gem 'e', '1'
+ f1, f1_gem = util_gem 'f', '1' do |s| s.add_dependency 'e' end
+ f2, f2_gem = util_gem 'f', '2'
+
+ FileUtils.mv e1_gem, @tempdir
+ FileUtils.mv f1_gem, @tempdir
+ FileUtils.mv f2_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'f'
+ end
+
+ assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_local
+ FileUtils.mv @a1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :domain => :local
+ inst.install 'a-1.gem'
+ end
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_local_dependency
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :domain => :local
+ inst.install 'b-1.gem'
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_local_dependency_installed
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+
+ inst = nil
+
+ Dir.chdir @tempdir do
+ Gem::Installer.new('a-1.gem').install
+
+ inst = Gem::DependencyInstaller.new :domain => :local
+ inst.install 'b-1.gem'
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_local_subdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :domain => :local
+ inst.install 'gems/a-1.gem'
+ end
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_env_shebang
+ FileUtils.mv @a1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true
+ inst.install 'a'
+ end
+
+ assert_match %r|\A#!/usr/bin/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}\n|,
+ File.read(File.join(@gemhome, 'bin', 'a_bin'))
+ end
+
+ def test_install_force
+ FileUtils.mv @b1_gem, @tempdir
+ si = util_setup_spec_fetcher @b1
+ @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :force => true
+ inst.install 'b'
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_ignore_dependencies
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :ignore_dependencies => true
+ inst.install 'b'
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_install_dir
+ FileUtils.mv @a1_gem, @tempdir
+ gemhome2 = File.join @tempdir, 'gemhome2'
+ Dir.mkdir gemhome2
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :install_dir => gemhome2
+ inst.install 'a'
+ end
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+
+ assert File.exist?(File.join(gemhome2, 'specifications',
+ "#{@a1.full_name}.gemspec"))
+ assert File.exist?(File.join(gemhome2, 'cache',
+ "#{@a1.full_name}.gem"))
+ end
+
+ def test_install_domain_both
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :domain => :both
+ inst.install 'b'
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ a1, b1 = inst.installed_gems
+
+ a1_expected = File.join(@gemhome, 'specifications',
+ "#{a1.full_name}.gemspec")
+ b1_expected = File.join(@gemhome, 'specifications',
+ "#{b1.full_name}.gemspec")
+
+ assert_equal a1_expected, a1.loaded_from
+ assert_equal b1_expected, b1.loaded_from
+ end
+
+ def test_install_domain_both_no_network
+ @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
+ proc do
+ raise Gem::RemoteFetcher::FetchError
+ end
+
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :domain => :both
+ inst.install 'b'
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_domain_local
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ Gem.source_index.gems.delete @a1.full_name
+
+ Dir.chdir @tempdir do
+ e = assert_raise Gem::InstallError do
+ inst = Gem::DependencyInstaller.new :domain => :local
+ inst.install 'b'
+ end
+ assert_equal 'b requires a (>= 0, runtime)', e.message
+ end
+
+ assert_equal [], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_domain_remote
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+ inst = Gem::DependencyInstaller.new :domain => :remote
+ inst.install 'a'
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_dual_repository
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ inst = nil
+
+ gemhome2 = "#{@gemhome}2"
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :install_dir => gemhome2
+ inst.install 'a'
+ end
+
+ ENV['GEM_HOME'] = @gemhome
+ ENV['GEM_PATH'] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
+ Gem.clear_paths
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'b'
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_remote
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+ inst = Gem::DependencyInstaller.new
+
+ Dir.chdir @tempdir do
+ inst.install 'a'
+ end
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_remote_dep
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+
+ inst = Gem::DependencyInstaller.new
+
+ Dir.chdir @tempdir do
+ dep = Gem::Dependency.new @a1.name, @a1.version
+ inst.install dep
+ end
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_domain_remote_platform_newer
+ a2_o, a2_o_gem = util_gem 'a', '2' do |s|
+ s.platform = Gem::Platform.new %w[cpu other_platform 1]
+ end
+
+ util_clear_gems
+
+ si = util_setup_spec_fetcher @a1, a2_o
+
+ @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+
+ a1_data = nil
+ a2_o_data = nil
+
+ File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end
+ File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end
+
+ @fetcher.data["http://gems.example.com/gems/#{@a1.full_name}.gem"] =
+ a1_data
+ @fetcher.data["http://gems.example.com/gems/#{a2_o.full_name}.gem"] =
+ a2_o_data
+
+ inst = Gem::DependencyInstaller.new :domain => :remote
+ inst.install 'a'
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_reinstall
+ Gem::Installer.new(@a1_gem).install
+ FileUtils.mv @a1_gem, @tempdir
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install 'a'
+ end
+
+ assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
+ Gem::SourceIndex.from_installed_gems
+
+ assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ if defined? OpenSSL then
+ def test_install_security_policy
+ data = File.open(@a1_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
+
+ data = File.open(@b1_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
+
+ policy = Gem::Security::HighSecurity
+ inst = Gem::DependencyInstaller.new :security_policy => policy
+
+ e = assert_raise Gem::Exception do
+ inst.install 'b'
+ end
+
+ assert_equal 'Unsigned gem', e.message
+
+ assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
+ end
+ end
+
+ # Wrappers don't work on mswin
+ unless win_platform? then
+ def test_install_no_wrappers
+ @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
+
+ inst = Gem::DependencyInstaller.new :wrappers => false
+ inst.install 'a'
+
+ assert_no_match(%r|This file was generated by RubyGems.|,
+ File.read(File.join(@gemhome, 'bin', 'a_bin')))
+ end
+ end
+
+ def test_install_version
+ data = File.open(@d2_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+
+ data = File.open(@d1_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
+
+ inst = Gem::DependencyInstaller.new
+
+ inst.install 'd', '= 1'
+
+ assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_install_version_default
+ data = File.open(@d2_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+
+ data = File.open(@d1_gem, 'rb') { |f| f.read }
+ @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
+
+ inst = Gem::DependencyInstaller.new
+ inst.install 'd'
+
+ assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
+ end
+
+ def test_find_gems_gems_with_sources
+ inst = Gem::DependencyInstaller.new
+ dep = Gem::Dependency.new 'b', '>= 0'
+
+ assert_equal [[@b1, @gem_repo]],
+ inst.find_gems_with_sources(dep)
+ end
+
+ def test_find_gems_with_sources_local
+ FileUtils.mv @a1_gem, @tempdir
+ inst = Gem::DependencyInstaller.new
+ dep = Gem::Dependency.new 'a', '>= 0'
+ gems = nil
+
+ Dir.chdir @tempdir do
+ gems = inst.find_gems_with_sources dep
+ end
+
+ assert_equal 2, gems.length
+ remote = gems.first
+ assert_equal 'a-1', remote.first.full_name, 'remote spec'
+ assert_equal @gem_repo, remote.last, 'remote path'
+
+ local = gems.last
+ assert_equal 'a-1', local.first.full_name, 'local spec'
+ assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"),
+ local.last, 'local path'
+ end
+
+ def test_gather_dependencies
+ inst = Gem::DependencyInstaller.new
+ inst.find_spec_by_name_and_version 'b'
+ inst.gather_dependencies
+
+ assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name }
+ end
+
+ def test_gather_dependencies_dropped
+ b2, = util_gem 'b', '2'
+ c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end
+
+ util_clear_gems
+
+ si = util_setup_spec_fetcher @a1, @b1, b2, c1
+
+ inst = Gem::DependencyInstaller.new
+ inst.find_spec_by_name_and_version 'c'
+ inst.gather_dependencies
+
+ assert_equal %w[b-2 c-1], inst.gems_to_install.map { |s| s.full_name }
+ end
+
+ def test_gather_dependencies_platform_alternate
+ util_set_arch 'cpu-my_platform1'
+
+ inst = Gem::DependencyInstaller.new
+ inst.find_spec_by_name_and_version 'w'
+ inst.gather_dependencies
+
+ assert_equal %w[x-1-cpu-my_platform-1 w-1],
+ inst.gems_to_install.map { |s| s.full_name }
+ end
+
+ def test_gather_dependencies_platform_bump
+ inst = Gem::DependencyInstaller.new
+ inst.find_spec_by_name_and_version 'z'
+ inst.gather_dependencies
+
+ assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name }
+ end
+
+ def test_gather_dependencies_old_required
+ e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
+
+ util_clear_gems
+
+ si = util_setup_spec_fetcher @d1, @d2, e1
+
+ inst = Gem::DependencyInstaller.new
+ inst.find_spec_by_name_and_version 'e'
+ inst.gather_dependencies
+
+ assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_dependency_list.rb b/trunk/test/rubygems/test_gem_dependency_list.rb
new file mode 100644
index 0000000000..5fdc227f05
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_dependency_list.rb
@@ -0,0 +1,212 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/dependency_list'
+
+class TestGemDependencyList < RubyGemTestCase
+
+ def setup
+ super
+
+ @deplist = Gem::DependencyList.new
+
+ @a1 = quick_gem 'a', '1'
+ @a2 = quick_gem 'a', '2'
+ @a3 = quick_gem 'a', '3'
+
+ @b1 = quick_gem 'b', '1' do |s| s.add_dependency 'a', '>= 1' end
+ @b2 = quick_gem 'b', '2' do |s| s.add_dependency 'a', '>= 1' end
+
+ @c1 = quick_gem 'c', '1' do |s| s.add_dependency 'b', '>= 1' end
+ @c2 = quick_gem 'c', '2'
+
+ @d1 = quick_gem 'd', '1' do |s| s.add_dependency 'c', '>= 1' end
+ end
+
+ def test_self_from_source_index
+ hash = {
+ 'a-1' => @a1,
+ 'b-2' => @b2,
+ }
+
+ si = Gem::SourceIndex.new hash
+ deps = Gem::DependencyList.from_source_index si
+
+ assert_equal %w[b-2 a-1], deps.dependency_order.map { |s| s.full_name }
+ end
+
+ def test_active_count
+ assert_equal 0, @deplist.send(:active_count, [], {})
+ assert_equal 1, @deplist.send(:active_count, [@a1], {})
+ assert_equal 0, @deplist.send(:active_count, [@a1],
+ { @a1.full_name => true })
+ end
+
+ def test_add
+ assert_equal [], @deplist.dependency_order
+
+ @deplist.add @a1, @b2
+
+ assert_equal [@b2, @a1], @deplist.dependency_order
+ end
+
+ def test_dependency_order
+ @deplist.add @a1, @b1, @c1, @d1
+
+ order = @deplist.dependency_order
+
+ assert_equal %w[d-1 c-1 b-1 a-1], order.map { |s| s.full_name }
+ end
+
+ def test_dependency_order_circle
+ @a1.add_dependency 'c', '>= 1'
+ @deplist.add @a1, @b1, @c1
+
+ order = @deplist.dependency_order
+
+ assert_equal %w[b-1 c-1 a-1], order.map { |s| s.full_name }
+ end
+
+ def test_dependency_order_diamond
+ util_diamond
+ e1 = quick_gem 'e', '1'
+ @deplist.add e1
+ @a1.add_dependency 'e', '>= 1'
+
+ order = @deplist.dependency_order
+
+ assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map { |s| s.full_name },
+ 'deps of trimmed specs not included'
+ end
+
+ def test_dependency_order_no_dependendencies
+ @deplist.add @a1, @c2
+
+ order = @deplist.dependency_order
+
+ assert_equal %w[c-2 a-1], order.map { |s| s.full_name }
+ end
+
+ def test_find_name
+ @deplist.add @a1, @b2
+
+ assert_equal "a-1", @deplist.find_name("a-1").full_name
+ assert_equal "b-2", @deplist.find_name("b-2").full_name
+
+ assert_nil @deplist.find_name("c-2")
+ end
+
+ def test_ok_eh
+ assert @deplist.ok?, 'no dependencies'
+
+ @deplist.add @b2
+
+ assert ! @deplist.ok?, 'unsatisfied dependency'
+
+ @deplist.add @a1
+
+ assert @deplist.ok?, 'satisfied dependency'
+ end
+
+ def test_ok_eh_mismatch
+ a1 = quick_gem 'a', '1'
+ a2 = quick_gem 'a', '2'
+
+ b = quick_gem 'b', '1' do |s| s.add_dependency 'a', '= 1' end
+ c = quick_gem 'c', '1' do |s| s.add_dependency 'a', '= 2' end
+
+ d = quick_gem 'd', '1' do |s|
+ s.add_dependency 'b'
+ s.add_dependency 'c'
+ end
+
+ @deplist.add a1, a2, b, c, d
+
+ assert @deplist.ok?, 'this will break on require'
+ end
+
+ def test_ok_eh_redundant
+ @deplist.add @a1, @a3, @b2
+
+ @deplist.remove_by_name("a-1")
+
+ assert @deplist.ok?
+ end
+
+ def test_ok_to_remove_eh
+ @deplist.add @a1
+
+ assert @deplist.ok_to_remove?("a-1")
+
+ @deplist.add @b2
+
+ assert ! @deplist.ok_to_remove?("a-1")
+
+ @deplist.add @a2
+
+ assert @deplist.ok_to_remove?("a-1")
+ assert @deplist.ok_to_remove?("a-2")
+ assert @deplist.ok_to_remove?("b-2")
+ end
+
+ def test_ok_to_remove_eh_after_sibling_removed
+ @deplist.add @a1, @a2, @b2
+
+ assert @deplist.ok_to_remove?("a-1")
+ assert @deplist.ok_to_remove?("a-2")
+
+ @deplist.remove_by_name("a-1")
+
+ assert ! @deplist.ok_to_remove?("a-2")
+ end
+
+ def test_remove_by_name
+ @deplist.add @a1, @b2
+
+ @deplist.remove_by_name "a-1"
+
+ assert ! @deplist.ok?
+ end
+
+ def test_tsort_each_node
+ util_diamond
+
+ order = %w[a-1 a-2 b-1 c-2 d-1]
+
+ @deplist.tsort_each_node do |node|
+ assert_equal order.shift, node.full_name
+ end
+
+ assert order.empty?
+ end
+
+ def test_tsort_each_child
+ util_diamond
+
+ order = %w[a-2]
+
+ @deplist.tsort_each_child(@b1) do |node|
+ assert_equal order.shift, node.full_name
+ end
+
+ assert order.empty?
+ end
+
+ # d1 -> b1 -> a1
+ # d1 -> c2 -> a2
+ def util_diamond
+ @c2.add_dependency 'a', '>= 2'
+ @d1.add_dependency 'b'
+
+ @deplist.add @a1, @a2, @b1, @c2, @d1
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_digest.rb b/trunk/test/rubygems/test_gem_digest.rb
new file mode 100755
index 0000000000..9d825b2796
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_digest.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require "test/unit"
+require "rubygems/digest/md5"
+require "rubygems/digest/sha1"
+require "rubygems/digest/sha2"
+
+class TestRubygemsGemDigest < Test::Unit::TestCase
+ def test_sha256_hex_digest_works
+ digester = Gem::SHA256.new
+ assert_equal "b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78", digester.hexdigest("ABC")
+ end
+
+ def test_sha256_digest_works
+ digester = Gem::SHA256.new
+ assert_equal "\265\324\004\\?Fo\251\037\342\314j\276y#*\032W\315\361\004\367\242nqn\n\036'\211\337x",
+ digester.digest("ABC")
+ end
+
+ def test_sha1_hex_digest_works
+ digester = Gem::SHA1.new
+ assert_equal "3c01bdbb26f358bab27f267924aa2c9a03fcfdb8", digester.hexdigest("ABC")
+ end
+
+ def test_sha1_digest_works
+ digester = Gem::SHA1.new
+ assert_equal "<\001\275\273&\363X\272\262\177&y$\252,\232\003\374\375\270", digester.digest("ABC")
+ end
+
+ def test_md5_hex_digest_works
+ digester = Gem::MD5.new
+ assert_equal "902fbdd2b1df0c4f70b4a5d23525e932", digester.hexdigest("ABC")
+ end
+
+ def test_md5_digest_works
+ digester = Gem::MD5.new
+ assert_equal "\220/\275\322\261\337\fOp\264\245\3225%\3512", digester.digest("ABC")
+ end
+end \ No newline at end of file
diff --git a/trunk/test/rubygems/test_gem_doc_manager.rb b/trunk/test/rubygems/test_gem_doc_manager.rb
new file mode 100644
index 0000000000..e52fb9f0cd
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_doc_manager.rb
@@ -0,0 +1,32 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/doc_manager'
+
+class TestGemDocManager < RubyGemTestCase
+
+ def setup
+ super
+
+ @spec = quick_gem 'a'
+ @manager = Gem::DocManager.new(@spec)
+ end
+
+ def test_uninstall_doc_unwritable
+ orig_mode = File.stat(@spec.installation_path).mode
+ File.chmod 0, @spec.installation_path
+
+ assert_raise Gem::FilePermissionError do
+ @manager.uninstall_doc
+ end
+ ensure
+ File.chmod orig_mode, @spec.installation_path
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_ext_configure_builder.rb b/trunk/test/rubygems/test_gem_ext_configure_builder.rb
new file mode 100644
index 0000000000..9ce17075bc
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_ext_configure_builder.rb
@@ -0,0 +1,86 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtConfigureBuilder < RubyGemTestCase
+
+ def setup
+ super
+
+ @makefile_body = "all:\n\t@echo ok\ninstall:\n\t@echo ok"
+
+ @ext = File.join @tempdir, 'ext'
+ @dest_path = File.join @tempdir, 'prefix'
+
+ FileUtils.mkdir_p @ext
+ FileUtils.mkdir_p @dest_path
+ end
+
+ def test_self_build
+ return if RUBY_PLATFORM =~ /mswin/ # HACK
+
+ File.open File.join(@ext, './configure'), 'w' do |configure|
+ configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile"
+ end
+
+ output = []
+
+ Dir.chdir @ext do
+ Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+ end
+
+ assert_equal "sh ./configure --prefix=#{@dest_path}", output.shift
+ assert_equal "", output.shift
+ assert_equal "make", output.shift
+ assert_match(/^ok$/m, output.shift)
+ assert_equal "make install", output.shift
+ assert_match(/^ok$/m, output.shift)
+ end
+
+ def test_self_build_fail
+ return if RUBY_PLATFORM =~ /mswin/ # HACK
+ output = []
+
+ error = assert_raise Gem::InstallError do
+ Dir.chdir @ext do
+ Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+ end
+ end
+
+ shell_error_msg = %r{(\./configure: .*)|(Can't open \./configure)}
+ sh_prefix_configure = "sh ./configure --prefix="
+
+ expected = %r(configure failed:
+
+#{Regexp.escape sh_prefix_configure}#{Regexp.escape @dest_path}
+.*?: #{shell_error_msg})
+
+ assert_match expected, error.message
+
+ assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
+ assert_match %r(#{shell_error_msg}\n), output.shift
+ assert_equal true, output.empty?
+ end
+
+ def test_self_build_has_makefile
+ File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
+ makefile.puts @makefile_body
+ end
+
+ output = []
+ Dir.chdir @ext do
+ Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
+ end
+
+ case RUBY_PLATFORM
+ when /mswin/ then
+ assert_equal 'nmake', output[0]
+ assert_equal 'nmake install', output[2]
+ else
+ assert_equal 'make', output[0]
+ assert_equal 'make install', output[2]
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_ext_ext_conf_builder.rb b/trunk/test/rubygems/test_gem_ext_ext_conf_builder.rb
new file mode 100644
index 0000000000..fb21fa0755
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_ext_ext_conf_builder.rb
@@ -0,0 +1,122 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtExtConfBuilder < RubyGemTestCase
+
+ def setup
+ super
+
+ @ext = File.join @tempdir, 'ext'
+ @dest_path = File.join @tempdir, 'prefix'
+
+ FileUtils.mkdir_p @ext
+ FileUtils.mkdir_p @dest_path
+ end
+
+ def test_class_build
+ File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
+ end
+
+ output = []
+
+ Dir.chdir @ext do
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output
+ end
+
+ expected = [
+ "ruby extconf.rb",
+ "creating Makefile\n",
+ "make",
+ "make: Nothing to be done for `all'.\n",
+ "make install",
+ "make: Nothing to be done for `install'.\n"
+ ]
+
+ assert_match(/^#{Gem.ruby} extconf.rb/, output[0])
+ assert_equal "creating Makefile\n", output[1]
+ case RUBY_PLATFORM
+ when /mswin/ then
+ assert_equal "nmake", output[2]
+ assert_equal "nmake install", output[4]
+ else
+ assert_equal "make", output[2]
+ assert_equal "make install", output[4]
+ end
+ end
+
+ def test_class_build_extconf_fail
+ File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ extconf.puts "require 'mkmf'"
+ extconf.puts "have_library 'nonexistent' or abort 'need libnonexistent'"
+ extconf.puts "create_makefile 'foo'"
+ end
+
+ output = []
+
+ error = assert_raise Gem::InstallError do
+ Dir.chdir @ext do
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output
+ end
+ end
+
+ assert_match(/\Aextconf failed:
+
+#{Gem.ruby} extconf.rb.*
+checking for main\(\) in .*?nonexistent/m, error.message)
+
+ assert_match(/^#{Gem.ruby} extconf.rb/, output[0])
+ end
+
+ def test_class_make
+ output = []
+ makefile_path = File.join(@ext, 'Makefile')
+ File.open makefile_path, 'w' do |makefile|
+ makefile.puts "RUBYARCHDIR = $(foo)$(target_prefix)"
+ makefile.puts "RUBYLIBDIR = $(bar)$(target_prefix)"
+ makefile.puts "all:"
+ makefile.puts "install:"
+ end
+
+ Dir.chdir @ext do
+ Gem::Ext::ExtConfBuilder.make @ext, output
+ end
+
+ case RUBY_PLATFORM
+ when /mswin/ then
+ assert_equal 'nmake', output[0]
+ assert_equal 'nmake install', output[2]
+ else
+ assert_equal 'make', output[0]
+ assert_equal 'make install', output[2]
+ end
+
+ edited_makefile = <<-EOF
+RUBYARCHDIR = #{@ext}$(target_prefix)
+RUBYLIBDIR = #{@ext}$(target_prefix)
+all:
+install:
+ EOF
+
+ assert_equal edited_makefile, File.read(makefile_path)
+ end
+
+ def test_class_make_no_Makefile
+ error = assert_raise Gem::InstallError do
+ Dir.chdir @ext do
+ Gem::Ext::ExtConfBuilder.make @ext, ['output']
+ end
+ end
+
+ expected = <<-EOF.strip
+Makefile not found:
+
+output
+ EOF
+
+ assert_equal expected, error.message
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_ext_rake_builder.rb b/trunk/test/rubygems/test_gem_ext_rake_builder.rb
new file mode 100644
index 0000000000..6d9184e804
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_ext_rake_builder.rb
@@ -0,0 +1,76 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/ext'
+
+class TestGemExtRakeBuilder < RubyGemTestCase
+ def setup
+ super
+
+ @ext = File.join @tempdir, 'ext'
+ @dest_path = File.join @tempdir, 'prefix'
+
+ FileUtils.mkdir_p @ext
+ FileUtils.mkdir_p @dest_path
+ end
+
+ def test_class_build
+ File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf|
+ mkrf_conf.puts <<-EO_MKRF
+ File.open("Rakefile","w") do |f|
+ f.puts "task :default"
+ end
+ EO_MKRF
+ end
+
+ output = []
+ realdir = nil # HACK /tmp vs. /private/tmp
+
+ build_rake_in do
+ Dir.chdir @ext do
+ realdir = Dir.pwd
+ Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', nil, @dest_path, output
+ end
+ end
+
+ expected = [
+ "#{@@ruby} mkrf_conf.rb",
+ "",
+ "#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}",
+ "(in #{realdir})\n"
+ ]
+
+ assert_equal expected, output
+ end
+
+ def test_class_build_fail
+ File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf|
+ mkrf_conf.puts <<-EO_MKRF
+ File.open("Rakefile","w") do |f|
+ f.puts "task :default do abort 'fail' end"
+ end
+ EO_MKRF
+ end
+
+ output = []
+
+ error = assert_raise Gem::InstallError do
+ build_rake_in do
+ Dir.chdir @ext do
+ Gem::Ext::RakeBuilder.build "mkrf_conf.rb", nil, @dest_path, output
+ end
+ end
+ end
+
+ expected = <<-EOF.strip
+rake failed:
+
+#{@@ruby} mkrf_conf.rb
+
+#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}
+ EOF
+
+ assert_equal expected, error.message.split("\n")[0..4].join("\n")
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_format.rb b/trunk/test/rubygems/test_gem_format.rb
new file mode 100644
index 0000000000..4014acfed9
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_format.rb
@@ -0,0 +1,69 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
+require 'rubygems/format'
+
+class TestGemFormat < RubyGemTestCase
+
+ def setup
+ super
+
+ @simple_gem = SIMPLE_GEM
+ end
+
+ def test_from_file_by_path
+ util_make_gems
+
+ gems = Dir[File.join(@gemhome, 'cache', '*.gem')]
+
+ names = [@a1, @a2, @a_evil9, @b2, @c1_2, @pl1].map do |spec|
+ spec.original_name
+ end
+
+ gems_n_names = gems.sort.zip names
+
+ gems_n_names.each do |gemfile, name|
+ spec = Gem::Format.from_file_by_path(gemfile).spec
+
+ assert_equal name, spec.original_name
+ end
+ end
+
+ def test_from_file_by_path_nonexistent
+ assert_raise Gem::Exception do
+ Gem::Format.from_file_by_path '/nonexistent'
+ end
+ end
+
+ def test_from_io_garbled
+ e = assert_raise Gem::Package::FormatError do
+ # subtly bogus input
+ Gem::Format.from_io(StringIO.new(@simple_gem.upcase))
+ end
+
+ assert_equal 'No metadata found!', e.message
+
+ e = assert_raise Gem::Package::FormatError do
+ # Totally bogus input
+ Gem::Format.from_io(StringIO.new(@simple_gem.reverse))
+ end
+
+ assert_equal 'No metadata found!', e.message
+
+ e = assert_raise Gem::Package::FormatError do
+ # This was intentionally screws up YAML parsing.
+ Gem::Format.from_io(StringIO.new(@simple_gem.gsub(/:/, "boom")))
+ end
+
+ assert_equal 'No metadata found!', e.message
+ end
+
+end
+
+
diff --git a/trunk/test/rubygems/test_gem_gem_path_searcher.rb b/trunk/test/rubygems/test_gem_gem_path_searcher.rb
new file mode 100644
index 0000000000..c9da4d2b05
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_gem_path_searcher.rb
@@ -0,0 +1,60 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/gem_path_searcher'
+
+class Gem::GemPathSearcher
+ attr_accessor :gemspecs
+ attr_accessor :lib_dirs
+
+ public :init_gemspecs
+ public :matching_file
+ public :lib_dirs_for
+end
+
+class TestGemGemPathSearcher < RubyGemTestCase
+
+ def setup
+ super
+
+ @foo1 = quick_gem 'foo', '0.1' do |s|
+ s.require_paths << 'lib2'
+ s.files << 'lib/foo.rb'
+ end
+
+ path = File.join 'gems', @foo1.full_name, 'lib', 'foo.rb'
+ write_file(path) { |fp| fp.puts "# #{path}" }
+
+ @foo2 = quick_gem 'foo', '0.2'
+ @bar1 = quick_gem 'bar', '0.1'
+ @bar2 = quick_gem 'bar', '0.2'
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ Gem.source_index = util_setup_spec_fetcher @foo1, @foo2, @bar1, @bar2
+
+ @gps = Gem::GemPathSearcher.new
+ end
+
+ def test_find
+ assert_equal @foo1, @gps.find('foo')
+ end
+
+ def test_init_gemspecs
+ assert_equal [@bar2, @bar1, @foo2, @foo1], @gps.init_gemspecs
+ end
+
+ def test_lib_dirs_for
+ lib_dirs = @gps.lib_dirs_for(@foo1)
+ expected = File.join @gemhome, 'gems', @foo1.full_name, '{lib,lib2}'
+
+ assert_equal expected, lib_dirs
+ end
+
+ def test_matching_file
+ assert !@gps.matching_file(@foo1, 'bar')
+ assert @gps.matching_file(@foo1, 'foo')
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_gem_runner.rb b/trunk/test/rubygems/test_gem_gem_runner.rb
new file mode 100644
index 0000000000..4e3239f015
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_gem_runner.rb
@@ -0,0 +1,35 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/gem_runner'
+
+class TestGemGemRunner < RubyGemTestCase
+
+ def test_do_configuration
+ Gem.clear_paths
+
+ temp_conf = File.join @tempdir, '.gemrc'
+
+ other_gem_path = File.join @tempdir, 'other_gem_path'
+ other_gem_home = File.join @tempdir, 'other_gem_home'
+
+ Gem.ensure_gem_subdirectories other_gem_path
+ Gem.ensure_gem_subdirectories other_gem_home
+
+ File.open temp_conf, 'w' do |fp|
+ fp.puts "gem: --commands"
+ fp.puts "gemhome: #{other_gem_home}"
+ fp.puts "gempath:"
+ fp.puts " - #{other_gem_path}"
+ fp.puts "rdoc: --all"
+ end
+
+ gr = Gem::GemRunner.new
+ gr.send :do_configuration, %W[--config-file #{temp_conf}]
+
+ assert_equal [other_gem_path, other_gem_home], Gem.path
+ assert_equal %w[--commands], Gem::Command.extra_args
+ assert_equal %w[--all], Gem::DocManager.configured_args
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_indexer.rb b/trunk/test/rubygems/test_gem_indexer.rb
new file mode 100644
index 0000000000..9d68a7f34d
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_indexer.rb
@@ -0,0 +1,263 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+
+require 'rubygems/indexer'
+
+unless ''.respond_to? :to_xs then
+ warn "Gem::Indexer tests are being skipped. Install builder gem."
+end
+
+class TestGemIndexer < RubyGemTestCase
+
+ def setup
+ super
+
+ util_make_gems
+
+ @d2_0 = quick_gem 'd', '2.0'
+ util_build_gem @d2_0
+
+ gems = File.join(@tempdir, 'gems')
+ FileUtils.mkdir_p gems
+ cache_gems = File.join @gemhome, 'cache', '*.gem'
+ FileUtils.mv Dir[cache_gems], gems
+
+ @indexer = Gem::Indexer.new @tempdir
+ end
+
+ def test_initialize
+ assert_equal @tempdir, @indexer.dest_directory
+ assert_equal File.join(Dir.tmpdir, "gem_generate_index_#{$$}"),
+ @indexer.directory
+ end
+
+ def test_build_indicies
+ spec = quick_gem 'd', '2.0'
+ spec.instance_variable_set :@original_platform, ''
+
+ @indexer.make_temp_directories
+
+ index = Gem::SourceIndex.new
+ index.add_spec spec
+
+ use_ui @ui do
+ @indexer.build_indicies index
+ end
+
+ specs_path = File.join @indexer.directory, "specs.#{@marshal_version}"
+ specs_dump = Gem.read_binary specs_path
+ specs = Marshal.load specs_dump
+
+ expected = [
+ ['d', Gem::Version.new('2.0'), 'ruby'],
+ ]
+
+ assert_equal expected, specs, 'specs'
+
+ latest_specs_path = File.join @indexer.directory,
+ "latest_specs.#{@marshal_version}"
+ latest_specs_dump = Gem.read_binary latest_specs_path
+ latest_specs = Marshal.load latest_specs_dump
+
+ expected = [
+ ['d', Gem::Version.new('2.0'), 'ruby'],
+ ]
+
+ assert_equal expected, latest_specs, 'latest_specs'
+ end
+
+ def test_generate_index
+ use_ui @ui do
+ @indexer.generate_index
+ end
+
+ assert_indexed @tempdir, 'yaml'
+ assert_indexed @tempdir, 'yaml.Z'
+ assert_indexed @tempdir, "Marshal.#{@marshal_version}"
+ assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
+
+ quickdir = File.join @tempdir, 'quick'
+ marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
+
+ assert File.directory?(quickdir)
+ assert File.directory?(marshal_quickdir)
+
+ assert_indexed quickdir, "index"
+ assert_indexed quickdir, "index.rz"
+
+ quick_index = File.read File.join(quickdir, 'index')
+ expected = <<-EOF
+a-1
+a-2
+a_evil-9
+b-2
+c-1.2
+d-2.0
+pl-1-i386-linux
+ EOF
+
+ assert_equal expected, quick_index
+
+ assert_indexed quickdir, "latest_index"
+ assert_indexed quickdir, "latest_index.rz"
+
+ latest_quick_index = File.read File.join(quickdir, 'latest_index')
+ expected = <<-EOF
+a-2
+a_evil-9
+b-2
+c-1.2
+d-2.0
+pl-1-i386-linux
+ EOF
+
+ assert_equal expected, latest_quick_index
+
+ assert_indexed quickdir, "#{@a1.full_name}.gemspec.rz"
+ assert_indexed quickdir, "#{@a2.full_name}.gemspec.rz"
+ assert_indexed quickdir, "#{@b2.full_name}.gemspec.rz"
+ assert_indexed quickdir, "#{@c1_2.full_name}.gemspec.rz"
+
+ assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
+ refute_indexed quickdir, "#{@pl1.full_name}.gemspec.rz"
+
+ assert_indexed marshal_quickdir, "#{@a1.full_name}.gemspec.rz"
+ assert_indexed marshal_quickdir, "#{@a2.full_name}.gemspec.rz"
+
+ refute_indexed quickdir, "#{@c1_2.full_name}.gemspec"
+ refute_indexed marshal_quickdir, "#{@c1_2.full_name}.gemspec"
+
+ assert_indexed @tempdir, "specs.#{@marshal_version}"
+ assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
+
+ assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
+ assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
+ end
+
+ def test_generate_index_ui
+ use_ui @ui do
+ @indexer.generate_index
+ end
+
+ expected = <<-EOF
+Loading 7 gems from #{@tempdir}
+.......
+Loaded all gems
+Generating quick index gemspecs for 7 gems
+.......
+Complete
+Generating specs index
+Generating latest specs index
+Generating quick index
+Generating latest index
+Generating Marshal master index
+Generating YAML master index for 7 gems (this may take a while)
+.......
+Complete
+Compressing indicies
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_generate_index_master
+ use_ui @ui do
+ @indexer.generate_index
+ end
+
+ yaml_path = File.join @tempdir, 'yaml'
+ dump_path = File.join @tempdir, "Marshal.#{@marshal_version}"
+
+ yaml_index = YAML.load_file yaml_path
+ dump_index = Marshal.load Gem.read_binary(dump_path)
+
+ dump_index.each do |_,gem|
+ gem.send :remove_instance_variable, :@loaded
+ end
+
+ assert_equal yaml_index, dump_index,
+ "expected YAML and Marshal to produce identical results"
+ end
+
+ def test_generate_index_specs
+ use_ui @ui do
+ @indexer.generate_index
+ end
+
+ specs_path = File.join @tempdir, "specs.#{@marshal_version}"
+
+ specs_dump = Gem.read_binary specs_path
+ specs = Marshal.load specs_dump
+
+ expected = [
+ ['a', Gem::Version.new(1), 'ruby'],
+ ['a', Gem::Version.new(2), 'ruby'],
+ ['a_evil', Gem::Version.new(9), 'ruby'],
+ ['b', Gem::Version.new(2), 'ruby'],
+ ['c', Gem::Version.new('1.2'), 'ruby'],
+ ['d', Gem::Version.new('2.0'), 'ruby'],
+ ['pl', Gem::Version.new(1), 'i386-linux'],
+ ]
+
+ assert_equal expected, specs
+
+ assert_same specs[0].first, specs[1].first,
+ 'identical names not identical'
+
+ assert_same specs[0][1], specs[-1][1],
+ 'identical versions not identical'
+
+ assert_same specs[0].last, specs[1].last,
+ 'identical platforms not identical'
+
+ assert_not_same specs[1][1], specs[5][1],
+ 'different versions not different'
+ end
+
+ def test_generate_index_latest_specs
+ use_ui @ui do
+ @indexer.generate_index
+ end
+
+ latest_specs_path = File.join @tempdir, "latest_specs.#{@marshal_version}"
+
+ latest_specs_dump = Gem.read_binary latest_specs_path
+ latest_specs = Marshal.load latest_specs_dump
+
+ expected = [
+ ['a', Gem::Version.new(2), 'ruby'],
+ ['a_evil', Gem::Version.new(9), 'ruby'],
+ ['b', Gem::Version.new(2), 'ruby'],
+ ['c', Gem::Version.new('1.2'), 'ruby'],
+ ['d', Gem::Version.new('2.0'), 'ruby'],
+ ['pl', Gem::Version.new(1), 'i386-linux'],
+ ]
+
+ assert_equal expected, latest_specs
+
+ assert_same latest_specs[0][1], latest_specs[2][1],
+ 'identical versions not identical'
+
+ assert_same latest_specs[0].last, latest_specs[1].last,
+ 'identical platforms not identical'
+ end
+
+ def assert_indexed(dir, name)
+ file = File.join dir, name
+ assert File.exist?(file), "#{file} does not exist"
+ end
+
+ def refute_indexed(dir, name)
+ file = File.join dir, name
+ assert !File.exist?(file), "#{file} exists"
+ end
+
+end if ''.respond_to? :to_xs
+
diff --git a/trunk/test/rubygems/test_gem_install_update_options.rb b/trunk/test/rubygems/test_gem_install_update_options.rb
new file mode 100644
index 0000000000..3638a0670a
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_install_update_options.rb
@@ -0,0 +1,61 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_installer_test_case')
+require 'rubygems/install_update_options'
+require 'rubygems/command'
+
+class TestGemInstallUpdateOptions < GemInstallerTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Command.new 'dummy', 'dummy'
+ @cmd.extend Gem::InstallUpdateOptions
+ @cmd.add_install_update_options
+ end
+
+ def test_add_install_update_options
+ args = %w[-i /install_to --rdoc --ri -E -f -t -w -P HighSecurity
+ --ignore-dependencies --format-exec --include-dependencies]
+
+ assert @cmd.handles?(args)
+ end
+
+ def test_security_policy
+ @cmd.handle_options %w[-P HighSecurity]
+
+ assert_equal Gem::Security::HighSecurity, @cmd.options[:security_policy]
+ end
+
+ def test_security_policy_unknown
+ @cmd.add_install_update_options
+
+ assert_raise OptionParser::InvalidArgument do
+ @cmd.handle_options %w[-P UnknownSecurity]
+ end
+ end
+
+ def test_user_install_enabled
+ @cmd.handle_options %w[--user-install]
+
+ @installer = Gem::Installer.new @gem, @cmd.options
+ @installer.install
+ assert File.exist?(File.join(@userhome, '.gem', 'gems'))
+ assert File.exist?(File.join(@userhome, '.gem', 'gems',
+ @spec.full_name))
+ end
+
+ def test_user_install_disabled_read_only
+ @cmd.handle_options %w[--no-user-install]
+
+ File.chmod 0755, @userhome
+ FileUtils.chmod 0000, @gemhome
+
+ assert_raises(Gem::FilePermissionError) do
+ @installer = Gem::Installer.new @gem, @cmd.options
+ end
+ ensure
+ FileUtils.chmod 0755, @gemhome
+ end
+end
diff --git a/trunk/test/rubygems/test_gem_installer.rb b/trunk/test/rubygems/test_gem_installer.rb
new file mode 100644
index 0000000000..eb9743dd42
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_installer.rb
@@ -0,0 +1,868 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_installer_test_case')
+
+class TestGemInstaller < GemInstallerTestCase
+
+ def test_app_script_text
+ util_make_exec '2', ''
+
+ expected = <<-EOF
+#!#{Gem.ruby}
+#
+# This file was generated by RubyGems.
+#
+# The application 'a' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = \">= 0\"
+
+if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
+ version = $1
+ ARGV.shift
+end
+
+gem 'a', version
+load 'my_exec'
+ EOF
+
+ wrapper = @installer.app_script_text 'my_exec'
+ assert_equal expected, wrapper
+ end
+
+ def test_build_extensions_none
+ use_ui @ui do
+ @installer.build_extensions
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+
+ assert !File.exist?('gem_make.out')
+ end
+
+ def test_build_extensions_extconf_bad
+ @spec.extensions << 'extconf.rb'
+
+ e = assert_raise Gem::Installer::ExtensionBuildError do
+ use_ui @ui do
+ @installer.build_extensions
+ end
+ end
+
+ assert_match(/\AERROR: Failed to build gem native extension.$/, e.message)
+
+ assert_equal "Building native extensions. This could take a while...\n",
+ @ui.output
+ assert_equal '', @ui.error
+
+ gem_make_out = File.join @gemhome, 'gems', @spec.full_name, 'gem_make.out'
+ expected = <<-EOF
+#{Gem.ruby} extconf.rb
+#{Gem.ruby}: No such file or directory -- extconf.rb (LoadError)
+ EOF
+
+ assert_equal expected, File.read(gem_make_out)
+ end
+
+ def test_build_extensions_unsupported
+ @spec.extensions << nil
+
+ e = assert_raise Gem::Installer::ExtensionBuildError do
+ use_ui @ui do
+ @installer.build_extensions
+ end
+ end
+
+ assert_match(/^No builder for extension ''$/, e.message)
+
+ assert_equal "Building native extensions. This could take a while...\n",
+ @ui.output
+ assert_equal '', @ui.error
+
+ assert_equal "No builder for extension ''\n", File.read('gem_make.out')
+ ensure
+ FileUtils.rm_f 'gem_make.out'
+ end
+
+ def test_ensure_dependency
+ dep = Gem::Dependency.new 'a', '>= 2'
+ assert @installer.ensure_dependency(@spec, dep)
+
+ dep = Gem::Dependency.new 'b', '> 2'
+ e = assert_raise Gem::InstallError do
+ @installer.ensure_dependency @spec, dep
+ end
+
+ assert_equal 'a requires b (> 2, runtime)', e.message
+ end
+
+ def test_expand_and_validate_gem_dir
+ @installer.gem_dir = '/nonexistent'
+ expanded_gem_dir = @installer.send(:expand_and_validate_gem_dir)
+ if win_platform?
+ expected = File.expand_path('/nonexistent').downcase
+ expanded_gem_dir = expanded_gem_dir.downcase
+ else
+ expected = '/nonexistent'
+ end
+
+ assert_equal expected, expanded_gem_dir
+ end
+
+ def test_extract_files
+ format = Object.new
+ def format.file_entries
+ [[{'size' => 7, 'mode' => 0400, 'path' => 'thefile'}, 'thefile']]
+ end
+
+ @installer.format = format
+
+ @installer.extract_files
+
+ thefile_path = File.join(util_gem_dir, 'thefile')
+ assert_equal 'thefile', File.read(thefile_path)
+
+ unless Gem.win_platform? then
+ assert_equal 0400, File.stat(thefile_path).mode & 0777
+ end
+ end
+
+ def test_extract_files_bad_dest
+ @installer.gem_dir = 'somedir'
+ @installer.format = nil
+ e = assert_raise ArgumentError do
+ @installer.extract_files
+ end
+
+ assert_equal 'format required to extract from', e.message
+ end
+
+ def test_extract_files_relative
+ format = Object.new
+ def format.file_entries
+ [[{'size' => 10, 'mode' => 0644, 'path' => '../thefile'}, '../thefile']]
+ end
+
+ @installer.format = format
+
+ e = assert_raise Gem::InstallError do
+ @installer.extract_files
+ end
+
+ assert_equal "attempt to install file into \"../thefile\" under #{util_gem_dir.inspect}",
+ e.message
+ assert_equal false, File.file?(File.join(@tempdir, '../thefile')),
+ "You may need to remove this file if you broke the test once"
+ end
+
+ def test_extract_files_absolute
+ format = Object.new
+ def format.file_entries
+ [[{'size' => 8, 'mode' => 0644, 'path' => '/thefile'}, '/thefile']]
+ end
+
+ @installer.format = format
+
+ e = assert_raise Gem::InstallError do
+ @installer.extract_files
+ end
+
+ assert_equal 'attempt to install file into "/thefile"', e.message
+ assert_equal false, File.file?(File.join('/thefile')),
+ "You may need to remove this file if you broke the test once"
+ end
+
+ def test_generate_bin_bindir
+ @installer.wrappers = true
+
+ @spec.executables = ["my_exec"]
+ @spec.bindir = '.'
+
+ exec_file = @installer.formatted_program_filename "my_exec"
+ exec_path = File.join util_gem_dir(@spec.version), exec_file
+ File.open exec_path, 'w' do |f|
+ f.puts '#!/usr/bin/ruby'
+ end
+
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal true, File.exist?(installed_exec)
+ assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+ wrapper = File.read installed_exec
+ assert_match %r|generated by RubyGems|, wrapper
+ end
+
+ def test_generate_bin_script
+ @installer.wrappers = true
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal true, File.exist?(installed_exec)
+ assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+ wrapper = File.read installed_exec
+ assert_match %r|generated by RubyGems|, wrapper
+ end
+
+ def test_generate_bin_script_format
+ @installer.format_executable = true
+ @installer.wrappers = true
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ Gem::Installer.exec_format = 'foo-%s-bar'
+ @installer.generate_bin
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join util_inst_bindir, 'foo-my_exec-bar'
+ assert_equal true, File.exist?(installed_exec)
+ ensure
+ Gem::Installer.exec_format = nil
+ end
+
+ def test_generate_bin_script_format_disabled
+ @installer.wrappers = true
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ Gem::Installer.exec_format = 'foo-%s-bar'
+ @installer.generate_bin
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join util_inst_bindir, 'my_exec'
+ assert_equal true, File.exist?(installed_exec)
+ ensure
+ Gem::Installer.exec_format = nil
+ end
+
+ def test_generate_bin_script_install_dir
+ @installer.wrappers = true
+ @spec.executables = ["my_exec"]
+
+ gem_dir = File.join "#{@gemhome}2", 'gems', @spec.full_name
+ gem_bindir = File.join gem_dir, 'bin'
+ FileUtils.mkdir_p gem_bindir
+ File.open File.join(gem_bindir, "my_exec"), 'w' do |f|
+ f.puts "#!/bin/ruby"
+ end
+
+ @installer.gem_home = "#{@gemhome}2"
+ @installer.gem_dir = gem_dir
+
+ @installer.generate_bin
+
+ installed_exec = File.join("#{@gemhome}2", 'bin', 'my_exec')
+ assert_equal true, File.exist?(installed_exec)
+ assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+ wrapper = File.read installed_exec
+ assert_match %r|generated by RubyGems|, wrapper
+ end
+
+ def test_generate_bin_script_no_execs
+ @installer.wrappers = true
+ @installer.generate_bin
+ assert_equal false, File.exist?(util_inst_bindir)
+ end
+
+ def test_generate_bin_script_no_perms
+ @installer.wrappers = true
+ util_make_exec
+
+ Dir.mkdir util_inst_bindir
+ File.chmod 0000, util_inst_bindir
+
+ assert_raises Gem::FilePermissionError do
+ @installer.generate_bin
+ end
+
+ ensure
+ File.chmod 0700, util_inst_bindir unless $DEBUG
+ end
+
+ def test_generate_bin_script_no_shebang
+ @installer.wrappers = true
+ @spec.executables = ["my_exec"]
+
+ gem_dir = File.join @gemhome, 'gems', @spec.full_name
+ gem_bindir = File.join gem_dir, 'bin'
+ FileUtils.mkdir_p gem_bindir
+ File.open File.join(gem_bindir, "my_exec"), 'w' do |f|
+ f.puts "blah blah blah"
+ end
+
+ @installer.generate_bin
+
+ installed_exec = File.join @gemhome, 'bin', 'my_exec'
+ assert_equal true, File.exist?(installed_exec)
+ assert_equal 0100755, File.stat(installed_exec).mode unless win_platform?
+
+ wrapper = File.read installed_exec
+ assert_match %r|generated by RubyGems|, wrapper
+ # HACK some gems don't have #! in their executables, restore 2008/06
+ #assert_no_match %r|generated by RubyGems|, wrapper
+ end
+
+ def test_generate_bin_script_wrappers
+ @installer.wrappers = true
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+
+ real_exec = File.join util_gem_dir, 'bin', 'my_exec'
+
+ # fake --no-wrappers for previous install
+ unless Gem.win_platform? then
+ FileUtils.mkdir_p File.dirname(installed_exec)
+ FileUtils.ln_s real_exec, installed_exec
+ end
+
+ @installer.generate_bin
+ assert_equal true, File.directory?(util_inst_bindir)
+ assert_equal true, File.exist?(installed_exec)
+ assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
+
+ assert_match %r|generated by RubyGems|, File.read(installed_exec)
+
+ assert_no_match %r|generated by RubyGems|, File.read(real_exec),
+ 'real executable overwritten'
+ end
+
+ def test_generate_bin_symlink
+ return if win_platform? #Windows FS do not support symlinks
+
+ @installer.wrappers = false
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal true, File.symlink?(installed_exec)
+ assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+ File.readlink(installed_exec))
+ end
+
+ def test_generate_bin_symlink_no_execs
+ @installer.wrappers = false
+ @installer.generate_bin
+ assert_equal false, File.exist?(util_inst_bindir)
+ end
+
+ def test_generate_bin_symlink_no_perms
+ @installer.wrappers = false
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ Dir.mkdir util_inst_bindir
+ File.chmod 0000, util_inst_bindir
+
+ assert_raises Gem::FilePermissionError do
+ @installer.generate_bin
+ end
+
+ ensure
+ File.chmod 0700, util_inst_bindir unless $DEBUG
+ end
+
+ def test_generate_bin_symlink_update_newer
+ return if win_platform? #Windows FS do not support symlinks
+
+ @installer.wrappers = false
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+ File.readlink(installed_exec))
+
+ @spec = Gem::Specification.new do |s|
+ s.files = ['lib/code.rb']
+ s.name = "a"
+ s.version = "3"
+ s.summary = "summary"
+ s.description = "desc"
+ s.require_path = 'lib'
+ end
+
+ util_make_exec '3'
+ @installer.gem_dir = File.join util_gem_dir('3')
+ @installer.generate_bin
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal(File.join(util_gem_bindir('3'), "my_exec"),
+ File.readlink(installed_exec),
+ "Ensure symlink moved to latest version")
+ end
+
+ def test_generate_bin_symlink_update_older
+ return if win_platform? #Windows FS do not support symlinks
+
+ @installer.wrappers = false
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal(File.join(util_gem_dir, "bin", "my_exec"),
+ File.readlink(installed_exec))
+
+ spec = Gem::Specification.new do |s|
+ s.files = ['lib/code.rb']
+ s.name = "a"
+ s.version = "1"
+ s.summary = "summary"
+ s.description = "desc"
+ s.require_path = 'lib'
+ end
+
+ util_make_exec '1'
+ @installer.gem_dir = util_gem_dir('1')
+ @installer.spec = spec
+
+ @installer.generate_bin
+
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal(File.join(util_gem_dir('2'), "bin", "my_exec"),
+ File.readlink(installed_exec),
+ "Ensure symlink not moved")
+ end
+
+ def test_generate_bin_symlink_update_remove_wrapper
+ return if win_platform? #Windows FS do not support symlinks
+
+ @installer.wrappers = true
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ @installer.generate_bin
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal true, File.exist?(installed_exec)
+
+ @spec = Gem::Specification.new do |s|
+ s.files = ['lib/code.rb']
+ s.name = "a"
+ s.version = "3"
+ s.summary = "summary"
+ s.description = "desc"
+ s.require_path = 'lib'
+ end
+
+ @installer.wrappers = false
+ util_make_exec '3'
+ @installer.gem_dir = util_gem_dir '3'
+ @installer.generate_bin
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal(File.join(util_gem_dir('3'), "bin", "my_exec"),
+ File.readlink(installed_exec),
+ "Ensure symlink moved to latest version")
+ end
+
+ def test_generate_bin_symlink_win32
+ old_win_platform = Gem.win_platform?
+ Gem.win_platform = true
+ @installer.wrappers = false
+ util_make_exec
+ @installer.gem_dir = util_gem_dir
+
+ use_ui @ui do
+ @installer.generate_bin
+ end
+
+ assert_equal true, File.directory?(util_inst_bindir)
+ installed_exec = File.join(util_inst_bindir, "my_exec")
+ assert_equal true, File.exist?(installed_exec)
+
+ assert_match(/Unable to use symlinks on Windows, installing wrapper/i,
+ @ui.error)
+
+ wrapper = File.read installed_exec
+ assert_match(/generated by RubyGems/, wrapper)
+ ensure
+ Gem.win_platform = old_win_platform
+ end
+
+ def test_generate_bin_uses_default_shebang
+ return if win_platform? #Windows FS do not support symlinks
+
+ @installer.wrappers = true
+ util_make_exec
+
+ @installer.generate_bin
+
+ default_shebang = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
+ shebang_line = open("#{@gemhome}/bin/my_exec") { |f| f.readlines.first }
+ assert_match(/\A#!/, shebang_line)
+ assert_match(/#{default_shebang}/, shebang_line)
+ end
+
+ def test_initialize
+ spec = quick_gem 'a' do |s| s.platform = Gem::Platform.new 'mswin32' end
+ gem = File.join @tempdir, "#{spec.full_name}.gem"
+
+ Dir.mkdir util_inst_bindir
+ util_build_gem spec
+ FileUtils.mv File.join(@gemhome, 'cache', "#{spec.full_name}.gem"),
+ @tempdir
+
+ installer = Gem::Installer.new gem
+
+ assert_equal File.join(@gemhome, 'gems', spec.full_name), installer.gem_dir
+ end
+
+ def test_install
+ Dir.mkdir util_inst_bindir
+ util_setup_gem
+
+ build_rake_in do
+ use_ui @ui do
+ assert_equal @spec, @installer.install
+ end
+ end
+
+ gemdir = File.join @gemhome, 'gems', @spec.full_name
+ assert File.exist?(gemdir)
+
+ exe = File.join(gemdir, 'bin', 'executable')
+ assert File.exist?(exe)
+ exe_mode = File.stat(exe).mode & 0111
+ assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
+
+ assert File.exist?(File.join(gemdir, 'lib', 'code.rb'))
+
+ assert File.exist?(File.join(gemdir, 'ext', 'a', 'Rakefile'))
+
+ spec_file = File.join(@gemhome, 'specifications',
+ "#{@spec.full_name}.gemspec")
+
+ assert_equal spec_file, @spec.loaded_from
+ assert File.exist?(spec_file)
+ end
+
+ def test_install_bad_gem
+ gem = nil
+
+ use_ui @ui do
+ Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+ gem = File.join @tempdir, "#{@spec.full_name}.gem"
+ end
+
+ gem_data = File.open gem, 'rb' do |fp| fp.read 1024 end
+ File.open gem, 'wb' do |fp| fp.write gem_data end
+
+ e = assert_raise Gem::InstallError do
+ use_ui @ui do
+ @installer = Gem::Installer.new gem
+ @installer.install
+ end
+ end
+
+ assert_equal "invalid gem format for #{gem}", e.message
+ end
+
+ def test_install_check_dependencies
+ @spec.add_dependency 'b', '> 5'
+ util_setup_gem
+
+ use_ui @ui do
+ assert_raise Gem::InstallError do
+ @installer.install
+ end
+ end
+ end
+
+ def test_install_force
+ use_ui @ui do
+ installer = Gem::Installer.new old_ruby_required, :force => true
+ installer.install
+ end
+
+ gem_dir = File.join(@gemhome, 'gems', 'old_ruby_required-1')
+ assert File.exist?(gem_dir)
+ end
+
+ def test_install_ignore_dependencies
+ Dir.mkdir util_inst_bindir
+ @spec.add_dependency 'b', '> 5'
+ util_setup_gem
+ @installer.ignore_dependencies = true
+
+ build_rake_in do
+ use_ui @ui do
+ assert_equal @spec, @installer.install
+ end
+ end
+
+ gemdir = File.join @gemhome, 'gems', @spec.full_name
+ assert File.exist?(gemdir)
+
+ exe = File.join(gemdir, 'bin', 'executable')
+ assert File.exist?(exe)
+ exe_mode = File.stat(exe).mode & 0111
+ assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
+ assert File.exist?(File.join(gemdir, 'lib', 'code.rb'))
+
+ assert File.exist?(File.join(@gemhome, 'specifications',
+ "#{@spec.full_name}.gemspec"))
+ end
+
+ def test_install_missing_dirs
+ FileUtils.rm_f File.join(Gem.dir, 'cache')
+ FileUtils.rm_f File.join(Gem.dir, 'docs')
+ FileUtils.rm_f File.join(Gem.dir, 'specifications')
+
+ use_ui @ui do
+ Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+ gem = File.join @tempdir, "#{@spec.full_name}.gem"
+
+ @installer.install
+ end
+
+ File.directory? File.join(Gem.dir, 'cache')
+ File.directory? File.join(Gem.dir, 'docs')
+ File.directory? File.join(Gem.dir, 'specifications')
+
+ assert File.exist?(File.join(@gemhome, 'cache', "#{@spec.full_name}.gem"))
+ assert File.exist?(File.join(@gemhome, 'specifications',
+ "#{@spec.full_name}.gemspec"))
+ end
+ unless win_platform? # File.chmod doesn't work
+ def test_install_user_local_fallback
+ Dir.mkdir util_inst_bindir
+ File.chmod 0755, @userhome
+ File.chmod 0000, util_inst_bindir
+ File.chmod 0000, Gem.dir
+ install_dir = File.join @userhome, '.gem', 'gems', @spec.full_name
+ @spec.executables = ["executable"]
+
+ build_rake_in do
+ use_ui @ui do
+ util_setup_gem
+ @installer.install
+ end
+ end
+
+ assert File.exist?(File.join(install_dir, 'lib', 'code.rb'))
+ assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+ ensure
+ File.chmod 0755, Gem.dir
+ File.chmod 0755, util_inst_bindir
+ end
+
+ def test_install_bindir_read_only
+ Dir.mkdir util_inst_bindir
+ File.chmod 0755, @userhome
+ File.chmod 0000, util_inst_bindir
+
+ build_rake_in do
+ use_ui @ui do
+ setup
+ util_setup_gem
+ @installer.install
+ end
+ end
+
+ assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+ ensure
+ File.chmod 0755, util_inst_bindir
+ end
+ end
+
+ def test_install_with_message
+ @spec.post_install_message = 'I am a shiny gem!'
+
+ use_ui @ui do
+ Dir.chdir @tempdir do Gem::Builder.new(@spec).build end
+
+ @installer.install
+ end
+
+ assert_match %r|I am a shiny gem!|, @ui.output
+ end
+
+ def test_install_wrong_ruby_version
+ use_ui @ui do
+ installer = Gem::Installer.new old_ruby_required
+ e = assert_raise Gem::InstallError do
+ installer.install
+ end
+ assert_equal 'old_ruby_required requires Ruby version = 1.4.6',
+ e.message
+ end
+ end
+
+ def test_install_wrong_rubygems_version
+ spec = quick_gem 'old_rubygems_required', '1' do |s|
+ s.required_rubygems_version = '< 0'
+ end
+
+ util_build_gem spec
+
+ gem = File.join @gemhome, 'cache', "#{spec.full_name}.gem"
+
+ use_ui @ui do
+ @installer = Gem::Installer.new gem
+ e = assert_raise Gem::InstallError do
+ @installer.install
+ end
+ assert_equal 'old_rubygems_required requires RubyGems version < 0',
+ e.message
+ end
+ end
+
+ def test_installation_satisfies_dependency_eh
+ dep = Gem::Dependency.new 'a', '>= 2'
+ assert @installer.installation_satisfies_dependency?(dep)
+
+ dep = Gem::Dependency.new 'a', '> 2'
+ assert ! @installer.installation_satisfies_dependency?(dep)
+ end
+
+ def test_shebang
+ util_make_exec '2', "#!/usr/bin/ruby"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_arguments
+ util_make_exec '2', "#!/usr/bin/ruby -ws"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+
+ def test_shebang_empty
+ util_make_exec '2', ''
+
+ shebang = @installer.shebang 'my_exec'
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_env
+ util_make_exec '2', "#!/usr/bin/env ruby"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_env_arguments
+ util_make_exec '2', "#!/usr/bin/env ruby -ws"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+
+ def test_shebang_env_shebang
+ util_make_exec '2', ''
+ @installer.env_shebang = true
+
+ shebang = @installer.shebang 'my_exec'
+ assert_equal "#!/usr/bin/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}", shebang
+ end
+
+ def test_shebang_nested
+ util_make_exec '2', "#!/opt/local/ruby/bin/ruby"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_nested_arguments
+ util_make_exec '2', "#!/opt/local/ruby/bin/ruby -ws"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+
+ def test_shebang_version
+ util_make_exec '2', "#!/usr/bin/ruby18"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_version_arguments
+ util_make_exec '2', "#!/usr/bin/ruby18 -ws"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+
+ def test_shebang_version_env
+ util_make_exec '2', "#!/usr/bin/env ruby18"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
+
+ def test_shebang_version_env_arguments
+ util_make_exec '2', "#!/usr/bin/env ruby18 -ws"
+
+ shebang = @installer.shebang 'my_exec'
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+
+ def test_unpack
+ util_setup_gem
+
+ dest = File.join @gemhome, 'gems', @spec.full_name
+
+ @installer.unpack dest
+
+ assert File.exist?(File.join(dest, 'lib', 'code.rb'))
+ assert File.exist?(File.join(dest, 'bin', 'executable'))
+ end
+
+ def test_write_spec
+ spec_dir = File.join @gemhome, 'specifications'
+ spec_file = File.join spec_dir, "#{@spec.full_name}.gemspec"
+ FileUtils.rm spec_file
+ assert !File.exist?(spec_file)
+
+ @installer.spec = @spec
+ @installer.gem_home = @gemhome
+
+ @installer.write_spec
+
+ assert File.exist?(spec_file)
+ assert_equal @spec, eval(File.read(spec_file))
+ end
+
+ def old_ruby_required
+ spec = quick_gem 'old_ruby_required', '1' do |s|
+ s.required_ruby_version = '= 1.4.6'
+ end
+
+ util_build_gem spec
+
+ File.join @gemhome, 'cache', "#{spec.full_name}.gem"
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_local_remote_options.rb b/trunk/test/rubygems/test_gem_local_remote_options.rb
new file mode 100644
index 0000000000..e676c94f21
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_local_remote_options.rb
@@ -0,0 +1,85 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/local_remote_options'
+require 'rubygems/command'
+
+class TestGemLocalRemoteOptions < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Command.new 'dummy', 'dummy'
+ @cmd.extend Gem::LocalRemoteOptions
+ end
+
+ def test_add_local_remote_options
+ @cmd.add_local_remote_options
+
+ args = %w[-l -r -b -B 10 --source http://gems.example.com -p --update-sources]
+ assert @cmd.handles?(args)
+ end
+
+ def test_local_eh
+ assert_equal false, @cmd.local?
+
+ @cmd.options[:domain] = :local
+
+ assert_equal true, @cmd.local?
+
+ @cmd.options[:domain] = :both
+
+ assert_equal true, @cmd.local?
+ end
+
+ def test_remote_eh
+ assert_equal false, @cmd.remote?
+
+ @cmd.options[:domain] = :remote
+
+ assert_equal true, @cmd.remote?
+
+ @cmd.options[:domain] = :both
+
+ assert_equal true, @cmd.remote?
+ end
+
+ def test_source_option
+ @cmd.add_source_option
+
+ s1 = URI.parse 'http://more-gems.example.com/'
+ s2 = URI.parse 'http://even-more-gems.example.com/'
+ s3 = URI.parse 'http://other-gems.example.com/some_subdir'
+
+ @cmd.handle_options %W[--source #{s1} --source #{s2} --source #{s3}]
+
+ assert_equal [s1.to_s, s2.to_s, "#{s3}/"], Gem.sources
+ end
+
+ def test_update_sources_option
+ @cmd.add_update_sources_option
+
+ Gem.configuration.update_sources = false
+
+ @cmd.handle_options %W[--update-sources]
+
+ assert_equal true, Gem.configuration.update_sources
+
+ @cmd.handle_options %W[--no-update-sources]
+
+ assert_equal false, Gem.configuration.update_sources
+ end
+
+ def test_source_option_bad
+ @cmd.add_source_option
+
+ s1 = 'htp://more-gems.example.com'
+
+ assert_raise OptionParser::InvalidArgument do
+ @cmd.handle_options %W[--source #{s1}]
+ end
+
+ assert_equal [@gem_repo], Gem.sources
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_header.rb b/trunk/test/rubygems/test_gem_package_tar_header.rb
new file mode 100644
index 0000000000..9b7708dca8
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_header.rb
@@ -0,0 +1,137 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarHeader < TarTestCase
+
+ def setup
+ super
+
+ header = {
+ :name => 'x',
+ :mode => 0644,
+ :uid => 1000,
+ :gid => 10000,
+ :size => 100,
+ :mtime => 12345,
+ :typeflag => '0',
+ :linkname => 'link',
+ :uname => 'user',
+ :gname => 'group',
+ :devmajor => 1,
+ :devminor => 2,
+ :prefix => 'y',
+ }
+
+ @tar_header = Gem::Package::TarHeader.new header
+ end
+
+ def test_self_from
+ io = TempIO.new @tar_header.to_s
+
+ new_header = Gem::Package::TarHeader.from io
+
+ assert_headers_equal @tar_header, new_header
+ end
+
+ def test_initialize
+ assert_equal '', @tar_header.checksum, 'checksum'
+ assert_equal 1, @tar_header.devmajor, 'devmajor'
+ assert_equal 2, @tar_header.devminor, 'devminor'
+ assert_equal 10000, @tar_header.gid, 'gid'
+ assert_equal 'group', @tar_header.gname, 'gname'
+ assert_equal 'link', @tar_header.linkname, 'linkname'
+ assert_equal 'ustar', @tar_header.magic, 'magic'
+ assert_equal 0644, @tar_header.mode, 'mode'
+ assert_equal 12345, @tar_header.mtime, 'mtime'
+ assert_equal 'x', @tar_header.name, 'name'
+ assert_equal 'y', @tar_header.prefix, 'prefix'
+ assert_equal 100, @tar_header.size, 'size'
+ assert_equal '0', @tar_header.typeflag, 'typeflag'
+ assert_equal 1000, @tar_header.uid, 'uid'
+ assert_equal 'user', @tar_header.uname, 'uname'
+ assert_equal '00', @tar_header.version, 'version'
+
+ assert !@tar_header.empty?, 'empty'
+ end
+
+ def test_initialize_bad
+ assert_raises ArgumentError do
+ Gem::Package::TarHeader.new :name => '', :size => '', :mode => ''
+ end
+
+ assert_raises ArgumentError do
+ Gem::Package::TarHeader.new :name => '', :size => '', :prefix => ''
+ end
+
+ assert_raises ArgumentError do
+ Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => ''
+ end
+
+ assert_raises ArgumentError do
+ Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => ''
+ end
+ end
+
+ def test_empty_eh
+ assert !@tar_header.empty?
+
+ @tar_header = Gem::Package::TarHeader.new :name => 'x', :prefix => '',
+ :mode => 0, :size => 0,
+ :empty => true
+
+ assert @tar_header.empty?
+ end
+
+ def test_equals2
+ assert_equal @tar_header, @tar_header
+ assert_equal @tar_header, @tar_header.dup
+ end
+
+ def test_to_s
+ expected = <<-EOF.split("\n").join
+x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\0000000644\0000001750\0000023420\00000000000144\00000000030071
+\000012467\000 0link\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000ustar\00000user\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\0000000001\0000000002\000y\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+\000\000\000\000\000\000\000\000\000\000
+ EOF
+
+ assert_headers_equal expected, @tar_header
+ end
+
+ def test_update_checksum
+ assert_equal '', @tar_header.checksum
+
+ @tar_header.update_checksum
+
+ assert_equal '012467', @tar_header.checksum
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_input.rb b/trunk/test/rubygems/test_gem_package_tar_input.rb
new file mode 100644
index 0000000000..279026b149
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_input.rb
@@ -0,0 +1,119 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package/tar_input'
+
+class TestGemPackageTarInput < TarTestCase
+
+ # Sometimes the setgid bit doesn't take. Don't know if this is a problem on
+ # all systems, or just some. But for now, we will ignore it in the tests.
+ SETGID_BIT = 02000
+
+ def setup
+ super
+
+ inner_tar = tar_file_header("bla", "", 0612, 10)
+ inner_tar += "0123456789" + "\0" * 502
+ inner_tar += tar_file_header("foo", "", 0636, 5)
+ inner_tar += "01234" + "\0" * 507
+ inner_tar += tar_dir_header("__dir__", "", 0600)
+ inner_tar += "\0" * 1024
+ str = TempIO.new
+
+ begin
+ os = Zlib::GzipWriter.new str
+ os.write inner_tar
+ ensure
+ os.finish
+ end
+
+ str.rewind
+
+ @file = File.join @tempdir, 'bla.tar'
+
+ File.open @file, 'wb' do |f|
+ f.write tar_file_header("data.tar.gz", "", 0644, str.string.size)
+ f.write str.string
+ f.write "\0" * ((512 - (str.string.size % 512)) % 512 )
+
+ @spec = Gem::Specification.new do |spec|
+ spec.author = "Mauricio :)"
+ end
+
+ meta = @spec.to_yaml
+
+ f.write tar_file_header("metadata", "", 0644, meta.size)
+ f.write meta + "\0" * (1024 - meta.size)
+ f.write "\0" * 1024
+ end
+
+ @entry_names = %w{bla foo __dir__}
+ @entry_sizes = [10, 5, 0]
+ #FIXME: are these modes system dependent?
+ @entry_modes = [0100612, 0100636, 040600]
+ @entry_files = %W[#{@tempdir}/bla #{@tempdir}/foo]
+ @entry_contents = %w[0123456789 01234]
+ end
+
+ def test_each_works
+ open @file, 'rb' do |io|
+ Gem::Package::TarInput.open io do |tar_input|
+ count = 0
+
+ tar_input.each_with_index do |entry, i|
+ count = i
+
+ assert_kind_of Gem::Package::TarReader::Entry, entry
+ assert_equal @entry_names[i], entry.header.name
+ assert_equal @entry_sizes[i], entry.header.size
+ end
+
+ assert_equal 2, count
+
+ assert_equal @spec, tar_input.metadata
+ end
+ end
+ end
+
+ def test_extract_entry_works
+ open @file, 'rb' do |io|
+ Gem::Package::TarInput.open io do |tar_input|
+ assert_equal @spec, tar_input.metadata
+
+ count = 0
+
+ tar_input.each_with_index do |entry, i|
+ count = i
+ tar_input.extract_entry @tempdir, entry
+ name = File.join @tempdir, entry.header.name
+
+ if entry.directory?
+ assert File.dir?(name)
+ else
+ assert File.file?(name)
+ assert_equal @entry_sizes[i], File.stat(name).size
+ #FIXME: win32? !!
+ end
+
+ unless Gem.win_platform? then
+ assert_equal @entry_modes[i], File.stat(name).mode & (~SETGID_BIT)
+ end
+ end
+
+ assert_equal 2, count
+ end
+ end
+
+ @entry_files.each_with_index do |x, i|
+ assert File.file?(x)
+ assert_equal @entry_contents[i], File.read_b(x)
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_output.rb b/trunk/test/rubygems/test_gem_package_tar_output.rb
new file mode 100644
index 0000000000..06dbb1a4da
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_output.rb
@@ -0,0 +1,104 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package/tar_output'
+
+class TestGemPackageTarOutput < TarTestCase
+
+ def setup
+ super
+
+ @file = File.join @tempdir, 'bla2.tar'
+ end
+
+ def test_self_open
+ open @file, 'wb' do |tar_io|
+ Gem::Package::TarOutput.open tar_io do |tar_writer|
+ tar_writer.add_file_simple 'README', 0, 17 do |io|
+ io.write "This is a README\n"
+ end
+
+ tar_writer.metadata = "This is some metadata\n"
+ end
+ end
+
+ files = util_extract
+
+ name, data = files.shift
+ assert_equal 'data.tar.gz', name
+
+ gz = Zlib::GzipReader.new StringIO.new(data)
+
+ Gem::Package::TarReader.new gz do |tar_reader|
+ tar_reader.each do |entry|
+ assert_equal 'README', entry.full_name
+ assert_equal "This is a README\n", entry.read
+ end
+ end
+
+ gz.close
+
+ name, data = files.shift
+ assert_equal 'metadata.gz', name
+
+ gz = Zlib::GzipReader.new StringIO.new(data)
+ assert_equal "This is some metadata\n", gz.read
+
+ assert files.empty?
+ ensure
+ gz.close if gz
+ end
+
+ if defined? OpenSSL then
+ def test_self_open_signed
+ signer = Gem::Security::Signer.new @private_key, [@public_cert]
+
+ open @file, 'wb' do |tar_io|
+ Gem::Package::TarOutput.open tar_io, signer do |tar_writer|
+ tar_writer.add_file_simple 'README', 0, 17 do |io|
+ io.write "This is a README\n"
+ end
+
+ tar_writer.metadata = "This is some metadata\n"
+ end
+ end
+
+ files = util_extract
+
+ name, data = files.shift
+ assert_equal 'data.tar.gz', name
+
+ name, data = files.shift
+ assert_equal 'metadata.gz', name
+
+ name, data = files.shift
+ assert_equal 'data.tar.gz.sig', name
+
+ name, data = files.shift
+ assert_equal 'metadata.gz.sig', name
+
+ assert files.empty?
+ end
+ end
+
+ def util_extract
+ files = []
+
+ open @file, 'rb' do |io|
+ Gem::Package::TarReader.new io do |tar_reader|
+ tar_reader.each do |entry|
+ files << [entry.full_name, entry.read]
+ end
+ end
+ end
+
+ files
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_reader.rb b/trunk/test/rubygems/test_gem_package_tar_reader.rb
new file mode 100644
index 0000000000..6962088878
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_reader.rb
@@ -0,0 +1,53 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarReader < TarTestCase
+
+ def test_each_entry
+ tar = tar_dir_header "foo", "bar", 0
+ tar << tar_file_header("bar", "baz", 0, 0)
+
+ io = TempIO.new tar
+
+ entries = 0
+
+ Gem::Package::TarReader.new io do |tar_reader|
+ tar_reader.each_entry do |entry|
+ assert_kind_of Gem::Package::TarReader::Entry, entry
+
+ entries += 1
+ end
+ end
+
+ assert_equal 2, entries
+ end
+
+ def test_rewind
+ content = ('a'..'z').to_a.join(" ")
+
+ str = tar_file_header("lib/foo", "", 010644, content.size) + content +
+ "\0" * (512 - content.size)
+ str << "\0" * 1024
+
+ Gem::Package::TarReader.new(TempIO.new(str)) do |tar_reader|
+ 3.times do
+ tar_reader.rewind
+ i = 0
+ tar_reader.each_entry do |entry|
+ assert_equal(content, entry.read)
+ i += 1
+ end
+ assert_equal(1, i)
+ end
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_reader_entry.rb b/trunk/test/rubygems/test_gem_package_tar_reader_entry.rb
new file mode 100644
index 0000000000..7e25143a85
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_reader_entry.rb
@@ -0,0 +1,116 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package'
+
+class TestGemPackageTarReaderEntry < TarTestCase
+
+ def setup
+ super
+
+ @contents = ('a'..'z').to_a.join * 100
+
+ @tar = ''
+ @tar << tar_file_header("lib/foo", "", 0, @contents.size)
+ @tar << @contents
+ @tar << "\0" * (512 - (@tar.size % 512))
+
+ @entry = util_entry @tar
+ end
+
+ def test_bytes_read
+ assert_equal 0, @entry.bytes_read
+
+ @entry.getc
+
+ assert_equal 1, @entry.bytes_read
+ end
+
+ def test_close
+ @entry.close
+
+ assert @entry.bytes_read
+
+ e = assert_raise IOError do @entry.eof? end
+ assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+ e = assert_raise IOError do @entry.getc end
+ assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+ e = assert_raise IOError do @entry.pos end
+ assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+ e = assert_raise IOError do @entry.read end
+ assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+
+ e = assert_raise IOError do @entry.rewind end
+ assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ end
+
+ def test_closed_eh
+ @entry.close
+
+ assert @entry.closed?
+ end
+
+ def test_eof_eh
+ @entry.read
+
+ assert @entry.eof?
+ end
+
+ def test_full_name
+ assert_equal 'lib/foo', @entry.full_name
+ end
+
+ def test_getc
+ assert_equal ?a, @entry.getc
+ end
+
+ def test_directory_eh
+ assert_equal false, @entry.directory?
+ assert_equal true, util_dir_entry.directory?
+ end
+
+ def test_file_eh
+ assert_equal true, @entry.file?
+ assert_equal false, util_dir_entry.file?
+ end
+
+ def test_pos
+ assert_equal 0, @entry.pos
+
+ @entry.getc
+
+ assert_equal 1, @entry.pos
+ end
+
+ def test_read
+ assert_equal @contents, @entry.read
+ end
+
+ def test_read_big
+ assert_equal @contents, @entry.read(@contents.size * 2)
+ end
+
+ def test_read_small
+ assert_equal @contents[0...100], @entry.read(100)
+ end
+
+ def test_rewind
+ char = @entry.getc
+
+ @entry.rewind
+
+ assert_equal 0, @entry.pos
+
+ assert_equal char, @entry.getc
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_package_tar_writer.rb b/trunk/test/rubygems/test_gem_package_tar_writer.rb
new file mode 100644
index 0000000000..e066c2967f
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_package_tar_writer.rb
@@ -0,0 +1,151 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_package_tar_test_case')
+require 'rubygems/package/tar_writer'
+
+class TestTarWriter < TarTestCase
+
+ def setup
+ super
+
+ @data = 'abcde12345'
+ @io = TempIO.new
+ @tar_writer = Gem::Package::TarWriter.new @io
+ end
+
+ def teardown
+ @tar_writer.close unless @tar_writer.closed?
+
+ super
+ end
+
+ def test_add_file
+ @tar_writer.add_file 'x', 0644 do |f| f.write 'a' * 10 end
+
+ assert_headers_equal(tar_file_header('x', '', 0644, 10),
+ @io.string[0, 512])
+ assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
+ assert_equal 1024, @io.pos
+ end
+
+ def test_add_file_simple
+ @tar_writer.add_file_simple 'x', 0644, 10 do |io| io.write "a" * 10 end
+
+ assert_headers_equal(tar_file_header('x', '', 0644, 10),
+ @io.string[0, 512])
+
+ assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
+ assert_equal 1024, @io.pos
+ end
+
+ def test_add_file_simple_padding
+ @tar_writer.add_file_simple 'x', 0, 100
+
+ assert_headers_equal tar_file_header('x', '', 0, 100),
+ @io.string[0, 512]
+
+ assert_equal "\0" * 512, @io.string[512, 512]
+ end
+
+ def test_add_file_simple_data
+ @tar_writer.add_file_simple("lib/foo/bar", 0, 10) { |f| f.write @data }
+ @tar_writer.flush
+
+ assert_equal @data + ("\0" * (512-@data.size)),
+ @io.string[512, 512]
+ end
+
+ def test_add_file_simple_size
+ assert_raise Gem::Package::TarWriter::FileOverflow do
+ @tar_writer.add_file_simple("lib/foo/bar", 0, 10) do |io|
+ io.write "1" * 11
+ end
+ end
+ end
+
+ def test_add_file_unseekable
+ assert_raise Gem::Package::NonSeekableIO do
+ Gem::Package::TarWriter.new(Object.new).add_file 'x', 0
+ end
+ end
+
+ def test_close
+ @tar_writer.close
+
+ assert_equal "\0" * 1024, @io.string
+
+ e = assert_raise IOError do
+ @tar_writer.close
+ end
+ assert_equal 'closed Gem::Package::TarWriter', e.message
+
+ e = assert_raise IOError do
+ @tar_writer.flush
+ end
+ assert_equal 'closed Gem::Package::TarWriter', e.message
+
+ e = assert_raise IOError do
+ @tar_writer.add_file 'x', 0
+ end
+ assert_equal 'closed Gem::Package::TarWriter', e.message
+
+ e = assert_raise IOError do
+ @tar_writer.add_file_simple 'x', 0, 0
+ end
+ assert_equal 'closed Gem::Package::TarWriter', e.message
+
+ e = assert_raise IOError do
+ @tar_writer.mkdir 'x', 0
+ end
+ assert_equal 'closed Gem::Package::TarWriter', e.message
+ end
+
+ def test_mkdir
+ @tar_writer.mkdir 'foo', 0644
+
+ assert_headers_equal tar_dir_header('foo', '', 0644),
+ @io.string[0, 512]
+ assert_equal 512, @io.pos
+ end
+
+ def test_split_name
+ assert_equal ['b' * 100, 'a' * 155],
+ @tar_writer.split_name("#{'a' * 155}/#{'b' * 100}")
+
+ assert_equal ["#{'qwer/' * 19}bla", 'a' * 151],
+ @tar_writer.split_name("#{'a' * 151}/#{'qwer/' * 19}bla")
+ end
+
+ def test_split_name_too_long_name
+ name = File.join 'a', 'b' * 100
+ assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name)
+
+ assert_raise Gem::Package::TooLongFileName do
+ name = File.join 'a', 'b' * 101
+ @tar_writer.split_name name
+ end
+ end
+
+ def test_split_name_too_long_prefix
+ name = File.join 'a' * 155, 'b'
+ assert_equal ['b', 'a' * 155], @tar_writer.split_name(name)
+
+ assert_raise Gem::Package::TooLongFileName do
+ name = File.join 'a' * 156, 'b'
+ @tar_writer.split_name name
+ end
+ end
+
+ def test_split_name_too_long_total
+ assert_raise Gem::Package::TooLongFileName do
+ @tar_writer.split_name 'a' * 257
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_platform.rb b/trunk/test/rubygems/test_gem_platform.rb
new file mode 100644
index 0000000000..648c2a9f36
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_platform.rb
@@ -0,0 +1,259 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'test/unit'
+require 'rubygems/platform'
+require 'rbconfig'
+
+class TestGemPlatform < RubyGemTestCase
+
+ def test_self_const_missing
+ consts = [:DARWIN, :LINUX_586, :MSWIN32, :PPC_DARWIN, :WIN32, :X86_LINUX]
+
+ consts.each do |const|
+ e = assert_raise NameError do
+ Gem::Platform.const_missing const
+ end
+
+ assert_equal "#{const} has been removed, use CURRENT instead",
+ e.message
+ end
+ end
+
+ def test_self_local
+ util_set_arch 'i686-darwin8.10.1'
+
+ assert_equal Gem::Platform.new(%w[x86 darwin 8]), Gem::Platform.local
+ end
+
+ def test_self_match
+ assert Gem::Platform.match(nil), 'nil == ruby'
+ assert Gem::Platform.match(Gem::Platform.local), 'exact match'
+ assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match'
+ assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby'
+ end
+
+ def test_self_new
+ assert_equal Gem::Platform.local, Gem::Platform.new(Gem::Platform::CURRENT)
+ assert_equal Gem::Platform::RUBY, Gem::Platform.new(Gem::Platform::RUBY)
+ assert_equal Gem::Platform::RUBY, Gem::Platform.new(nil)
+ assert_equal Gem::Platform::RUBY, Gem::Platform.new('')
+ end
+
+ def test_initialize
+ test_cases = {
+ 'amd64-freebsd6' => ['amd64', 'freebsd', '6'],
+ 'hppa2.0w-hpux11.31' => ['hppa2.0w', 'hpux', '11'],
+ 'java' => [nil, 'java', nil],
+ 'jruby' => [nil, 'java', nil],
+ 'powerpc-aix5.3.0.0' => ['powerpc', 'aix', '5'],
+ 'powerpc-darwin7' => ['powerpc', 'darwin', '7'],
+ 'powerpc-darwin8' => ['powerpc', 'darwin', '8'],
+ 'powerpc-linux' => ['powerpc', 'linux', nil],
+ 'powerpc64-linux' => ['powerpc64', 'linux', nil],
+ 'sparc-solaris2.10' => ['sparc', 'solaris', '2.10'],
+ 'sparc-solaris2.8' => ['sparc', 'solaris', '2.8'],
+ 'sparc-solaris2.9' => ['sparc', 'solaris', '2.9'],
+ 'universal-darwin8' => ['universal', 'darwin', '8'],
+ 'universal-darwin9' => ['universal', 'darwin', '9'],
+ 'i386-cygwin' => ['x86', 'cygwin', nil],
+ 'i686-darwin' => ['x86', 'darwin', nil],
+ 'i686-darwin8.4.1' => ['x86', 'darwin', '8'],
+ 'i386-freebsd4.11' => ['x86', 'freebsd', '4'],
+ 'i386-freebsd5' => ['x86', 'freebsd', '5'],
+ 'i386-freebsd6' => ['x86', 'freebsd', '6'],
+ 'i386-freebsd7' => ['x86', 'freebsd', '7'],
+ 'i386-java1.5' => ['x86', 'java', '1.5'],
+ 'x86-java1.6' => ['x86', 'java', '1.6'],
+ 'i386-java1.6' => ['x86', 'java', '1.6'],
+ 'i686-linux' => ['x86', 'linux', nil],
+ 'i586-linux' => ['x86', 'linux', nil],
+ 'i486-linux' => ['x86', 'linux', nil],
+ 'i386-linux' => ['x86', 'linux', nil],
+ 'i586-linux-gnu' => ['x86', 'linux', nil],
+ 'i386-linux-gnu' => ['x86', 'linux', nil],
+ 'i386-mingw32' => ['x86', 'mingw32', nil],
+ 'i386-mswin32' => ['x86', 'mswin32', nil],
+ 'i386-mswin32_80' => ['x86', 'mswin32', '80'],
+ 'i386-mswin32-80' => ['x86', 'mswin32', '80'],
+ 'x86-mswin32' => ['x86', 'mswin32', nil],
+ 'x86-mswin32_60' => ['x86', 'mswin32', '60'],
+ 'x86-mswin32-60' => ['x86', 'mswin32', '60'],
+ 'i386-netbsdelf' => ['x86', 'netbsdelf', nil],
+ 'i386-openbsd4.0' => ['x86', 'openbsd', '4.0'],
+ 'i386-solaris2.10' => ['x86', 'solaris', '2.10'],
+ 'i386-solaris2.8' => ['x86', 'solaris', '2.8'],
+ 'mswin32' => ['x86', 'mswin32', nil],
+ 'x86_64-linux' => ['x86_64', 'linux', nil],
+ 'x86_64-openbsd3.9' => ['x86_64', 'openbsd', '3.9'],
+ 'x86_64-openbsd4.0' => ['x86_64', 'openbsd', '4.0'],
+ }
+
+ test_cases.each do |arch, expected|
+ platform = Gem::Platform.new arch
+ assert_equal expected, platform.to_a, arch.inspect
+ end
+ end
+
+ def test_initialize_command_line
+ expected = ['x86', 'mswin32', nil]
+
+ platform = Gem::Platform.new 'i386-mswin32'
+
+ assert_equal expected, platform.to_a, 'i386-mswin32'
+
+ expected = ['x86', 'mswin32', '80']
+
+ platform = Gem::Platform.new 'i386-mswin32-80'
+
+ assert_equal expected, platform.to_a, 'i386-mswin32-80'
+ end
+
+ def test_initialize_mswin32_vc6
+ orig_RUBY_SO_NAME = Config::CONFIG['RUBY_SO_NAME']
+ Config::CONFIG['RUBY_SO_NAME'] = 'msvcrt-ruby18'
+
+ expected = ['x86', 'mswin32', nil]
+
+ platform = Gem::Platform.new 'i386-mswin32'
+
+ assert_equal expected, platform.to_a, 'i386-mswin32 VC6'
+ ensure
+ Config::CONFIG['RUBY_SO_NAME'] = orig_RUBY_SO_NAME
+ end
+
+ def test_initialize_platform
+ platform = Gem::Platform.new 'cpu-my_platform1'
+ expected = Gem::Platform.new platform
+
+ assert_equal 'cpu', platform.cpu
+ assert_equal 'my_platform', platform.os
+ assert_equal '1', platform.version
+ end
+
+ def test_initialize_test
+ platform = Gem::Platform.new 'cpu-my_platform1'
+ assert_equal 'cpu', platform.cpu
+ assert_equal 'my_platform', platform.os
+ assert_equal '1', platform.version
+
+ platform = Gem::Platform.new 'cpu-other_platform1'
+ assert_equal 'cpu', platform.cpu
+ assert_equal 'other_platform', platform.os
+ assert_equal '1', platform.version
+ end
+
+ def test_to_s
+ if win_platform? then
+ assert_equal 'x86-mswin32-60', Gem::Platform.local.to_s
+ else
+ assert_equal 'x86-darwin-8', Gem::Platform.local.to_s
+ end
+ end
+
+ def test_equals2
+ my = Gem::Platform.new %w[cpu my_platform 1]
+ other = Gem::Platform.new %w[cpu other_platform 1]
+
+ assert_equal my, my
+ assert_not_equal my, other
+ assert_not_equal other, my
+ end
+
+ def test_equals3
+ my = Gem::Platform.new %w[cpu my_platform 1]
+ other = Gem::Platform.new %w[cpu other_platform 1]
+
+ assert(my === my)
+ assert !(other === my)
+ assert !(my === other)
+ end
+
+ def test_equals3_cpu
+ ppc_darwin8 = Gem::Platform.new 'powerpc-darwin8.0'
+ uni_darwin8 = Gem::Platform.new 'universal-darwin8.0'
+ x86_darwin8 = Gem::Platform.new 'i686-darwin8.0'
+
+ util_set_arch 'powerpc-darwin8'
+ assert((ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+ assert((uni_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+ assert !(x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal'
+
+ util_set_arch 'i686-darwin8'
+ assert !(ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal'
+ assert((uni_darwin8 === Gem::Platform.local), 'x86 =~ universal')
+ assert((x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
+
+ util_set_arch 'universal-darwin8'
+ assert((ppc_darwin8 === Gem::Platform.local), 'universal =~ ppc')
+ assert((uni_darwin8 === Gem::Platform.local), 'universal =~ universal')
+ assert((x86_darwin8 === Gem::Platform.local), 'universal =~ x86')
+ end
+
+ def test_equals3_version
+ util_set_arch 'i686-darwin8'
+
+ x86_darwin = Gem::Platform.new ['x86', 'darwin', nil]
+ x86_darwin7 = Gem::Platform.new ['x86', 'darwin', '7']
+ x86_darwin8 = Gem::Platform.new ['x86', 'darwin', '8']
+ x86_darwin9 = Gem::Platform.new ['x86', 'darwin', '9']
+
+ assert((x86_darwin === Gem::Platform.local), 'x86_darwin === x86_darwin8')
+ assert((x86_darwin8 === Gem::Platform.local), 'x86_darwin8 === x86_darwin8')
+
+ assert !(x86_darwin7 === Gem::Platform.local), 'x86_darwin7 === x86_darwin8'
+ assert !(x86_darwin9 === Gem::Platform.local), 'x86_darwin9 === x86_darwin8'
+ end
+
+ def test_equals_tilde
+ util_set_arch 'i386-mswin32'
+
+ assert_match 'mswin32', Gem::Platform.local
+ assert_match 'i386-mswin32', Gem::Platform.local
+
+ # oddballs
+ assert_match 'i386-mswin32-mq5.3', Gem::Platform.local
+ assert_match 'i386-mswin32-mq6', Gem::Platform.local
+ deny_match 'win32-1.8.2-VC7', Gem::Platform.local
+ deny_match 'win32-1.8.4-VC6', Gem::Platform.local
+ deny_match 'win32-source', Gem::Platform.local
+ deny_match 'windows', Gem::Platform.local
+
+ util_set_arch 'i686-linux'
+ assert_match 'i486-linux', Gem::Platform.local
+ assert_match 'i586-linux', Gem::Platform.local
+ assert_match 'i686-linux', Gem::Platform.local
+
+ util_set_arch 'i686-darwin8'
+ assert_match 'i686-darwin8.4.1', Gem::Platform.local
+ assert_match 'i686-darwin8.8.2', Gem::Platform.local
+
+ util_set_arch 'java'
+ assert_match 'java', Gem::Platform.local
+ assert_match 'jruby', Gem::Platform.local
+
+ util_set_arch 'powerpc-darwin'
+ assert_match 'powerpc-darwin', Gem::Platform.local
+
+ util_set_arch 'powerpc-darwin7'
+ assert_match 'powerpc-darwin7.9.0', Gem::Platform.local
+
+ util_set_arch 'powerpc-darwin8'
+ assert_match 'powerpc-darwin8.10.0', Gem::Platform.local
+
+ util_set_arch 'sparc-solaris2.8'
+ assert_match 'sparc-solaris2.8-mq5.3', Gem::Platform.local
+ end
+
+ def assert_match(pattern, platform, message = '')
+ full_message = build_message message, "<?> expected to be =~\n<?>.",
+ platform, pattern
+ assert_block(full_message) { platform =~ pattern }
+ end
+
+ def deny_match(pattern, platform, message = '')
+ full_message = build_message message, "<?> expected to be !~\n<?>.",
+ platform, pattern
+ assert_block(full_message) { platform !~ pattern }
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_remote_fetcher.rb b/trunk/test/rubygems/test_gem_remote_fetcher.rb
new file mode 100644
index 0000000000..484104dd8f
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_remote_fetcher.rb
@@ -0,0 +1,692 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'webrick'
+require 'zlib'
+require 'rubygems/remote_fetcher'
+require 'ostruct'
+
+# = Testing Proxy Settings
+#
+# These tests check the proper proxy server settings by running two
+# web servers. The web server at http://localhost:#{SERVER_PORT}
+# represents the normal gem server and returns a gemspec with a rake
+# version of 0.4.11. The web server at http://localhost:#{PROXY_PORT}
+# represents the proxy server and returns a different dataset where
+# rake has version 0.4.2. This allows us to detect which server is
+# returning the data.
+#
+# Note that the proxy server is not a *real* proxy server. But our
+# software doesn't really care, as long as we hit the proxy URL when a
+# proxy is configured.
+
+class TestGemRemoteFetcher < RubyGemTestCase
+
+ include Gem::DefaultUserInteraction
+
+ SERVER_DATA = <<-EOY
+--- !ruby/object:Gem::Cache
+gems:
+ rake-0.4.11: !ruby/object:Gem::Specification
+ rubygems_version: "0.7"
+ specification_version: 1
+ name: rake
+ version: !ruby/object:Gem::Version
+ version: 0.4.11
+ date: 2004-11-12
+ summary: Ruby based make-like utility.
+ require_paths:
+ - lib
+ author: Jim Weirich
+ email: jim@weirichhouse.org
+ homepage: http://rake.rubyforge.org
+ rubyforge_project: rake
+ description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
+ autorequire:
+ default_executable: rake
+ bindir: bin
+ has_rdoc: true
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
+ requirements:
+ -
+ - ">"
+ - !ruby/object:Gem::Version
+ version: 0.0.0
+ version:
+ platform: ruby
+ files:
+ - README
+ test_files: []
+ library_stubs:
+ rdoc_options:
+ extra_rdoc_files:
+ executables:
+ - rake
+ extensions: []
+ requirements: []
+ dependencies: []
+ EOY
+
+ PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2')
+
+ # don't let 1.8 and 1.9 autotest collide
+ RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/
+ # don't let parallel runners collide
+ PROXY_PORT = process_based_port + 100 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
+ SERVER_PORT = process_based_port + 200 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
+
+ def setup
+ super
+ self.class.start_servers
+ self.class.enable_yaml = true
+ self.class.enable_zip = false
+ ENV.delete 'http_proxy'
+ ENV.delete 'HTTP_PROXY'
+ ENV.delete 'http_proxy_user'
+ ENV.delete 'HTTP_PROXY_USER'
+ ENV.delete 'http_proxy_pass'
+ ENV.delete 'HTTP_PROXY_PASS'
+
+ base_server_uri = "http://localhost:#{SERVER_PORT}"
+ @proxy_uri = "http://localhost:#{PROXY_PORT}"
+
+ @server_uri = base_server_uri + "/yaml"
+ @server_z_uri = base_server_uri + "/yaml.Z"
+
+ # REFACTOR: copied from test_gem_dependency_installer.rb
+ @gems_dir = File.join @tempdir, 'gems'
+ @cache_dir = File.join @gemhome, 'cache'
+ FileUtils.mkdir @gems_dir
+
+ @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
+
+ Gem::RemoteFetcher.fetcher = nil
+
+ @fetcher = Gem::RemoteFetcher.fetcher
+ end
+
+ def test_self_fetcher
+ fetcher = Gem::RemoteFetcher.fetcher
+ assert_not_nil fetcher
+ assert_kind_of Gem::RemoteFetcher, fetcher
+ end
+
+ def test_self_fetcher_with_proxy
+ proxy_uri = 'http://proxy.example.com'
+ Gem.configuration[:http_proxy] = proxy_uri
+ Gem::RemoteFetcher.fetcher = nil
+
+ fetcher = Gem::RemoteFetcher.fetcher
+
+ assert_not_nil fetcher
+ assert_kind_of Gem::RemoteFetcher, fetcher
+ assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri).to_s
+ end
+
+ def test_self_fetcher_with_proxy_URI
+ proxy_uri = URI.parse 'http://proxy.example.com'
+ Gem.configuration[:http_proxy] = proxy_uri
+ fetcher = Gem::RemoteFetcher.fetcher
+ assert_not_nil fetcher
+ assert_kind_of Gem::RemoteFetcher, fetcher
+ assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri)
+ end
+
+ def test_fetch_size_bad_uri
+ fetcher = Gem::RemoteFetcher.new nil
+
+ e = assert_raise ArgumentError do
+ fetcher.fetch_size 'gems.example.com/yaml'
+ end
+
+ assert_equal 'uri is not an HTTP URI', e.message
+ end
+
+ def test_fetch_size_socket_error
+ fetcher = Gem::RemoteFetcher.new nil
+ def fetcher.connection_for(uri)
+ raise SocketError, "tarded"
+ end
+
+ uri = 'http://gems.example.com/yaml'
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_size uri
+ end
+
+ assert_equal "SocketError: tarded (#{uri})", e.message
+ end
+
+ def test_no_proxy
+ use_ui @ui do
+ assert_data_from_server @fetcher.fetch_path(@server_uri)
+ assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri)
+ end
+ end
+
+ def util_fuck_with_fetcher data, blow = false
+ fetcher = Gem::RemoteFetcher.fetcher
+ fetcher.instance_variable_set :@test_data, data
+
+ unless blow then
+ def fetcher.fetch_path arg
+ @test_arg = arg
+ @test_data
+ end
+ else
+ def fetcher.fetch_path arg
+ # OMG I'm such an ass
+ class << self; remove_method :fetch_path; end
+ def self.fetch_path arg
+ @test_arg = arg
+ @test_data
+ end
+
+ raise Gem::RemoteFetcher::FetchError.new("haha!", nil)
+ end
+ end
+
+ fetcher
+ end
+
+ def test_download
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ a1_cache_gem = File.join(@gemhome, 'cache', "#{@a1.full_name}.gem")
+ assert_equal a1_cache_gem, fetcher.download(@a1, 'http://gems.example.com')
+ assert_equal("http://gems.example.com/gems/a-1.gem",
+ fetcher.instance_variable_get(:@test_arg).to_s)
+ assert File.exist?(a1_cache_gem)
+ end
+
+ def test_download_cached
+ FileUtils.mv @a1_gem, @cache_dir
+
+ inst = Gem::RemoteFetcher.fetcher
+
+ assert_equal File.join(@gemhome, 'cache', "#{@a1.full_name}.gem"),
+ inst.download(@a1, 'http://gems.example.com')
+ end
+
+ def test_download_local
+ FileUtils.mv @a1_gem, @tempdir
+ local_path = File.join @tempdir, "#{@a1.full_name}.gem"
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::RemoteFetcher.fetcher
+ end
+
+ assert_equal File.join(@gemhome, 'cache', "#{@a1.full_name}.gem"),
+ inst.download(@a1, local_path)
+ end
+
+ def test_download_install_dir
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ install_dir = File.join @tempdir, 'more_gems'
+
+ a1_cache_gem = File.join install_dir, 'cache', "#{@a1.full_name}.gem"
+ FileUtils.mkdir_p(File.dirname(a1_cache_gem))
+ actual = fetcher.download(@a1, 'http://gems.example.com', install_dir)
+
+ assert_equal a1_cache_gem, actual
+ assert_equal("http://gems.example.com/gems/a-1.gem",
+ fetcher.instance_variable_get(:@test_arg).to_s)
+
+ assert File.exist?(a1_cache_gem)
+ end
+
+ unless win_platform? # File.chmod doesn't work
+ def test_download_local_read_only
+ FileUtils.mv @a1_gem, @tempdir
+ local_path = File.join @tempdir, "#{@a1.full_name}.gem"
+ inst = nil
+ File.chmod 0555, File.join(@gemhome, 'cache')
+
+ Dir.chdir @tempdir do
+ inst = Gem::RemoteFetcher.fetcher
+ end
+
+ assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"),
+ inst.download(@a1, local_path)
+ ensure
+ File.chmod 0755, File.join(@gemhome, 'cache')
+ end
+
+ def test_download_read_only
+ File.chmod 0555, File.join(@gemhome, 'cache')
+ File.chmod 0555, File.join(@gemhome)
+
+ fetcher = util_fuck_with_fetcher File.read(@a1_gem)
+ fetcher.download(@a1, 'http://gems.example.com')
+ assert File.exist?(File.join(@userhome, '.gem',
+ 'cache', "#{@a1.full_name}.gem"))
+ ensure
+ File.chmod 0755, File.join(@gemhome)
+ File.chmod 0755, File.join(@gemhome, 'cache')
+ end
+ end
+
+ def test_download_platform_legacy
+ original_platform = 'old-platform'
+
+ e1, e1_gem = util_gem 'e', '1' do |s|
+ s.platform = Gem::Platform::CURRENT
+ s.instance_variable_set :@original_platform, original_platform
+ end
+
+ e1_data = nil
+ File.open e1_gem, 'rb' do |fp|
+ e1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher e1_data, :blow_chunks
+
+ e1_cache_gem = File.join(@gemhome, 'cache', "#{e1.full_name}.gem")
+
+ assert_equal e1_cache_gem, fetcher.download(e1, 'http://gems.example.com')
+
+ assert_equal("http://gems.example.com/gems/#{e1.original_name}.gem",
+ fetcher.instance_variable_get(:@test_arg).to_s)
+ assert File.exist?(e1_cache_gem)
+ end
+
+ def test_download_unsupported
+ inst = Gem::RemoteFetcher.fetcher
+
+ e = assert_raise Gem::InstallError do
+ inst.download @a1, 'ftp://gems.rubyforge.org'
+ end
+
+ assert_equal 'unsupported URI scheme ftp', e.message
+ end
+
+ def test_explicit_proxy
+ use_ui @ui do
+ fetcher = Gem::RemoteFetcher.new @proxy_uri
+ assert_equal PROXY_DATA.size, fetcher.fetch_size(@server_uri)
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_explicit_proxy_with_user_auth
+ use_ui @ui do
+ uri = URI.parse @proxy_uri
+ uri.user, uri.password = 'foo', 'bar'
+ fetcher = Gem::RemoteFetcher.new uri.to_s
+ proxy = fetcher.instance_variable_get("@proxy_uri")
+ assert_equal 'foo', proxy.user
+ assert_equal 'bar', proxy.password
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+
+ use_ui @ui do
+ uri = URI.parse @proxy_uri
+ uri.user, uri.password = 'domain%5Cuser', 'bar'
+ fetcher = Gem::RemoteFetcher.new uri.to_s
+ proxy = fetcher.instance_variable_get("@proxy_uri")
+ assert_equal 'domain\user', URI.unescape(proxy.user)
+ assert_equal 'bar', proxy.password
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+
+ use_ui @ui do
+ uri = URI.parse @proxy_uri
+ uri.user, uri.password = 'user', 'my%20pass'
+ fetcher = Gem::RemoteFetcher.new uri.to_s
+ proxy = fetcher.instance_variable_get("@proxy_uri")
+ assert_equal 'user', proxy.user
+ assert_equal 'my pass', URI.unescape(proxy.password)
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_explicit_proxy_with_user_auth_in_env
+ use_ui @ui do
+ ENV['http_proxy'] = @proxy_uri
+ ENV['http_proxy_user'] = 'foo'
+ ENV['http_proxy_pass'] = 'bar'
+ fetcher = Gem::RemoteFetcher.new nil
+ proxy = fetcher.instance_variable_get("@proxy_uri")
+ assert_equal 'foo', proxy.user
+ assert_equal 'bar', proxy.password
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+
+ use_ui @ui do
+ ENV['http_proxy'] = @proxy_uri
+ ENV['http_proxy_user'] = 'foo\user'
+ ENV['http_proxy_pass'] = 'my bar'
+ fetcher = Gem::RemoteFetcher.new nil
+ proxy = fetcher.instance_variable_get("@proxy_uri")
+ assert_equal 'foo\user', URI.unescape(proxy.user)
+ assert_equal 'my bar', URI.unescape(proxy.password)
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_fetch_path_gzip
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ Gem.gzip 'foo'
+ end
+
+ assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
+ end
+
+ def test_fetch_path_io_error
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ raise EOFError
+ end
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path 'uri'
+ end
+
+ assert_equal 'EOFError: EOFError (uri)', e.message
+ assert_equal 'uri', e.uri
+ end
+
+ def test_fetch_path_socket_error
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ raise SocketError
+ end
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path 'uri'
+ end
+
+ assert_equal 'SocketError: SocketError (uri)', e.message
+ assert_equal 'uri', e.uri
+ end
+
+ def test_fetch_path_system_call_error
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime = nil, head = nil)
+ raise Errno::ECONNREFUSED, 'connect(2)'
+ end
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path 'uri'
+ end
+
+ assert_match %r|ECONNREFUSED:.*connect\(2\) \(uri\)\z|,
+ e.message
+ assert_equal 'uri', e.uri
+ end
+
+ def test_fetch_path_unmodified
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ ''
+ end
+
+ assert_equal '', fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
+ end
+
+ def test_get_proxy_from_env_empty
+ orig_env_HTTP_PROXY = ENV['HTTP_PROXY']
+ orig_env_http_proxy = ENV['http_proxy']
+
+ ENV['HTTP_PROXY'] = ''
+ ENV.delete 'http_proxy'
+
+ fetcher = Gem::RemoteFetcher.new nil
+
+ assert_equal nil, fetcher.send(:get_proxy_from_env)
+
+ ensure
+ orig_env_HTTP_PROXY.nil? ? ENV.delete('HTTP_PROXY') :
+ ENV['HTTP_PROXY'] = orig_env_HTTP_PROXY
+ orig_env_http_proxy.nil? ? ENV.delete('http_proxy') :
+ ENV['http_proxy'] = orig_env_http_proxy
+ end
+
+ def test_implicit_no_proxy
+ use_ui @ui do
+ ENV['http_proxy'] = 'http://fakeurl:12345'
+ fetcher = Gem::RemoteFetcher.new :no_proxy
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy
+ use_ui @ui do
+ ENV['http_proxy'] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_upper_case_proxy
+ use_ui @ui do
+ ENV['HTTP_PROXY'] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy_no_env
+ use_ui @ui do
+ fetcher = Gem::RemoteFetcher.new nil
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_open_uri_or_path
+ fetcher = Gem::RemoteFetcher.new nil
+
+ conn = Object.new
+ def conn.started?() true end
+ def conn.request(req)
+ unless defined? @requested then
+ @requested = true
+ res = Net::HTTPRedirection.new nil, 301, nil
+ res.add_field 'Location', 'http://gems.example.com/real_path'
+ res
+ else
+ res = Net::HTTPOK.new nil, 200, nil
+ def res.body() 'real_path' end
+ res
+ end
+ end
+
+ conn = { 'gems.example.com:80' => conn }
+ fetcher.instance_variable_set :@connections, conn
+
+ data = fetcher.open_uri_or_path 'http://gems.example.com/redirect'
+
+ assert_equal 'real_path', data
+ end
+
+ def test_open_uri_or_path_limited_redirects
+ fetcher = Gem::RemoteFetcher.new nil
+
+ conn = Object.new
+ def conn.started?() true end
+ def conn.request(req)
+ res = Net::HTTPRedirection.new nil, 301, nil
+ res.add_field 'Location', 'http://gems.example.com/redirect'
+ res
+ end
+
+ conn = { 'gems.example.com:80' => conn }
+ fetcher.instance_variable_set :@connections, conn
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.open_uri_or_path 'http://gems.example.com/redirect'
+ end
+
+ assert_equal 'too many redirects (http://gems.example.com/redirect)',
+ e.message
+ end
+
+ def test_request
+ uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ util_stub_connection_for :body => :junk, :code => 200
+
+ response = @fetcher.request uri, Net::HTTP::Get
+
+ assert_equal 200, response.code
+ assert_equal :junk, response.body
+ end
+
+ def test_request_head
+ uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ util_stub_connection_for :body => '', :code => 200
+ response = @fetcher.request uri, Net::HTTP::Head
+
+ assert_equal 200, response.code
+ assert_equal '', response.body
+ end
+
+ def test_request_unmodifed
+ uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ conn = util_stub_connection_for :body => '', :code => 304
+
+ t = Time.now
+ response = @fetcher.request uri, Net::HTTP::Head, t
+
+ assert_equal 304, response.code
+ assert_equal '', response.body
+
+ assert_equal t.rfc2822, conn.payload['if-modified-since']
+ end
+
+ def test_yaml_error_on_size
+ use_ui @ui do
+ self.class.enable_yaml = false
+ fetcher = Gem::RemoteFetcher.new nil
+ assert_error { fetcher.size }
+ end
+ end
+
+ def util_stub_connection_for hash
+ def @fetcher.connection= conn
+ @conn = conn
+ end
+
+ def @fetcher.connection_for uri
+ @conn
+ end
+
+ @fetcher.connection = Conn.new OpenStruct.new(hash)
+ end
+
+ def assert_error(exception_class=Exception)
+ got_exception = false
+ begin
+ yield
+ rescue exception_class => ex
+ got_exception = true
+ end
+ assert got_exception, "Expected exception conforming to #{exception_class}"
+ end
+
+ def assert_data_from_server(data)
+ assert_block("Data is not from server") { data =~ /0\.4\.11/ }
+ end
+
+ def assert_data_from_proxy(data)
+ assert_block("Data is not from proxy") { data =~ /0\.4\.2/ }
+ end
+
+ class Conn
+ attr_accessor :payload
+
+ def initialize(response)
+ @response = response
+ self.payload = nil
+ end
+
+ def request(req)
+ self.payload = req
+ @response
+ end
+ end
+
+ class NilLog < WEBrick::Log
+ def log(level, data) #Do nothing
+ end
+ end
+
+ class << self
+ attr_reader :normal_server, :proxy_server
+ attr_accessor :enable_zip, :enable_yaml
+
+ def start_servers
+ @normal_server ||= start_server(SERVER_PORT, SERVER_DATA)
+ @proxy_server ||= start_server(PROXY_PORT, PROXY_DATA)
+ @enable_yaml = true
+ @enable_zip = false
+ end
+
+ private
+
+ def start_server(port, data)
+ Thread.new do
+ begin
+ null_logger = NilLog.new
+ s = WEBrick::HTTPServer.new(
+ :Port => port,
+ :DocumentRoot => nil,
+ :Logger => null_logger,
+ :AccessLog => null_logger
+ )
+ s.mount_proc("/kill") { |req, res| s.shutdown }
+ s.mount_proc("/yaml") { |req, res|
+ if @enable_yaml
+ res.body = data
+ res['Content-Type'] = 'text/plain'
+ res['content-length'] = data.size
+ else
+ res.status = "404"
+ res.body = "<h1>NOT FOUND</h1>"
+ res['Content-Type'] = 'text/html'
+ end
+ }
+ s.mount_proc("/yaml.Z") { |req, res|
+ if @enable_zip
+ res.body = Zlib::Deflate.deflate(data)
+ res['Content-Type'] = 'text/plain'
+ else
+ res.status = "404"
+ res.body = "<h1>NOT FOUND</h1>"
+ res['Content-Type'] = 'text/html'
+ end
+ }
+ s.start
+ rescue Exception => ex
+ abort ex.message
+ puts "ERROR during server thread: #{ex.message}"
+ end
+ end
+ sleep 0.2 # Give the servers time to startup
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_requirement.rb b/trunk/test/rubygems/test_gem_requirement.rb
new file mode 100644
index 0000000000..c441bd16df
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_requirement.rb
@@ -0,0 +1,223 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/version'
+
+class TestGemRequirement < RubyGemTestCase
+
+ def setup
+ super
+
+ @r1_2 = Gem::Requirement.new '= 1.2'
+ @r1_3 = Gem::Requirement.new '= 1.3'
+ end
+
+ def test_initialize
+ r = Gem::Requirement.new '2'
+ assert_equal '= 2', r.to_s, 'String'
+
+ r = Gem::Requirement.new %w[2]
+ assert_equal '= 2', r.to_s, 'Array of Strings'
+
+ r = Gem::Requirement.new Gem::Version.new('2')
+ assert_equal '= 2', r.to_s, 'Gem::Version'
+ end
+
+ def test_equals2
+ assert_equal @r1_2, @r1_2.dup
+ assert_equal @r1_2.dup, @r1_2
+
+ assert_not_equal @r1_3, @r1_2
+ assert_not_equal @r1_2, @r1_3
+
+ assert_not_equal Object.new, @r1_2
+ assert_not_equal @r1_2, Object.new
+ end
+
+ def test_hash
+ assert_equal @r1_2.hash, @r1_2.dup.hash
+ assert_equal @r1_2.dup.hash, @r1_2.hash
+
+ assert_not_equal @r1_2.hash, @r1_3.hash
+ assert_not_equal @r1_3.hash, @r1_2.hash
+ end
+
+ # We may get some old gems that have requirements in old formats.
+ # We need to be able to handle those old requirements by normalizing
+ # them to the latest format.
+ def test_normalization
+ require 'yaml'
+ yamldep = %{--- !ruby/object:Gem::Requirement
+ nums:
+ - 1
+ - 0
+ - 4
+ op: ">="
+ version: ">= 1.0.4"}
+ dep = YAML.load(yamldep)
+ dep.normalize
+ assert_equal ">= 1.0.4", dep.to_s
+ end
+
+ def test_parse
+ assert_equal ['=', Gem::Version.new(1)], @r1_2.parse(' 1')
+
+ assert_equal ['=', Gem::Version.new(1)], @r1_2.parse('= 1')
+ assert_equal ['>', Gem::Version.new(1)], @r1_2.parse('> 1')
+
+ assert_equal ['=', Gem::Version.new(0)], @r1_2.parse('=')
+ assert_equal ['>', Gem::Version.new(0)], @r1_2.parse('>')
+
+ assert_equal ['=', Gem::Version.new(1)], @r1_2.parse("=\n1")
+ assert_equal ['=', Gem::Version.new(0)], @r1_2.parse("=\njunk")
+
+ assert_equal ['=', Gem::Version.new(2)], @r1_2.parse(Gem::Version.new('2'))
+ end
+
+ def test_parse_illformed
+ e = assert_raise ArgumentError do
+ @r1_2.parse(nil)
+ end
+
+ assert_equal 'Illformed requirement [nil]', e.message
+
+ e = assert_raise ArgumentError do
+ @r1_2.parse('')
+ end
+
+ assert_equal 'Illformed requirement [""]', e.message
+ end
+
+ def test_satisfied_by_eh_bang_equal
+ r1_2 = Gem::Requirement.new '!= 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal true, r1_2.satisfied_by?(nil)
+ assert_equal true, r1_2.satisfied_by?(v1_1)
+ assert_equal false, r1_2.satisfied_by?(v1_2)
+ assert_equal true, r1_2.satisfied_by?(v1_3)
+ end
+
+ def test_satisfied_by_eh_blank
+ r1_2 = Gem::Requirement.new '1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r1_2.satisfied_by?(nil)
+ assert_equal false, r1_2.satisfied_by?(v1_1)
+ assert_equal true, r1_2.satisfied_by?(v1_2)
+ assert_equal false, r1_2.satisfied_by?(v1_3)
+ end
+
+ def test_satisfied_by_eh_equal
+ r1_2 = @r1_2
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r1_2.satisfied_by?(nil)
+ assert_equal false, r1_2.satisfied_by?(v1_1)
+ assert_equal true, r1_2.satisfied_by?(v1_2)
+ assert_equal false, r1_2.satisfied_by?(v1_3)
+ end
+
+ def test_satisfied_by_eh_gt
+ r1_2 = Gem::Requirement.new '> 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r1_2.satisfied_by?(v1_1)
+ assert_equal false, r1_2.satisfied_by?(v1_2)
+ assert_equal true, r1_2.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r1_2.satisfied_by?(nil)
+ end
+ end
+
+ def test_satisfied_by_eh_gte
+ r1_2 = Gem::Requirement.new '>= 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r1_2.satisfied_by?(v1_1)
+ assert_equal true, r1_2.satisfied_by?(v1_2)
+ assert_equal true, r1_2.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r1_2.satisfied_by?(nil)
+ end
+ end
+
+ def test_satisfied_by_eh_list
+ r = Gem::Requirement.create(['> 1.1', '< 1.3'])
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r.satisfied_by?(v1_1)
+ assert_equal true, r.satisfied_by?(v1_2)
+ assert_equal false, r.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r.satisfied_by?(nil)
+ end
+ end
+
+ def test_satisfied_by_eh_lt
+ r1_2 = Gem::Requirement.new '< 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal true, r1_2.satisfied_by?(v1_1)
+ assert_equal false, r1_2.satisfied_by?(v1_2)
+ assert_equal false, r1_2.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r1_2.satisfied_by?(nil)
+ end
+ end
+
+ def test_satisfied_by_eh_lte
+ r1_2 = Gem::Requirement.new '<= 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal true, r1_2.satisfied_by?(v1_1)
+ assert_equal true, r1_2.satisfied_by?(v1_2)
+ assert_equal false, r1_2.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r1_2.satisfied_by?(nil)
+ end
+ end
+
+ def test_satisfied_by_eh_tilde_gt
+ r1_2 = Gem::Requirement.new '~> 1.2'
+ v1_1 = Gem::Version.new '1.1'
+ v1_2 = Gem::Version.new '1.2'
+ v1_3 = Gem::Version.new '1.3'
+
+ assert_equal false, r1_2.satisfied_by?(v1_1)
+ assert_equal true, r1_2.satisfied_by?(v1_2)
+ assert_equal true, r1_2.satisfied_by?(v1_3)
+
+ assert_raise NoMethodError do
+ assert_equal true, r1_2.satisfied_by?(nil)
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_server.rb b/trunk/test/rubygems/test_gem_server.rb
new file mode 100644
index 0000000000..dcdc766f0f
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_server.rb
@@ -0,0 +1,301 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/server'
+require 'stringio'
+
+class Gem::Server
+ attr_accessor :source_index
+ attr_reader :server
+end
+
+class TestGemServer < RubyGemTestCase
+
+ def setup
+ super
+
+ @a1 = quick_gem 'a', '1'
+ @a2 = quick_gem 'a', '2'
+
+ @server = Gem::Server.new Gem.dir, process_based_port, false
+ @req = WEBrick::HTTPRequest.new :Logger => nil
+ @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
+ end
+
+ def test_Marshal
+ data = StringIO.new "GET /Marshal.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.Marshal @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/octet-stream', @res['content-type']
+
+ si = Gem::SourceIndex.new
+ si.add_specs @a1, @a2
+
+ assert_equal si, Marshal.load(@res.body)
+ end
+
+ def test_Marshal_Z
+ data = StringIO.new "GET /Marshal.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.Marshal @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ si = Gem::SourceIndex.new
+ si.add_specs @a1, @a2
+
+ assert_equal si, Marshal.load(Gem.inflate(@res.body))
+ end
+
+ def test_latest_specs
+ data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.latest_specs @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/octet-stream', @res['content-type']
+ assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+ Marshal.load(@res.body)
+ end
+
+ def test_latest_specs_gz
+ data = StringIO.new "GET /latest_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.latest_specs @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-gzip', @res['content-type']
+ assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+ Marshal.load(Gem.gunzip(@res.body))
+ end
+
+ def test_quick_a_1_gemspec_rz
+ data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ spec = YAML.load Gem.inflate(@res.body)
+ assert_equal 'a', spec.name
+ assert_equal Gem::Version.new(1), spec.version
+ end
+
+ def test_quick_a_1_mswin32_gemspec_rz
+ a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
+
+ data = StringIO.new "GET /quick/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ spec = YAML.load Gem.inflate(@res.body)
+ assert_equal 'a', spec.name
+ assert_equal Gem::Version.new(1), spec.version
+ assert_equal Gem::Platform.local, spec.platform
+ end
+
+ def test_quick_common_substrings
+ ab1 = quick_gem 'ab', '1'
+
+ data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ spec = YAML.load Gem.inflate(@res.body)
+ assert_equal 'a', spec.name
+ assert_equal Gem::Version.new(1), spec.version
+ end
+
+ def test_quick_index
+ data = StringIO.new "GET /quick/index HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'text/plain', @res['content-type']
+ assert_equal "a-1\na-2", @res.body
+ end
+
+ def test_quick_index_rz
+ data = StringIO.new "GET /quick/index.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+ assert_equal "a-1\na-2", Gem.inflate(@res.body)
+ end
+
+ def test_quick_latest_index
+ data = StringIO.new "GET /quick/latest_index HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'text/plain', @res['content-type']
+ assert_equal 'a-2', @res.body
+ end
+
+ def test_quick_latest_index_rz
+ data = StringIO.new "GET /quick/latest_index.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+ assert_equal 'a-2', Gem.inflate(@res.body)
+ end
+
+ def test_quick_missing
+ data = StringIO.new "GET /quick/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 404, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'text/plain', @res['content-type']
+ assert_equal 'No gems found matching "z" "9" nil', @res.body
+ assert_equal 404, @res.status
+ end
+
+ def test_quick_marshal_a_1_gemspec_rz
+ data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ spec = Marshal.load Gem.inflate(@res.body)
+ assert_equal 'a', spec.name
+ assert_equal Gem::Version.new(1), spec.version
+ end
+
+ def test_quick_marshal_a_1_mswin32_gemspec_rz
+ a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
+
+ data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.quick @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ spec = Marshal.load Gem.inflate(@res.body)
+ assert_equal 'a', spec.name
+ assert_equal Gem::Version.new(1), spec.version
+ assert_equal Gem::Platform.local, spec.platform
+ end
+
+
+ def test_root
+ data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.root @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'text/html', @res['content-type']
+ end
+
+ def test_specs
+ data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.specs @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/octet-stream', @res['content-type']
+
+ assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
+ ['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+ Marshal.load(@res.body)
+ end
+
+ def test_specs_gz
+ data = StringIO.new "GET /specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.specs @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-gzip', @res['content-type']
+
+ assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
+ ['a', Gem::Version.new(2), Gem::Platform::RUBY]],
+ Marshal.load(Gem.gunzip(@res.body))
+ end
+
+ def test_yaml
+ data = StringIO.new "GET /yaml.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.yaml @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'text/plain', @res['content-type']
+
+ si = Gem::SourceIndex.new
+ si.add_specs @a1, @a2
+
+ assert_equal si, YAML.load(@res.body)
+ end
+
+ def test_yaml_Z
+ data = StringIO.new "GET /yaml.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
+ @req.parse data
+
+ @server.yaml @req, @res
+
+ assert_equal 200, @res.status, @res.body
+ assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_equal 'application/x-deflate', @res['content-type']
+
+ si = Gem::SourceIndex.new
+ si.add_specs @a1, @a2
+
+ assert_equal si, YAML.load(Gem.inflate(@res.body))
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_source_index.rb b/trunk/test/rubygems/test_gem_source_index.rb
new file mode 100644
index 0000000000..263826759a
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_source_index.rb
@@ -0,0 +1,834 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/source_index'
+require 'rubygems/config_file'
+
+class Gem::SourceIndex
+ public :fetcher, :fetch_bulk_index, :fetch_quick_index,
+ :find_missing, :gems, :remove_extra,
+ :update_with_missing, :unzip
+end
+
+class TestGemSourceIndex < RubyGemTestCase
+
+ def setup
+ super
+
+ util_setup_fake_fetcher
+ end
+
+ def test_self_from_gems_in
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.rm_r spec_dir
+
+ FileUtils.mkdir_p spec_dir
+
+ a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+
+ spec_file = File.join spec_dir, "#{a1.full_name}.gemspec"
+
+ File.open spec_file, 'w' do |fp|
+ fp.write a1.to_ruby
+ end
+
+ si = Gem::SourceIndex.from_gems_in spec_dir
+
+ assert_equal [spec_dir], si.spec_dirs
+ assert_equal [a1.full_name], si.gems.keys
+ end
+
+ def test_self_load_specification
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.rm_r spec_dir
+
+ FileUtils.mkdir_p spec_dir
+
+ a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+
+ spec_file = File.join spec_dir, "#{a1.full_name}.gemspec"
+
+ File.open spec_file, 'w' do |fp|
+ fp.write a1.to_ruby
+ end
+
+ spec = Gem::SourceIndex.load_specification spec_file
+
+ assert_equal a1.author, spec.author
+ end
+
+ def test_self_load_specification_exception
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, 'a-1.gemspec'
+
+ File.open spec_file, 'w' do |fp|
+ fp.write 'raise Exception, "epic fail"'
+ end
+
+ use_ui @ui do
+ assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
+ end
+
+ assert_equal '', @ui.output
+
+ expected = <<-EOF
+WARNING: #<Exception: epic fail>
+raise Exception, "epic fail"
+WARNING: Invalid .gemspec format in '#{spec_file}'
+ EOF
+
+ assert_equal expected, @ui.error
+ end
+
+ def test_self_load_specification_interrupt
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, 'a-1.gemspec'
+
+ File.open spec_file, 'w' do |fp|
+ fp.write 'raise Interrupt, "^C"'
+ end
+
+ use_ui @ui do
+ assert_raise Interrupt do
+ Gem::SourceIndex.load_specification(spec_file)
+ end
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_self_load_specification_syntax_error
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, 'a-1.gemspec'
+
+ File.open spec_file, 'w' do |fp|
+ fp.write '1 +'
+ end
+
+ use_ui @ui do
+ assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
+ end
+
+ assert_equal '', @ui.output
+
+ assert_match(/syntax error/, @ui.error)
+ assert_match(/1 \+/, @ui.error)
+ end
+
+ def test_self_load_specification_system_exit
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, 'a-1.gemspec'
+
+ File.open spec_file, 'w' do |fp|
+ fp.write 'raise SystemExit, "bye-bye"'
+ end
+
+ use_ui @ui do
+ assert_raise SystemExit do
+ Gem::SourceIndex.load_specification(spec_file)
+ end
+ end
+
+ assert_equal '', @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_create_from_directory
+ # TODO
+ end
+
+ def test_fetcher
+ assert_equal @fetcher, @source_index.fetcher
+ end
+
+ def test_fetch_bulk_index_compressed
+ util_setup_bulk_fetch true
+
+ use_ui @ui do
+ fetched_index = @source_index.fetch_bulk_index @uri
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name].sort,
+ fetched_index.gems.map { |n,s| n }.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_bulk_index_error
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] = proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}yaml.Z"] = proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}yaml"] = proc { raise SocketError }
+
+ e = assert_raise Gem::RemoteSourceException do
+ use_ui @ui do
+ @source_index.fetch_bulk_index @uri
+ end
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
+ assert_equal "#{@gem_repo}yaml.Z", paths.shift
+ assert_equal "#{@gem_repo}yaml", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+
+ assert_equal 'Error fetching remote gem cache: SocketError',
+ e.message
+ end
+
+ def test_fetch_bulk_index_fallback
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] =
+ proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] =
+ proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}yaml.Z"] = proc { raise SocketError }
+ @fetcher.data["#{@gem_repo}yaml"] = @source_index.to_yaml
+
+ use_ui @ui do
+ fetched_index = @source_index.fetch_bulk_index @uri
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name].sort,
+ fetched_index.gems.map { |n,s| n }.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
+ assert_equal "#{@gem_repo}yaml.Z", paths.shift
+ assert_equal "#{@gem_repo}yaml", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_bulk_index_marshal_mismatch
+ marshal = @source_index.dump
+ marshal[0] = (Marshal::MAJOR_VERSION - 1).chr
+
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = marshal
+ @fetcher.data["#{@gem_repo}yaml"] = @source_index.to_yaml
+
+ use_ui @ui do
+ fetched_index = @source_index.fetch_bulk_index @uri
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name].sort,
+ fetched_index.gems.map { |n,s| n }.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
+ assert_equal "#{@gem_repo}yaml.Z", paths.shift
+ assert_equal "#{@gem_repo}yaml", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_bulk_index_uncompressed
+ util_setup_bulk_fetch false
+ use_ui @ui do
+ fetched_index = @source_index.fetch_bulk_index @uri
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name].sort,
+ fetched_index.gems.map { |n,s| n }.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_quick_index
+ index = util_zip @gem_names
+ latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
+
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = index
+ @fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
+
+ quick_index = @source_index.fetch_quick_index @uri, false
+ assert_equal [@a2.full_name, @b2.full_name].sort,
+ quick_index.sort
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_quick_index_all
+ index = util_zip @gem_names
+ latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
+
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = index
+ @fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
+
+ quick_index = @source_index.fetch_quick_index @uri, true
+ assert_equal [@a1.full_name, @a2.full_name, @b2.full_name].sort,
+ quick_index.sort
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_quick_index_error
+ @fetcher.data["#{@gem_repo}quick/index.rz"] =
+ proc { raise Exception }
+
+ e = assert_raise Gem::OperationNotSupportedError do
+ @source_index.fetch_quick_index @uri, true
+ end
+
+ assert_equal 'No quick index found: Exception', e.message
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_quick_index_fallback
+ index = util_zip @gem_names
+
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = index
+
+ quick_index = @source_index.fetch_quick_index @uri, false
+ assert_equal @gem_names.split, quick_index.sort
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_quick_index_subdir
+ latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
+ repo = URI.parse "#{@gem_repo}~nobody/mirror/"
+
+ @fetcher.data["#{repo}quick/latest_index.rz"] = latest_index
+
+ quick_index = @source_index.fetch_quick_index repo, false
+ assert_equal [@a2.full_name, @b2.full_name].sort,
+ quick_index.sort
+
+ paths = @fetcher.paths
+
+ assert_equal "#{repo}quick/latest_index.rz", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_single_spec
+ a1_spec_url = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz"
+ @fetcher.data[a1_spec_url] = util_zip Marshal.dump(@a1)
+
+ spec = @source_index.send :fetch_single_spec, URI.parse(@gem_repo),
+ @a1.full_name
+
+ assert_equal @a1.full_name, spec.full_name
+
+ paths = @fetcher.paths
+
+ assert_equal a1_spec_url, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_single_spec_subdir
+ repo = URI.parse "#{@gem_repo}~nobody/mirror/"
+
+ a1_spec_url = "#{repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz"
+ @fetcher.data[a1_spec_url] = util_zip Marshal.dump(@a1)
+
+ spec = @source_index.send :fetch_single_spec, repo, @a1.full_name
+
+ assert_equal @a1.full_name, spec.full_name
+
+ paths = @fetcher.paths
+
+ assert_equal a1_spec_url, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_single_spec_yaml
+ a1_spec_url = "#{@gem_repo}quick/#{@a1.full_name}.gemspec.rz"
+ @fetcher.data[a1_spec_url] = util_zip @a1.to_yaml
+
+ repo = URI.parse @gem_repo
+
+ spec = @source_index.send :fetch_single_spec, repo, @a1.full_name
+
+ assert_equal @a1.full_name, spec.full_name
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz", paths.shift
+ assert_equal a1_spec_url, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_fetch_single_spec_yaml_subdir
+ repo = URI.parse "#{@gem_repo}~nobody/mirror/"
+
+ a1_spec_url = "#{repo}quick/#{@a1.full_name}.gemspec.rz"
+ @fetcher.data[a1_spec_url] = util_zip @a1.to_yaml
+
+ spec = @source_index.send :fetch_single_spec, repo, @a1.full_name
+
+ assert_equal @a1.full_name, spec.full_name
+
+ paths = @fetcher.paths
+
+ assert_equal "#{repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz", paths.shift
+ assert_equal a1_spec_url, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_find_missing
+ missing = @source_index.find_missing [@b2.full_name]
+ assert_equal [@b2.full_name], missing
+ end
+
+ def test_find_missing_none_missing
+ missing = @source_index.find_missing [
+ @a1.full_name, @a2.full_name, @c1_2.full_name
+ ]
+
+ assert_equal [], missing
+ end
+
+ def test_latest_specs
+ p1_ruby = quick_gem 'p', '1'
+ p1_platform = quick_gem 'p', '1' do |spec|
+ spec.platform = Gem::Platform::CURRENT
+ end
+
+ a1_platform = quick_gem @a1.name, (@a1.version) do |s|
+ s.platform = Gem::Platform.new 'x86-my_platform1'
+ end
+
+ a2_platform = quick_gem @a2.name, (@a2.version) do |s|
+ s.platform = Gem::Platform.new 'x86-my_platform1'
+ end
+
+ a2_platform_other = quick_gem @a2.name, (@a2.version) do |s|
+ s.platform = Gem::Platform.new 'x86-other_platform1'
+ end
+
+ a3_platform_other = quick_gem @a2.name, (@a2.version.bump) do |s|
+ s.platform = Gem::Platform.new 'x86-other_platform1'
+ end
+
+ @source_index.add_spec p1_ruby
+ @source_index.add_spec p1_platform
+ @source_index.add_spec a1_platform
+ @source_index.add_spec a2_platform
+ @source_index.add_spec a2_platform_other
+ @source_index.add_spec a3_platform_other
+
+ expected = [
+ @a2.full_name,
+ a2_platform.full_name,
+ a3_platform_other.full_name,
+ @c1_2.full_name,
+ @a_evil9.full_name,
+ p1_ruby.full_name,
+ p1_platform.full_name,
+ ].sort
+
+ latest_specs = @source_index.latest_specs.map { |s| s.full_name }.sort
+
+ assert_equal expected, latest_specs
+ end
+
+ def test_load_gems_in
+ spec_dir1 = File.join @gemhome, 'specifications'
+ spec_dir2 = File.join @tempdir, 'gemhome2', 'specifications'
+
+ FileUtils.rm_r spec_dir1
+
+ FileUtils.mkdir_p spec_dir1
+ FileUtils.mkdir_p spec_dir2
+
+ a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
+ a2 = quick_gem 'a', '1' do |spec| spec.author = 'author 2' end
+
+ File.open File.join(spec_dir1, "#{a1.full_name}.gemspec"), 'w' do |fp|
+ fp.write a1.to_ruby
+ end
+
+ File.open File.join(spec_dir2, "#{a2.full_name}.gemspec"), 'w' do |fp|
+ fp.write a2.to_ruby
+ end
+
+ @source_index.load_gems_in spec_dir1, spec_dir2
+
+ assert_equal a1.author, @source_index.specification(a1.full_name).author
+ end
+
+ def test_outdated
+ util_setup_spec_fetcher
+
+ assert_equal [], @source_index.outdated
+
+ updated = quick_gem @a2.name, (@a2.version.bump)
+ util_setup_spec_fetcher updated
+
+ assert_equal [updated.name], @source_index.outdated
+
+ updated_platform = quick_gem @a2.name, (updated.version.bump) do |s|
+ s.platform = Gem::Platform.new 'x86-other_platform1'
+ end
+
+ util_setup_spec_fetcher updated, updated_platform
+
+ assert_equal [updated_platform.name], @source_index.outdated
+ end
+
+ def test_refresh_bang
+ a1_spec = File.join @gemhome, "specifications", "#{@a1.full_name}.gemspec"
+
+ FileUtils.mv a1_spec, @tempdir
+
+ source_index = Gem::SourceIndex.from_installed_gems
+
+ assert !source_index.gems.include?(@a1.full_name)
+
+ FileUtils.mv File.join(@tempdir, "#{@a1.full_name}.gemspec"), a1_spec
+
+ source_index.refresh!
+
+ assert source_index.gems.include?(@a1.full_name)
+ end
+
+ def test_refresh_bang_not_from_dir
+ source_index = Gem::SourceIndex.new
+
+ e = assert_raise RuntimeError do
+ source_index.refresh!
+ end
+
+ assert_equal 'source index not created from disk', e.message
+ end
+
+ def test_remove_extra
+ @source_index.add_spec @a1
+ @source_index.add_spec @a2
+ @source_index.add_spec @pl1
+
+ @source_index.remove_extra [@a1.full_name, @pl1.full_name]
+
+ assert_equal [@a1.full_name],
+ @source_index.gems.map { |n,s| n }.sort
+ end
+
+ def test_remove_extra_no_changes
+ gems = [@a1.full_name, @a2.full_name]
+ @source_index.add_spec @a1
+ @source_index.add_spec @a2
+
+ @source_index.remove_extra gems
+
+ assert_equal gems, @source_index.gems.map { |n,s| n }.sort
+ end
+
+ def test_search
+ assert_equal [@a1, @a2, @a_evil9], @source_index.search('a')
+ assert_equal [@a2], @source_index.search('a', '= 2')
+
+ assert_equal [], @source_index.search('bogusstring')
+ assert_equal [], @source_index.search('a', '= 3')
+
+ source_index = Gem::SourceIndex.new
+ source_index.add_spec @a1
+ source_index.add_spec @a2
+
+ assert_equal [@a1], source_index.search(@a1.name, '= 1')
+
+ r1 = Gem::Requirement.create '= 1'
+ assert_equal [@a1], source_index.search(@a1.name, r1)
+
+ dep = Gem::Dependency.new @a1.name, r1
+ assert_equal [@a1], source_index.search(dep)
+ end
+
+ def test_search_empty_cache
+ empty_source_index = Gem::SourceIndex.new({})
+ assert_equal [], empty_source_index.search("foo")
+ end
+
+ def test_search_platform
+ util_set_arch 'x86-my_platform1'
+
+ a1 = quick_gem 'a', '1'
+ a1_mine = quick_gem 'a', '1' do |s|
+ s.platform = Gem::Platform.new 'x86-my_platform1'
+ end
+ a1_other = quick_gem 'a', '1' do |s|
+ s.platform = Gem::Platform.new 'x86-other_platform1'
+ end
+
+ si = Gem::SourceIndex.new(a1.full_name => a1, a1_mine.full_name => a1_mine,
+ a1_other.full_name => a1_other)
+
+ dep = Gem::Dependency.new 'a', Gem::Requirement.new('1')
+
+ gems = si.search dep, true
+
+ assert_equal [a1, a1_mine], gems.sort
+ end
+
+ def test_signature
+ sig = @source_index.gem_signature('foo-1.2.3')
+ assert_equal 64, sig.length
+ assert_match(/^[a-f0-9]{64}$/, sig)
+ end
+
+ def test_specification
+ assert_equal @a1, @source_index.specification(@a1.full_name)
+
+ assert_nil @source_index.specification("foo-1.2.4")
+ end
+
+ def test_index_signature
+ sig = @source_index.index_signature
+ assert_match(/^[a-f0-9]{64}$/, sig)
+ end
+
+ def test_unzip
+ input = "x\234+\316\317MU(I\255(\001\000\021\350\003\232"
+ assert_equal 'some text', @source_index.unzip(input)
+ end
+
+ def test_update_bulk
+ util_setup_bulk_fetch true
+
+ @source_index.gems.replace({})
+ assert_equal [], @source_index.gems.keys.sort
+
+ use_ui @ui do
+ @source_index.update @uri, true
+
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name],
+ @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_update_incremental
+ old_gem_conf = Gem.configuration
+ Gem.configuration = Gem::ConfigFile.new([])
+
+ latest_names = [@a2, @a_evil9, @b2, @c1_2].map { |s| s.full_name }
+ latest_index = util_zip latest_names.join("\n")
+ @fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
+
+ marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
+ "#{@b2.full_name}.gemspec.rz"
+ @fetcher.data[marshal_uri] = util_zip Marshal.dump(@b2)
+
+ use_ui @ui do
+ @source_index.update @uri, false
+
+ assert_equal latest_names, @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+ assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
+ assert_equal marshal_uri, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ ensure
+ Gem.configuration = old_gem_conf
+ end
+
+ def test_update_incremental_all
+ old_gem_conf = Gem.configuration
+ Gem.configuration = Gem::ConfigFile.new([])
+
+ quick_index = util_zip @all_gem_names.join("\n")
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
+
+ marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
+ "#{@b2.full_name}.gemspec.rz"
+ @fetcher.data[marshal_uri] = util_zip Marshal.dump(@b2)
+
+ use_ui @ui do
+ @source_index.update @uri, true
+
+ assert_equal @all_gem_names, @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+ assert_equal marshal_uri, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ ensure
+ Gem.configuration = old_gem_conf
+ end
+
+ def test_update_incremental_fallback
+ old_gem_conf = Gem.configuration
+ Gem.configuration = Gem::ConfigFile.new([])
+
+ quick_index = util_zip @all_gem_names.join("\n")
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
+
+ marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
+ "#{@b2.full_name}.gemspec.rz"
+
+ yaml_uri = "#{@gem_repo}quick/#{@b2.full_name}.gemspec.rz"
+ @fetcher.data[yaml_uri] = util_zip @b2.to_yaml
+
+ use_ui @ui do
+ @source_index.update @uri, true
+
+ assert_equal @all_gem_names, @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+ assert_equal marshal_uri, paths.shift
+ assert_equal yaml_uri, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ ensure
+ Gem.configuration = old_gem_conf
+ end
+
+ def test_update_incremental_marshal_mismatch
+ old_gem_conf = Gem.configuration
+ Gem.configuration = Gem::ConfigFile.new([])
+
+ quick_index = util_zip @all_gem_names.join("\n")
+ @fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
+
+ marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
+ "#{@b2.full_name}.gemspec.rz"
+ marshal_data = Marshal.dump(@b2)
+ marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr
+ @fetcher.data[marshal_uri] = util_zip marshal_data
+
+ yaml_uri = "#{@gem_repo}quick/#{@b2.full_name}.gemspec.rz"
+ @fetcher.data[yaml_uri] = util_zip @b2.to_yaml
+
+ use_ui @ui do
+ @source_index.update @uri, true
+
+ assert_equal @all_gem_names, @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+ assert_equal marshal_uri, paths.shift
+ assert_equal yaml_uri, paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ ensure
+ Gem.configuration = old_gem_conf
+ end
+
+ def test_update_subdir
+ @gem_repo = @gem_repo + 'subdir/'
+
+ util_setup_bulk_fetch true
+
+ @source_index.gems.replace({})
+ assert_equal [], @source_index.gems.keys.sort
+
+ uri = @uri.to_s + 'subdir/'
+
+ use_ui @ui do
+ @source_index.update uri, true
+
+ assert_equal [@a1.full_name, @a2.full_name, @a_evil9.full_name,
+ @c1_2.full_name],
+ @source_index.gems.keys.sort
+ end
+
+ paths = @fetcher.paths
+
+ assert_equal "#{@gem_repo}quick/index.rz", paths.shift
+ assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
+
+ assert paths.empty?, paths.join(', ')
+ end
+
+ def test_update_with_missing
+ marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
+ "#{@c1_2.full_name}.gemspec.rz"
+ dumped = Marshal.dump @c1_2
+ @fetcher.data[marshal_uri] = util_zip(dumped)
+
+ use_ui @ui do
+ @source_index.update_with_missing @uri, [@c1_2.full_name]
+ end
+
+ spec = @source_index.specification(@c1_2.full_name)
+ # We don't care about the equality of undumped attributes
+ @c1_2.files = spec.files
+ @c1_2.loaded_from = spec.loaded_from
+
+ assert_equal @c1_2, spec
+ end
+
+ def util_setup_bulk_fetch(compressed)
+ source_index = @source_index.dump
+
+ if compressed then
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] = util_zip source_index
+ else
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = source_index
+ end
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_source_info_cache.rb b/trunk/test/rubygems/test_gem_source_info_cache.rb
new file mode 100644
index 0000000000..86866a8012
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_source_info_cache.rb
@@ -0,0 +1,448 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/source_info_cache'
+
+class Gem::SourceIndex
+ public :gems
+end
+
+class TestGemSourceInfoCache < RubyGemTestCase
+
+ def setup
+ @original_sources = Gem.sources
+
+ super
+
+ util_setup_fake_fetcher
+
+ @sic = Gem::SourceInfoCache.new
+ @sic.instance_variable_set :@fetcher, @fetcher
+
+ @si_new = Gem::SourceIndex.new
+ @sice_new = Gem::SourceInfoCacheEntry.new @si_new, 0
+
+ prep_cache_files @sic
+
+ @sic.reset_cache_data
+ end
+
+ def teardown
+ super
+ Gem.sources.replace @original_sources
+ Gem::SourceInfoCache.instance_variable_set :@cache, nil
+ end
+
+ def test_self_cache_refreshes
+ Gem.configuration.update_sources = true #true by default
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
+
+ Gem.sources.replace %W[#{@gem_repo}]
+
+ use_ui @ui do
+ assert_not_nil Gem::SourceInfoCache.cache
+ assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
+ assert_equal Gem::SourceInfoCache.cache.object_id,
+ Gem::SourceInfoCache.cache.object_id
+ end
+
+ assert_match %r|Bulk updating|, @ui.output
+ end
+
+ def test_self_cache_skips_refresh_based_on_configuration
+ Gem.configuration.update_sources = false
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
+
+ Gem.sources.replace %w[#{@gem_repo}]
+
+ use_ui @ui do
+ assert_not_nil Gem::SourceInfoCache.cache
+ assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
+ assert_equal Gem::SourceInfoCache.cache.object_id,
+ Gem::SourceInfoCache.cache.object_id
+ assert_no_match %r|Bulk updating|, @ui.output
+ end
+ end
+
+ def test_self_cache_data
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
+
+ Gem::SourceInfoCache.instance_variable_set :@cache, nil
+ sice = Gem::SourceInfoCacheEntry.new si, 0
+
+ use_ui @ui do
+ gems = Gem::SourceInfoCache.cache_data[@gem_repo].source_index.gems
+ gem_names = gems.map { |_, spec| spec.full_name }
+
+ assert_equal si.gems.map { |_,spec| spec.full_name }, gem_names
+ end
+ end
+
+ def test_cache_data
+ assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
+ end
+
+ def test_cache_data_dirty
+ def @sic.dirty() @dirty; end
+ assert_equal false, @sic.dirty, 'clean on init'
+ @sic.cache_data
+ assert_equal false, @sic.dirty, 'clean on fetch'
+ @sic.update
+ @sic.cache_data
+ assert_equal true, @sic.dirty, 'still dirty'
+ end
+
+ def test_cache_data_irreparable
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = @source_index.dump
+
+ data = { @gem_repo => { 'totally' => 'borked' } }
+
+ cache_files = [
+ @sic.system_cache_file,
+ @sic.latest_system_cache_file,
+ @sic.user_cache_file,
+ @sic.latest_user_cache_file
+ ]
+
+ cache_files.each do |fn|
+ FileUtils.mkdir_p File.dirname(fn)
+ open(fn, "wb") { |f| f.write Marshal.dump(data) }
+ end
+
+ @sic.instance_eval { @cache_data = nil }
+
+ fetched = use_ui @ui do @sic.cache_data end
+
+ fetched_si = fetched["#{@gem_repo}"].source_index
+
+ assert_equal @source_index.index_signature, fetched_si.index_signature
+ end
+
+ def test_cache_data_none_readable
+ FileUtils.chmod 0222, @sic.system_cache_file
+ FileUtils.chmod 0222, @sic.latest_system_cache_file
+ FileUtils.chmod 0222, @sic.user_cache_file
+ FileUtils.chmod 0222, @sic.latest_user_cache_file
+ return if (File.stat(@sic.system_cache_file).mode & 0222) != 0222
+ return if (File.stat(@sic.user_cache_file).mode & 0222) != 0222
+ # HACK for systems that don't support chmod
+ assert_equal({}, @sic.cache_data)
+ end
+
+ def test_cache_data_none_writable
+ FileUtils.chmod 0444, @sic.system_cache_file
+ FileUtils.chmod 0444, @sic.user_cache_file
+ e = assert_raise RuntimeError do
+ @sic.cache_data
+ end
+ assert_equal 'unable to locate a writable cache file', e.message
+ end
+
+ def test_cache_data_nonexistent
+ FileUtils.rm @sic.system_cache_file
+ FileUtils.rm @sic.latest_system_cache_file
+ FileUtils.rm @sic.user_cache_file
+ FileUtils.rm @sic.latest_user_cache_file
+
+ # TODO test verbose output
+ assert_equal [], @sic.cache_data.to_a.sort
+ end
+
+ def test_cache_data_repair
+ data = {
+ @gem_repo => {
+ 'cache' => Gem::SourceIndex.new,
+ 'size' => 0,
+ }
+ }
+ [@sic.system_cache_file, @sic.user_cache_file].each do |fn|
+ FileUtils.mkdir_p File.dirname(fn)
+ open(fn, "wb") { |f| f.write Marshal.dump(data) }
+ end
+
+ @sic.instance_eval { @cache_data = nil }
+
+ expected = {
+ @gem_repo =>
+ Gem::SourceInfoCacheEntry.new(Gem::SourceIndex.new, 0)
+ }
+ assert_equal expected, @sic.cache_data
+ end
+
+ def test_cache_data_user_fallback
+ FileUtils.chmod 0444, @sic.system_cache_file
+
+ assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
+ end
+
+ def test_cache_file
+ assert_equal @gemcache, @sic.cache_file
+ end
+
+ def test_cache_file_user_fallback
+ FileUtils.chmod 0444, @sic.system_cache_file
+ assert_equal @usrcache, @sic.cache_file
+ end
+
+ def test_cache_file_none_writable
+ FileUtils.chmod 0444, @sic.system_cache_file
+ FileUtils.chmod 0444, @sic.user_cache_file
+ e = assert_raise RuntimeError do
+ @sic.cache_file
+ end
+ assert_equal 'unable to locate a writable cache file', e.message
+ end
+
+ def test_flush
+ @sic.cache_data[@gem_repo] = @sice_new
+ @sic.update
+ @sic.flush
+
+ assert_equal [[@gem_repo, @sice_new]],
+ read_cache(@sic.system_cache_file).to_a.sort
+ end
+
+ def test_latest_cache_data
+ util_make_gems
+
+ sice = Gem::SourceInfoCacheEntry.new @source_index, 0
+
+ @sic.set_cache_data @gem_repo => sice
+ latest = @sic.latest_cache_data
+ gems = latest[@gem_repo].source_index.search('a').map { |s| s.full_name }
+
+ assert_equal %w[a-2 a_evil-9], gems
+ end
+
+ def test_latest_cache_file
+ latest_cache_file = File.join File.dirname(@gemcache),
+ "latest_#{File.basename @gemcache}"
+ assert_equal latest_cache_file, @sic.latest_cache_file
+ end
+
+ def test_latest_system_cache_file
+ assert_equal File.join(Gem.dir, "latest_source_cache"),
+ @sic.latest_system_cache_file
+ end
+
+ def test_latest_user_cache_file
+ assert_equal @latest_usrcache, @sic.latest_user_cache_file
+ end
+
+ def test_read_system_cache
+ assert_equal [[@gem_repo, @sys_sice]], @sic.cache_data.to_a.sort
+ end
+
+ def test_read_user_cache
+ FileUtils.chmod 0444, @sic.user_cache_file
+ FileUtils.chmod 0444, @sic.latest_user_cache_file
+
+ @si = Gem::SourceIndex.new
+ @si.add_specs @a1, @a2
+
+ @sice = Gem::SourceInfoCacheEntry.new @si, 0
+
+ @sic.set_cache_data({ @gem_repo => @sice })
+ @sic.update
+ @sic.write_cache
+ @sic.reset_cache_data
+
+ user_cache_data = @sic.cache_data.to_a.sort
+
+ assert_equal 1, user_cache_data.length
+ user_cache_data = user_cache_data.first
+
+ assert_equal @gem_repo, user_cache_data.first
+
+ gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
+ assert_equal [@a2.full_name], gems
+ end
+
+ def test_search
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
+ @sic.instance_variable_set :@cache_data, cache_data
+
+ assert_equal [@a1], @sic.search(//)
+ end
+
+ def test_search_all
+ util_make_gems
+
+ sice = Gem::SourceInfoCacheEntry.new @source_index, 0
+
+ @sic.set_cache_data @gem_repo => sice
+ @sic.update
+ @sic.instance_variable_set :@only_latest, false
+ @sic.write_cache
+ @sic.reset_cache_data
+
+ gem_names = @sic.search(//, false, true).map { |spec| spec.full_name }
+
+ assert_equal %w[a-1 a-2 a_evil-9 c-1.2], gem_names
+ end
+
+ def test_search_dependency
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
+ @sic.instance_variable_set :@cache_data, cache_data
+
+ dep = Gem::Dependency.new @a1.name, @a1.version
+
+ assert_equal [@a1], @sic.search(dep)
+ end
+
+ def test_search_no_matches
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
+ @sic.instance_variable_set :@cache_data, cache_data
+
+ assert_equal [], @sic.search(/nonexistent/)
+ end
+
+ def test_search_no_matches_in_source
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
+ @sic.instance_variable_set :@cache_data, cache_data
+ Gem.sources.replace %w[more-gems.example.com]
+
+ assert_equal [], @sic.search(/nonexistent/)
+ end
+
+ def test_search_with_source
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
+ @sic.instance_variable_set :@cache_data, cache_data
+
+ assert_equal [[@a1, @gem_repo]],
+ @sic.search_with_source(//)
+ end
+
+ def test_system_cache_file
+ assert_equal File.join(Gem.dir, "source_cache"), @sic.system_cache_file
+ end
+
+ def test_user_cache_file
+ assert_equal @usrcache, @sic.user_cache_file
+ end
+
+ def test_write_cache
+ @sic.cache_data[@gem_repo] = @sice_new
+ @sic.write_cache
+
+ assert_equal [[@gem_repo, @sice_new]],
+ read_cache(@sic.system_cache_file).to_a.sort
+ assert_equal [[@gem_repo, @usr_sice]],
+ read_cache(@sic.user_cache_file).to_a.sort
+ end
+
+ def test_write_cache_user
+ FileUtils.chmod 0444, @sic.system_cache_file
+ @sic.set_cache_data({@gem_repo => @sice_new})
+ @sic.update
+ @sic.write_cache
+ @sic.instance_variable_set :@only_latest, false
+
+ assert File.exist?(@sic.user_cache_file), 'user_cache_file'
+ assert File.exist?(@sic.latest_user_cache_file),
+ 'latest_user_cache_file exists'
+
+ assert_equal [[@gem_repo, @sys_sice]],
+ read_cache(@sic.system_cache_file).to_a.sort
+ assert_equal [[@gem_repo, @sice_new]],
+ read_cache(@sic.user_cache_file).to_a.sort
+ end
+
+ def test_write_cache_user_from_scratch
+ FileUtils.rm_rf @sic.user_cache_file
+ FileUtils.rm_rf @sic.latest_user_cache_file
+
+ FileUtils.chmod 0444, @sic.system_cache_file
+ FileUtils.chmod 0444, @sic.latest_system_cache_file
+
+ @si = Gem::SourceIndex.new
+ @si.add_specs @a1, @a2
+
+ @sice = Gem::SourceInfoCacheEntry.new @si, 0
+
+ @sic.set_cache_data({ @gem_repo => @sice })
+ @sic.update
+
+ @sic.write_cache
+
+ assert File.exist?(@sic.user_cache_file), 'system_cache_file'
+ assert File.exist?(@sic.latest_user_cache_file),
+ 'latest_system_cache_file'
+
+ user_cache_data = read_cache(@sic.user_cache_file).to_a.sort
+ assert_equal 1, user_cache_data.length, 'user_cache_data length'
+ user_cache_data = user_cache_data.first
+
+ assert_equal @gem_repo, user_cache_data.first
+
+ gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
+ assert_equal [@a1.full_name, @a2.full_name], gems.sort
+
+ user_cache_data = read_cache(@sic.latest_user_cache_file).to_a.sort
+ assert_equal 1, user_cache_data.length
+ user_cache_data = user_cache_data.first
+
+ assert_equal @gem_repo, user_cache_data.first
+
+ gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
+ assert_equal [@a2.full_name], gems
+ end
+
+ def test_write_cache_user_no_directory
+ FileUtils.rm_rf File.dirname(@sic.user_cache_file)
+ FileUtils.chmod 0444, @sic.system_cache_file
+ @sic.set_cache_data({ @gem_repo => @sice_new })
+ @sic.update
+ @sic.write_cache
+
+ assert_equal [[@gem_repo, @sys_sice]],
+ read_cache(@sic.system_cache_file).to_a.sort
+ assert_equal [[@gem_repo, @sys_sice]],
+ read_cache(@sic.user_cache_file).to_a.sort
+ assert_equal [[@gem_repo, @sice_new]],
+ read_cache(@sic.latest_user_cache_file).to_a.sort
+ end
+
+ def test_write_cache_user_only_latest
+ FileUtils.chmod 0444, @sic.system_cache_file
+ @sic.set_cache_data({@gem_repo => @sice_new})
+ @sic.update
+ @sic.write_cache
+
+ assert File.exist?(@sic.user_cache_file), 'user_cache_file'
+ assert File.exist?(@sic.latest_user_cache_file),
+ 'latest_user_cache_file exists'
+
+ assert_equal [[@gem_repo, @sys_sice]],
+ read_cache(@sic.system_cache_file).to_a.sort
+ assert_equal [[@gem_repo, @sice_new]],
+ read_cache(@sic.user_cache_file).to_a.sort
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_source_info_cache_entry.rb b/trunk/test/rubygems/test_gem_source_info_cache_entry.rb
new file mode 100644
index 0000000000..6986c9cd7f
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_source_info_cache_entry.rb
@@ -0,0 +1,79 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/source_info_cache_entry'
+
+class TestGemSourceInfoCacheEntry < RubyGemTestCase
+
+ def setup
+ super
+
+ util_setup_fake_fetcher
+
+ @si = Gem::SourceIndex.new
+ @si.add_spec @a1
+ @sic_e = Gem::SourceInfoCacheEntry.new @si, @si.dump.size
+ end
+
+ def test_refresh
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] =
+ proc { raise }
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = @si.dump
+
+ use_ui @ui do
+ @sic_e.refresh @gem_repo, true
+ end
+ end
+
+ def test_refresh_all
+ @si.add_spec @a2
+
+ a1_name = @a1.full_name
+ a2_name = @a2.full_name
+
+ @fetcher.data["#{@gem_repo}quick/index.rz"] =
+ util_zip [a1_name, a2_name].join("\n")
+ @fetcher.data["#{@gem_repo}quick/latest_index.rz"] = util_zip a2_name
+ @fetcher.data["#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a1_name}.gemspec.rz"] = util_zip Marshal.dump(@a1)
+ @fetcher.data["#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a2_name}.gemspec.rz"] = util_zip Marshal.dump(@a2)
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
+ Marshal.dump @si
+
+ sic_e = Gem::SourceInfoCacheEntry.new Gem::SourceIndex.new, 0
+
+ assert_equal [], sic_e.source_index.map { |n,| n }
+
+ use_ui @ui do
+ assert sic_e.refresh(@gem_repo, false)
+ end
+
+ assert_equal [a2_name], sic_e.source_index.map { |n,| n }.sort
+
+ use_ui @ui do
+ sic_e.refresh @gem_repo, true
+ end
+
+ assert_equal [a1_name, a2_name], sic_e.source_index.map { |n,| n }.sort
+ end
+
+ def test_refresh_bad_uri
+ assert_raise URI::BadURIError do
+ @sic_e.refresh 'gems.example.com', true
+ end
+ end
+
+ def test_refresh_update
+ si = Gem::SourceIndex.new
+ si.add_spec @a1
+ si.add_spec @b2
+ @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
+
+ use_ui @ui do
+ @sic_e.refresh @gem_repo, true
+ end
+
+ new_gem = @sic_e.source_index.specification(@b2.full_name)
+ assert_equal @b2.full_name, new_gem.full_name
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_spec_fetcher.rb b/trunk/test/rubygems/test_gem_spec_fetcher.rb
new file mode 100644
index 0000000000..2e9ce1b7eb
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_spec_fetcher.rb
@@ -0,0 +1,303 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/spec_fetcher'
+
+class TestGemSpecFetcher < RubyGemTestCase
+
+ def setup
+ super
+
+ @uri = URI.parse @gem_repo
+
+ util_setup_fake_fetcher
+
+ @source_index.add_spec @pl1
+
+ @specs = @source_index.gems.sort.map do |name, spec|
+ [spec.name, spec.version, spec.original_platform]
+ end.sort
+
+ @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
+ util_gzip(Marshal.dump(@specs))
+
+ @latest_specs = @source_index.latest_specs.sort.map do |spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
+ util_gzip(Marshal.dump(@latest_specs))
+
+ @sf = Gem::SpecFetcher.new
+ end
+
+ def test_fetch_all
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@a1))
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.full_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@a2))
+
+ dep = Gem::Dependency.new 'a', 1
+ specs_and_sources = @sf.fetch dep, true
+
+ spec_names = specs_and_sources.map do |spec, source_uri|
+ [spec.full_name, source_uri]
+ end
+
+ expected = [[@a1.full_name, @gem_repo], [@a2.full_name, @gem_repo]]
+
+ assert_equal expected, spec_names
+
+ assert_same specs_and_sources.first.last, specs_and_sources.last.last
+ end
+
+ def test_fetch_latest
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@a1))
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.full_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@a2))
+
+ dep = Gem::Dependency.new 'a', 1
+ specs_and_sources = @sf.fetch dep
+
+ spec_names = specs_and_sources.map do |spec, source_uri|
+ [spec.full_name, source_uri]
+ end
+
+ assert_equal [[@a2.full_name, @gem_repo]], spec_names
+ end
+
+ def test_fetch_legacy_repo
+ @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data["#{@gem_repo}yaml"] = ''
+ util_setup_source_info_cache @a1, @a2
+
+ dep = Gem::Dependency.new 'a', 1
+ specs = nil
+
+ use_ui @ui do
+ specs = @sf.fetch dep, true
+ end
+
+ expected = <<-EOF
+WARNING: RubyGems 1.2+ index not found for:
+\thttp://gems.example.com/
+
+RubyGems will revert to legacy indexes degrading performance.
+ EOF
+
+ assert_equal expected, @ui.error
+
+ specs = specs.map { |spec, source_uri| [spec.full_name, source_uri] }
+
+ expected = [
+ [@a1.full_name, @gem_repo],
+ [@a2.full_name, @gem_repo],
+ ]
+
+ assert_equal expected, specs
+ end
+
+ def test_fetch_platform
+ util_set_arch 'i386-linux'
+
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@pl1))
+
+ dep = Gem::Dependency.new 'pl', 1
+ specs_and_sources = @sf.fetch dep
+
+ spec_names = specs_and_sources.map do |spec, source_uri|
+ [spec.full_name, source_uri]
+ end
+
+ assert_equal [[@pl1.full_name, @gem_repo]], spec_names
+ end
+
+ def test_fetch_spec
+ spec_uri = "#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec"
+ @fetcher.data["#{spec_uri}.rz"] = util_zip(Marshal.dump(@a1))
+
+ spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
+ assert_equal @a1.full_name, spec.full_name
+
+ cache_dir = @sf.cache_dir URI.parse(spec_uri)
+
+ cache_file = File.join cache_dir, "#{@a1.full_name}.gemspec"
+
+ assert File.exist?(cache_file)
+ end
+
+ def test_fetch_spec_cached
+ spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec"
+ @fetcher.data["#{spec_uri}.rz"] = nil
+
+ cache_dir = @sf.cache_dir URI.parse(spec_uri)
+ FileUtils.mkdir_p cache_dir
+
+ cache_file = File.join cache_dir, "#{@a1.full_name}.gemspec"
+
+ open cache_file, 'wb' do |io|
+ Marshal.dump @a1, io
+ end
+
+ spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
+ assert_equal @a1.full_name, spec.full_name
+ end
+
+ def test_fetch_spec_platform
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@pl1))
+
+ spec = @sf.fetch_spec ['pl', Gem::Version.new(1), 'i386-linux'], @uri
+
+ assert_equal @pl1.full_name, spec.full_name
+ end
+
+ def test_fetch_spec_platform_ruby
+ @fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
+ util_zip(Marshal.dump(@a1))
+
+ spec = @sf.fetch_spec ['a', Gem::Version.new(1), nil], @uri
+ assert_equal @a1.full_name, spec.full_name
+
+ spec = @sf.fetch_spec ['a', Gem::Version.new(1), ''], @uri
+ assert_equal @a1.full_name, spec.full_name
+ end
+
+ def test_find_matching_all
+ dep = Gem::Dependency.new 'a', 1
+ specs = @sf.find_matching dep, true
+
+ expected = [
+ [['a', Gem::Version.new(1), Gem::Platform::RUBY], @gem_repo],
+ [['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
+ ]
+
+ assert_equal expected, specs
+ end
+
+ def test_find_matching_latest
+ dep = Gem::Dependency.new 'a', 1
+ specs = @sf.find_matching dep
+
+ expected = [
+ [['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
+ ]
+
+ assert_equal expected, specs
+ end
+
+ def test_find_matching_platform
+ util_set_arch 'i386-linux'
+
+ dep = Gem::Dependency.new 'pl', 1
+ specs = @sf.find_matching dep
+
+ expected = [
+ [['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
+ ]
+
+ assert_equal expected, specs
+
+ util_set_arch 'i386-freebsd6'
+
+ dep = Gem::Dependency.new 'pl', 1
+ specs = @sf.find_matching dep
+
+ assert_equal [], specs
+ end
+
+ def test_find_all_platforms
+ util_set_arch 'i386-freebsd6'
+
+ dep = Gem::Dependency.new 'pl', 1
+ specs = @sf.find_matching dep, false, false
+
+ expected = [
+ [['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
+ ]
+
+ assert_equal expected, specs
+ end
+
+ def test_list
+ specs = @sf.list
+
+ assert_equal [@uri], specs.keys
+ assert_equal @latest_specs, specs[@uri].sort
+ end
+
+ def test_list_all
+ specs = @sf.list true
+
+ assert_equal [@uri], specs.keys
+
+ assert_equal @specs, specs[@uri].sort
+ end
+
+ def test_list_cache
+ specs = @sf.list
+
+ assert !specs[@uri].empty?
+
+ @fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = nil
+
+ cached_specs = @sf.list
+
+ assert_equal specs, cached_specs
+ end
+
+ def test_list_cache_all
+ specs = @sf.list true
+
+ assert !specs[@uri].empty?
+
+ @fetcher.data["#{@gem_repo}/specs.#{Gem.marshal_version}.gz"] = nil
+
+ cached_specs = @sf.list true
+
+ assert_equal specs, cached_specs
+ end
+
+ def test_load_specs
+ specs = @sf.load_specs @uri, 'specs'
+
+ expected = [
+ ['a', Gem::Version.new(1), Gem::Platform::RUBY],
+ ['a', Gem::Version.new(2), Gem::Platform::RUBY],
+ ['a_evil', Gem::Version.new(9), Gem::Platform::RUBY],
+ ['c', Gem::Version.new('1.2'), Gem::Platform::RUBY],
+ ['pl', Gem::Version.new(1), 'i386-linux'],
+ ]
+
+ assert_equal expected, specs
+
+ cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
+ assert File.exist?(cache_dir), "#{cache_dir} does not exist"
+
+ cache_file = File.join cache_dir, "specs.#{Gem.marshal_version}"
+ assert File.exist?(cache_file)
+ end
+
+ def test_load_specs_cached
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = ''
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
+ ' ' * Marshal.dump(@latest_specs).length
+
+ cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
+
+ FileUtils.mkdir_p cache_dir
+
+ cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
+
+ open cache_file, 'wb' do |io|
+ Marshal.dump @latest_specs, io
+ end
+
+ latest_specs = @sf.load_specs @uri, 'latest_specs'
+
+ assert_equal @latest_specs, latest_specs
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_specification.rb b/trunk/test/rubygems/test_gem_specification.rb
new file mode 100644
index 0000000000..57c3fdc158
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_specification.rb
@@ -0,0 +1,954 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'stringio'
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/specification'
+
+class TestGemSpecification < RubyGemTestCase
+
+ LEGACY_YAML_SPEC = <<-EOF
+--- !ruby/object:Gem::Specification
+rubygems_version: "1.0"
+name: keyedlist
+version: !ruby/object:Gem::Version
+ version: 0.4.0
+date: 2004-03-28 15:37:49.828000 +02:00
+platform:
+summary: A Hash which automatically computes keys.
+require_paths:
+ - lib
+files:
+ - lib/keyedlist.rb
+autorequire: keyedlist
+author: Florian Gross
+email: flgr@ccan.de
+has_rdoc: true
+ EOF
+
+ LEGACY_RUBY_SPEC = <<-EOF
+Gem::Specification.new do |s|
+ s.name = %q{keyedlist}
+ s.version = %q{0.4.0}
+ s.has_rdoc = true
+ s.summary = %q{A Hash which automatically computes keys.}
+ s.files = ["lib/keyedlist.rb"]
+ s.require_paths = ["lib"]
+ s.autorequire = %q{keyedlist}
+ s.author = %q{Florian Gross}
+ s.email = %q{flgr@ccan.de}
+end
+ EOF
+
+ def setup
+ super
+
+ @a1 = quick_gem 'a', '1' do |s|
+ s.executable = 'exec'
+ s.extensions << 'ext/a/extconf.rb'
+ s.has_rdoc = 'true'
+ s.test_file = 'test/suite.rb'
+ s.requirements << 'A working computer'
+ s.rubyforge_project = 'example'
+
+ s.add_dependency 'rake', '> 0.4'
+ s.add_dependency 'jabber4r', '> 0.0.0'
+ s.add_dependency 'pqa', ['> 0.4', '<= 0.6']
+
+ s.mark_version
+ s.files = %w[lib/code.rb]
+ end
+
+ @a2 = quick_gem 'a', '2' do |s|
+ s.files = %w[lib/code.rb]
+ end
+
+ FileUtils.mkdir_p File.join(@tempdir, 'bin')
+ File.open File.join(@tempdir, 'bin', 'exec'), 'w' do |fp|
+ fp.puts "#!#{Gem.ruby}"
+ end
+
+ @current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ end
+
+ def test_self_attribute_names
+ expected_value = %w[
+ authors
+ autorequire
+ bindir
+ cert_chain
+ date
+ default_executable
+ dependencies
+ description
+ email
+ executables
+ extensions
+ extra_rdoc_files
+ files
+ has_rdoc
+ homepage
+ name
+ platform
+ post_install_message
+ rdoc_options
+ require_paths
+ required_ruby_version
+ required_rubygems_version
+ requirements
+ rubyforge_project
+ rubygems_version
+ signing_key
+ specification_version
+ summary
+ test_files
+ version
+ ]
+
+ actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort
+
+ assert_equal expected_value, actual_value
+ end
+
+ def test_self__load_future
+ spec = Gem::Specification.new
+ spec.name = 'a'
+ spec.version = '1'
+ spec.specification_version = @current_version + 1
+
+ new_spec = Marshal.load Marshal.dump(spec)
+
+ assert_equal 'a', new_spec.name
+ assert_equal Gem::Version.new(1), new_spec.version
+ assert_equal @current_version, new_spec.specification_version
+ end
+
+ def test_self_load
+ spec = File.join @gemhome, 'specifications', "#{@a2.full_name}.gemspec"
+ gs = Gem::Specification.load spec
+
+ assert_equal @a2, gs
+ end
+
+ def test_self_load_legacy_ruby
+ spec = eval LEGACY_RUBY_SPEC
+ assert_equal 'keyedlist', spec.name
+ assert_equal '0.4.0', spec.version.to_s
+ assert_equal true, spec.has_rdoc?
+ assert_equal Gem::Specification::TODAY, spec.date
+ assert spec.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
+ assert_equal false, spec.has_unit_tests?
+ end
+
+ def test_self_load_legacy_yaml
+ s = YAML.load StringIO.new(LEGACY_YAML_SPEC)
+ assert_equal 'keyedlist', s.name
+ assert_equal '0.4.0', s.version.to_s
+ assert_equal true, s.has_rdoc?
+ #assert_equal Date.today, s.date
+ #assert s.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
+ assert_equal false, s.has_unit_tests?
+ end
+
+ def test_self_normalize_yaml_input_with_183_yaml
+ input = "!ruby/object:Gem::Specification "
+ assert_equal "--- #{input}", Gem::Specification.normalize_yaml_input(input)
+ end
+
+ def test_self_normalize_yaml_input_with_non_183_yaml
+ input = "--- !ruby/object:Gem::Specification "
+ assert_equal input, Gem::Specification.normalize_yaml_input(input)
+ end
+
+ def test_self_normalize_yaml_input_with_183_io
+ input = "!ruby/object:Gem::Specification "
+ assert_equal "--- #{input}",
+ Gem::Specification.normalize_yaml_input(StringIO.new(input))
+ end
+
+ def test_self_normalize_yaml_input_with_non_183_io
+ input = "--- !ruby/object:Gem::Specification "
+ assert_equal input,
+ Gem::Specification.normalize_yaml_input(StringIO.new(input))
+ end
+
+ def test_initialize
+ spec = Gem::Specification.new do |s|
+ s.name = "blah"
+ s.version = "1.3.5"
+ end
+
+ assert_equal "blah", spec.name
+ assert_equal "1.3.5", spec.version.to_s
+ assert_equal Gem::Platform::RUBY, spec.platform
+ assert_equal nil, spec.summary
+ assert_equal [], spec.files
+
+ assert_equal [], spec.test_files
+ assert_equal [], spec.rdoc_options
+ assert_equal [], spec.extra_rdoc_files
+ assert_equal [], spec.executables
+ assert_equal [], spec.extensions
+ assert_equal [], spec.requirements
+ assert_equal [], spec.dependencies
+ assert_equal 'bin', spec.bindir
+ assert_equal false, spec.has_rdoc
+ assert_equal false, spec.has_rdoc?
+ assert_equal '>= 0', spec.required_ruby_version.to_s
+ assert_equal '>= 0', spec.required_rubygems_version.to_s
+ end
+
+ def test_initialize_future
+ version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + 1
+ spec = Gem::Specification.new do |s|
+ s.name = "blah"
+ s.version = "1.3.5"
+
+ s.specification_version = version
+
+ s.new_unknown_attribute = "a value"
+ end
+
+ assert_equal "blah", spec.name
+ assert_equal "1.3.5", spec.version.to_s
+ end
+
+ def test__dump
+ @a2.platform = Gem::Platform.local
+ @a2.instance_variable_set :@original_platform, 'old_platform'
+
+ data = Marshal.dump @a2
+
+ same_spec = Marshal.load data
+
+ assert_equal 'old_platform', same_spec.original_platform
+ end
+
+ def test_add_dependency_with_explicit_type
+ gem = quick_gem "awesome", "1.0" do |awesome|
+ awesome.add_development_dependency "monkey"
+ end
+
+ monkey = gem.dependencies.detect { |d| d.name == "monkey" }
+ assert_equal(:development, monkey.type)
+ end
+
+ def test_author
+ assert_equal 'A User', @a1.author
+ end
+
+ def test_authors
+ assert_equal ['A User'], @a1.authors
+ end
+
+ def test_bindir_equals
+ @a1.bindir = 'apps'
+
+ assert_equal 'apps', @a1.bindir
+ end
+
+ def test_bindir_equals_nil
+ @a2.bindir = nil
+ @a2.executable = 'app'
+
+ assert_equal nil, @a2.bindir
+ assert_equal %w[lib/code.rb app], @a2.files
+ end
+
+ def test_date
+ assert_equal Gem::Specification::TODAY, @a1.date
+ end
+
+ def test_date_equals_date
+ @a1.date = Date.new(2003, 9, 17)
+ assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+ end
+
+ def test_date_equals_string
+ @a1.date = '2003-09-17'
+ assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+ end
+
+ def test_date_equals_time
+ @a1.date = Time.local(2003, 9, 17, 0,0,0)
+ assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+ end
+
+ def test_date_equals_time_local
+ # HACK PDT
+ @a1.date = Time.local(2003, 9, 17, 19,50,0)
+ assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+ end
+
+ def test_date_equals_time_utc
+ # HACK PDT
+ @a1.date = Time.local(2003, 9, 17, 19,50,0)
+ assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
+ end
+
+ def test_default_executable
+ assert_equal 'exec', @a1.default_executable
+
+ @a1.default_executable = nil
+ @a1.instance_variable_set :@executables, nil
+ assert_equal nil, @a1.default_executable
+ end
+
+ def test_dependencies
+ rake = Gem::Dependency.new 'rake', '> 0.4'
+ jabber = Gem::Dependency.new 'jabber4r', '> 0.0.0'
+ pqa = Gem::Dependency.new 'pqa', ['> 0.4', '<= 0.6']
+
+ assert_equal [rake, jabber, pqa], @a1.dependencies
+ end
+
+ def test_dependencies_scoped_by_type
+ gem = quick_gem "awesome", "1.0" do |awesome|
+ awesome.add_runtime_dependency "bonobo", []
+ awesome.add_development_dependency "monkey", []
+ end
+
+ bonobo = Gem::Dependency.new("bonobo", [])
+ monkey = Gem::Dependency.new("monkey", [], :development)
+
+ assert_equal([bonobo, monkey], gem.dependencies)
+ assert_equal([bonobo], gem.runtime_dependencies)
+ assert_equal([monkey], gem.development_dependencies)
+ end
+
+ def test_description
+ assert_equal 'This is a test description', @a1.description
+ end
+
+ def test_eql_eh
+ g1 = quick_gem 'gem'
+ g2 = quick_gem 'gem'
+
+ assert_equal g1, g2
+ assert_equal g1.hash, g2.hash
+ assert_equal true, g1.eql?(g2)
+ end
+
+ def test_equals2
+ assert_equal @a1, @a1
+ assert_equal @a1, @a1.dup
+ assert_not_equal @a1, @a2
+ assert_not_equal @a1, Object.new
+ end
+
+ # The cgikit specification was reported to be causing trouble in at least
+ # one version of RubyGems, so we test explicitly for it.
+ def test_equals2_cgikit
+ cgikit = Gem::Specification.new do |s|
+ s.name = %q{cgikit}
+ s.version = "1.1.0"
+ s.date = %q{2004-03-13}
+ s.summary = %q{CGIKit is a componented-oriented web application } +
+ %q{framework like Apple Computers WebObjects. } +
+ %{This framework services Model-View-Controller architecture } +
+ %q{programming by components based on a HTML file, a definition } +
+ %q{file and a Ruby source. }
+ s.email = %q{info@spice-of-life.net}
+ s.homepage = %q{http://www.spice-of-life.net/download/cgikit/}
+ s.autorequire = %q{cgikit}
+ s.bindir = nil
+ s.has_rdoc = nil
+ s.required_ruby_version = nil
+ s.platform = nil
+ s.files = ["lib/cgikit", "lib/cgikit.rb", "lib/cgikit/components", "..."]
+ end
+
+ assert_equal cgikit, cgikit
+ end
+
+ def test_equals2_default_executable
+ spec = @a1.dup
+ spec.default_executable = 'xx'
+
+ assert_not_equal @a1, spec
+ assert_not_equal spec, @a1
+ end
+
+ def test_equals2_extensions
+ spec = @a1.dup
+ spec.extensions = 'xx'
+
+ assert_not_equal @a1, spec
+ assert_not_equal spec, @a1
+ end
+
+ def test_executables
+ @a1.executable = 'app'
+ assert_equal %w[app], @a1.executables
+ end
+
+ def test_executable_equals
+ @a2.executable = 'app'
+ assert_equal 'app', @a2.executable
+ assert_equal %w[lib/code.rb bin/app], @a2.files
+ end
+
+ def test_extensions
+ assert_equal ['ext/a/extconf.rb'], @a1.extensions
+ end
+
+ def test_files
+ @a1.files = %w(files bin/common)
+ @a1.test_files = %w(test_files bin/common)
+ @a1.executables = %w(executables common)
+ @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
+ @a1.extensions = %w(extensions bin/common)
+
+ expected = %w[
+ bin/common
+ bin/executables
+ extensions
+ extra_rdoc_files
+ files
+ test_files
+ ]
+ assert_equal expected, @a1.files.sort
+ end
+
+ def test_files_duplicate
+ @a2.files = %w[a b c d b]
+ @a2.extra_rdoc_files = %w[x y z x]
+ @a2.normalize
+
+ assert_equal %w[a b c d x y z], @a2.files
+ assert_equal %w[x y z], @a2.extra_rdoc_files
+ end
+
+ def test_files_extra_rdoc_files
+ @a2.files = %w[a b c d]
+ @a2.extra_rdoc_files = %w[x y z]
+ @a2.normalize
+ assert_equal %w[a b c d x y z], @a2.files
+ end
+
+ def test_files_non_array
+ @a1.files = "F"
+ @a1.test_files = "TF"
+ @a1.executables = "X"
+ @a1.extra_rdoc_files = "ERF"
+ @a1.extensions = "E"
+
+ assert_equal %w[E ERF F TF bin/X], @a1.files.sort
+ end
+
+ def test_files_non_array_pathological
+ @a1.instance_variable_set :@files, "F"
+ @a1.instance_variable_set :@test_files, "TF"
+ @a1.instance_variable_set :@extra_rdoc_files, "ERF"
+ @a1.instance_variable_set :@extensions, "E"
+ @a1.instance_variable_set :@executables, "X"
+
+ assert_equal %w[E ERF F TF bin/X], @a1.files.sort
+ assert_kind_of Integer, @a1.hash
+ end
+
+ def test_full_gem_path
+ assert_equal File.join(@gemhome, 'gems', @a1.full_name),
+ @a1.full_gem_path
+
+ @a1.original_platform = 'mswin32'
+
+ assert_equal File.join(@gemhome, 'gems', @a1.original_name),
+ @a1.full_gem_path
+ end
+
+ def test_full_gem_path_double_slash
+ gemhome = @gemhome.sub(/\w\//, '\&/')
+ @a1.loaded_from = File.join gemhome, 'specifications',
+ "#{@a1.full_name}.gemspec"
+
+ assert_equal File.join(@gemhome, 'gems', @a1.full_name),
+ @a1.full_gem_path
+ end
+
+ def test_full_name
+ assert_equal 'a-1', @a1.full_name
+
+ @a1.platform = Gem::Platform.new ['universal', 'darwin', nil]
+ assert_equal 'a-1-universal-darwin', @a1.full_name
+
+ @a1.instance_variable_set :@new_platform, 'mswin32'
+ assert_equal 'a-1-mswin32', @a1.full_name, 'legacy'
+
+ return if win_platform?
+
+ @a1.platform = 'current'
+ assert_equal 'a-1-x86-darwin-8', @a1.full_name
+ end
+
+ def test_full_name_windows
+ test_cases = {
+ 'i386-mswin32' => 'a-1-x86-mswin32-60',
+ 'i386-mswin32_80' => 'a-1-x86-mswin32-80',
+ 'i386-mingw32' => 'a-1-x86-mingw32'
+ }
+
+ test_cases.each do |arch, expected|
+ util_set_arch arch
+ @a1.platform = 'current'
+ assert_equal expected, @a1.full_name
+ end
+ end
+
+ def test_has_rdoc_eh
+ assert_equal true, @a1.has_rdoc?
+ end
+
+ def test_hash
+ assert_equal @a1.hash, @a1.hash
+ assert_equal @a1.hash, @a1.dup.hash
+ assert_not_equal @a1.hash, @a2.hash
+ end
+
+ def test_lib_files
+ @a1.files = %w[lib/foo.rb Rakefile]
+
+ assert_equal %w[lib/foo.rb], @a1.lib_files
+ end
+
+ def test_name
+ assert_equal 'a', @a1.name
+ end
+
+ def test_original_name
+ assert_equal 'a-1', @a1.full_name
+
+ @a1.platform = 'i386-linux'
+ @a1.instance_variable_set :@original_platform, 'i386-linux'
+ assert_equal 'a-1-i386-linux', @a1.original_name
+ end
+
+ def test_platform
+ assert_equal Gem::Platform::RUBY, @a1.platform
+ end
+
+ def test_platform_equals
+ @a1.platform = nil
+ assert_equal Gem::Platform::RUBY, @a1.platform
+
+ @a1.platform = Gem::Platform::RUBY
+ assert_equal Gem::Platform::RUBY, @a1.platform
+
+ test_cases = {
+ 'i386-mswin32' => ['x86', 'mswin32', '60'],
+ 'i386-mswin32_80' => ['x86', 'mswin32', '80'],
+ 'i386-mingw32' => ['x86', 'mingw32', nil ],
+ 'x86-darwin8' => ['x86', 'darwin', '8' ],
+ }
+
+ test_cases.each do |arch, expected|
+ util_set_arch arch
+ @a1.platform = Gem::Platform::CURRENT
+ assert_equal Gem::Platform.new(expected), @a1.platform
+ end
+ end
+
+ def test_platform_equals_current
+ @a1.platform = Gem::Platform::CURRENT
+ assert_equal Gem::Platform.local, @a1.platform
+ assert_equal Gem::Platform.local.to_s, @a1.original_platform
+ end
+
+ def test_platform_equals_legacy
+ @a1.platform = 'mswin32'
+ assert_equal Gem::Platform.new('x86-mswin32'), @a1.platform
+
+ @a1.platform = 'i586-linux'
+ assert_equal Gem::Platform.new('x86-linux'), @a1.platform
+
+ @a1.platform = 'powerpc-darwin'
+ assert_equal Gem::Platform.new('ppc-darwin'), @a1.platform
+ end
+
+ def test_require_paths
+ @a1.require_path = 'lib'
+ assert_equal %w[lib], @a1.require_paths
+ end
+
+ def test_requirements
+ assert_equal ['A working computer'], @a1.requirements
+ end
+
+ def test_runtime_dependencies_legacy
+ # legacy gems don't have a type
+ @a1.runtime_dependencies.each do |dep|
+ dep.instance_variable_set :@type, nil
+ end
+
+ expected = %w[rake jabber4r pqa]
+
+ assert_equal expected, @a1.runtime_dependencies.map { |d| d.name }
+ end
+
+ def test_spaceship_name
+ s1 = quick_gem 'a', '1'
+ s2 = quick_gem 'b', '1'
+
+ assert_equal(-1, (s1 <=> s2))
+ assert_equal( 0, (s1 <=> s1))
+ assert_equal( 1, (s2 <=> s1))
+ end
+
+ def test_spaceship_platform
+ s1 = quick_gem 'a', '1'
+ s2 = quick_gem 'a', '1' do |s|
+ s.platform = Gem::Platform.new 'x86-my_platform1'
+ end
+
+ assert_equal( -1, (s1 <=> s2))
+ assert_equal( 0, (s1 <=> s1))
+ assert_equal( 1, (s2 <=> s1))
+ end
+
+ def test_spaceship_version
+ s1 = quick_gem 'a', '1'
+ s2 = quick_gem 'a', '2'
+
+ assert_equal( -1, (s1 <=> s2))
+ assert_equal( 0, (s1 <=> s1))
+ assert_equal( 1, (s2 <=> s1))
+ end
+
+ def test_summary
+ assert_equal 'this is a summary', @a1.summary
+ end
+
+ def test_test_files
+ @a1.test_file = 'test/suite.rb'
+ assert_equal ['test/suite.rb'], @a1.test_files
+ end
+
+ def test_to_ruby
+ @a2.add_runtime_dependency 'b', '1'
+ @a2.dependencies.first.instance_variable_set :@type, nil
+ @a2.required_rubygems_version = Gem::Requirement.new '> 0'
+
+ ruby_code = @a2.to_ruby
+
+ expected = "Gem::Specification.new do |s|
+ s.name = %q{a}
+ s.version = \"2\"
+
+ s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
+ s.authors = [\"A User\"]
+ s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
+ s.description = %q{This is a test description}
+ s.email = %q{example@example.com}
+ s.files = [\"lib/code.rb\"]
+ s.has_rdoc = true
+ s.homepage = %q{http://example.com}
+ s.require_paths = [\"lib\"]
+ s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
+ s.summary = %q{this is a summary}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
+
+ if current_version >= 3 then
+ s.add_runtime_dependency(%q<b>, [\"= 1\"])
+ else
+ s.add_dependency(%q<b>, [\"= 1\"])
+ end
+ else
+ s.add_dependency(%q<b>, [\"= 1\"])
+ end
+end
+"
+
+ assert_equal expected, ruby_code
+
+ same_spec = eval ruby_code
+
+ assert_equal @a2, same_spec
+ end
+
+ def test_to_ruby_fancy
+ @a1.platform = Gem::Platform.local
+ ruby_code = @a1.to_ruby
+
+ local = Gem::Platform.local
+ expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
+
+ expected = "Gem::Specification.new do |s|
+ s.name = %q{a}
+ s.version = \"1\"
+ s.platform = Gem::Platform.new(#{expected_platform})
+
+ s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=
+ s.authors = [\"A User\"]
+ s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
+ s.default_executable = %q{exec}
+ s.description = %q{This is a test description}
+ s.email = %q{example@example.com}
+ s.executables = [\"exec\"]
+ s.extensions = [\"ext/a/extconf.rb\"]
+ s.files = [\"lib/code.rb\", \"test/suite.rb\", \"bin/exec\", \"ext/a/extconf.rb\"]
+ s.has_rdoc = %q{true}
+ s.homepage = %q{http://example.com}
+ s.require_paths = [\"lib\"]
+ s.requirements = [\"A working computer\"]
+ s.rubyforge_project = %q{example}
+ s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
+ s.summary = %q{this is a summary}
+ s.test_files = [\"test/suite.rb\"]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 2
+
+ if current_version >= 3 then
+ s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
+ s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+ s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+ else
+ s.add_dependency(%q<rake>, [\"> 0.4\"])
+ s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+ s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+ end
+ else
+ s.add_dependency(%q<rake>, [\"> 0.4\"])
+ s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
+ s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
+ end
+end
+"
+
+ assert_equal expected, ruby_code
+
+ same_spec = eval ruby_code
+
+ assert_equal @a1, same_spec
+ end
+
+ def test_to_ruby_legacy
+ gemspec1 = eval LEGACY_RUBY_SPEC
+ ruby_code = gemspec1.to_ruby
+ gemspec2 = eval ruby_code
+
+ assert_equal gemspec1, gemspec2
+ end
+
+ def test_to_ruby_platform
+ @a2.platform = Gem::Platform.local
+ @a2.instance_variable_set :@original_platform, 'old_platform'
+
+ ruby_code = @a2.to_ruby
+
+ same_spec = eval ruby_code
+
+ assert_equal 'old_platform', same_spec.original_platform
+ end
+
+ def test_to_yaml
+ yaml_str = @a1.to_yaml
+ same_spec = YAML.load(yaml_str)
+
+ assert_equal @a1, same_spec
+ end
+
+ def test_to_yaml_fancy
+ @a1.platform = Gem::Platform.local
+ yaml_str = @a1.to_yaml
+
+ same_spec = YAML.load(yaml_str)
+
+ assert_equal Gem::Platform.local, same_spec.platform
+
+ assert_equal @a1, same_spec
+ end
+
+ def test_to_yaml_platform_empty_string
+ @a1.instance_variable_set :@original_platform, ''
+
+ assert_match %r|^platform: ruby$|, @a1.to_yaml
+ end
+
+ def test_to_yaml_platform_legacy
+ @a1.platform = 'powerpc-darwin7.9.0'
+ @a1.instance_variable_set :@original_platform, 'powerpc-darwin7.9.0'
+
+ yaml_str = @a1.to_yaml
+
+ same_spec = YAML.load(yaml_str)
+
+ assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
+ assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
+ end
+
+ def test_to_yaml_platform_nil
+ @a1.instance_variable_set :@original_platform, nil
+
+ assert_match %r|^platform: ruby$|, @a1.to_yaml
+ end
+
+ def test_validate
+ Dir.chdir @tempdir do
+ assert @a1.validate
+ end
+ end
+
+ def test_validate_authors
+ Dir.chdir @tempdir do
+ @a1.authors = []
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: no author specified\n", @ui.error, 'error'
+
+ @a1.authors = [Object.new]
+
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.validate
+ end
+
+ assert_equal 'authors must be Array of Strings', e.message
+ end
+ end
+
+ def test_validate_autorequire
+ Dir.chdir @tempdir do
+ @a1.autorequire = 'code'
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: deprecated autorequire specified\n",
+ @ui.error, 'error'
+ end
+ end
+
+ def test_validate_email
+ Dir.chdir @tempdir do
+ @a1.email = ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: no email specified\n", @ui.error, 'error'
+ end
+ end
+
+ def test_validate_empty
+ e = assert_raise Gem::InvalidSpecificationException do
+ Gem::Specification.new.validate
+ end
+
+ assert_equal 'missing value for attribute name', e.message
+ end
+
+ def test_validate_executables
+ FileUtils.mkdir_p File.join(@tempdir, 'bin')
+ File.open File.join(@tempdir, 'bin', 'exec'), 'w' do end
+
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ assert @a1.validate
+ end
+ end
+
+ assert_equal '', @ui.output, 'output'
+ assert_equal "WARNING: bin/exec is missing #! line\n", @ui.error, 'error'
+ end
+
+ def test_validate_empty_require_paths
+ @a1.require_paths = []
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.validate
+ end
+
+ assert_equal 'specification must have at least one require_path', e.message
+ end
+
+ def test_validate_homepage
+ Dir.chdir @tempdir do
+ @a1.homepage = ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: no homepage specified\n", @ui.error, 'error'
+ end
+ end
+
+ def test_validate_has_rdoc
+ Dir.chdir @tempdir do
+ @a1.has_rdoc = false
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: RDoc will not be generated (has_rdoc == false)\n",
+ @ui.error, 'error'
+ end
+ end
+
+ def test_validate_platform_legacy
+ Dir.chdir @tempdir do
+ @a1.platform = 'mswin32'
+ assert @a1.validate
+
+ @a1.platform = 'i586-linux'
+ assert @a1.validate
+
+ @a1.platform = 'powerpc-darwin'
+ assert @a1.validate
+ end
+ end
+
+ def test_validate_rubyforge_project
+ Dir.chdir @tempdir do
+ @a1.rubyforge_project = ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: no rubyforge_project specified\n",
+ @ui.error, 'error'
+ end
+ end
+
+ def test_validate_rubygems_version
+ @a1.rubygems_version = "3"
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.validate
+ end
+
+ assert_equal "expected RubyGems version #{Gem::RubyGemsVersion}, was 3",
+ e.message
+ end
+
+ def test_validate_summary
+ Dir.chdir @tempdir do
+ @a1.summary = ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "WARNING: no summary specified\n", @ui.error, 'error'
+ end
+ end
+
+ def test_version
+ assert_equal Gem::Version.new('1'), @a1.version
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_stream_ui.rb b/trunk/test/rubygems/test_gem_stream_ui.rb
new file mode 100644
index 0000000000..a8564ba94f
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_stream_ui.rb
@@ -0,0 +1,117 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/user_interaction'
+
+class TestGemStreamUI < RubyGemTestCase
+
+ module IsTty
+ attr_accessor :tty
+
+ def tty?
+ @tty = true unless defined? @tty
+ return @tty
+ end
+
+ alias_method :isatty, :tty?
+ end
+
+ def setup
+ super
+
+ @cfg = Gem.configuration
+
+ @in = StringIO.new
+ @out = StringIO.new
+ @err = StringIO.new
+
+ @in.extend IsTty
+
+ @sui = Gem::StreamUI.new @in, @out, @err
+ end
+
+ def test_ask
+ timeout(1) do
+ expected_answer = "Arthur, King of the Britons"
+ @in.string = "#{expected_answer}\n"
+ actual_answer = @sui.ask("What is your name?")
+ assert_equal expected_answer, actual_answer
+ end
+ end
+
+ def test_ask_no_tty
+ @in.tty = false
+
+ timeout(0.1) do
+ answer = @sui.ask("what is your favorite color?")
+ assert_equal nil, answer
+ end
+ end
+
+ def test_ask_yes_no_no_tty_with_default
+ @in.tty = false
+
+ timeout(0.1) do
+ answer = @sui.ask_yes_no("do coconuts migrate?", false)
+ assert_equal false, answer
+
+ answer = @sui.ask_yes_no("do coconuts migrate?", true)
+ assert_equal true, answer
+ end
+ end
+
+ def test_ask_yes_no_no_tty_without_default
+ @in.tty = false
+
+ timeout(0.1) do
+ assert_raises(Gem::OperationNotSupportedError) do
+ @sui.ask_yes_no("do coconuts migrate?")
+ end
+ end
+ end
+
+ def test_choose_from_list
+ @in.puts "1"
+ @in.rewind
+
+ result = @sui.choose_from_list 'which one?', %w[foo bar]
+
+ assert_equal ['foo', 0], result
+ assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string
+ end
+
+ def test_choose_from_list_EOF
+ result = @sui.choose_from_list 'which one?', %w[foo bar]
+
+ assert_equal [nil, nil], result
+ assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string
+ end
+
+ def test_proress_reporter_silent_nil
+ @cfg.verbose = nil
+ reporter = @sui.progress_reporter 10, 'hi'
+ assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
+ end
+
+ def test_proress_reporter_silent_false
+ @cfg.verbose = false
+ reporter = @sui.progress_reporter 10, 'hi'
+ assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
+ assert_equal "", @out.string
+ end
+
+ def test_proress_reporter_simple
+ @cfg.verbose = true
+ reporter = @sui.progress_reporter 10, 'hi'
+ assert_kind_of Gem::StreamUI::SimpleProgressReporter, reporter
+ assert_equal "hi\n", @out.string
+ end
+
+ def test_proress_reporter_verbose
+ @cfg.verbose = 0
+ reporter = @sui.progress_reporter 10, 'hi'
+ assert_kind_of Gem::StreamUI::VerboseProgressReporter, reporter
+ assert_equal "hi\n", @out.string
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_uninstaller.rb b/trunk/test/rubygems/test_gem_uninstaller.rb
new file mode 100644
index 0000000000..7d7890c3ea
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_uninstaller.rb
@@ -0,0 +1,66 @@
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_installer_test_case')
+require 'rubygems/uninstaller'
+
+class TestGemUninstaller < GemInstallerTestCase
+
+ def setup
+ super
+
+ ui = MockGemUi.new
+ util_setup_gem ui
+
+ build_rake_in do
+ use_ui ui do
+ @installer.install
+ end
+ end
+ end
+
+ def test_initialize_expand_path
+ uninstaller = Gem::Uninstaller.new nil, :install_dir => '/foo//bar'
+
+ assert_match %r|/foo/bar$|, uninstaller.instance_variable_get(:@gem_home)
+ end
+
+ def test_remove_executables_force_keep
+ uninstaller = Gem::Uninstaller.new nil, :executables => false
+
+ use_ui @ui do
+ uninstaller.remove_executables @spec
+ end
+
+ assert_equal true, File.exist?(File.join(@gemhome, 'bin', 'executable'))
+
+ assert_equal "Executables and scripts will remain installed.\n", @ui.output
+ end
+
+ def test_remove_executables_force_remove
+ uninstaller = Gem::Uninstaller.new nil, :executables => true
+
+ use_ui @ui do
+ uninstaller.remove_executables @spec
+ end
+
+ assert_equal "Removing executable\n", @ui.output
+
+ assert_equal false, File.exist?(File.join(@gemhome, 'bin', 'executable'))
+ end
+
+ def test_path_ok_eh
+ uninstaller = Gem::Uninstaller.new nil
+
+ assert_equal true, uninstaller.path_ok?(@spec)
+ end
+
+ def test_path_ok_eh_legacy
+ uninstaller = Gem::Uninstaller.new nil
+
+ @spec.loaded_from.gsub! @spec.full_name, '\&-legacy'
+ @spec.platform = 'legacy'
+
+ assert_equal true, uninstaller.path_ok?(@spec)
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_validator.rb b/trunk/test/rubygems/test_gem_validator.rb
new file mode 100644
index 0000000000..c910cfdf11
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_validator.rb
@@ -0,0 +1,70 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
+require 'rubygems/validator'
+
+class TestGemValidator < RubyGemTestCase
+
+ def setup
+ super
+
+ @simple_gem = SIMPLE_GEM
+ @validator = Gem::Validator.new
+ end
+
+ def test_verify_gem_file
+ gem_file = File.join @tempdir, 'simple_gem.gem'
+ File.open gem_file, 'wb' do |fp| fp.write @simple_gem end
+
+ assert_equal nil, @validator.verify_gem_file(gem_file)
+ end
+
+ def test_verify_gem_file_empty
+ e = assert_raise Gem::VerificationError do
+ @validator.verify_gem_file ''
+ end
+
+ assert_equal 'missing gem file ', e.message
+ end
+
+ def test_verify_gem_file_nonexistent
+ file = '/nonexistent/nonexistent.gem'
+ e = assert_raise Gem::VerificationError do
+ @validator.verify_gem_file file
+ end
+
+ assert_equal "missing gem file #{file}", e.message
+ end
+
+ def test_verify_gem
+ assert_equal nil, @validator.verify_gem(@simple_gem)
+ end
+
+ def test_verify_gem_empty
+ e = assert_raise Gem::VerificationError do
+ @validator.verify_gem ''
+ end
+
+ assert_equal 'empty gem file', e.message
+ end
+
+ def test_verify_gem_invalid_checksum
+ e = assert_raise Gem::VerificationError do
+ @validator.verify_gem @simple_gem.upcase
+ end
+
+ assert_equal 'invalid checksum for gem file', e.message
+ end
+
+ def test_verify_gem_no_sum
+ assert_equal nil, @validator.verify_gem('words')
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_version.rb b/trunk/test/rubygems/test_gem_version.rb
new file mode 100644
index 0000000000..8d10700490
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_version.rb
@@ -0,0 +1,215 @@
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/version'
+
+class TestGemVersion < RubyGemTestCase
+
+ def setup
+ super
+
+ @v1_0 = Gem::Version.new '1.0'
+ @v1_2 = Gem::Version.new '1.2'
+ @v1_3 = Gem::Version.new '1.3'
+ end
+
+ def test_class_create
+ assert_version Gem::Version.create('1.0')
+ assert_version Gem::Version.create("1.0 ")
+ assert_version Gem::Version.create(" 1.0 ")
+ assert_version Gem::Version.create("1.0\n")
+ assert_version Gem::Version.create("\n1.0\n")
+
+ assert_equal Gem::Version.create('1'), Gem::Version.create(1)
+ end
+
+ def test_class_create_malformed
+ e = assert_raise ArgumentError do Gem::Version.create("junk") end
+ assert_equal "Malformed version number string junk", e.message
+
+ e = assert_raise ArgumentError do Gem::Version.create("1.0\n2.0") end
+ assert_equal "Malformed version number string 1.0\n2.0", e.message
+ end
+
+ def test_bad
+ assert_inadequate( "", "> 0.1")
+ assert_inadequate( "1.2.3", "!= 1.2.3")
+ assert_inadequate( "1.2.003.0.0", "!= 1.02.3")
+ assert_inadequate( "4.5.6", "< 1.2.3")
+ assert_inadequate( "1.0", "> 1.1")
+ assert_inadequate( "0", ">")
+ assert_inadequate( "0", "<")
+ assert_inadequate( "", "= 0.1")
+ assert_inadequate( "1.1.1", "> 1.1.1")
+ assert_inadequate( "1.2", "= 1.1")
+ assert_inadequate( "1.40", "= 1.1")
+ assert_inadequate( "1.3", "= 1.40")
+ assert_inadequate( "9.3.3", "<= 9.3.2")
+ assert_inadequate( "9.3.1", ">= 9.3.2")
+ assert_inadequate( "9.3.03", "<= 9.3.2")
+ assert_inadequate( "1.0.0.1", "= 1.0")
+ end
+
+ def test_bump_trailing_zeros
+ v = Gem::Version.new("5.0.0")
+ assert_equal "5.1", v.bump.to_s
+ end
+
+ def test_bump
+ v = Gem::Version.new("5.2.4")
+ assert_equal "5.3", v.bump.to_s
+ end
+
+ def test_bump_one_level
+ v = Gem::Version.new("5")
+ assert_equal "6", v.bump.to_s
+ end
+
+ def test_eql_eh
+ v1_2 = Gem::Version.new '1.2'
+ v1_2_0 = Gem::Version.new '1.2.0'
+
+ assert_equal true, v1_2.eql?(@v1_2)
+ assert_equal true, @v1_2.eql?(v1_2)
+
+ assert_equal false, v1_2_0.eql?(@v1_2)
+ assert_equal false, @v1_2.eql?(v1_2_0)
+
+ assert_equal false, @v1_2.eql?(@v1_3)
+ assert_equal false, @v1_3.eql?(@v1_2)
+ end
+
+ def test_equals2
+ v = Gem::Version.new("1.2")
+
+ assert_equal v, @v1_2
+ assert_equal @v1_2, v
+
+ assert_not_equal @v1_2, @v1_3
+ assert_not_equal @v1_3, @v1_2
+ end
+
+ def test_hash
+ v1_2 = Gem::Version.new "1.2"
+ v1_2_0 = Gem::Version.new "1.2.0"
+
+ assert_equal v1_2.hash, @v1_2.hash
+
+ assert_not_equal v1_2_0.hash, @v1_2.hash
+
+ assert_not_equal @v1_2.hash, @v1_3.hash
+ end
+
+ def test_illformed_requirements
+ [ ">>> 1.3.5", "> blah" ].each do |rq|
+ assert_raises(ArgumentError, "req [#{rq}] should fail") {
+ Gem::Version::Requirement.new(rq)
+ }
+ end
+ end
+
+ def test_normalize
+ assert_equal [1], Gem::Version.new("1").to_ints
+ assert_equal [1], Gem::Version.new("1.0").to_ints
+ assert_equal [1, 1], Gem::Version.new("1.1").to_ints
+ end
+
+ def test_ok
+ assert_adequate( "0.2.33", "= 0.2.33")
+ assert_adequate( "0.2.34", "> 0.2.33")
+ assert_adequate( "1.0", "= 1.0")
+ assert_adequate( "1.0", "1.0")
+ assert_adequate( "1.8.2", "> 1.8.0")
+ assert_adequate( "1.112", "> 1.111")
+ assert_adequate( "0.2", "> 0.0.0")
+ assert_adequate( "0.0.0.0.0.2", "> 0.0.0")
+ assert_adequate( "0.0.1.0", "> 0.0.0.1")
+ assert_adequate( "10.3.2", "> 9.3.2")
+ assert_adequate( "1.0.0.0", "= 1.0")
+ assert_adequate( "10.3.2", "!= 9.3.4")
+ assert_adequate( "10.3.2", "> 9.3.2")
+ assert_adequate( "10.3.2", "> 9.3.2")
+ assert_adequate( " 9.3.2", ">= 9.3.2")
+ assert_adequate( "9.3.2 ", ">= 9.3.2")
+ assert_adequate( "", "= 0")
+ assert_adequate( "", "< 0.1")
+ assert_adequate( " ", "< 0.1 ")
+ assert_adequate( "", " < 0.1")
+ assert_adequate( "0", "=")
+ assert_adequate( "0", ">=")
+ assert_adequate( "0", "<=")
+ end
+
+ def test_satisfied_by_eh_boxed
+ assert_inadequate("1.3", "~> 1.4")
+ assert_adequate( "1.4", "~> 1.4")
+ assert_adequate( "1.5", "~> 1.4")
+ assert_inadequate("2.0", "~> 1.4")
+
+ assert_inadequate("1.3", "~> 1.4.4")
+ assert_inadequate("1.4", "~> 1.4.4")
+ assert_adequate( "1.4.4", "~> 1.4.4")
+ assert_adequate( "1.4.5", "~> 1.4.4")
+ assert_inadequate("1.5", "~> 1.4.4")
+ assert_inadequate("2.0", "~> 1.4.4")
+ end
+
+ def test_satisfied_by_eh_multiple
+ req = [">= 1.4", "<= 1.6", "!= 1.5"]
+ assert_inadequate("1.3", req)
+ assert_adequate( "1.4", req)
+ assert_inadequate("1.5", req)
+ assert_adequate( "1.6", req)
+ assert_inadequate("1.7", req)
+ assert_inadequate("2.0", req)
+ end
+
+ def test_spaceship
+ assert_equal 1, Gem::Version.new('1.8.2') <=> Gem::Version.new('0.0.0')
+ end
+
+ def test_boxed
+ assert_inadequate("1.3", "~> 1.4")
+ assert_adequate( "1.4", "~> 1.4")
+ assert_adequate( "1.5", "~> 1.4")
+ assert_inadequate("2.0", "~> 1.4")
+
+ assert_inadequate("1.3", "~> 1.4.4")
+ assert_inadequate("1.4", "~> 1.4.4")
+ assert_adequate( "1.4.4", "~> 1.4.4")
+ assert_adequate( "1.4.5", "~> 1.4.4")
+ assert_inadequate("1.5", "~> 1.4.4")
+ assert_inadequate("2.0", "~> 1.4.4")
+ end
+
+ def test_to_s
+ v = Gem::Version.new("5.2.4")
+ assert_equal "5.2.4", v.to_s
+ end
+
+ def assert_adequate(version, requirement)
+ ver = Gem::Version.new(version)
+ req = Gem::Requirement.new(requirement)
+ assert req.satisfied_by?(ver),
+ "Version #{version} should be adequate for Requirement #{requirement}"
+ end
+
+ def assert_inadequate(version, requirement)
+ ver = Gem::Version.new(version)
+ req = Gem::Version::Requirement.new(requirement)
+ assert ! req.satisfied_by?(ver),
+ "Version #{version} should not be adequate for Requirement #{requirement}"
+ end
+
+ def assert_version(actual)
+ assert_equal @v1_0, actual
+ assert_equal @v1_0.version, actual.version
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_gem_version_option.rb b/trunk/test/rubygems/test_gem_version_option.rb
new file mode 100644
index 0000000000..30c73390fe
--- /dev/null
+++ b/trunk/test/rubygems/test_gem_version_option.rb
@@ -0,0 +1,77 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/command'
+require 'rubygems/version_option'
+
+class TestGemVersionOption < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Command.new 'dummy', 'dummy'
+ @cmd.extend Gem::VersionOption
+ end
+
+ def test_add_platform_option
+ @cmd.add_platform_option
+
+ assert @cmd.handles?(%w[--platform x86-darwin])
+ end
+
+ def test_add_version_option
+ @cmd.add_version_option
+
+ assert @cmd.handles?(%w[--version >1])
+ end
+
+ def test_platform_option
+ @cmd.add_platform_option
+
+ @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd7]
+
+ expected = [
+ Gem::Platform::RUBY,
+ Gem::Platform.new('x86-freebsd6'),
+ Gem::Platform.new('x86-freebsd7'),
+ ]
+
+ assert_equal expected, Gem.platforms
+ end
+
+ def test_platform_option_ruby
+ @cmd.add_platform_option
+
+ @cmd.handle_options %w[--platform ruby]
+
+ expected = [
+ Gem::Platform::RUBY
+ ]
+
+ assert_equal expected, Gem.platforms
+ end
+
+ def test_platform_option_twice
+ @cmd.add_platform_option
+
+ @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd-6]
+
+ expected = [
+ Gem::Platform::RUBY,
+ Gem::Platform.new('x86-freebsd6'),
+ ]
+
+ assert_equal expected, Gem.platforms
+ end
+
+ def test_version_option
+ @cmd.add_version_option
+
+ @cmd.handle_options %w[--version >1]
+
+ expected = { :version => Gem::Requirement.new('> 1'), :args => [] }
+
+ assert_equal expected, @cmd.options
+ end
+
+end
+
diff --git a/trunk/test/rubygems/test_kernel.rb b/trunk/test/rubygems/test_kernel.rb
new file mode 100644
index 0000000000..da31d772eb
--- /dev/null
+++ b/trunk/test/rubygems/test_kernel.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+#--
+# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
+# All rights reserved.
+# See LICENSE.txt for permissions.
+#++
+
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/package'
+
+class TestKernel < RubyGemTestCase
+
+ def setup
+ super
+
+ @old_path = $:.dup
+
+ util_make_gems
+ end
+
+ def teardown
+ super
+
+ $:.replace @old_path
+ end
+
+ def test_gem
+ assert gem('a', '= 1'), "Should load"
+ assert $:.any? { |p| %r{a-1/lib} =~ p }
+ assert $:.any? { |p| %r{a-1/bin} =~ p }
+ end
+
+ def test_gem_redundent
+ assert gem('a', '= 1'), "Should load"
+ assert ! gem('a', '= 1'), "Should not load"
+ assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+ assert_equal 1, $:.select { |p| %r{a-1/bin} =~ p }.size
+ end
+
+ def test_gem_overlapping
+ assert gem('a', '= 1'), "Should load"
+ assert ! gem('a', '>= 1'), "Should not load"
+ assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+ assert_equal 1, $:.select { |p| %r{a-1/bin} =~ p }.size
+ end
+
+ def test_gem_conflicting
+ assert gem('a', '= 1'), "Should load"
+
+ ex = assert_raise Gem::Exception do
+ gem 'a', '= 2'
+ end
+
+ assert_match(/activate a \(= 2, runtime\)/, ex.message)
+ assert_match(/activated a-1/, ex.message)
+
+ assert $:.any? { |p| %r{a-1/lib} =~ p }
+ assert $:.any? { |p| %r{a-1/bin} =~ p }
+ assert ! $:.any? { |p| %r{a-2/lib} =~ p }
+ assert ! $:.any? { |p| %r{a-2/bin} =~ p }
+ end
+
+end
+
diff --git a/trunk/test/runner.rb b/trunk/test/runner.rb
new file mode 100644
index 0000000000..f9ed25a931
--- /dev/null
+++ b/trunk/test/runner.rb
@@ -0,0 +1,9 @@
+require 'rbconfig'
+exit if CROSS_COMPILING
+require 'test/unit'
+
+rcsid = %w$Id$
+Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
+Release = rcsid[3].freeze
+
+exit Test::Unit::AutoRunner.run(true, File.dirname($0))
diff --git a/trunk/test/scanf/data.txt b/trunk/test/scanf/data.txt
new file mode 100644
index 0000000000..302cfd0089
--- /dev/null
+++ b/trunk/test/scanf/data.txt
@@ -0,0 +1,6 @@
+this is 33 a fun
+little input file
+
+with
+
+characters
diff --git a/trunk/test/scanf/test_scanf.rb b/trunk/test/scanf/test_scanf.rb
new file mode 100644
index 0000000000..fe4ac507b4
--- /dev/null
+++ b/trunk/test/scanf/test_scanf.rb
@@ -0,0 +1,313 @@
+# $Id$
+#
+# scanf for Ruby
+#
+# Unit tests
+#
+
+require 'scanf.rb'
+require 'test/unit'
+require 'tmpdir'
+
+# Comment out either of these lines to skip those tests.
+
+class TestStringScanf < Test::Unit::TestCase;end
+class TestIOScanf < Test::Unit::TestCase;end
+
+module ScanfTests
+
+def tests
+ [
+
+# Scratchpad
+ [ "%2[a]", "nbc", []],
+ [ "%*d %*3d %*s", "123 +456 abc", [] ],
+ [ "%d%c", "123 x", [ 123, " " ] ],
+ [ "%d%c", "123x", [ 123, "x" ] ],
+ [ "%d %c", "123x", [ 123, "x" ] ],
+ [ "%d %c", "123 x", [ 123, "x" ] ],
+
+# Testing failures
+ [ "%x", "x", [] ],
+ [ "%2x", "x", [] ],
+ [ "%i", "x", [] ],
+# ]; end; def nothing; [
+ [ "%2i", "x", [] ],
+ [ "%2o", "x", [] ],
+ [ "%d", "x", [] ],
+ [ "%2d", "x", [] ],
+ [ "%3d", "+x3", [] ],
+ [ "%d%[abc]", "eabc", [] ],
+ [ "%d\n%[abc]", "\neabc", [] ],
+ [ "%d%[^abc]", "ghiabc", [ ] ],
+ [ "%d%[abc]", "abc", [] ],
+ [ "%*d %*3d %*s", "123 +456 abc", [] ],
+ [ "%d%s", "", [] ],
+ [ "%d%s", "blah 123 string", [] ],
+ [ "%[\n]", "abc\n", [] ],
+ [ "%[\n]", "abc\n", [] ],
+ [ "%[\n]", "abc\n", [] ],
+ [ "%f", "x", [] ],
+ [ "%f", "z", [] ],
+ [ "%f", "z3.2534", [] ],
+ [ "", "", [] ],
+ [ "", "abc 123", [] ],
+ [ '%[^\\w]%c', "a...1", [] ],
+
+# Testing 'x'
+ [ "%3x", "0xz", [0] ],
+
+# Testing 'i'
+ [ "%3i", "097", [0] ],
+ [ "%3i", "0xz", [0] ],
+ [ "%1i", "3", [ 3 ] ],
+ [ "%2i", "07", [ 7 ] ],
+ [ "%2i", "0a", [ 0 ] ],
+
+# Testing 'c'
+ [ "%3c", "abc", [ "abc" ] ],
+ [ "%3c", "a\nb", [ "a\nb" ] ],
+ [ "%3c", "a\nbcd", [ "a\nb" ] ],
+ [ "%c\n\n", "x\n\n", [ "x" ] ],
+ [ "%c\n\n", "x\n\n", [ "x" ] ],
+ [ "%c", "\n", [ "\n" ] ],
+ [ "%c", "x\n", [ "x" ] ],
+ [ "%2c", " 123", [" 1"] ],
+ [ " %c", " x", ["x"] ],
+ [ "%c", " x", [" "] ],
+ [ "%c", "123", ["1"] ],
+ [ "%2c", "123", ["12"] ],
+ [ "%5c", "a\nb\n\n", [ "a\nb\n\n" ] ],
+ [ "%6c", "a\nb\n\nx", [ "a\nb\n\nx" ] ],
+ [ "%5c", "ab\ncd", [ "ab\ncd" ] ],
+ [ "%5c", "a\nb\n\n", [ "a\nb\n\n" ] ],
+
+# Testing 'o'
+ [ "%3o", "0xz", [0] ],
+
+# Testing 'd'
+ [ "%d", "\n123", [ 123 ] ],
+ [ "%d", "\n\n123", [ 123 ] ],
+ [ "%d", "\n123", [ 123 ] ],
+ [ "%1d", "2", [2] ],
+
+# Mixed tests
+# Includes:
+# whitespace/newline
+# mixed integer bases
+# various mixed specifiers
+
+ [ "%[^\\w]%c", "...1", [ "...", "1"] ],
+ [ '%[^\\w]%c', "...1", [ "...", "1"] ],
+ [ "%[abc\n]%d", "a\n\nb\n\nc 123", [ "a\n\nb\n\nc", 123 ] ],
+ [ "%[abc\n]%d", "a\n\nb\n\nc \t 123", [ "a\n\nb\n\nc", 123 ] ],
+ [ "%[abc\t]%d", "a\t\tb\t\tc 123", [ "a\t\tb\t\tc", 123 ] ],
+ [ "%d%3[abc\n]", "123a\nbeaab", [ 123, "a\nb" ] ],
+ [ "%d%20c", "42 is the key", [ 42, " is the key" ] ],
+ [ "%d %20c", "42 is the key", [ 42, "is the key" ] ],
+ [ "%d%3[^abc\n]%d", "123de\nf123", [ 123, "de" ] ],
+ [ "%d %4c", "3abc", [ 3, "abc" ] ],
+ [ "%f%d\n%[abc]", "1\neabc", [1.0] ],
+ [ "%d%3[abc]", "123aaab", [ 123, "aaa" ] ],
+ [ "%d%3[abc]", "123 aaab", [ 123 ] ],
+ [ "%d%3[abc]", "123aeaab", [ 123, "a" ] ],
+ [ "%d%[^abc]", "123defabc", [123, "def" ] ],
+ [ "%d%3[^abc]", "123defdef", [ 123, "def" ] ],
+ [ "%d%3[^abc] ", "123defdef ", [ 123, "def" ] ],
+ [ "%d%3[^abc]ghi", "123defghi", [ 123, "def" ] ],
+ [ "%d%3[^abc]", "123defdef", [ 123, "def" ] ],
+ [ "%d%3[^abc]", "123adefdef", [ 123 ] ],
+ [ "%d%3[^abc]", "123deafdef", [ 123, "de" ] ],
+ [ "%d%3[^abc\n]", "123de\nf", [ 123, "de" ] ],
+ [ "%s%c%c%s", "abc\n\ndef", ["abc", "\n","\n", "def" ] ],
+ [ "%c%d", "\n\n123", [ "\n",123 ] ],
+ [ "%s%c%d", "abc\n123", [ "abc", "\n", 123 ] ],
+ [ "%s%c%d", "abc\n\n123", [ "abc", "\n", 123 ] ],
+ [ "%c%d", "\t\n123", [ "\t",123 ] ],
+ [ "%s%c%d", "abc\t\n123", [ "abc", "\t", 123 ] ],
+ [ "%3c%d", "abc123", [ "abc", 123 ] ],
+ [ "%3c\n%d", "abc123", [ "abc", 123 ] ],
+ [ "%3c\n%d", "abc 123", [ "abc", 123 ] ],
+ [ "%3c %d", "abc123", [ "abc", 123 ] ],
+ [ "%3c\t%d", "abc \n 123", [ "abc", 123 ] ],
+ [ "%3c\t%d", "abc \n 123 ", [ "abc", 123 ] ],
+ [ "%3c%d", "a\nb123", [ "a\nb", 123 ] ],
+ [ "%f%3c", "1.2x\ny", [ 1.2, "x\ny"] ],
+ [ "%d\n%d\n%d", "123 456 789", [ 123,456,789 ] ],
+ [ "%d\n%i%2d%x\n%d", "123 0718932", [ 123, 071, 89, 0x32] ],
+ [ "%c\n%c", "x y", [ "x", "y" ] ],
+ [ "%c\t%c", "x y", [ "x", "y" ] ],
+ [ "%s\n%s", "x y", [ "x", "y" ] ],
+ [ "%s%s\n", "x y", [ "x", "y" ] ],
+ [ "%c\n\n%c", "x\n\ny", [ "x", "y" ] ],
+ [ "%s%d%d", "abc\n123\n456", [ "abc", 123, 456 ] ],
+ [ "%3s%c%3c%d", "1.2x\n\ny123", [ "1.2", "x", "\n\ny", 123 ] ],
+ [ "%f%3c", "1.2x\ny", [ 1.2, "x\ny"] ],
+ [ "%c\n%c", "x\n\ny", [ "x", "y" ] ],
+ [ "%c\n\n%c", "x\n\ny", [ "x", "y" ] ],
+ [ "%c %c", "x\n\ny", [ "x", "y" ] ],
+ [ "%s\n\n%c", "x\n\ny", [ "x", "y" ] ],
+ [ "%s\n\n%s", "x\n\ny", [ "x", "y" ] ],
+ [ "%d\n\n%d", "23\n\n45", [ 23, 45 ] ],
+ [ "%d\n%d", "23\n\n45", [ 23, 45 ] ],
+ [ "%c\n\n%c", "x y", [ "x", "y" ] ],
+ [ "%c%c", "x\n\ny", [ "x", "\n" ] ],
+ [ "%c\n%c", "x y", [ "x", "y" ] ],
+ [ "%c\t%c", "x y", [ "x", "y" ] ],
+ [ "%s\n%s", "x y", [ "x", "y" ] ],
+ [ "%s%s\n", "x y", [ "x", "y" ] ],
+ [ "%c%c", "x\n", [ "x", "\n" ] ],
+ [ "%d%c%c%d", "345 678", [ 345, " ", " ", 678] ],
+ [ "%d %c%s", "123 x hello", [123, "x", "hello"] ],
+ [ "%d%2c", "654 123", [654," 1"] ],
+ [ "%5c%s", "a\nb\n\nxyz", [ "a\nb\n\n","xyz" ] ],
+ [ "%s%[ xyz]%d", "hello x 32", ["hello", " x ", 32] ],
+ [ "%5s%8[a-z]%d", "helloblahblah 32", ["hello", "blahblah", 32] ],
+ [ '%s%[abcde\\s]%d', "hello badea 32", ["hello", " badea ", 32] ],
+ [ '%d%[\\s]%c', "123 \n\t X", [ 123," \n\t ", "X"] ],
+ [ "%4s%2c%c", "1.2x\n\ny", [ "1.2x", "\n\n","y"] ],
+ [ "%f%c %3c%d", "1.2x\n\ny123", [ 1.2, "x", "y12", 3 ] ],
+ [ "%s%5c", "abc ab\ncd", [ "abc", " ab\nc" ] ],
+ [ "%5c%f", "ab\ncd1.2", [ "ab\ncd",1.2 ] ],
+ [ "%5c%c", "ab\ncd1", [ "ab\ncd","1" ] ],
+ [ "%f%c%2c%d", "1.2x\ny123", [ 1.2, "x", "\ny", 123 ] ],
+ [ "%f%c%3c", "1.2x\ny123", [ 1.2, "x", "\ny1"] ],
+ [ "%s\n%s", "blah\n\nand\nmore stuff", [ "blah", "and" ] ],
+ [ "%o%d%x", "21912a3", [ "21".oct, 912, "a3".hex ] ],
+ [ "%3o%4d%3x", "21912a3", [ "21".oct, 912, "a3".hex ] ],
+ [ "%3o%4d%5x", "2191240xa3", [ "21".oct, 9124, "a3".hex ] ],
+ [ "%3d%3x", "12abc", [12, "abc".hex] ],
+ [ "%s%i%d", "hello +0xdef 123", [ "hello", "def".hex, 123] ],
+ [ "%s%i%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%i%i%i%i", "hello 012 -012 100 1", [ "hello", 10, -10, 100, 1 ] ],
+ [ "%s%i%i%i%i", "hello 012 0x12 100 1", [ "hello", 10, 18, 100, 1 ] ],
+ [ "%s%5i%3i%4i", "hello 0x123 123 0123", [ "hello", "0x123".hex, 123,"0123".oct] ],
+ [ "%s%3i%4i", "hello 1230123", [ "hello", 123,"0123".oct] ],
+ [ "%s%3i", "hello 1230", [ "hello", 123] ],
+ [ "%s%5x%d", "hello 0xdef 123", [ "hello", "def".hex, 123] ],
+ [ "%s%6x%d", "hello +0xdef 123", [ "hello", "def".hex, 123] ],
+ [ "%s%6x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%6x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%4x%d", "hello -def 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%3x%d", "hello def 123", [ "hello", "def".hex, 123] ],
+ [ "%s%x%d", "hello -def 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+ [ "%s%x%d", "hello 0xdef 123", [ "hello", "def".hex, 123] ],
+ [ "%s%d%x%s", "hello 123 abc def", [ "hello", 123, "abc".hex, "def"] ],
+ [ "%s%d%o%d", "hello 012 012 100", [ "hello", 12, 10, 100 ] ],
+ [ "%s%d%o%d", "hello 012 -012 100", [ "hello", 12, -10, 100 ] ],
+ [ "%s%o%x%d", "hello 012 0x12 100", [ "hello", 10, 18, 100 ] ],
+ [ "%s%d%o%d", "hello 012 +01288", [ "hello", 12, 10, 88 ] ],
+ [ "%f %d %s", "12.3e23 45 string", ["12.3e23".to_f, 45, "string"] ],
+ [ "%f %d %s", "12.3e+23 45 string", ["12.3e23".to_f, 45, "string"] ],
+ [ "%f %d %s", "12.3e-23 45 string", ["12.3e-23".to_f, 45, "string"] ],
+ [ "%f %d %s", "12.3e23 45 string", ["12.3e23".to_f, 45, "string"] ],
+ [ "%f %d %s", "-12.3e-23 45 string", ["-12.3e-23".to_f, 45, "string"] ],
+ [ "%f %d %s", "12.e23 45 string", ["12.e23".to_f, 45, "string"] ],
+ [ "%5f %d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+ [ "%5f%d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+ [ "%5f%d %d %s", "1.2e23 45 string", ["1.2e2".to_f, 3, 45, "string"] ],
+ [ "%6f %d %d %s", "+1.2e23 45 string", ["1.2e2".to_f, 3, 45, "string"] ],
+ [ "%d %d", "123 \n 345", [123, 345] ],
+ [ "%d %*d", "123 \n 345", [123] ],
+ [ "%d %3d789", "123 +45789", [123, 45] ],
+ [ "%d %3d%d", "123 +456789", [123, 45, 6789] ],
+ [ "%d %3dabc", "123 456abc", [123, 456] ],
+ [ "%d %s", "123abc", [123, "abc"] ],
+ [ "%d%s %s", "123 abc def", [123, "abc", "def"] ],
+ [ "%s%s", "abc123 def", ["abc123", "def"] ],
+ [ "%s%s %s", "123 abc def", ["123", "abc", "def"] ],
+ [ "%s%%%s", "abc % def", ["abc", "def"] ],
+ [ "%d %3d %s", "+123 456abc", [123, 456, "abc"] ],
+ [ "%d %3d %s", "123 456abc", [123, 456, "abc"] ],
+ [ "%d %3d %s", "123 +456 abc", [123, 45, "6"] ],
+ [ "%d %3d %s", "-123-456abc", [-123, -45, "6abc"] ],
+ [ "%dabc%d", "123abc345", [123, 345] ],
+ [ "%d%5s%d", "123 abcde12", [123, "abcde", 12] ],
+ [ "%5d%5s%5d", "12345abcde67890", [12345, "abcde", 67890] ],
+ [ "%5d%*5s%5d", "12345abcde67890", [12345, 67890] ],
+ [ " 12345%5s%5d", "12345abcde67890", [ "abcde", 67890] ],
+ [ "%5dabcde%5d", "12345abcde67890", [ 12345, 67890] ],
+ [ "%s%%%*s", "abc % def", ["abc"] ],
+ [ "%*6s %d", "string 123", [123] ],
+ [ "%d %*3d %s", "-123-456abc", [-123, "6abc"] ],
+ [ "%d%s", "123", [123] ],
+ [ "%s%d", "abc", ["abc"] ],
+ [ "%f%x", "3.2e45x", ["3.2e45x".to_f] ],
+ [ "%s%d", "abc", ["abc"] ],
+ [ "%*5f%d %d %s", "1.2e23 45 string", [3, 45, "string"] ],
+ [ "%5f%*d %d %s", "1.2e23 45 string", ["1.2e2".to_f, 45, "string"] ],
+ [ "%*5f%*d %*d %s", "1.2e23 45 string", ["string"] ],
+ [ "%f %*d %s", "12.e23 45 string", ["12.e23".to_f, "string"] ],
+ [ "%5f %d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+ [ "%s %f %s %d %x%c%c%c%c",
+ "float: 1.2e23 dec/hex: 135a23 abc",
+ ["float:", "1.2e23".to_f, "dec/hex:", 135, "a23".hex, " ", "a", "b", "c" ] ],
+
+# Testing 's'
+ [ "%s\n", "blah\n\n\n", [ "blah" ] ],
+
+# Testing '['
+ [ "%[a\nb]", "a\nb", [ "a\nb" ] ],
+ [ "%[abc]", "acb", [ "acb" ] ],
+ [ "%[abc\n]", "a\nb", [ "a\nb" ] ],
+ [ "%[^abc]", "defabc", [ "def" ] ],
+ [ "%[-abc]", "abc-cba", [ "abc-cba" ] ],
+ [ "%[\n]", "\n", [ "\n" ] ],
+ [ "%[\n]", "\nabc", [ "\n" ] ],
+ [ "%[\n\t]", "\t\n", [ "\t\n" ] ],
+ [ "%[a-f]", "abczef", [ "abc" ] ],
+ [ "%d%3[abc]", "123 aaab", [ 123 ] ],
+ [ "%d%3[^abc]", "123adefdef", [ 123 ] ],
+ [ "%d%3[[:lower:]] %f", "123ade1.2", [ 123,"ade",1.2 ] ],
+ [ "%d%3[[:lower:]] %f", "123ad1.2", [ 123,"ad",1.2 ] ],
+ [ "%d%3[[:lower:]] %f", "123 ad1.2", [ 123 ] ],
+ [ "%d%[[:lower:]]", "123abcdef1.2", [ 123, "abcdef" ] ],
+ [ "%[[:lower:]]%d", "abcdef123", [ "abcdef", 123 ] ],
+ [ "%[[:digit:]]%[[:alpha:]]", "123abcdef", [ "123", "abcdef" ] ],
+ [ "%[[:digit:]]%d", "123 123", [ "123", 123 ] ],
+ [ "%[[:upper:]]", "ABCdefGHI", [ "ABC" ] ],
+
+# Testing 'f'
+ [ "%2f", "x", [0.0] ], # width-floats match anything (by design)
+ [ "%f", "1.23e45", [1.23e+45] ],
+ [ "%f", "3.25ee", [3.25] ],
+ [ "%f", "3..25", [3.0] ],
+ [ "%f", "+3.25", [3.25] ],
+ [ "%f", "+3.25e2", [325.0] ],
+ [ "%f", "3.z", [3.0] ],
+ ]
+ end
+ end
+
+class TestStringScanf
+ include Scanf
+ extend ScanfTests
+
+ i = 1
+ self.tests.each do |test|
+ define_method("test_#{i}") do ||
+ assert_equal(test[2], test[1].scanf(test[0]))
+ end
+ i += 1
+ end
+end
+
+class TestIOScanf
+ include Scanf
+ extend ScanfTests
+
+ tmpfilename = "#{Dir.tmpdir}/iotest.dat.#{$$}"
+
+ i = 1
+ self.tests.each do |test|
+ define_method("test_#{i}") do ||
+ File.open(tmpfilename, "w") {|fh| fh.print test[1]}
+ File.open(tmpfilename, "r") { |fh|
+ assert_equal(test[2], fh.scanf(test[0]))
+ }
+ File.delete(tmpfilename)
+ end
+ i += 1
+ end
+end
diff --git a/trunk/test/scanf/test_scanfblocks.rb b/trunk/test/scanf/test_scanfblocks.rb
new file mode 100644
index 0000000000..907a3c2838
--- /dev/null
+++ b/trunk/test/scanf/test_scanfblocks.rb
@@ -0,0 +1,81 @@
+# $Id$
+#
+# scanf for Ruby
+#
+# Some not very comprehensive tests of block behavior.
+
+
+require 'test/unit'
+require 'scanf'
+require 'tmpdir'
+
+class TestScanfBlock < Test::Unit::TestCase
+
+ def setup
+ @str = <<-EOS
+ Beethoven 1770
+ Bach 1685
+ Handel 1685
+ Scarlatti 1685
+ Brahms 1833
+ EOS
+ end
+
+alias set_up setup
+ def test_str1
+ res = @str.scanf("%s%d") { |name, year| "#{name} was born in #{year}." }
+ assert_equal(res,
+ [ "Beethoven was born in 1770.",
+ "Bach was born in 1685.",
+ "Handel was born in 1685.",
+ "Scarlatti was born in 1685.",
+ "Brahms was born in 1833." ])
+ end
+
+ def test_str2
+ names = @str.scanf("%s%d") { |name, year| name.upcase }
+ assert_equal(names, ["BEETHOVEN", "BACH", "HANDEL", "SCARLATTI", "BRAHMS"])
+ end
+
+ def test_str3
+ assert_equal("".scanf("%d%f%s") {}, [])
+ end
+
+ def test_str4
+ assert_equal("abc".scanf("%d%f%s") {}, [])
+ end
+
+ def test_str5
+ assert_equal("abc".scanf("") {}, [])
+ end
+
+ def test_io1
+ fn = "#{Dir.tmpdir}/iotest.dat.#{$$}"
+ File.open(fn, "w") { |fh| fh.puts(@str) }
+ fh = File.open(fn, "rb")
+ res = fh.scanf("%s%d") { |name, year| "#{name} was born in #{year}." }
+
+ assert_equal(
+ [ "Beethoven was born in 1770.",
+ "Bach was born in 1685.",
+ "Handel was born in 1685.",
+ "Scarlatti was born in 1685.",
+ "Brahms was born in 1833." ],res)
+ fh.close
+ ensure
+ File.delete(fn)
+ end
+
+ def test_io2
+ fn = "#{Dir.tmpdir}/iotest.dat.#{$$}"
+ File.open(fn, "w").close
+ fh = File.open(fn,"rb")
+ assert_equal(fh.scanf("") {}, [])
+ fh.seek(0)
+ assert_equal(fh.scanf("%d%f%s") {}, [])
+ fh.close
+ ensure
+ File.delete(fn)
+ end
+
+end
diff --git a/trunk/test/scanf/test_scanfio.rb b/trunk/test/scanf/test_scanfio.rb
new file mode 100644
index 0000000000..c8740aed43
--- /dev/null
+++ b/trunk/test/scanf/test_scanfio.rb
@@ -0,0 +1,19 @@
+# $Id$
+#
+# scanf for Ruby
+#
+# Ad hoc tests of IO#scanf (needs to be expanded)
+
+
+require "scanf"
+
+class TestScanfIO
+ def test_io
+ fh = File.new(File.join(File.dirname(__FILE__), "data.txt"), "r")
+ assert_equal(0, fh.pos)
+ assert_equal(["this", "is"], fh.scanf("%s%s"))
+ assert_equal([33, "littel"], fh.scanf("%da fun%s"))
+ #p fh.pos
+ end
+end
+
diff --git a/trunk/test/sdbm/test_sdbm.rb b/trunk/test/sdbm/test_sdbm.rb
new file mode 100644
index 0000000000..0c6df66fb2
--- /dev/null
+++ b/trunk/test/sdbm/test_sdbm.rb
@@ -0,0 +1,563 @@
+require 'test/unit'
+require 'tmpdir'
+
+begin
+ require 'sdbm'
+rescue LoadError
+end
+
+class TestSDBM < Test::Unit::TestCase
+ def setup
+ @tmpdir = Dir.mktmpdir("tmptest_sdbm")
+ @prefix = "tmptest_sdbm_#{$$}"
+ @path = "#{@tmpdir}/#{@prefix}_"
+ assert_instance_of(SDBM, @sdbm = SDBM.new(@path))
+ end
+ def teardown
+ assert_nil(@sdbm.close)
+ ObjectSpace.each_object(SDBM) do |obj|
+ obj.close unless obj.closed?
+ end
+ FileUtils.remove_entry_secure @tmpdir
+ end
+
+ def check_size(expect, sdbm=@sdbm)
+ assert_equal(expect, sdbm.size)
+ n = 0
+ sdbm.each { n+=1 }
+ assert_equal(expect, n)
+ if expect == 0
+ assert_equal(true, sdbm.empty?)
+ else
+ assert_equal(false, sdbm.empty?)
+ end
+ end
+
+ def have_fork?
+ begin
+ fork{}
+ true
+ rescue NotImplementedError
+ false
+ end
+ end
+
+ def test_version
+ assert(! SDBM.const_defined?(:VERSION))
+ end
+
+ def test_s_new_has_no_block
+ # SDBM.new ignore the block
+ foo = true
+ assert_instance_of(SDBM, sdbm = SDBM.new("#{@tmpdir}/#{@prefix}") { foo = false })
+ assert_equal(foo, true)
+ assert_nil(sdbm.close)
+ end
+ def test_s_open_no_create
+ assert_nil(sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", nil))
+ ensure
+ sdbm.close if sdbm
+ end
+ def test_s_open_with_block
+ assert_equal(SDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo)
+ end
+=begin
+ # Is it guaranteed on many OS?
+ def test_s_open_lock_one_process
+ # locking on one process
+ assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ assert_raise(Errno::EWOULDBLOCK) {
+ begin
+ SDBM.open("#{@tmpdir}/#{@prefix}", 0644)
+ rescue Errno::EAGAIN
+ raise Errno::EWOULDBLOCK
+ end
+ }
+ end
+=end
+
+ def test_s_open_nolock
+ # sdbm 1.8.0 specific
+ if not defined? SDBM::NOLOCK
+ return
+ end
+ return unless have_fork? # snip this test
+
+ pid = fork() {
+ assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ SDBM::NOLOCK))
+ sleep 2
+ }
+ sleep 1
+ begin
+ sdbm2 = nil
+ assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
+ assert_instance_of(SDBM, sdbm2 = SDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ }
+ ensure
+ Process.wait pid
+ sdbm2.close if sdbm2
+ end
+
+ p Dir.glob("#{@tmpdir}/#{@prefix}*") if $DEBUG
+
+ pid = fork() {
+ assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644))
+ sleep 2
+ }
+ begin
+ sleep 1
+ sdbm2 = nil
+ assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
+ # this test is failed on Cygwin98 (???)
+ assert_instance_of(SDBM, sdbm2 = SDBM.open("#{@tmpdir}/#{@prefix}", 0644,
+ SDBM::NOLOCK))
+ }
+ ensure
+ Process.wait pid
+ sdbm2.close if sdbm2
+ end
+ end
+
+ def test_s_open_error
+ assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0))
+ assert_raise(Errno::EACCES) {
+ SDBM.open("#{@tmpdir}/#{@prefix}", 0)
+ }
+ sdbm.close
+ end
+
+ def test_close
+ assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}"))
+ assert_nil(sdbm.close)
+
+ # closed SDBM file
+ assert_raise(SDBMError) { sdbm.close }
+ end
+
+ def test_aref
+ assert_equal('bar', @sdbm['foo'] = 'bar')
+ assert_equal('bar', @sdbm['foo'])
+
+ assert_nil(@sdbm['bar'])
+ end
+
+ def test_fetch
+ assert_equal('bar', @sdbm['foo']='bar')
+ assert_equal('bar', @sdbm.fetch('foo'))
+
+ # key not found
+ assert_raise(IndexError) {
+ @sdbm.fetch('bar')
+ }
+
+ # test for `ifnone' arg
+ assert_equal('baz', @sdbm.fetch('bar', 'baz'))
+
+ # test for `ifnone' block
+ assert_equal('foobar', @sdbm.fetch('bar') {|key| 'foo' + key })
+ end
+
+ def test_aset
+ num = 0
+ 2.times {|i|
+ assert_equal('foo', @sdbm['foo'] = 'foo')
+ assert_equal('foo', @sdbm['foo'])
+ assert_equal('bar', @sdbm['foo'] = 'bar')
+ assert_equal('bar', @sdbm['foo'])
+
+ num += 1 if i == 0
+ assert_equal(num, @sdbm.size)
+
+ # assign nil
+ assert_equal('', @sdbm['bar'] = '')
+ assert_equal('', @sdbm['bar'])
+
+ num += 1 if i == 0
+ assert_equal(num, @sdbm.size)
+
+ # empty string
+ assert_equal('', @sdbm[''] = '')
+ assert_equal('', @sdbm[''])
+
+ num += 1 if i == 0
+ assert_equal(num, @sdbm.size)
+
+ # Fixnum
+ assert_equal('200', @sdbm['100'] = '200')
+ assert_equal('200', @sdbm['100'])
+
+ num += 1 if i == 0
+ assert_equal(num, @sdbm.size)
+
+ # Big key and value
+ assert_equal('y' * 100, @sdbm['x' * 100] = 'y' * 100)
+ assert_equal('y' * 100, @sdbm['x' * 100])
+
+ num += 1 if i == 0
+ assert_equal(num, @sdbm.size)
+ }
+ end
+
+ def test_index
+ assert_equal('bar', @sdbm['foo'] = 'bar')
+ assert_equal('foo', @sdbm.index('bar'))
+ assert_nil(@sdbm['bar'])
+ end
+
+ def test_values_at
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+ assert_equal(values.reverse, @sdbm.values_at(*keys.reverse))
+ end
+
+ def test_select_with_block
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+ ret = @sdbm.select {|k,v|
+ assert_equal(k.upcase, v)
+ k != "bar"
+ }
+ assert_equal([['baz', 'BAZ'], ['foo', 'FOO']],
+ ret.sort)
+ end
+
+ def test_length
+ num = 10
+ assert_equal(0, @sdbm.size)
+ num.times {|i|
+ i = i.to_s
+ @sdbm[i] = i
+ }
+ assert_equal(num, @sdbm.size)
+
+ @sdbm.shift
+
+ assert_equal(num - 1, @sdbm.size)
+ end
+
+ def test_empty?
+ assert_equal(true, @sdbm.empty?)
+ @sdbm['foo'] = 'FOO'
+ assert_equal(false, @sdbm.empty?)
+ end
+
+ def test_each_pair
+ n = 0
+ @sdbm.each_pair { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ n = 0
+ ret = @sdbm.each_pair {|key, val|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@sdbm, ret)
+ end
+
+ def test_each_value
+ n = 0
+ @sdbm.each_value { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ n = 0
+ ret = @sdbm.each_value {|val|
+ assert_not_nil(key = @sdbm.index(val))
+ assert_not_nil(i = keys.index(key))
+ assert_equal(val, values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@sdbm, ret)
+ end
+
+ def test_each_key
+ n = 0
+ @sdbm.each_key { n += 1 }
+ assert_equal(0, n)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ n = 0
+ ret = @sdbm.each_key {|key|
+ assert_not_nil(i = keys.index(key))
+ assert_equal(@sdbm[key], values[i])
+
+ n += 1
+ }
+ assert_equal(keys.size, n)
+ assert_equal(@sdbm, ret)
+ end
+
+ def test_keys
+ assert_equal([], @sdbm.keys)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ assert_equal(keys.sort, @sdbm.keys.sort)
+ assert_equal(values.sort, @sdbm.values.sort)
+ end
+
+ def test_values
+ test_keys
+ end
+
+ def test_shift
+ assert_nil(@sdbm.shift)
+ assert_equal(0, @sdbm.size)
+
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ ret_keys = []
+ ret_values = []
+ while ret = @sdbm.shift
+ ret_keys.push ret[0]
+ ret_values.push ret[1]
+
+ assert_equal(keys.size - ret_keys.size, @sdbm.size)
+ end
+
+ assert_equal(keys.sort, ret_keys.sort)
+ assert_equal(values.sort, ret_values.sort)
+ end
+
+ def test_delete
+ keys = %w(foo bar baz)
+ values = %w(FOO BAR BAZ)
+ key = keys[1]
+
+ assert_nil(@sdbm.delete(key))
+ assert_equal(0, @sdbm.size)
+
+ @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
+
+ assert_equal('BAR', @sdbm.delete(key))
+ assert_nil(@sdbm[key])
+ assert_equal(2, @sdbm.size)
+
+ assert_nil(@sdbm.delete(key))
+ end
+ def test_delete_with_block
+ key = 'no called block'
+ @sdbm[key] = 'foo'
+ assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'})
+ assert_equal('no called block', key)
+ assert_equal(0, @sdbm.size)
+
+ key = 'no called block'
+ assert_equal(:blockval,
+ @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
+ assert_equal('called block', key)
+ assert_equal(0, @sdbm.size)
+ end
+
+ def test_delete_if
+ v = "0"
+ 100.times {@sdbm[v] = v; v = v.next}
+
+ ret = @sdbm.delete_if {|key, val| key.to_i < 50}
+ assert_equal(@sdbm, ret)
+ check_size(50, @sdbm)
+
+ ret = @sdbm.delete_if {|key, val| key.to_i >= 50}
+ assert_equal(@sdbm, ret)
+ check_size(0, @sdbm)
+
+ # break
+ v = "0"
+ 100.times {@sdbm[v] = v; v = v.next}
+ check_size(100, @sdbm)
+ n = 0;
+ @sdbm.delete_if {|key, val|
+ break if n > 50
+ n+=1
+ true
+ }
+ assert_equal(51, n)
+ check_size(49, @sdbm)
+
+ @sdbm.clear
+
+ # raise
+ v = "0"
+ 100.times {@sdbm[v] = v; v = v.next}
+ check_size(100, @sdbm)
+ n = 0;
+ begin
+ @sdbm.delete_if {|key, val|
+ raise "runtime error" if n > 50
+ n+=1
+ true
+ }
+ rescue
+ end
+ assert_equal(51, n)
+ check_size(49, @sdbm)
+ end
+
+ def test_reject
+ v = "0"
+ 100.times {@sdbm[v] = v; v = v.next}
+
+ hash = @sdbm.reject {|key, val| key.to_i < 50}
+ assert_instance_of(Hash, hash)
+ assert_equal(100, @sdbm.size)
+
+ assert_equal(50, hash.size)
+ hash.each_pair {|key,val|
+ assert_equal(false, key.to_i < 50)
+ assert_equal(key, val)
+ }
+
+ hash = @sdbm.reject {|key, val| key.to_i < 100}
+ assert_instance_of(Hash, hash)
+ assert_equal(true, hash.empty?)
+ end
+
+ def test_clear
+ v = "1"
+ 100.times {v = v.next; @sdbm[v] = v}
+
+ assert_equal(@sdbm, @sdbm.clear)
+
+ # validate SDBM#size
+ i = 0
+ @sdbm.each { i += 1 }
+ assert_equal(@sdbm.size, i)
+ assert_equal(0, i)
+ end
+
+ def test_invert
+ v = "0"
+ 100.times {@sdbm[v] = v; v = v.next}
+
+ hash = @sdbm.invert
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_update
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @sdbm["101"] = "101"
+ @sdbm.update hash
+ assert_equal(101, @sdbm.size)
+ @sdbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_replace
+ hash = {}
+ v = "0"
+ 100.times {v = v.next; hash[v] = v}
+
+ @sdbm["101"] = "101"
+ @sdbm.replace hash
+ assert_equal(100, @sdbm.size)
+ @sdbm.each_pair {|key, val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_haskey?
+ assert_equal('bar', @sdbm['foo']='bar')
+ assert_equal(true, @sdbm.has_key?('foo'))
+ assert_equal(false, @sdbm.has_key?('bar'))
+ end
+
+ def test_has_value?
+ assert_equal('bar', @sdbm['foo']='bar')
+ assert_equal(true, @sdbm.has_value?('bar'))
+ assert_equal(false, @sdbm.has_value?('foo'))
+ end
+
+ def test_to_a
+ v = "0"
+ 100.times {v = v.next; @sdbm[v] = v}
+
+ ary = @sdbm.to_a
+ assert_instance_of(Array, ary)
+ assert_equal(100, ary.size)
+ ary.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_to_hash
+ v = "0"
+ 100.times {v = v.next; @sdbm[v] = v}
+
+ hash = @sdbm.to_hash
+ assert_instance_of(Hash, hash)
+ assert_equal(100, hash.size)
+ hash.each {|key,val|
+ assert_equal(key.to_i, val.to_i)
+ }
+ end
+
+ def test_closed
+ assert_equal(false, @sdbm.closed?)
+ @sdbm.close
+ assert_equal(true, @sdbm.closed?)
+ @sdbm = SDBM.new(@path)
+ end
+
+ def test_index
+ assert_equal(nil, @sdbm.index("foo"))
+ @sdbm["bar"] = "foo"
+ assert_equal("bar", @sdbm.index("foo"))
+ end
+
+ def test_readonly
+ @sdbm["bar"] = "baz"
+ @sdbm.close
+ File.chmod(0444, @path + ".dir")
+ File.chmod(0444, @path + ".pag")
+ @sdbm = SDBM.new(@path)
+ assert_raise(SDBMError) { @sdbm["bar"] = "foo" }
+ assert_raise(SDBMError) { @sdbm.delete("bar") }
+ assert_raise(SDBMError) { @sdbm.delete_if { true } }
+ assert_raise(SDBMError) { @sdbm.clear }
+ assert_nil(@sdbm.store("bar", nil))
+ end
+
+ def test_update2
+ obj = Object.new
+ def obj.each_pair
+ yield []
+ end
+ assert_raise(ArgumentError) { @sdbm.update(obj) }
+ end
+end
+
diff --git a/trunk/test/socket/test_nonblock.rb b/trunk/test/socket/test_nonblock.rb
new file mode 100644
index 0000000000..ed6487b49f
--- /dev/null
+++ b/trunk/test/socket/test_nonblock.rb
@@ -0,0 +1,179 @@
+begin
+ require "socket"
+rescue LoadError
+end
+
+require "test/unit"
+require "tempfile"
+require "timeout"
+
+class TestNonblockSocket < Test::Unit::TestCase
+ def test_accept_nonblock
+ serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
+ serv.listen(5)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { serv.accept_nonblock }
+ c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ c.connect(serv.getsockname)
+ s, sockaddr = serv.accept_nonblock
+ assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr))
+ ensure
+ serv.close if serv
+ c.close if c
+ s.close if s
+ end
+
+ def test_connect_nonblock
+ serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
+ serv.listen(5)
+ c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ servaddr = serv.getsockname
+ begin
+ c.connect_nonblock(servaddr)
+ rescue Errno::EINPROGRESS
+ IO.select nil, [c]
+ assert_nothing_raised {
+ begin
+ c.connect_nonblock(servaddr)
+ rescue Errno::EISCONN
+ end
+ }
+ end
+ s, sockaddr = serv.accept
+ assert_equal(Socket.unpack_sockaddr_in(c.getsockname), Socket.unpack_sockaddr_in(sockaddr))
+ ensure
+ serv.close if serv
+ c.close if c
+ s.close if s
+ end
+
+ def test_udp_recvfrom_nonblock
+ u1 = UDPSocket.new
+ u2 = UDPSocket.new
+ u1.bind("127.0.0.1", 0)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recvfrom_nonblock(100) }
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { u2.recvfrom_nonblock(100) }
+ u2.send("aaa", 0, u1.getsockname)
+ IO.select [u1]
+ mesg, inet_addr = u1.recvfrom_nonblock(100)
+ assert_equal(4, inet_addr.length)
+ assert_equal("aaa", mesg)
+ af, port, host, addr = inet_addr
+ u2_port, u2_addr = Socket.unpack_sockaddr_in(u2.getsockname)
+ assert_equal(u2_port, port)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recvfrom_nonblock(100) }
+ u2.send("", 0, u1.getsockname)
+ assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
+ timeout(1) { IO.select [u1] }
+ }
+ mesg, inet_addr = u1.recvfrom_nonblock(100)
+ assert_equal("", mesg)
+ ensure
+ u1.close if u1
+ u2.close if u2
+ end
+
+ def test_udp_recv_nonblock
+ u1 = UDPSocket.new
+ u2 = UDPSocket.new
+ u1.bind("127.0.0.1", 0)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recv_nonblock(100) }
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { u2.recv_nonblock(100) }
+ u2.send("aaa", 0, u1.getsockname)
+ IO.select [u1]
+ mesg = u1.recv_nonblock(100)
+ assert_equal("aaa", mesg)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { u1.recv_nonblock(100) }
+ u2.send("", 0, u1.getsockname)
+ assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
+ timeout(1) { IO.select [u1] }
+ }
+ mesg = u1.recv_nonblock(100)
+ assert_equal("", mesg)
+ ensure
+ u1.close if u1
+ u2.close if u2
+ end
+
+ def test_socket_recvfrom_nonblock
+ s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ s1.bind(Socket.sockaddr_in(0, "127.0.0.1"))
+ s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s1.recvfrom_nonblock(100) }
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINVAL) { s2.recvfrom_nonblock(100) }
+ s2.send("aaa", 0, s1.getsockname)
+ IO.select [s1]
+ mesg, sockaddr = s1.recvfrom_nonblock(100)
+ assert_equal("aaa", mesg)
+ port, addr = Socket.unpack_sockaddr_in(sockaddr)
+ s2_port, s2_addr = Socket.unpack_sockaddr_in(s2.getsockname)
+ assert_equal(s2_port, port)
+ ensure
+ s1.close if s1
+ s2.close if s2
+ end
+
+ def tcp_pair
+ serv = TCPServer.new("127.0.0.1", 0)
+ af, port, host, addr = serv.addr
+ c = TCPSocket.new(addr, port)
+ s = serv.accept
+ return c, s
+ ensure
+ serv.close if serv
+ end
+
+ def test_tcp_recv_nonblock
+ c, s = tcp_pair
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { c.recv_nonblock(100) }
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.recv_nonblock(100) }
+ c.write("abc")
+ IO.select [s]
+ assert_equal("a", s.recv_nonblock(1))
+ assert_equal("bc", s.recv_nonblock(100))
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.recv_nonblock(100) }
+ ensure
+ c.close if c
+ s.close if s
+ end
+
+ def test_read_nonblock
+ c, s = tcp_pair
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { c.read_nonblock(100) }
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.read_nonblock(100) }
+ c.write("abc")
+ IO.select [s]
+ assert_equal("a", s.read_nonblock(1))
+ assert_equal("bc", s.read_nonblock(100))
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) { s.read_nonblock(100) }
+ ensure
+ c.close if c
+ s.close if s
+ end
+
+=begin
+ def test_write_nonblock
+ c, s = tcp_pair
+ str = "a" * 10000
+ _, ws, _ = IO.select(nil, [c], nil)
+ assert_equal([c], ws)
+ ret = c.write_nonblock(str)
+ assert_operator(ret, :>, 0)
+ loop {
+ assert_raise(Errno::EAGAIN, Errno::EWOULDBLOCK) {
+ loop {
+ ret = c.write_nonblock(str)
+ assert_operator(ret, :>, 0)
+ }
+ }
+ _, ws, _ = IO.select(nil, [c], nil, 0)
+ break if !ws
+ }
+ ensure
+ c.close if c
+ s.close if s
+ end
+=end
+
+end if defined?(Socket)
diff --git a/trunk/test/socket/test_socket.rb b/trunk/test/socket/test_socket.rb
new file mode 100644
index 0000000000..90f1037db8
--- /dev/null
+++ b/trunk/test/socket/test_socket.rb
@@ -0,0 +1,100 @@
+begin
+ require "socket"
+ require "test/unit"
+rescue LoadError
+end
+
+class TestBasicSocket < Test::Unit::TestCase
+ def inet_stream
+ sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ yield sock
+ ensure
+ assert_raise(IOError) {sock.close}
+ end
+
+ def test_getsockopt
+ inet_stream do |s|
+ n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
+ assert_equal([Socket::SOCK_STREAM].pack("i"), n)
+ n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ assert_equal([0].pack("i"), n)
+ val = Object.new
+ class << val; self end.send(:define_method, :to_int) {
+ s.close
+ Socket::SO_TYPE
+ }
+ assert_raise(IOError) {
+ n = s.getsockopt(Socket::SOL_SOCKET, val)
+ }
+ end
+ end
+
+ def test_setsockopt
+ s = nil
+ linger = [0, 0].pack("ii")
+
+ val = Object.new
+ class << val; self end.send(:define_method, :to_str) {
+ s.close
+ linger
+ }
+ inet_stream do |sock|
+ s = sock
+ assert_equal(0, s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger))
+
+ assert_raise(IOError, "[ruby-dev:25039]") {
+ s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, val)
+ }
+ end
+
+ val = Object.new
+ class << val; self end.send(:define_method, :to_int) {
+ s.close
+ Socket::SO_LINGER
+ }
+ inet_stream do |sock|
+ s = sock
+ assert_raise(IOError) {
+ s.setsockopt(Socket::SOL_SOCKET, val, linger)
+ }
+ end
+ end
+
+ def test_listen
+ s = nil
+ log = Object.new
+ class << log; self end.send(:define_method, :to_int) {
+ s.close
+ 2
+ }
+ inet_stream do |sock|
+ s = sock
+ assert_raise(IOError) {
+ s.listen(log)
+ }
+ end
+ end
+end if defined?(Socket)
+
+class TestSocket < Test::Unit::TestCase
+ def test_unpack_sockaddr
+ sockaddr_in = Socket.sockaddr_in(80, "")
+ assert_raise(ArgumentError) { Socket.unpack_sockaddr_un(sockaddr_in) }
+ sockaddr_un = Socket.sockaddr_un("/tmp/s")
+ assert_raise(ArgumentError) { Socket.unpack_sockaddr_in(sockaddr_un) }
+ end if Socket.respond_to?(:sockaddr_un)
+
+ def test_sysaccept
+ serv = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ serv.bind(Socket.sockaddr_in(0, "127.0.0.1"))
+ serv.listen 5
+ c = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ c.connect(serv.getsockname)
+ fd, peeraddr = serv.sysaccept
+ assert_equal(c.getsockname, peeraddr)
+ ensure
+ serv.close if serv
+ c.close if c
+ IO.for_fd(fd).close if fd
+ end
+end if defined?(Socket)
diff --git a/trunk/test/socket/test_tcp.rb b/trunk/test/socket/test_tcp.rb
new file mode 100644
index 0000000000..3aa7be82c3
--- /dev/null
+++ b/trunk/test/socket/test_tcp.rb
@@ -0,0 +1,24 @@
+begin
+ require "socket"
+ require "test/unit"
+rescue LoadError
+end
+
+
+class TestTCPSocket < Test::Unit::TestCase
+ def test_recvfrom
+assert false, "TODO: doesn't work on mswin32/64" if /mswin/ =~ RUBY_PLATFORM
+ svr = TCPServer.new("localhost", 0)
+ th = Thread.new {
+ c = svr.accept
+ c.write "foo"
+ c.close
+ }
+ addr = svr.addr
+ sock = TCPSocket.open(addr[2], addr[1])
+ assert_equal(["foo", nil], sock.recvfrom(0x10000))
+ ensure
+ th.kill
+ th.join
+ end
+end if defined?(TCPSocket)
diff --git a/trunk/test/socket/test_udp.rb b/trunk/test/socket/test_udp.rb
new file mode 100644
index 0000000000..d515ad4dbb
--- /dev/null
+++ b/trunk/test/socket/test_udp.rb
@@ -0,0 +1,32 @@
+begin
+ require "socket"
+ require "test/unit"
+rescue LoadError
+end
+
+
+class TestUDPSocket < Test::Unit::TestCase
+ def test_connect
+ s = UDPSocket.new
+ host = Object.new
+ class << host; self end.send(:define_method, :to_str) {
+ s.close
+ "127.0.0.1"
+ }
+ assert_raise(IOError, "[ruby-dev:25045]") {
+ s.connect(host, 1)
+ }
+ end
+
+ def test_bind
+ s = UDPSocket.new
+ host = Object.new
+ class << host; self end.send(:define_method, :to_str) {
+ s.close
+ "127.0.0.1"
+ }
+ assert_raise(IOError, "[ruby-dev:25057]") {
+ s.bind(host, 2000)
+ }
+ end
+end if defined?(UDPSocket)
diff --git a/trunk/test/socket/test_unix.rb b/trunk/test/socket/test_unix.rb
new file mode 100644
index 0000000000..58350c4486
--- /dev/null
+++ b/trunk/test/socket/test_unix.rb
@@ -0,0 +1,149 @@
+begin
+ require "socket"
+rescue LoadError
+end
+
+require "test/unit"
+require "tempfile"
+
+class TestUNIXSocket < Test::Unit::TestCase
+ def test_fd_passing
+ r1, w = IO.pipe
+ s1, s2 = UNIXSocket.pair
+ begin
+ s1.send_io(nil)
+ rescue NotImplementedError
+ assert_raise(NotImplementedError) { s2.recv_io }
+ rescue TypeError
+ s1.send_io(r1)
+ r2 = s2.recv_io
+ assert_equal(r1.stat.ino, r2.stat.ino)
+ assert_not_equal(r1.fileno, r2.fileno)
+ w.syswrite "a"
+ assert_equal("a", r2.sysread(10))
+ ensure
+ s1.close
+ s2.close
+ w.close
+ r1.close
+ r2.close if r2 && !r2.closed?
+ end
+ end
+
+ def bound_unix_socket(klass)
+ tmpfile = Tempfile.new("testrubysock")
+ path = tmpfile.path
+ tmpfile.close(true)
+ yield klass.new(path), path
+ ensure
+ File.unlink path if path && File.socket?(path)
+ end
+
+ def test_addr
+ bound_unix_socket(UNIXServer) {|serv, path|
+ c = UNIXSocket.new(path)
+ s = serv.accept
+ assert_equal(["AF_UNIX", path], c.peeraddr)
+ assert_equal(["AF_UNIX", ""], c.addr)
+ assert_equal(["AF_UNIX", ""], s.peeraddr)
+ assert_equal(["AF_UNIX", path], s.addr)
+ assert_equal(path, s.path)
+ assert_equal("", c.path)
+ }
+ end
+
+ def test_noname_path
+ s1, s2 = UNIXSocket.pair
+ assert_equal("", s1.path)
+ assert_equal("", s2.path)
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_noname_addr
+ s1, s2 = UNIXSocket.pair
+ assert_equal(["AF_UNIX", ""], s1.addr)
+ assert_equal(["AF_UNIX", ""], s2.addr)
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_noname_peeraddr
+ s1, s2 = UNIXSocket.pair
+ assert_equal(["AF_UNIX", ""], s1.peeraddr)
+ assert_equal(["AF_UNIX", ""], s2.peeraddr)
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_noname_unpack_sockaddr_un
+ s1, s2 = UNIXSocket.pair
+ n = nil
+ assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != ""
+ assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != ""
+ assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getsockname) != ""
+ assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getpeername) != ""
+ assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getpeername) != ""
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_noname_recvfrom
+ s1, s2 = UNIXSocket.pair
+ s2.write("a")
+ assert_equal(["a", ["AF_UNIX", ""]], s1.recvfrom(10))
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_noname_recv_nonblock
+ s1, s2 = UNIXSocket.pair
+ s2.write("a")
+ IO.select [s1]
+ assert_equal("a", s1.recv_nonblock(10))
+ ensure
+ s1.close
+ s2.close
+ end
+
+ def test_too_long_path
+ assert_raise(ArgumentError) { Socket.sockaddr_un("a" * 300) }
+ assert_raise(ArgumentError) { UNIXServer.new("a" * 300) }
+ end
+
+ def test_nul
+ assert_raise(ArgumentError) { Socket.sockaddr_un("a\0b") }
+ end
+
+ def test_dgram_pair
+ s1, s2 = UNIXSocket.pair(Socket::SOCK_DGRAM)
+ assert_raise(Errno::EAGAIN) { s1.recv_nonblock(10) }
+ s2.send("", 0)
+ s2.send("haha", 0)
+ s2.send("", 0)
+ s2.send("", 0)
+ assert_equal("", s1.recv(10))
+ assert_equal("haha", s1.recv(10))
+ assert_equal("", s1.recv(10))
+ assert_equal("", s1.recv(10))
+ assert_raise(Errno::EAGAIN) { s1.recv_nonblock(10) }
+ ensure
+ s1.close if s1
+ s2.close if s2
+ end
+
+ def test_epipe # [ruby-dev:34619]
+ s1, s2 = UNIXSocket.pair
+ s1.shutdown(Socket::SHUT_WR)
+ assert_raise(Errno::EPIPE) { s1.write "a" }
+ assert_equal(nil, s2.read(1))
+ s2.write "a"
+ assert_equal("a", s1.read(1))
+ end
+
+end if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM
diff --git a/trunk/test/stringio/test_stringio.rb b/trunk/test/stringio/test_stringio.rb
new file mode 100644
index 0000000000..8f0dc8702c
--- /dev/null
+++ b/trunk/test/stringio/test_stringio.rb
@@ -0,0 +1,382 @@
+require 'test/unit'
+require 'stringio'
+dir = File.expand_path(__FILE__)
+2.times {dir = File.dirname(dir)}
+$:.replace([File.join(dir, "ruby")] | $:)
+require 'ut_eof'
+
+class TestStringIO < Test::Unit::TestCase
+ include TestEOF
+ def open_file(content)
+ f = StringIO.new(content)
+ yield f
+ end
+ alias open_file_rw open_file
+
+ include TestEOF::Seek
+
+ def test_truncate
+ io = StringIO.new("")
+ io.puts "abc"
+ io.truncate(0)
+ io.puts "def"
+ assert_equal("\0\0\0\0def\n", io.string, "[ruby-dev:24190]")
+ assert_raise(Errno::EINVAL) { io.truncate(-1) }
+ io.truncate(10)
+ assert_equal("\0\0\0\0def\n\0\0", io.string)
+ end
+
+ def test_seek_beyond_eof
+ io = StringIO.new
+ n = 100
+ io.seek(n)
+ io.print "last"
+ assert_equal("\0" * n + "last", io.string, "[ruby-dev:24194]")
+ end
+
+ def test_overwrite
+ stringio = StringIO.new
+ responses = ['', 'just another ruby', 'hacker']
+ responses.each do |resp|
+ stringio.puts(resp)
+ stringio.rewind
+ end
+ assert_equal("hacker\nother ruby\n", stringio.string, "[ruby-core:3836]")
+ end
+
+ def test_gets
+ assert_equal(nil, StringIO.new("").gets)
+ assert_equal("\n", StringIO.new("\n").gets)
+ assert_equal("a\n", StringIO.new("a\n").gets)
+ assert_equal("a\n", StringIO.new("a\nb\n").gets)
+ assert_equal("a", StringIO.new("a").gets)
+ assert_equal("a\n", StringIO.new("a\nb").gets)
+ assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets)
+ assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil))
+ assert_equal("abc\n\n", StringIO.new("abc\n\ndef\n").gets(""))
+ end
+
+ def test_readlines
+ assert_equal([], StringIO.new("").readlines)
+ assert_equal(["\n"], StringIO.new("\n").readlines)
+ assert_equal(["a\n"], StringIO.new("a\n").readlines)
+ assert_equal(["a\n", "b\n"], StringIO.new("a\nb\n").readlines)
+ assert_equal(["a"], StringIO.new("a").readlines)
+ assert_equal(["a\n", "b"], StringIO.new("a\nb").readlines)
+ assert_equal(["abc\n", "\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines)
+ assert_equal(["abc\n\ndef\n"], StringIO.new("abc\n\ndef\n").readlines(nil), "[ruby-dev:34591]")
+ assert_equal(["abc\n\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines(""))
+ end
+
+ def test_write
+ s = ""
+ f = StringIO.new(s, "w")
+ f.print("foo")
+ f.close
+ assert_equal("foo", s)
+
+ f = StringIO.new(s, File::WRONLY)
+ f.print("bar")
+ f.close
+ assert_equal("bar", s)
+
+ f = StringIO.new(s, "a")
+ o = Object.new
+ def o.to_s; "baz"; end
+ f.print(o)
+ f.close
+ assert_equal("barbaz", s)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_mode_error
+ f = StringIO.new("", "r")
+ assert_raise(IOError) { f.write("foo") }
+
+ f = StringIO.new("", "w")
+ assert_raise(IOError) { f.read }
+
+ assert_raise(Errno::EACCES) { StringIO.new("".freeze, "w") }
+ s = ""
+ f = StringIO.new(s, "w")
+ s.freeze
+ assert_raise(IOError) { f.write("foo") }
+
+ assert_raise(IOError) { StringIO.allocate.read }
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_open
+ s = ""
+ StringIO.open("foo") {|f| s = f.read }
+ assert_equal("foo", s)
+ end
+
+ def test_isatty
+ assert_equal(false, StringIO.new("").isatty)
+ end
+
+ def test_path
+ assert_equal(nil, StringIO.new("").path)
+ end
+
+ def test_fsync
+ assert_equal(0, StringIO.new("").fsync)
+ end
+
+ def test_sync
+ assert_equal(true, StringIO.new("").sync)
+ assert_equal(false, StringIO.new("").sync = false)
+ end
+
+ def test_set_fcntl
+ assert_raise(NotImplementedError) { StringIO.new("").fcntl }
+ end
+
+ def test_close
+ f = StringIO.new("")
+ f.close
+ assert_raise(IOError) { f.close }
+
+ f = StringIO.new("")
+ f.close_read
+ f.close_write
+ assert_raise(IOError) { f.close }
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_close_read
+ f = StringIO.new("")
+ f.close_read
+ assert_raise(IOError) { f.read }
+ assert_raise(IOError) { f.close_read }
+ f.close
+
+ f = StringIO.new("", "w")
+ assert_raise(IOError) { f.close_read }
+ f.close
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_close_write
+ f = StringIO.new("")
+ f.close_write
+ assert_raise(IOError) { f.write("foo") }
+ assert_raise(IOError) { f.close_write }
+ f.close
+
+ f = StringIO.new("", "r")
+ assert_raise(IOError) { f.close_write }
+ f.close
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_closed
+ f = StringIO.new("")
+ assert_equal(false, f.closed?)
+ f.close
+ assert_equal(true, f.closed?)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_closed_read
+ f = StringIO.new("")
+ assert_equal(false, f.closed_read?)
+ f.close_write
+ assert_equal(false, f.closed_read?)
+ f.close_read
+ assert_equal(true, f.closed_read?)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_closed_write
+ f = StringIO.new("")
+ assert_equal(false, f.closed_write?)
+ f.close_read
+ assert_equal(false, f.closed_write?)
+ f.close_write
+ assert_equal(true, f.closed_write?)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_dup
+ f1 = StringIO.new("1234")
+ assert_equal("1", f1.getc)
+ f2 = f1.dup
+ assert_equal("2", f2.getc)
+ assert_equal("3", f1.getc)
+ assert_equal("4", f2.getc)
+ assert_equal(nil, f1.getc)
+ assert_equal(true, f2.eof?)
+ f1.close
+ assert_equal(true, f2.closed?)
+ ensure
+ f1.close unless f1.closed?
+ f2.close unless f2.closed?
+ end
+
+ def test_lineno
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal([0, "foo\n"], [f.lineno, f.gets])
+ assert_equal([1, "bar\n"], [f.lineno, f.gets])
+ f.lineno = 1000
+ assert_equal([1000, "baz\n"], [f.lineno, f.gets])
+ assert_equal([1001, nil], [f.lineno, f.gets])
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_pos
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal([0, "foo\n"], [f.pos, f.gets])
+ assert_equal([4, "bar\n"], [f.pos, f.gets])
+ assert_raise(Errno::EINVAL) { f.pos = -1 }
+ f.pos = 1
+ assert_equal([1, "oo\n"], [f.pos, f.gets])
+ assert_equal([4, "bar\n"], [f.pos, f.gets])
+ assert_equal([8, "baz\n"], [f.pos, f.gets])
+ assert_equal([12, nil], [f.pos, f.gets])
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_reopen
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal("foo\n", f.gets)
+ f.reopen("qux\nquux\nquuux\n")
+ assert_equal("qux\n", f.gets)
+
+ f2 = StringIO.new("")
+ f2.reopen(f)
+ assert_equal("quux\n", f2.gets)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_seek
+ f = StringIO.new("1234")
+ assert_raise(Errno::EINVAL) { f.seek(-1) }
+ f.seek(-1, 2)
+ assert_equal("4", f.getc)
+ assert_raise(Errno::EINVAL) { f.seek(1, 3) }
+ f.close
+ assert_raise(IOError) { f.seek(0) }
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_each_byte
+ f = StringIO.new("1234")
+ a = []
+ f.each_byte {|c| a << c }
+ assert_equal(%w(1 2 3 4).map {|c| c.ord }, a)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_getbyte
+ f = StringIO.new("1234")
+ assert_equal("1".ord, f.getbyte)
+ assert_equal("2".ord, f.getbyte)
+ assert_equal("3".ord, f.getbyte)
+ assert_equal("4".ord, f.getbyte)
+ assert_equal(nil, f.getbyte)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_ungetc
+ s = "1234"
+ f = StringIO.new(s, "r")
+ assert_nothing_raised { f.ungetc("x") }
+ assert_equal("x", f.getc) # bug?
+ assert_equal("1", f.getc)
+
+ s = "1234"
+ f = StringIO.new(s, "r")
+ assert_equal("1", f.getc)
+ f.ungetc("y".ord)
+ assert_equal("y", f.getc)
+ assert_equal("2", f.getc)
+ ensure
+ f.close unless f.closed?
+ end
+
+ def test_readchar
+ f = StringIO.new("1234")
+ a = ""
+ assert_raise(EOFError) { loop { a << f.readchar } }
+ assert_equal("1234", a)
+ end
+
+ def test_readbyte
+ f = StringIO.new("1234")
+ a = []
+ assert_raise(EOFError) { loop { a << f.readbyte } }
+ assert_equal("1234".unpack("C*"), a)
+ end
+
+ def test_each_char
+ f = StringIO.new("1234")
+ assert_equal(%w(1 2 3 4), f.each_char.to_a)
+ end
+
+ def test_gets2
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal("fo", f.gets(2))
+
+ o = Object.new
+ def o.to_str; "z"; end
+ assert_equal("o\nbar\nbaz", f.gets(o))
+
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal("foo\nbar\nbaz", f.gets("az"))
+ f = StringIO.new("a" * 10000 + "zz!")
+ assert_equal("a" * 10000 + "zz", f.gets("zz"))
+ f = StringIO.new("a" * 10000 + "zz!")
+ assert_equal("a" * 10000 + "zz!", f.gets("zzz"))
+ end
+
+ def test_each
+ f = StringIO.new("foo\nbar\nbaz\n")
+ assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)
+ end
+
+ def test_putc
+ s = ""
+ f = StringIO.new(s, "w")
+ f.putc("1")
+ f.putc("2")
+ f.putc("3")
+ f.close
+ assert_equal("123", s)
+
+ s = "foo"
+ f = StringIO.new(s, "a")
+ f.putc("1")
+ f.putc("2")
+ f.putc("3")
+ f.close
+ assert_equal("foo123", s)
+ end
+
+ def test_read
+ f = StringIO.new("1234")
+ assert_raise(ArgumentError) { f.read(-1) }
+ assert_raise(ArgumentError) { f.read(1, 2, 3) }
+ end
+
+ def test_size
+ f = StringIO.new("1234")
+ assert_equal(4, f.size)
+ end
+
+end
diff --git a/trunk/test/strscan/test_stringscanner.rb b/trunk/test/strscan/test_stringscanner.rb
new file mode 100644
index 0000000000..ff1eb7a298
--- /dev/null
+++ b/trunk/test/strscan/test_stringscanner.rb
@@ -0,0 +1,674 @@
+#
+# test/strscan/test_stringscanner.rb
+#
+
+require 'strscan'
+require 'test/unit'
+
+class TestStringScanner < Test::Unit::TestCase
+ def test_s_new
+ s = StringScanner.new('test string')
+ assert_instance_of StringScanner, s
+ assert_equal false, s.eos?
+ assert_equal false, s.tainted?
+
+ str = 'test string'
+ str.taint
+ s = StringScanner.new(str, false)
+ assert_instance_of StringScanner, s
+ assert_equal false, s.eos?
+ assert_same str, s.string
+ assert_equal true, s.string.tainted?
+
+ str = 'test string'
+ str.taint
+ s = StringScanner.new(str)
+ assert_equal true, s.string.tainted?
+ end
+
+ UNINIT_ERROR = ArgumentError
+
+ def test_s_allocate
+ s = StringScanner.allocate
+ assert_equal '#<StringScanner (uninitialized)>', s.inspect.sub(/StringScanner_C/, 'StringScanner')
+ assert_raises(UNINIT_ERROR) { s.eos? }
+ assert_raises(UNINIT_ERROR) { s.scan(/a/) }
+ s.string = 'test'
+ assert_equal '#<StringScanner 0/4 @ "test">', s.inspect.sub(/StringScanner_C/, 'StringScanner')
+ assert_nothing_raised(UNINIT_ERROR) { s.eos? }
+ assert_equal false, s.eos?
+ end
+
+ def test_s_mustc
+ assert_nothing_raised(NotImplementedError) {
+ StringScanner.must_C_version
+ }
+ end
+
+ def test_dup
+ s = StringScanner.new('test string')
+ d = s.dup
+ assert_equal s.inspect, d.inspect
+ assert_equal s.string, d.string
+ assert_equal s.pos, d.pos
+ assert_equal s.matched?, d.matched?
+ assert_equal s.eos?, d.eos?
+
+ s = StringScanner.new('test string')
+ s.scan(/test/)
+ d = s.dup
+ assert_equal s.inspect, d.inspect
+ assert_equal s.string, d.string
+ assert_equal s.pos, d.pos
+ assert_equal s.matched?, d.matched?
+ assert_equal s.eos?, d.eos?
+
+ s = StringScanner.new('test string')
+ s.scan(/test/)
+ s.scan(/NOT MATCH/)
+ d = s.dup
+ assert_equal s.inspect, d.inspect
+ assert_equal s.string, d.string
+ assert_equal s.pos, d.pos
+ assert_equal s.matched?, d.matched?
+ assert_equal s.eos?, d.eos?
+
+ s = StringScanner.new('test string')
+ s.terminate
+ d = s.dup
+ assert_equal s.inspect, d.inspect
+ assert_equal s.string, d.string
+ assert_equal s.pos, d.pos
+ assert_equal s.matched?, d.matched?
+ assert_equal s.eos?, d.eos?
+ end
+
+ def test_const_Version
+ assert_instance_of String, StringScanner::Version
+ assert_equal true, StringScanner::Version.frozen?
+ end
+
+ def test_const_Id
+ assert_instance_of String, StringScanner::Id
+ assert_equal true, StringScanner::Id.frozen?
+ end
+
+ def test_inspect
+ str = 'test string'
+ str.taint
+ s = StringScanner.new(str, false)
+ assert_instance_of String, s.inspect
+ assert_equal s.inspect, s.inspect
+ assert_equal '#<StringScanner 0/11 @ "test ...">', s.inspect.sub(/StringScanner_C/, 'StringScanner')
+ s.get_byte
+ assert_equal '#<StringScanner 1/11 "t" @ "est s...">', s.inspect.sub(/StringScanner_C/, 'StringScanner')
+ assert_equal true, s.inspect.tainted?
+
+ s = StringScanner.new("\n")
+ assert_equal '#<StringScanner 0/1 @ "\n">', s.inspect
+ end
+
+ def test_eos?
+ s = StringScanner.new('test string')
+ assert_equal false, s.eos?
+ assert_equal false, s.eos?
+ s.scan(/\w+/)
+ assert_equal false, s.eos?
+ assert_equal false, s.eos?
+ s.scan(/\s+/)
+ s.scan(/\w+/)
+ assert_equal true, s.eos?
+ assert_equal true, s.eos?
+ s.scan(/\w+/)
+ assert_equal true, s.eos?
+
+ s = StringScanner.new('test')
+ s.scan(/te/)
+ s.string.replace ''
+ assert_equal true, s.eos?
+ end
+
+ def test_bol?
+ s = StringScanner.new("a\nbbb\n\ncccc\nddd\r\neee")
+ assert_equal true, s.bol?
+ assert_equal true, s.bol?
+ s.scan(/a/)
+ assert_equal false, s.bol?
+ assert_equal false, s.bol?
+ s.scan(/\n/)
+ assert_equal true, s.bol?
+ s.scan(/b/)
+ assert_equal false, s.bol?
+ s.scan(/b/)
+ assert_equal false, s.bol?
+ s.scan(/b/)
+ assert_equal false, s.bol?
+ s.scan(/\n/)
+ assert_equal true, s.bol?
+ s.unscan
+ assert_equal false, s.bol?
+ s.scan(/\n/)
+ s.scan(/\n/)
+ assert_equal true, s.bol?
+ s.scan(/c+\n/)
+ assert_equal true, s.bol?
+ s.scan(/d+\r\n/)
+ assert_equal true, s.bol?
+ s.scan(/e+/)
+ assert_equal false, s.bol?
+ end
+
+ def test_string
+ s = StringScanner.new('test')
+ assert_equal 'test', s.string
+ s.string = 'a'
+ assert_equal 'a', s.string
+ s.scan(/a/)
+ s.string = 'b'
+ assert_equal 0, s.pos
+ end
+
+ def test_pos
+ s = StringScanner.new('test string')
+ assert_equal 0, s.pos
+ s.get_byte
+ assert_equal 1, s.pos
+ s.get_byte
+ assert_equal 2, s.pos
+ s.terminate
+ assert_equal 11, s.pos
+ end
+
+ def test_concat
+ s = StringScanner.new('a')
+ s.scan(/a/)
+ s.concat 'b'
+ assert_equal false, s.eos?
+ assert_equal 'b', s.scan(/b/)
+ assert_equal true, s.eos?
+ s.concat 'c'
+ assert_equal false, s.eos?
+ assert_equal 'c', s.scan(/c/)
+ assert_equal true, s.eos?
+ end
+
+ def test_scan
+ s = StringScanner.new('stra strb strc', true)
+ tmp = s.scan(/\w+/)
+ assert_equal 'stra', tmp
+ assert_equal false, tmp.tainted?
+
+ tmp = s.scan(/\s+/)
+ assert_equal ' ', tmp
+ assert_equal false, tmp.tainted?
+
+ assert_equal 'strb', s.scan(/\w+/)
+ assert_equal ' ', s.scan(/\s+/)
+
+ tmp = s.scan(/\w+/)
+ assert_equal 'strc', tmp
+ assert_equal false, tmp.tainted?
+
+ assert_nil s.scan(/\w+/)
+ assert_nil s.scan(/\w+/)
+
+
+ str = 'stra strb strc'
+ str.taint
+ s = StringScanner.new(str, false)
+ tmp = s.scan(/\w+/)
+ assert_equal 'stra', tmp
+ assert_equal true, tmp.tainted?
+
+ tmp = s.scan(/\s+/)
+ assert_equal ' ', tmp
+ assert_equal true, tmp.tainted?
+
+ assert_equal 'strb', s.scan(/\w+/)
+ assert_equal ' ', s.scan(/\s+/)
+
+ tmp = s.scan(/\w+/)
+ assert_equal 'strc', tmp
+ assert_equal true, tmp.tainted?
+
+ assert_nil s.scan(/\w+/)
+ assert_nil s.scan(/\w+/)
+
+ s = StringScanner.new('test')
+ s.scan(/te/)
+ # This assumes #string does not duplicate string,
+ # but it is implementation specific issue.
+ # DO NOT RELY ON THIS FEATURE.
+ s.string.replace ''
+ # unspecified: assert_equal 2, s.pos
+ assert_equal nil, s.scan(/test/)
+
+ # [ruby-bugs:4361]
+ s = StringScanner.new("")
+ assert_equal "", s.scan(//)
+ assert_equal "", s.scan(//)
+ end
+
+ def test_skip
+ s = StringScanner.new('stra strb strc', true)
+ assert_equal 4, s.skip(/\w+/)
+ assert_equal 1, s.skip(/\s+/)
+ assert_equal 4, s.skip(/\w+/)
+ assert_equal 1, s.skip(/\s+/)
+ assert_equal 4, s.skip(/\w+/)
+ assert_nil s.skip(/\w+/)
+ assert_nil s.skip(/\s+/)
+ assert_equal true, s.eos?
+
+ s = StringScanner.new('test')
+ s.scan(/te/)
+ s.string.replace ''
+ assert_equal nil, s.skip(/./)
+
+ # [ruby-bugs:4361]
+ s = StringScanner.new("")
+ assert_equal 0, s.skip(//)
+ assert_equal 0, s.skip(//)
+ end
+
+ def test_getch
+ s = StringScanner.new('abcde')
+ assert_equal 'a', s.getch
+ assert_equal 'b', s.getch
+ assert_equal 'c', s.getch
+ assert_equal 'd', s.getch
+ assert_equal 'e', s.getch
+ assert_nil s.getch
+
+ str = 'abc'
+ str.taint
+ s = StringScanner.new(str)
+ assert_equal true, s.getch.tainted?
+ assert_equal true, s.getch.tainted?
+ assert_equal true, s.getch.tainted?
+ assert_nil s.getch
+
+ s = StringScanner.new("\244\242".force_encoding("euc-jp"))
+ assert_equal "\244\242".force_encoding("euc-jp"), s.getch
+ assert_nil s.getch
+
+ s = StringScanner.new('test')
+ s.scan(/te/)
+ s.string.replace ''
+ assert_equal nil, s.getch
+ end
+
+ def test_get_byte
+ s = StringScanner.new('abcde')
+ assert_equal 'a', s.get_byte
+ assert_equal 'b', s.get_byte
+ assert_equal 'c', s.get_byte
+ assert_equal 'd', s.get_byte
+ assert_equal 'e', s.get_byte
+ assert_nil s.get_byte
+ assert_nil s.get_byte
+
+ str = 'abc'
+ str.taint
+ s = StringScanner.new(str)
+ assert_equal true, s.get_byte.tainted?
+ assert_equal true, s.get_byte.tainted?
+ assert_equal true, s.get_byte.tainted?
+ assert_nil s.get_byte
+
+ s = StringScanner.new("\244\242".force_encoding("euc-jp"))
+ assert_equal "\244".force_encoding("euc-jp"), s.get_byte
+ assert_equal "\242".force_encoding("euc-jp"), s.get_byte
+ assert_nil s.get_byte
+
+ s = StringScanner.new('test')
+ s.scan(/te/)
+ s.string.replace ''
+ assert_equal nil, s.get_byte
+ end
+
+ def test_matched
+ s = StringScanner.new('stra strb strc')
+ s.scan(/\w+/)
+ assert_equal 'stra', s.matched
+ assert_equal false, s.matched.tainted?
+ s.scan(/\s+/)
+ assert_equal ' ', s.matched
+ s.scan(/\w+/)
+ assert_equal 'strb', s.matched
+ s.scan(/\s+/)
+ assert_equal ' ', s.matched
+ s.scan(/\w+/)
+ assert_equal 'strc', s.matched
+ s.scan(/\w+/)
+ assert_nil s.matched
+ s.getch
+ assert_nil s.matched
+
+ s = StringScanner.new('stra strb strc')
+ s.getch
+ assert_equal 's', s.matched
+ assert_equal false, s.matched.tainted?
+ s.get_byte
+ assert_equal 't', s.matched
+ assert_equal 't', s.matched
+ assert_equal false, s.matched.tainted?
+
+ str = 'test'
+ str.taint
+ s = StringScanner.new(str)
+ s.scan(/\w+/)
+ assert_equal true, s.matched.tainted?
+ assert_equal true, s.matched.tainted?
+ end
+
+ def test_AREF
+ s = StringScanner.new('stra strb strc')
+
+ s.scan(/\w+/)
+ assert_nil s[-2]
+ assert_equal 'stra', s[-1]
+ assert_equal 'stra', s[0]
+ assert_nil s[1]
+
+ assert_equal false, s[-1].tainted?
+ assert_equal false, s[0].tainted?
+
+ s.skip(/\s+/)
+ assert_nil s[-2]
+ assert_equal ' ', s[-1]
+ assert_equal ' ', s[0]
+ assert_nil s[1]
+
+ s.scan(/(s)t(r)b/)
+ assert_nil s[-100]
+ assert_nil s[-4]
+ assert_equal 'strb', s[-3]
+ assert_equal 's', s[-2]
+ assert_equal 'r', s[-1]
+ assert_equal 'strb', s[0]
+ assert_equal 's', s[1]
+ assert_equal 'r', s[2]
+ assert_nil s[3]
+ assert_nil s[100]
+
+ s.scan(/\s+/)
+
+ s.getch
+ assert_nil s[-2]
+ assert_equal 's', s[-1]
+ assert_equal 's', s[0]
+ assert_nil s[1]
+
+ s.get_byte
+ assert_nil s[-2]
+ assert_equal 't', s[-1]
+ assert_equal 't', s[0]
+ assert_nil s[1]
+
+ s.scan(/.*/)
+ s.scan(/./)
+ assert_nil s[0]
+ assert_nil s[0]
+
+
+ s = StringScanner.new("\244\242".force_encoding("euc-jp"))
+ s.getch
+ assert_equal "\244\242".force_encoding("euc-jp"), s[0]
+
+ str = 'test'
+ str.taint
+ s = StringScanner.new(str)
+ s.scan(/(t)(e)(s)(t)/)
+ assert_equal true, s[0].tainted?
+ assert_equal true, s[1].tainted?
+ assert_equal true, s[2].tainted?
+ assert_equal true, s[3].tainted?
+ assert_equal true, s[4].tainted?
+ end
+
+ def test_pre_match
+ s = StringScanner.new('a b c d e')
+ s.scan(/\w/)
+ assert_equal '', s.pre_match
+ assert_equal false, s.pre_match.tainted?
+ s.skip(/\s/)
+ assert_equal 'a', s.pre_match
+ assert_equal false, s.pre_match.tainted?
+ s.scan(/\w/)
+ assert_equal 'a ', s.pre_match
+ s.scan_until(/c/)
+ assert_equal 'a b ', s.pre_match
+ s.getch
+ assert_equal 'a b c', s.pre_match
+ s.get_byte
+ assert_equal 'a b c ', s.pre_match
+ s.get_byte
+ assert_equal 'a b c d', s.pre_match
+ s.scan(/never match/)
+ assert_nil s.pre_match
+
+ str = 'test string'
+ str.taint
+ s = StringScanner.new(str)
+ s.scan(/\w+/)
+ assert_equal true, s.pre_match.tainted?
+ s.scan(/\s+/)
+ assert_equal true, s.pre_match.tainted?
+ s.scan(/\w+/)
+ assert_equal true, s.pre_match.tainted?
+ end
+
+ def test_post_match
+ s = StringScanner.new('a b c d e')
+ s.scan(/\w/)
+ assert_equal ' b c d e', s.post_match
+ s.skip(/\s/)
+ assert_equal 'b c d e', s.post_match
+ s.scan(/\w/)
+ assert_equal ' c d e', s.post_match
+ s.scan_until(/c/)
+ assert_equal ' d e', s.post_match
+ s.getch
+ assert_equal 'd e', s.post_match
+ s.get_byte
+ assert_equal ' e', s.post_match
+ s.get_byte
+ assert_equal 'e', s.post_match
+ s.scan(/never match/)
+ assert_nil s.post_match
+ s.scan(/./)
+ assert_equal '', s.post_match
+ s.scan(/./)
+ assert_nil s.post_match
+
+ str = 'test string'
+ str.taint
+ s = StringScanner.new(str)
+ s.scan(/\w+/)
+ assert_equal true, s.post_match.tainted?
+ s.scan(/\s+/)
+ assert_equal true, s.post_match.tainted?
+ s.scan(/\w+/)
+ assert_equal true, s.post_match.tainted?
+ end
+
+ def test_terminate
+ s = StringScanner.new('ssss')
+ s.getch
+ s.terminate
+ assert_equal true, s.eos?
+ s.terminate
+ assert_equal true, s.eos?
+ end
+
+ def test_reset
+ s = StringScanner.new('ssss')
+ s.getch
+ s.reset
+ assert_equal 0, s.pos
+ s.scan(/\w+/)
+ s.reset
+ assert_equal 0, s.pos
+ s.reset
+ assert_equal 0, s.pos
+ end
+
+ def test_matched_size
+ s = StringScanner.new('test string')
+ assert_nil s.matched_size
+ s.scan(/test/)
+ assert_equal 4, s.matched_size
+ assert_equal 4, s.matched_size
+ s.scan(//)
+ assert_equal 0, s.matched_size
+ s.scan(/x/)
+ assert_nil s.matched_size
+ assert_nil s.matched_size
+ s.terminate
+ assert_nil s.matched_size
+
+ # obsolete
+ s = StringScanner.new('test string')
+ assert_nil s.matchedsize
+ s.scan(/test/)
+ assert_equal 4, s.matched_size
+ s.terminate
+ assert_nil s.matched_size
+ end
+
+ def test_encoding
+ ss = StringScanner.new("\xA1\xA2".force_encoding("euc-jp"))
+ assert_equal(Encoding::EUC_JP, ss.scan(/./e).encoding)
+ end
+
+ def test_generic_regexp
+ ss = StringScanner.new("\xA1\xA2".force_encoding("euc-jp"))
+ t = ss.scan(/./)
+ assert_equal("\xa1\xa2".force_encoding("euc-jp"), t)
+ end
+
+ def test_set_pos
+ s = StringScanner.new("test string")
+ s.pos = 7
+ assert_equal("ring", s.rest)
+ end
+
+ def test_match_p
+ s = StringScanner.new("test string")
+ assert_equal(4, s.match?(/\w+/))
+ assert_equal(4, s.match?(/\w+/))
+ assert_equal(nil, s.match?(/\s+/))
+ end
+
+ def test_check
+ s = StringScanner.new("Foo Bar Baz")
+ assert_equal("Foo", s.check(/Foo/))
+ assert_equal(0, s.pos)
+ assert_equal("Foo", s.matched)
+ assert_equal(nil, s.check(/Bar/))
+ assert_equal(nil, s.matched)
+ end
+
+ def test_scan_full
+ s = StringScanner.new("Foo Bar Baz")
+ assert_equal(4, s.scan_full(/Foo /, false, false))
+ assert_equal(0, s.pos)
+ assert_equal(nil, s.scan_full(/Baz/, false, false))
+ assert_equal("Foo ", s.scan_full(/Foo /, false, true))
+ assert_equal(0, s.pos)
+ assert_equal(nil, s.scan_full(/Baz/, false, false))
+ assert_equal(4, s.scan_full(/Foo /, true, false))
+ assert_equal(4, s.pos)
+ assert_equal(nil, s.scan_full(/Baz /, false, false))
+ assert_equal("Bar ", s.scan_full(/Bar /, true, true))
+ assert_equal(8, s.pos)
+ assert_equal(nil, s.scan_full(/az/, false, false))
+ end
+
+ def test_exist_p
+ s = StringScanner.new("test string")
+ assert_equal(3, s.exist?(/s/))
+ assert_equal(0, s.pos)
+ s.scan(/test/)
+ assert_equal(2, s.exist?(/s/))
+ assert_equal(4, s.pos)
+ assert_equal(nil, s.exist?(/e/))
+ end
+
+ def test_skip_until
+ s = StringScanner.new("Foo Bar Baz")
+ assert_equal(3, s.skip_until(/Foo/))
+ assert_equal(3, s.pos)
+ assert_equal(4, s.skip_until(/Bar/))
+ assert_equal(7, s.pos)
+ assert_equal(nil, s.skip_until(/Qux/))
+ end
+
+ def test_check_until
+ s = StringScanner.new("Foo Bar Baz")
+ assert_equal("Foo", s.check_until(/Foo/))
+ assert_equal(0, s.pos)
+ assert_equal("Foo Bar", s.check_until(/Bar/))
+ assert_equal(0, s.pos)
+ assert_equal(nil, s.check_until(/Qux/))
+ end
+
+ def test_search_full
+ s = StringScanner.new("Foo Bar Baz")
+ assert_equal(8, s.search_full(/Bar /, false, false))
+ assert_equal(0, s.pos)
+ assert_equal("Foo Bar ", s.search_full(/Bar /, false, true))
+ assert_equal(0, s.pos)
+ assert_equal(8, s.search_full(/Bar /, true, false))
+ assert_equal(8, s.pos)
+ assert_equal("Baz", s.search_full(/az/, true, true))
+ assert_equal(11, s.pos)
+ end
+
+ def test_peek
+ s = StringScanner.new("test string")
+ assert_equal("test st", s.peek(7))
+ assert_equal("test st", s.peek(7))
+ s.scan(/test/)
+ assert_equal(" stri", s.peek(5))
+ assert_equal(" string", s.peek(10))
+ s.scan(/ string/)
+ assert_equal("", s.peek(10))
+ end
+
+ def test_unscan
+ s = StringScanner.new('test string')
+ assert_equal("test", s.scan(/\w+/))
+ s.unscan
+ assert_equal("te", s.scan(/../))
+ assert_equal(nil, s.scan(/\d/))
+ assert_raise(ScanError) { s.unscan }
+ end
+
+ def test_rest
+ s = StringScanner.new('test string')
+ assert_equal("test string", s.rest)
+ s.scan(/test/)
+ assert_equal(" string", s.rest)
+ s.scan(/ string/)
+ assert_equal("", s.rest)
+ s.scan(/ string/)
+ end
+
+ def test_rest_size
+ s = StringScanner.new('test string')
+ assert_equal(11, s.rest_size)
+ s.scan(/test/)
+ assert_equal(7, s.rest_size)
+ s.scan(/ string/)
+ assert_equal(0, s.rest_size)
+ s.scan(/ string/)
+ end
+
+ def test_inspect
+ s = StringScanner.new('test string test')
+ s.scan(/test strin/)
+ assert_equal('#<StringScanner 10/16 "...strin" @ "g tes...">', s.inspect)
+ end
+end
diff --git a/trunk/test/test_delegate.rb b/trunk/test/test_delegate.rb
new file mode 100644
index 0000000000..42abbb6f81
--- /dev/null
+++ b/trunk/test/test_delegate.rb
@@ -0,0 +1,20 @@
+require 'test/unit'
+require 'delegate'
+
+class TestDelegateClass < Test::Unit::TestCase
+ module M
+ attr_reader :m
+ end
+
+ def test_extend
+ obj = DelegateClass(Array).new([])
+ obj.instance_eval { @m = :m }
+ obj.extend M
+ assert_equal(:m, obj.m, "[ruby-dev:33116]")
+ end
+
+ def test_systemcallerror_eq
+ e = SystemCallError.new(0)
+ assert((SimpleDelegator.new(e) == e) == (e == SimpleDelegator.new(e)), "[ruby-dev:34808]")
+ end
+end
diff --git a/trunk/test/test_ipaddr.rb b/trunk/test/test_ipaddr.rb
new file mode 100644
index 0000000000..604ce93caa
--- /dev/null
+++ b/trunk/test/test_ipaddr.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest__END__part(target)
diff --git a/trunk/test/test_pp.rb b/trunk/test/test_pp.rb
new file mode 100644
index 0000000000..981fedd98f
--- /dev/null
+++ b/trunk/test/test_pp.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest(target)
diff --git a/trunk/test/test_prettyprint.rb b/trunk/test/test_prettyprint.rb
new file mode 100644
index 0000000000..981fedd98f
--- /dev/null
+++ b/trunk/test/test_prettyprint.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest(target)
diff --git a/trunk/test/test_pstore.rb b/trunk/test/test_pstore.rb
new file mode 100644
index 0000000000..678ffa4a62
--- /dev/null
+++ b/trunk/test/test_pstore.rb
@@ -0,0 +1,74 @@
+require 'test/unit'
+require 'pstore'
+
+class PStoreTest < Test::Unit::TestCase
+ def setup
+ @pstore_file = "pstore.tmp.#{Process.pid}"
+ @pstore = PStore.new(@pstore_file)
+ end
+
+ def teardown
+ File.unlink(@pstore_file) rescue nil
+ end
+
+ def test_opening_new_file_in_readonly_mode_should_result_in_empty_values
+ @pstore.transaction(true) do
+ assert_nil @pstore[:foo]
+ assert_nil @pstore[:bar]
+ end
+ end
+
+ def test_opening_new_file_in_readwrite_mode_should_result_in_empty_values
+ @pstore.transaction do
+ assert_nil @pstore[:foo]
+ assert_nil @pstore[:bar]
+ end
+ end
+
+ def test_data_should_be_loaded_correctly_when_in_readonly_mode
+ @pstore.transaction do
+ @pstore[:foo] = "bar"
+ end
+ @pstore.transaction(true) do
+ assert_equal "bar", @pstore[:foo]
+ end
+ end
+
+ def test_data_should_be_loaded_correctly_when_in_readwrite_mode
+ @pstore.transaction do
+ @pstore[:foo] = "bar"
+ end
+ @pstore.transaction do
+ assert_equal "bar", @pstore[:foo]
+ end
+ end
+
+ def test_changes_after_commit_are_discarded
+ @pstore.transaction do
+ @pstore[:foo] = "bar"
+ @pstore.commit
+ @pstore[:foo] = "baz"
+ end
+ @pstore.transaction(true) do
+ assert_equal "bar", @pstore[:foo]
+ end
+ end
+
+ def test_changes_are_not_written_on_abort
+ @pstore.transaction do
+ @pstore[:foo] = "bar"
+ @pstore.abort
+ end
+ @pstore.transaction(true) do
+ assert_nil @pstore[:foo]
+ end
+ end
+
+ def test_writing_inside_readonly_transaction_raises_error
+ assert_raise(PStore::Error) do
+ @pstore.transaction(true) do
+ @pstore[:foo] = "bar"
+ end
+ end
+ end
+end
diff --git a/trunk/test/test_set.rb b/trunk/test/test_set.rb
new file mode 100644
index 0000000000..604ce93caa
--- /dev/null
+++ b/trunk/test/test_set.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest__END__part(target)
diff --git a/trunk/test/test_shellwords.rb b/trunk/test/test_shellwords.rb
new file mode 100644
index 0000000000..ddb2d870b0
--- /dev/null
+++ b/trunk/test/test_shellwords.rb
@@ -0,0 +1,39 @@
+require 'test/unit'
+require 'shellwords'
+
+class TestShellwords < Test::Unit::TestCase
+
+ include Shellwords
+
+ def setup
+ @not_string = Class.new
+ @cmd = "ruby my_prog.rb | less"
+ end
+
+
+ def test_string
+ assert_instance_of(Array, shellwords(@cmd))
+ assert_equal(4, shellwords(@cmd).length)
+ end
+
+ def test_unmatched_double_quote
+ bad_cmd = 'one two "three'
+ assert_raises ArgumentError do
+ shellwords(bad_cmd)
+ end
+ end
+
+ def test_unmatched_single_quote
+ bad_cmd = "one two 'three"
+ assert_raises ArgumentError do
+ shellwords(bad_cmd)
+ end
+ end
+
+ def test_unmatched_quotes
+ bad_cmd = "one '"'"''""'""
+ assert_raises ArgumentError do
+ shellwords(bad_cmd)
+ end
+ end
+end
diff --git a/trunk/test/test_singleton.rb b/trunk/test/test_singleton.rb
new file mode 100644
index 0000000000..bd11095cf2
--- /dev/null
+++ b/trunk/test/test_singleton.rb
@@ -0,0 +1,15 @@
+require 'test/unit'
+require 'singleton'
+
+class TestSingleton < Test::Unit::TestCase
+ class C
+ include Singleton
+ end
+
+ def test_marshal
+ o1 = C.instance
+ m = Marshal.dump(o1)
+ o2 = Marshal.load(m)
+ assert_same(o1, o2)
+ end
+end
diff --git a/trunk/test/test_tempfile.rb b/trunk/test/test_tempfile.rb
new file mode 100644
index 0000000000..c4234e551d
--- /dev/null
+++ b/trunk/test/test_tempfile.rb
@@ -0,0 +1,14 @@
+require 'test/unit'
+require 'tempfile'
+
+class TestTempfile < Test::Unit::TestCase
+ module M
+ end
+
+ def test_extend
+ o = Tempfile.new("foo")
+ o.extend M
+ assert(M === o, "[ruby-dev:32932]")
+ end
+end
+
diff --git a/trunk/test/test_time.rb b/trunk/test/test_time.rb
new file mode 100644
index 0000000000..981fedd98f
--- /dev/null
+++ b/trunk/test/test_time.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest(target)
diff --git a/trunk/test/test_timeout.rb b/trunk/test/test_timeout.rb
new file mode 100644
index 0000000000..dfa863b373
--- /dev/null
+++ b/trunk/test/test_timeout.rb
@@ -0,0 +1,13 @@
+require 'test/unit'
+require 'timeout'
+require 'thread'
+
+class TestTimeout < Test::Unit::TestCase
+ def test_queue
+ q = Queue.new
+ assert_raise(Timeout::Error, "[ruby-dev:32935]") {
+ timeout(0.1) { q.pop }
+ }
+ end
+end
+
diff --git a/trunk/test/test_tsort.rb b/trunk/test/test_tsort.rb
new file mode 100644
index 0000000000..981fedd98f
--- /dev/null
+++ b/trunk/test/test_tsort.rb
@@ -0,0 +1,4 @@
+require 'pathname'
+require Pathname.new(__FILE__).dirname.join('inlinetest.rb')
+target = __FILE__[/test_(.*\.rb)$/, 1]
+InlineTest.loadtest(target)
diff --git a/trunk/test/testunit/collector/test_dir.rb b/trunk/test/testunit/collector/test_dir.rb
new file mode 100644
index 0000000000..eb61f9e6b5
--- /dev/null
+++ b/trunk/test/testunit/collector/test_dir.rb
@@ -0,0 +1,411 @@
+require 'test/unit'
+require 'test/unit/collector/dir'
+require 'pp'
+
+module Test
+ module Unit
+ module Collector
+ class TestDir < TestCase
+ class FileSystem
+ class Directory
+ def initialize(name, fs, parent=self, &block)
+ @name = name
+ @fs = fs
+ @parent = parent
+ @contents = {'.' => self, '..' => parent}
+ instance_eval(&block) if(block)
+ end
+
+ def file(name, contents)
+ @contents[name] = contents
+ end
+
+ def dir(name, &block)
+ @contents[name] = self.class.new(name, @fs, self, &block)
+ end
+
+ def entries
+ @contents.keys
+ end
+
+ def directory?(name)
+ return true if(name.nil? || name.empty?)
+ return false unless(@contents.include?(name))
+ @contents[name].kind_of?(self.class)
+ end
+
+ def file?(name)
+ return false unless(@contents.include?(name))
+ !directory?(name)
+ end
+
+ def exist?(name)
+ @contents.include?(name)
+ end
+
+ def [](name)
+ raise Errno::ENOENT, name unless(@contents.include?(name))
+ @contents[name]
+ end
+
+ def path_to(name=nil)
+ if(!name)
+ @parent.path_to(@name)
+ elsif(@parent == self)
+ @fs.join('/', name)
+ else
+ @fs.join(@parent.path_to(@name), name)
+ end
+ end
+ end
+
+ class ObjectSpace
+ def initialize
+ @objects = []
+ end
+
+ def each_object(klass, &block)
+ @objects.find_all{|o| o.kind_of?(klass)}.each(&block)
+ end
+
+ def <<(object)
+ @objects << object
+ end
+ end
+
+ attr_reader :object_space
+
+ def initialize(&block)
+ @root = Directory.new('/', self, &block)
+ @pwd = @root
+ @object_space = ObjectSpace.new
+ @required = []
+ end
+
+ def entries(dir)
+ e = find(dir)
+ require_directory(dir)
+ e.entries
+ end
+
+ def directory?(name)
+ return true if (base = basename(name)) == '/'
+ e = find(dirname(name))
+ return false unless(e)
+ e.directory?(base)
+ end
+
+ def find(path)
+ if(/\A\// =~ path)
+ thing = @root
+ else
+ thing = @pwd
+ end
+ path.scan(/[^\/]+/) do |e|
+ break thing = false unless(thing.kind_of?(Directory))
+ thing = thing[e]
+ end
+ thing
+ end
+
+ def dirname(name)
+ if (name = name.tr_s('/', '/')) == '/'
+ name
+ else
+ name[%r"\A.+(?=/[^/]+/?\z)|\A/"] || "."
+ end
+ end
+
+ def basename(name)
+ name[%r"(\A/|[^/]+)/*\z", 1]
+ end
+
+ def split(name)
+ [dirname(name), basename(name)]
+ end
+
+ def join(*parts)
+ parts.join('/').gsub(%r{/+}, '/')
+ end
+
+ def file?(name)
+ e = find(dirname(name))
+ return false unless(e)
+ e.file?(basename(name))
+ end
+
+ def pwd
+ @pwd.path_to
+ end
+
+ def chdir(to)
+ e = find(to)
+ require_directory(to)
+ @pwd = e
+ end
+
+ def expand_path(path, base = nil)
+ until /\A\// =~ path
+ base ||= pwd
+ path = join(base, path)
+ base = nil
+ end
+ path.gsub!(%r"(?:/\.)+(?=/)", '')
+ nil while path.sub!(%r"/(?!\.\./)[^/]+/\.\.(?=/)", '')
+ path.sub!(%r"\A(?:/\.\.)+(?=/)", '')
+ path.sub!(%r"(?:\A(/)|/)\.\.?\z", '\1')
+ path
+ end
+
+ def require_directory(path)
+ raise Errno::ENOTDIR, path unless(directory?(path))
+ end
+
+ def require(file)
+ return false if(@required.include?(file))
+ begin
+ e = find(file)
+ rescue Errno::ENOENT => ex
+ if(/\.rb\Z/ =~ file)
+ raise LoadError, file
+ end
+ e = find(file + '.rb')
+ end
+ @required << file
+ @object_space << e
+ true
+ rescue Errno::ENOENT
+ raise LoadError, file
+ end
+ end
+
+ def test_dir
+ inner_dir = nil
+ dirs = FileSystem::Directory.new('/', nil) do
+ file 'a', nil
+ inner_dir = dir 'b'
+ end
+ assert_equal(inner_dir, dirs['b'])
+ end
+
+ def test_fs
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b'
+ end
+ assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort)
+ assert(fs.directory?('/'))
+ assert(!fs.directory?('/a'))
+ assert(!fs.directory?('/bogus'))
+ assert(fs.file?('/a'))
+ assert(!fs.file?('/'))
+ assert(!fs.file?('/bogus'))
+ assert(fs.directory?('/b'))
+ assert(fs.file?('a'))
+ assert(fs.directory?('b'))
+ end
+
+ def test_fs_sub
+ fs = FileSystem.new do
+ dir 'a' do
+ file 'b', nil
+ dir 'c' do
+ file 'd', nil
+ end
+ end
+ end
+ assert(fs.file?('/a/b'))
+ assert(!fs.file?('/a/b/c/d'))
+ assert(fs.file?('/a/c/d'))
+ end
+
+ def test_fs_pwd
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b' do
+ file 'c', nil
+ dir 'd' do
+ file 'e', nil
+ end
+ end
+ end
+ assert_equal('/', fs.pwd)
+ assert_raise(Errno::ENOENT) do
+ fs.chdir('bogus')
+ end
+ assert_raise(Errno::ENOTDIR) do
+ fs.chdir('a')
+ end
+ fs.chdir('b')
+ assert_equal('/b', fs.pwd)
+ fs.chdir('d')
+ assert_equal('/b/d', fs.pwd)
+ fs.chdir('..')
+ assert_equal('/b', fs.pwd)
+ fs.chdir('..')
+ assert_equal('/', fs.pwd)
+ end
+
+ def test_fs_entries
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b' do
+ file 'c', nil
+ file 'd', nil
+ end
+ file 'e', nil
+ dir 'f' do
+ file 'g', nil
+ dir 'h' do
+ file 'i', nil
+ end
+ end
+ end
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort)
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort)
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort)
+ assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort)
+ assert_raise(Errno::ENOENT) do
+ fs.entries('z')
+ end
+ assert_raise(Errno::ENOTDIR) do
+ fs.entries('a')
+ end
+ fs.chdir('f')
+ assert_equal(['.', '..', 'i'], fs.entries('h').sort)
+ end
+
+ class TestClass1
+ end
+ class TestClass2
+ end
+ def test_fs_require
+ fs = FileSystem.new do
+ file 'test_class1.rb', TestClass1
+ dir 'dir' do
+ file 'test_class2.rb', TestClass2
+ end
+ end
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([], c)
+
+ assert_raise(LoadError) do
+ fs.require('bogus')
+ end
+
+ assert(fs.require('test_class1.rb'))
+ assert(!fs.require('test_class1.rb'))
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([TestClass1], c)
+
+ fs.require('dir/test_class2')
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([TestClass1, TestClass2], c)
+
+ c = []
+ fs.object_space.each_object(Time) do |o|
+ c << o
+ end
+ assert_equal([], c)
+ end
+
+ def setup
+ @t1 = t1 = create_test(1)
+ @t2 = t2 = create_test(2)
+ @t3 = t3 = create_test(3)
+ @t4 = t4 = create_test(4)
+ @t5 = t5 = create_test(5)
+ @t6 = t6 = create_test(6)
+ fs = FileSystem.new do
+ file 'test_1.rb', t1
+ file 'test_2.rb', t2
+ dir 'd1' do
+ file 'test_3.rb', t3
+ end
+ file 't4.rb', t4
+ dir 'd2' do
+ file 'test_5', t5
+ file 'test_6.rb', Time
+ end
+ file 't6.rb', t6
+ end
+ fs.require('t6')
+ @c = Dir.new(fs, fs, fs.object_space, fs)
+ end
+
+ def create_test(name)
+ t = Class.new(TestCase)
+ t.class_eval <<-EOC
+ def self.name
+ "T\#{#{name}}"
+ end
+ def test_#{name}a
+ end
+ def test_#{name}b
+ end
+ EOC
+ t
+ end
+
+ def test_simple_collect
+ expected = TestSuite.new('d1')
+ expected << (@t3.suite)
+ assert_equal(expected, @c.collect('d1'))
+ end
+
+ def test_multilevel_collect
+ expected = TestSuite.new('.')
+ expected << @t1.suite << @t2.suite
+ expected << (TestSuite.new('d1') << @t3.suite)
+ assert_equal(expected, @c.collect)
+ end
+
+ def test_collect_file
+ expected = [@t1.suite]
+ subsuites = []
+ @c.collect_file('test_1.rb', subsuites, @c.find_test_cases)
+ assert_equal(expected, subsuites)
+
+ expected = [@t4.suite]
+ subsuites = []
+ @c.collect_file('t4.rb', subsuites, @c.find_test_cases)
+ assert_equal(expected, subsuites)
+ assert_raise(LoadError) do
+ @c.collect_file('tloaderr.rb', [], [])
+ end
+ end
+
+ def test_nil_pattern
+ expected = TestSuite.new('d2')
+ expected << @t5.suite
+ @c.pattern.clear
+ assert_equal(expected, @c.collect('d2'))
+ end
+
+ def test_filtering
+ expected = TestSuite.new('.')
+ expected << @t1.suite
+ @c.filter = proc{|t| t.method_name == "test_1a" || t.method_name == "test_1b"}
+ assert_equal(expected, @c.collect)
+ end
+
+ def test_collect_multi
+ expected = TestSuite.new('[d1, d2]')
+ expected << (TestSuite.new('d1') << @t3.suite)
+ expected << (TestSuite.new('d2') << @t5.suite)
+ @c.pattern.replace([/\btest_/])
+ assert_equal(expected, @c.collect('d1', 'd2'))
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/collector/test_objectspace.rb b/trunk/test/testunit/collector/test_objectspace.rb
new file mode 100644
index 0000000000..74c796eb78
--- /dev/null
+++ b/trunk/test/testunit/collector/test_objectspace.rb
@@ -0,0 +1,98 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/collector/objectspace'
+
+module Test
+ module Unit
+ module Collector
+ class TC_ObjectSpace < TestCase
+ def setup
+ @tc1 = Class.new(TestCase) do
+ def self.name
+ "tc_1"
+ end
+ def test_1
+ end
+ def test_2
+ end
+ end
+
+ @tc2 = Class.new(TestCase) do
+ def self.name
+ "tc_2"
+ end
+ def test_0
+ end
+ end
+
+ @no_tc = Class.new do
+ def test_4
+ end
+ end
+
+ @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']}
+ def @object_space.each_object(type)
+ self[type].each{|item| yield(item) }
+ end
+
+ @c = ObjectSpace.new(@object_space)
+ end
+
+ def full_suite(name=ObjectSpace::NAME)
+ expected = TestSuite.new(name)
+ expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1") << @tc1.new("test_2"))
+ expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
+ end
+
+ def empty_suite
+ TestSuite.new(ObjectSpace::NAME)
+ end
+
+ def test_basic_collection
+ assert_equal(full_suite("name"), @c.collect("name"))
+
+ @c.filter = []
+ assert_equal(full_suite("name"), @c.collect("name"))
+ end
+
+ def test_filtered_collection
+ @c.filter = proc{false}
+ assert_equal(empty_suite, @c.collect)
+
+ @c.filter = proc{true}
+ assert_equal(full_suite, @c.collect)
+
+ @c.filter = proc{nil}
+ assert_equal(full_suite, @c.collect)
+
+ @c.filter = [proc{false}, proc{true}]
+ assert_equal(empty_suite, @c.collect)
+
+ @c.filter = [proc{true}, proc{false}]
+ assert_equal(full_suite, @c.collect)
+
+ @c.filter = [proc{nil}, proc{false}]
+ assert_equal(empty_suite, @c.collect)
+
+ @c.filter = [proc{nil}, proc{true}]
+ assert_equal(full_suite, @c.collect)
+
+ expected = TestSuite.new(ObjectSpace::NAME)
+ expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1"))
+ expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
+ @c.filter = proc{|test| ["test_1", "test_0"].include?(test.method_name)}
+ assert_equal(expected, @c.collect)
+
+ expected = TestSuite.new(ObjectSpace::NAME)
+ expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1"))
+ expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
+ @c.filter = [proc{|t| t.method_name == "test_1" ? true : nil}, proc{|t| t.method_name == "test_0" ? true : nil}, proc{false}]
+ assert_equal(expected, @c.collect)
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_assertions.rb b/trunk/test/testunit/test_assertions.rb
new file mode 100644
index 0000000000..d39c089b39
--- /dev/null
+++ b/trunk/test/testunit/test_assertions.rb
@@ -0,0 +1,543 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+ module Unit
+ class TC_Assertions < TestCase
+ def check(value, message="")
+ add_assertion
+ if (!value)
+ raise AssertionFailedError.new(message)
+ end
+ end
+
+ def check_assertions(expect_fail, expected_message="", return_value_expected=false)
+ @actual_assertion_count = 0
+ failed = true
+ actual_message = nil
+ @catch_assertions = true
+ return_value = nil
+ begin
+ return_value = yield
+ failed = false
+ rescue AssertionFailedError => error
+ actual_message = error.message
+ end
+ @catch_assertions = false
+ check(expect_fail == failed, (expect_fail ? "Should have failed, but didn't" : "Should not have failed, but did with message\n<#{actual_message}>"))
+ check(1 == @actual_assertion_count, "Should have made one assertion but made <#{@actual_assertion_count}>")
+ if (expect_fail)
+ case expected_message
+ when String
+ check(actual_message == expected_message, "Should have the correct message.\n<#{expected_message.inspect}> expected but was\n<#{actual_message.inspect}>")
+ when Regexp
+ check(actual_message =~ expected_message, "The message should match correctly.\n</#{expected_message.source}/> expected to match\n<#{actual_message.inspect}>")
+ else
+ check(false, "Incorrect expected message type in assert_nothing_failed")
+ end
+ else
+ if (!return_value_expected)
+ check(return_value.nil?, "Should not return a value but returned <#{return_value}>")
+ else
+ check(!return_value.nil?, "Should return a value")
+ end
+ end
+ return return_value
+ end
+
+ def check_nothing_fails(return_value_expected=false, &proc)
+ check_assertions(false, "", return_value_expected, &proc)
+ end
+
+ def check_fails(expected_message="", &proc)
+ check_assertions(true, expected_message, &proc)
+ end
+
+ def test_assert_block
+ check_nothing_fails {
+ assert_block {true}
+ }
+ check_nothing_fails {
+ assert_block("successful assert_block") {true}
+ }
+ check_nothing_fails {
+ assert_block("successful assert_block") {true}
+ }
+ check_fails("assert_block failed.") {
+ assert_block {false}
+ }
+ check_fails("failed assert_block") {
+ assert_block("failed assert_block") {false}
+ }
+ end
+
+ def test_assert
+ check_nothing_fails{assert("a")}
+ check_nothing_fails{assert(true)}
+ check_nothing_fails{assert(true, "successful assert")}
+ check_fails("<nil> is not true."){assert(nil)}
+ check_fails("<false> is not true."){assert(false)}
+ check_fails("failed assert.\n<false> is not true."){assert(false, "failed assert")}
+ end
+
+ def test_assert_equal
+ check_nothing_fails {
+ assert_equal("string1", "string1")
+ }
+ check_nothing_fails {
+ assert_equal( "string1", "string1", "successful assert_equal")
+ }
+ check_nothing_fails {
+ assert_equal("string1", "string1", "successful assert_equal")
+ }
+ check_fails(%Q{<"string1"> expected but was\n<"string2">.}) {
+ assert_equal("string1", "string2")
+ }
+ check_fails(%Q{failed assert_equal.\n<"string1"> expected but was\n<"string2">.}) {
+ assert_equal("string1", "string2", "failed assert_equal")
+ }
+ check_fails(%Q{<"1"> expected but was\n<1>.}) do
+ assert_equal("1", 1)
+ end
+ end
+
+ def test_assert_raise
+ return_value = nil
+ check_nothing_fails(true) {
+ return_value = assert_raise(RuntimeError) {
+ raise "Error"
+ }
+ }
+ check(return_value.kind_of?(Exception), "Should have returned the exception from a successful assert_raise")
+ check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
+ check_nothing_fails(true) {
+ assert_raise(ArgumentError, "successful assert_raise") {
+ raise ArgumentError.new("Error")
+ }
+ }
+ check_nothing_fails(true) {
+ assert_raise(RuntimeError) {
+ raise "Error"
+ }
+ }
+ check_nothing_fails(true) {
+ assert_raise(RuntimeError, "successful assert_raise") {
+ raise "Error"
+ }
+ }
+ check_fails("<RuntimeError> exception expected but none was thrown.") {
+ assert_raise(RuntimeError) {
+ 1 + 1
+ }
+ }
+ check_fails(%r{\Afailed assert_raise.\n<ArgumentError> exception expected but was\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+ assert_raise(ArgumentError, "failed assert_raise") {
+ raise "Error"
+ }
+ }
+ check_fails("Should expect a class of exception, Object.\n<false> is not true.") {
+ assert_nothing_raised(Object) {
+ 1 + 1
+ }
+ }
+
+ exceptions = [ArgumentError, TypeError]
+ modules = [Math, Comparable]
+ rescues = exceptions + modules
+ exceptions.each do |exc|
+ check_nothing_fails(true) {
+ return_value = assert_raise(*rescues) {
+ raise exc, "Error"
+ }
+ }
+ check(return_value.instance_of?(exc), "Should have returned #{exc} but was #{return_value.class}")
+ check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
+ end
+ modules.each do |mod|
+ check_nothing_fails(true) {
+ return_value = assert_raise(*rescues) {
+ raise Exception.new("Error").extend(mod)
+ }
+ }
+ check(mod === return_value, "Should have returned #{mod}")
+ check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
+ end
+ check_fails("<[ArgumentError, TypeError, Math, Comparable]> exception expected but none was thrown.") {
+ assert_raise(*rescues) {
+ 1 + 1
+ }
+ }
+ check_fails(%r{\Afailed assert_raise.
+<\[ArgumentError, TypeError\]> exception expected but was
+Class: <RuntimeError>
+Message: <"Error">
+---Backtrace---
+.+
+---------------\Z}m) {
+ assert_raise(ArgumentError, TypeError, "failed assert_raise") {
+ raise "Error"
+ }
+ }
+ end
+
+ def test_assert_instance_of
+ check_nothing_fails {
+ assert_instance_of(String, "string")
+ }
+ check_nothing_fails {
+ assert_instance_of(String, "string", "successful assert_instance_of")
+ }
+ check_nothing_fails {
+ assert_instance_of(String, "string", "successful assert_instance_of")
+ }
+ check_fails(%Q{<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
+ assert_instance_of(Hash, "string")
+ }
+ check_fails(%Q{failed assert_instance_of.\n<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
+ assert_instance_of(Hash, "string", "failed assert_instance_of")
+ }
+ end
+
+ def test_assert_nil
+ check_nothing_fails {
+ assert_nil(nil)
+ }
+ check_nothing_fails {
+ assert_nil(nil, "successful assert_nil")
+ }
+ check_nothing_fails {
+ assert_nil(nil, "successful assert_nil")
+ }
+ check_fails(%Q{<nil> expected but was\n<"string">.}) {
+ assert_nil("string")
+ }
+ check_fails(%Q{failed assert_nil.\n<nil> expected but was\n<"string">.}) {
+ assert_nil("string", "failed assert_nil")
+ }
+ end
+
+ def test_assert_not_nil
+ check_nothing_fails{assert_not_nil(false)}
+ check_nothing_fails{assert_not_nil(false, "message")}
+ check_fails("<nil> expected to not be nil."){assert_not_nil(nil)}
+ check_fails("message.\n<nil> expected to not be nil.") {assert_not_nil(nil, "message")}
+ end
+
+ def test_assert_kind_of
+ check_nothing_fails {
+ assert_kind_of(Module, Array)
+ }
+ check_nothing_fails {
+ assert_kind_of(Object, "string", "successful assert_kind_of")
+ }
+ check_nothing_fails {
+ assert_kind_of(Object, "string", "successful assert_kind_of")
+ }
+ check_nothing_fails {
+ assert_kind_of(Comparable, 1)
+ }
+ check_fails(%Q{<"string">\nexpected to be kind_of?\n<Class> but was\n<String>.}) {
+ assert_kind_of(Class, "string")
+ }
+ check_fails(%Q{failed assert_kind_of.\n<"string">\nexpected to be kind_of?\n<Class> but was\n<String>.}) {
+ assert_kind_of(Class, "string", "failed assert_kind_of")
+ }
+ end
+
+ def test_assert_match
+ check_nothing_fails {
+ assert_match(/strin./, "string")
+ }
+ check_nothing_fails {
+ assert_match("strin", "string")
+ }
+ check_nothing_fails {
+ assert_match(/strin./, "string", "successful assert_match")
+ }
+ check_nothing_fails {
+ assert_match(/strin./, "string", "successful assert_match")
+ }
+ check_fails(%Q{<"string"> expected to be =~\n</slin./>.}) {
+ assert_match(/slin./, "string")
+ }
+ check_fails(%Q{<"string"> expected to be =~\n</strin\\./>.}) {
+ assert_match("strin.", "string")
+ }
+ check_fails(%Q{failed assert_match.\n<"string"> expected to be =~\n</slin./>.}) {
+ assert_match(/slin./, "string", "failed assert_match")
+ }
+ end
+
+ def test_assert_same
+ thing = "thing"
+ check_nothing_fails {
+ assert_same(thing, thing)
+ }
+ check_nothing_fails {
+ assert_same(thing, thing, "successful assert_same")
+ }
+ check_nothing_fails {
+ assert_same(thing, thing, "successful assert_same")
+ }
+ thing2 = "thing"
+ check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
+ assert_same(thing, thing2)
+ }
+ check_fails(%Q{failed assert_same.\n<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
+ assert_same(thing, thing2, "failed assert_same")
+ }
+ end
+
+ def test_assert_nothing_raised
+ check_nothing_fails {
+ assert_nothing_raised {
+ 1 + 1
+ }
+ }
+ check_nothing_fails {
+ assert_nothing_raised("successful assert_nothing_raised") {
+ 1 + 1
+ }
+ }
+ check_nothing_fails {
+ assert_nothing_raised("successful assert_nothing_raised") {
+ 1 + 1
+ }
+ }
+ check_nothing_fails {
+ begin
+ assert_nothing_raised(RuntimeError, StandardError, Comparable, "successful assert_nothing_raised") {
+ raise ZeroDivisionError.new("ArgumentError")
+ }
+ rescue ZeroDivisionError
+ end
+ }
+ check_fails("Should expect a class of exception, Object.\n<false> is not true.") {
+ assert_nothing_raised(Object) {
+ 1 + 1
+ }
+ }
+ check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+ assert_nothing_raised {
+ raise "Error"
+ }
+ }
+ check_fails(%r{\Afailed assert_nothing_raised\.\nException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+ assert_nothing_raised("failed assert_nothing_raised") {
+ raise "Error"
+ }
+ }
+ check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
+ assert_nothing_raised(StandardError, RuntimeError) {
+ raise "Error"
+ }
+ }
+ check_fails("Failure.") do
+ assert_nothing_raised do
+ flunk("Failure")
+ end
+ end
+ end
+
+ def test_flunk
+ check_fails("Flunked.") {
+ flunk
+ }
+ check_fails("flunk message.") {
+ flunk("flunk message")
+ }
+ end
+
+ def test_assert_not_same
+ thing = "thing"
+ thing2 = "thing"
+ check_nothing_fails {
+ assert_not_same(thing, thing2)
+ }
+ check_nothing_fails {
+ assert_not_same(thing, thing2, "message")
+ }
+ check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
+ assert_not_same(thing, thing)
+ }
+ check_fails(%Q{message.\n<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
+ assert_not_same(thing, thing, "message")
+ }
+ end
+
+ def test_assert_not_equal
+ check_nothing_fails {
+ assert_not_equal("string1", "string2")
+ }
+ check_nothing_fails {
+ assert_not_equal("string1", "string2", "message")
+ }
+ check_fails(%Q{<"string"> expected to be != to\n<"string">.}) {
+ assert_not_equal("string", "string")
+ }
+ check_fails(%Q{message.\n<"string"> expected to be != to\n<"string">.}) {
+ assert_not_equal("string", "string", "message")
+ }
+ end
+
+ def test_assert_no_match
+ check_nothing_fails{assert_no_match(/sling/, "string")}
+ check_nothing_fails{assert_no_match(/sling/, "string", "message")}
+ check_fails(%Q{The first argument to assert_no_match should be a Regexp.\n<"asdf"> expected to be an instance of\n<Regexp> but was\n<String>.}) do
+ assert_no_match("asdf", "asdf")
+ end
+ check_fails(%Q{</string/> expected to not match\n<"string">.}) do
+ assert_no_match(/string/, "string")
+ end
+ check_fails(%Q{message.\n</string/> expected to not match\n<"string">.}) do
+ assert_no_match(/string/, "string", "message")
+ end
+ end
+
+ def test_assert_throws
+ check_nothing_fails {
+ assert_throws(:thing, "message") {
+ throw :thing
+ }
+ }
+ check_nothing_fails {
+ assert_throws(0, "message") {
+ throw 0
+ }
+ }
+ obj = Object.new
+ check_nothing_fails {
+ assert_throws(obj, "message") {
+ throw obj
+ }
+ }
+ check_fails("message.\n<\"string\"> expected to be thrown but\n<\"string\"> was thrown.") {
+ assert_throws("string", "message") {
+ throw "string"
+ }
+ }
+ check_fails("message.\n<:thing> expected to be thrown but\n<:thing2> was thrown.") {
+ assert_throws(:thing, "message") {
+ throw :thing2
+ }
+ }
+ check_fails("message.\n<:thing> should have been thrown.") {
+ assert_throws(:thing, "message") {
+ 1 + 1
+ }
+ }
+ end
+
+ def test_assert_nothing_thrown
+ check_nothing_fails {
+ assert_nothing_thrown("message") {
+ 1 + 1
+ }
+ }
+ check_fails("message.\n<:thing> was thrown when nothing was expected.") {
+ assert_nothing_thrown("message") {
+ throw :thing
+ }
+ }
+ end
+
+ def test_assert_operator
+ check_nothing_fails {
+ assert_operator("thing", :==, "thing", "message")
+ }
+ check_fails(%Q{<0.15>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to?(:to_str).}) do
+ assert_operator("thing", 0.15, "thing")
+ end
+ check_fails(%Q{message.\n<"thing1"> expected to be\n==\n<"thing2">.}) {
+ assert_operator("thing1", :==, "thing2", "message")
+ }
+ end
+
+ def test_assert_respond_to
+ check_nothing_fails {
+ assert_respond_to("thing", :to_s, "message")
+ }
+ check_nothing_fails {
+ assert_respond_to("thing", "to_s", "message")
+ }
+ check_fails("<0.15>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to?(:to_str).") {
+ assert_respond_to("thing", 0.15)
+ }
+ check_fails("message.\n<:symbol>\nof type <Symbol>\nexpected to respond_to?<:non_existent>.") {
+ assert_respond_to(:symbol, :non_existent, "message")
+ }
+ end
+
+ def test_assert_in_delta
+ check_nothing_fails {
+ assert_in_delta(1.4, 1.4, 0)
+ }
+ check_nothing_fails {
+ assert_in_delta(0.5, 0.4, 0.1, "message")
+ }
+ check_nothing_fails {
+ float_thing = Object.new
+ def float_thing.to_f
+ 0.2
+ end
+ assert_in_delta(0.1, float_thing, 0.1)
+ }
+ check_fails("message.\n<0.5> and\n<0.4> expected to be within\n<0.05> of each other.") {
+ assert_in_delta(0.5, 0.4, 0.05, "message")
+ }
+ check_fails(%r{The arguments must respond to to_f; the first float did not\.\n<.+>\nof type <Object>\nexpected to respond_to\?<:to_f>.}) {
+ assert_in_delta(Object.new, 0.4, 0.1)
+ }
+ check_fails("The delta should not be negative.\n<-0.1> expected to be\n>=\n<0.0>.") {
+ assert_in_delta(0.5, 0.4, -0.1, "message")
+ }
+ end
+
+ def test_assert_send
+ object = Object.new
+ class << object
+ def return_argument(argument, bogus)
+ return argument
+ end
+ end
+ check_nothing_fails {
+ assert_send([object, :return_argument, true, "bogus"], "message")
+ }
+ check_fails(%r{\Amessage\.\n<.+> expected to respond to\n<return_argument\(\[false, "bogus"\]\)> with a true value.\Z}) {
+ assert_send([object, :return_argument, false, "bogus"], "message")
+ }
+ end
+
+ def test_condition_invariant
+ object = Object.new
+ def object.inspect
+ @changed = true
+ end
+ def object.==(other)
+ @changed ||= false
+ return (!@changed)
+ end
+ check_nothing_fails {
+ assert_equal(object, object, "message")
+ }
+ end
+
+ def add_failure(message, location=caller)
+ if (!@catch_assertions)
+ super
+ end
+ end
+
+ def add_assertion
+ if (!@catch_assertions)
+ super
+ else
+ @actual_assertion_count += 1
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_error.rb b/trunk/test/testunit/test_error.rb
new file mode 100644
index 0000000000..56b275b362
--- /dev/null
+++ b/trunk/test/testunit/test_error.rb
@@ -0,0 +1,26 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+ module Unit
+ class TC_Error < TestCase
+ TF_Exception = Struct.new('TF_Exception', :message, :backtrace)
+ def test_display
+ ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2'])
+ e = Error.new("name", ex)
+ assert_equal("name: #{TF_Exception.name}: message1", e.short_display)
+ assert_equal(<<EOM.strip, e.long_display)
+Error:
+name:
+Struct::TF_Exception: message1
+message2
+ line1
+ line2
+EOM
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_failure.rb b/trunk/test/testunit/test_failure.rb
new file mode 100644
index 0000000000..164f942476
--- /dev/null
+++ b/trunk/test/testunit/test_failure.rb
@@ -0,0 +1,33 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/failure'
+
+module Test::Unit
+ class TestFailure < TestCase
+ def test_display
+ f = Failure.new("name", [%q{location:1 in 'l'}], "message1\nmessage2")
+ assert_equal("name: message1", f.short_display)
+ assert_equal(<<EOM.strip, f.long_display)
+Failure:
+name [location:1]:
+message1
+message2
+EOM
+
+ f = Failure.new("name", [%q{location1:2 in 'l1'}, 'location2:1', %q{location3:3 in 'l3'}], "message1\nmessage2")
+ assert_equal("name: message1", f.short_display)
+ assert_equal(<<EOM.strip, f.long_display)
+Failure:
+name
+ [location1:2 in 'l1'
+ location2:1
+ location3:3 in 'l3']:
+message1
+message2
+EOM
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_testcase.rb b/trunk/test/testunit/test_testcase.rb
new file mode 100644
index 0000000000..2934a92fef
--- /dev/null
+++ b/trunk/test/testunit/test_testcase.rb
@@ -0,0 +1,275 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+ module Unit
+ class TC_TestCase < TestCase
+ def test_creation
+ tc = Class.new(TestCase) do
+ def test_with_arguments(arg1, arg2)
+ end
+ end
+
+ caught = true
+ catch(:invalid_test) do
+ tc.new(:test_with_arguments)
+ caught = false
+ end
+ check("Should have caught an invalid test when there are arguments", caught)
+
+ caught = true
+ catch(:invalid_test) do
+ tc.new(:non_existent_test)
+ caught = false
+ end
+ check("Should have caught an invalid test when the method does not exist", caught)
+ end
+
+ def setup
+ @tc_failure_error = Class.new(TestCase) do
+ def test_failure
+ assert_block("failure") { false }
+ end
+ def test_error
+ 1 / 0
+ end
+ def test_nested_failure
+ nested
+ end
+ def nested
+ assert_block("nested"){false}
+ end
+ def return_passed?
+ return passed?
+ end
+ end
+
+ def @tc_failure_error.name
+ "TC_FailureError"
+ end
+ end
+
+ def test_add_failed_assertion
+ test_case = @tc_failure_error.new(:test_failure)
+ check("passed? should start out true", test_case.return_passed?)
+ result = TestResult.new
+ called = false
+ result.add_listener(TestResult::FAULT) {
+ | fault |
+ check("Should have a Failure", fault.instance_of?(Failure))
+ check("The Failure should have the correct message", "failure" == fault.message)
+ check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_failure(TC_FailureError)")
+ r = /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_failure'\Z/
+
+ location = fault.location
+ check("The location should be an array", location.kind_of?(Array))
+ check("The location should have two lines (was: <#{location.inspect}>)", location.size == 2)
+ check("The Failure should have the correct location (was <#{location[0].inspect}>, expected <#{r.inspect}>)", r =~ location[0])
+ called = true
+ }
+ progress = []
+ test_case.run(result) { |*arguments| progress << arguments }
+ check("The failure should have triggered the listener", called)
+ check("The failure should have set passed?", !test_case.return_passed?)
+ check("The progress block should have been updated correctly", [[TestCase::STARTED, test_case.name], [TestCase::FINISHED, test_case.name]] == progress)
+ end
+
+ def test_add_failure_nested
+ test_case = @tc_failure_error.new(:test_nested_failure)
+ check("passed? should start out true", test_case.return_passed?)
+
+ result = TestResult.new
+ called = false
+ result.add_listener(TestResult::FAULT) {
+ | fault |
+ check("Should have a Failure", fault.instance_of?(Failure))
+ check("The Failure should have the correct message", "nested" == fault.message)
+ check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_nested_failure(TC_FailureError)")
+ r =
+
+ location = fault.location
+ check("The location should be an array", location.kind_of?(Array))
+ check("The location should have the correct number of lines (was: <#{location.inspect}>)", location.size == 3)
+ check("The Failure should have the correct location (was <#{location[0].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `nested'\Z/ =~ location[0])
+ check("The Failure should have the correct location (was <#{location[1].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_nested_failure'\Z/ =~ location[1])
+ called = true
+ }
+ test_case.run(result){}
+ check("The failure should have triggered the listener", called)
+ end
+
+ def test_add_error
+ test_case = @tc_failure_error.new(:test_error)
+ check("passed? should start out true", test_case.return_passed?)
+ result = TestResult.new
+ called = false
+ result.add_listener(TestResult::FAULT) {
+ | fault |
+ check("Should have a TestError", fault.instance_of?(Error))
+ check("The Error should have the correct message", "ZeroDivisionError: divided by 0" == fault.message)
+ check("The Error should have the correct test_name", "test_error(TC_FailureError)" == fault.test_name)
+ check("The Error should have the correct exception", fault.exception.instance_of?(ZeroDivisionError))
+ called = true
+ }
+ test_case.run(result) {}
+ check("The error should have triggered the listener", called)
+ check("The error should have set passed?", !test_case.return_passed?)
+ end
+
+ def test_no_tests
+ suite = TestCase.suite
+ check("Should have a test suite", suite.instance_of?(TestSuite))
+ check("Should have one test", suite.size == 1)
+ check("Should have the default test", suite.tests.first.name == "default_test(Test::Unit::TestCase)")
+
+ result = TestResult.new
+ suite.run(result) {}
+ check("Should have had one test run", result.run_count == 1)
+ check("Should have had one test failure", result.failure_count == 1)
+ check("Should have had no errors", result.error_count == 0)
+ end
+
+ def test_suite
+ tc = Class.new(TestCase) do
+ def test_succeed
+ assert_block {true}
+ end
+ def test_fail
+ assert_block {false}
+ end
+ def test_error
+ 1/0
+ end
+ def dont_run
+ assert_block {true}
+ end
+ def test_dont_run(argument)
+ assert_block {true}
+ end
+ def test
+ assert_block {true}
+ end
+ end
+
+ suite = tc.suite
+ check("Should have a test suite", suite.instance_of?(TestSuite))
+ check("Should have three tests", suite.size == 3)
+
+ result = TestResult.new
+ suite.run(result) {}
+ check("Should have had three test runs", result.run_count == 3)
+ check("Should have had one test failure", result.failure_count == 1)
+ check("Should have had one test error", result.error_count == 1)
+ end
+
+
+ def test_setup_teardown
+ tc = Class.new(TestCase) do
+ attr_reader(:setup_called, :teardown_called)
+ def initialize(test)
+ super(test)
+ @setup_called = false
+ @teardown_called = false
+ end
+ def setup
+ @setup_called = true
+ end
+ def teardown
+ @teardown_called = true
+ end
+ def test_succeed
+ assert_block {true}
+ end
+ def test_fail
+ assert_block {false}
+ end
+ def test_error
+ raise "Error!"
+ end
+ end
+ result = TestResult.new
+
+ test = tc.new(:test_succeed)
+ test.run(result) {}
+ check("Should have called setup the correct number of times", test.setup_called)
+ check("Should have called teardown the correct number of times", test.teardown_called)
+
+ test = tc.new(:test_fail)
+ test.run(result) {}
+ check("Should have called setup the correct number of times", test.setup_called)
+ check("Should have called teardown the correct number of times", test.teardown_called)
+
+ test = tc.new(:test_error)
+ test.run(result) {}
+ check("Should have called setup the correct number of times", test.setup_called)
+ check("Should have called teardown the correct number of times", test.teardown_called)
+
+ check("Should have had two test runs", result.run_count == 3)
+ check("Should have had a test failure", result.failure_count == 1)
+ check("Should have had a test error", result.error_count == 1)
+ end
+
+ def test_assertion_failed_not_called
+ tc = Class.new(TestCase) do
+ def test_thing
+ raise AssertionFailedError.new
+ end
+ end
+
+ suite = tc.suite
+ check("Should have one test", suite.size == 1)
+ result = TestResult.new
+ suite.run(result) {}
+ check("Should have had one test run", result.run_count == 1)
+ check("Should have had one assertion failure", result.failure_count == 1)
+ check("Should not have any assertion errors but had #{result.error_count}", result.error_count == 0)
+ end
+
+ def test_equality
+ tc1 = Class.new(TestCase) do
+ def test_1
+ end
+ def test_2
+ end
+ end
+
+ tc2 = Class.new(TestCase) do
+ def test_1
+ end
+ end
+
+ test1 = tc1.new('test_1')
+ test2 = tc1.new('test_1')
+ check("Should be equal", test1 == test2)
+ check("Should be equal", test2 == test1)
+
+ test1 = tc1.new('test_2')
+ check("Should not be equal", test1 != test2)
+ check("Should not be equal", test2 != test1)
+
+ test2 = tc1.new('test_2')
+ check("Should be equal", test1 == test2)
+ check("Should be equal", test2 == test1)
+
+ test1 = tc1.new('test_1')
+ test2 = tc2.new('test_1')
+ check("Should not be equal", test1 != test2)
+ check("Should not be equal", test2 != test1)
+
+
+ check("Should not be equal", test1 != Object.new)
+ check("Should not be equal", Object.new != test1)
+ end
+
+ def check(message, passed)
+ @_result.add_assertion
+ if ! passed
+ raise AssertionFailedError.new(message)
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_testresult.rb b/trunk/test/testunit/test_testresult.rb
new file mode 100644
index 0000000000..95d631a082
--- /dev/null
+++ b/trunk/test/testunit/test_testresult.rb
@@ -0,0 +1,104 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/testcase'
+require 'test/unit/testresult'
+
+module Test
+ module Unit
+ class TC_TestResult < TestCase
+ def setup
+ @my_result = TestResult.new
+ @my_result.add_assertion()
+ @my_result.add_failure("")
+ @my_result.add_error("")
+ end
+ def test_result_changed_notification
+ called1 = false
+ @my_result.add_listener( TestResult::CHANGED) {
+ |result|
+ assert_block("The result should be correct") { result == @my_result }
+ called1 = true
+ }
+ @my_result.add_assertion
+ assert_block("Should have been notified when the assertion happened") { called1 }
+
+ called1, called2 = false, false
+ @my_result.add_listener( TestResult::CHANGED) {
+ |result|
+ assert_block("The result should be correct") { result == @my_result }
+ called2 = true
+ }
+ @my_result.add_assertion
+ assert_block("Both listeners should have been notified for a success") { called1 && called2 }
+
+ called1, called2 = false, false
+ @my_result.add_failure("")
+ assert_block("Both listeners should have been notified for a failure") { called1 && called2 }
+
+ called1, called2 = false, false
+ @my_result.add_error("")
+ assert_block("Both listeners should have been notified for an error") { called1 && called2 }
+
+ called1, called2 = false, false
+ @my_result.add_run
+ assert_block("Both listeners should have been notified for a run") { called1 && called2 }
+ end
+ def test_fault_notification
+ called1 = false
+ fault = "fault"
+ @my_result.add_listener(TestResult::FAULT) {
+ | passed_fault |
+ assert_block("The fault should be correct") { passed_fault == fault }
+ called1 = true
+ }
+
+ @my_result.add_assertion
+ assert_block("Should not have been notified when the assertion happened") { !called1 }
+
+ @my_result.add_failure(fault)
+ assert_block("Should have been notified when the failure happened") { called1 }
+
+ called1, called2 = false, false
+ @my_result.add_listener(TestResult::FAULT) {
+ | passed_fault |
+ assert_block("The fault should be correct") { passed_fault == fault }
+ called2 = true
+ }
+
+ @my_result.add_assertion
+ assert_block("Neither listener should have been notified for a success") { !(called1 || called2) }
+
+ called1, called2 = false, false
+ @my_result.add_failure(fault)
+ assert_block("Both listeners should have been notified for a failure") { called1 && called2 }
+
+ called1, called2 = false, false
+ @my_result.add_error(fault)
+ assert_block("Both listeners should have been notified for an error") { called1 && called2 }
+
+ called1, called2 = false, false
+ @my_result.add_run
+ assert_block("Neither listener should have been notified for a run") { !(called1 || called2) }
+ end
+ def test_passed?
+ result = TestResult.new
+ assert(result.passed?, "An empty result should have passed")
+
+ result.add_assertion
+ assert(result.passed?, "Adding an assertion should not cause the result to not pass")
+
+ result.add_run
+ assert(result.passed?, "Adding a run should not cause the result to not pass")
+
+ result.add_failure("")
+ assert(!result.passed?, "Adding a failed assertion should cause the result to not pass")
+
+ result = TestResult.new
+ result.add_error("")
+ assert(!result.passed?, "Adding an error should cause the result to not pass")
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/test_testsuite.rb b/trunk/test/testunit/test_testsuite.rb
new file mode 100644
index 0000000000..5f6631d3eb
--- /dev/null
+++ b/trunk/test/testunit/test_testsuite.rb
@@ -0,0 +1,129 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+
+module Test
+ module Unit
+ class TC_TestSuite < TestCase
+ def setup
+ @testcase1 = Class.new(TestCase) do
+ def test_succeed1
+ assert_block { true }
+ end
+ def test_fail
+ assert_block { false }
+ end
+ end
+
+ @testcase2 = Class.new(TestCase) do
+ def test_succeed2
+ assert_block { true }
+ end
+ def test_error
+ raise
+ end
+ end
+ end
+
+ def test_add
+ s = TestSuite.new
+ assert_equal(s, s << self.class.new("test_add"))
+ end
+
+ def test_delete
+ s = TestSuite.new
+ t1 = self.class.new("test_delete")
+ s << t1
+ t2 = self.class.new("test_add")
+ s << t2
+ assert_equal(t1, s.delete(t1))
+ assert_nil(s.delete(t1))
+ assert_equal(TestSuite.new << t2, s)
+ end
+
+ def test_size
+ suite = TestSuite.new
+ suite2 = TestSuite.new
+ suite2 << self.class.new("test_size")
+ suite << suite2
+ suite << self.class.new("test_size")
+ assert_equal(2, suite.size, "The count should be correct")
+ end
+
+ def test_run
+ progress = []
+ suite = @testcase1.suite
+ result = TestResult.new
+ suite.run(result) { |*values| progress << values }
+
+ assert_equal(2, result.run_count, "Should have had four test runs")
+ assert_equal(1, result.failure_count, "Should have had one test failure")
+ assert_equal(0, result.error_count, "Should have had one test error")
+ assert_equal([[TestSuite::STARTED, suite.name],
+ [TestCase::STARTED, "test_fail(#{suite.name})"],
+ [TestCase::FINISHED, "test_fail(#{suite.name})"],
+ [TestCase::STARTED, "test_succeed1(#{suite.name})"],
+ [TestCase::FINISHED, "test_succeed1(#{suite.name})"],
+ [TestSuite::FINISHED, suite.name]],
+ progress, "Should have had the correct progress")
+
+ suite = TestSuite.new
+ suite << @testcase1.suite
+ suite << @testcase2.suite
+ result = TestResult.new
+ progress = []
+ suite.run(result) { |*values| progress << values }
+
+ assert_equal(4, result.run_count, "Should have had four test runs")
+ assert_equal(1, result.failure_count, "Should have had one test failure")
+ assert_equal(1, result.error_count, "Should have had one test error")
+ assert_equal(14, progress.size, "Should have had the correct number of progress calls")
+ end
+
+ def test_empty?
+ assert(TestSuite.new.empty?, "A new test suite should be empty?")
+ assert(!@testcase2.suite.empty?, "A test suite with tests should not be empty")
+ end
+
+ def test_equality
+ suite1 = TestSuite.new
+ suite2 = TestSuite.new
+ assert_equal(suite1, suite2)
+ assert_equal(suite2, suite1)
+
+ suite1 = TestSuite.new('name')
+ assert_not_equal(suite1, suite2)
+ assert_not_equal(suite2, suite1)
+
+ suite2 = TestSuite.new('name')
+ assert_equal(suite1, suite2)
+ assert_equal(suite2, suite1)
+
+ suite1 << 'test'
+ assert_not_equal(suite1, suite2)
+ assert_not_equal(suite2, suite1)
+
+ suite2 << 'test'
+ assert_equal(suite1, suite2)
+ assert_equal(suite2, suite1)
+
+ suite2 = Object.new
+ class << suite2
+ def name
+ 'name'
+ end
+ def tests
+ ['test']
+ end
+ end
+ assert_not_equal(suite1, suite2)
+ assert_not_equal(suite2, suite1)
+
+ assert_not_equal(suite1, Object.new)
+ assert_not_equal(Object.new, suite1)
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/util/test_backtracefilter.rb b/trunk/test/testunit/util/test_backtracefilter.rb
new file mode 100644
index 0000000000..d4e40ea6ab
--- /dev/null
+++ b/trunk/test/testunit/util/test_backtracefilter.rb
@@ -0,0 +1,41 @@
+require 'test/unit'
+
+require 'test/unit/util/backtracefilter'
+
+module Test::Unit::Util
+ class TestBacktraceFilter < Test::Unit::TestCase
+ include BacktraceFilter
+
+ def test_filter_backtrace
+ backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+ %q{tc_thing.rb:4:in 'a'},
+ %q{tc_thing.rb:4:in 'test_stuff'},
+ %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
+ %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
+ %q{C:\some\old\path\test\unit.rb:44:in 'run'},
+ %q{tc_thing.rb:3}]
+ assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+
+backtrace = [%q{tc_thing.rb:4:in 'a'},
+ %q{tc_thing.rb:4:in 'test_stuff'},
+ %q{tc_thing.rb:3}]
+ assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much")
+
+ backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+ %q{tc_thing.rb:4:in 'a'},
+ %q{tc_thing.rb:4:in 'test_stuff'},
+ %q{tc_thing.rb:3}]
+ assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+
+ backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
+ %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
+ %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
+ %q{C:\some\old\path\test\unit.rb:44:in 'run'}]
+ assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
+ end
+
+ def test_nil_backtrace
+ assert_equal(["No backtrace"], filter_backtrace(nil))
+ end
+ end
+end
diff --git a/trunk/test/testunit/util/test_observable.rb b/trunk/test/testunit/util/test_observable.rb
new file mode 100644
index 0000000000..6cd10184f1
--- /dev/null
+++ b/trunk/test/testunit/util/test_observable.rb
@@ -0,0 +1,102 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/observable'
+
+module Test
+ module Unit
+ module Util
+ class TC_Observable < TestCase
+
+ class TF_Observable
+ include Observable
+ end
+
+ def setup
+ @observable = TF_Observable.new
+ end
+
+ def test_simple_observation
+ assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
+ @observable.add_listener(:property, "a")
+ end
+
+ heard = false
+ callback = proc { heard = true }
+ assert_equal("a", @observable.add_listener(:property, "a", &callback), "add_listener should return the listener that was added")
+
+ count = 0
+ @observable.instance_eval do
+ count = notify_listeners(:property)
+ end
+ assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
+ assert(heard, "Should have heard the property changed")
+
+ heard = false
+ assert_equal(callback, @observable.remove_listener(:property, "a"), "remove_listener should return the callback")
+
+ count = 1
+ @observable.instance_eval do
+ count = notify_listeners(:property)
+ end
+ assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
+ assert(!heard, "Should not have heard the property change")
+ end
+
+ def test_value_observation
+ value = nil
+ @observable.add_listener(:property, "a") do |passed_value|
+ value = passed_value
+ end
+ count = 0
+ @observable.instance_eval do
+ count = notify_listeners(:property, "stuff")
+ end
+ assert_equal(1, count, "Should have update the correct number of listeners")
+ assert_equal("stuff", value, "Should have received the value as an argument to the listener")
+ end
+
+ def test_multiple_value_observation
+ values = []
+ @observable.add_listener(:property, "a") do |first_value, second_value|
+ values = [first_value, second_value]
+ end
+ count = 0
+ @observable.instance_eval do
+ count = notify_listeners(:property, "stuff", "more stuff")
+ end
+ assert_equal(1, count, "Should have update the correct number of listeners")
+ assert_equal(["stuff", "more stuff"], values, "Should have received the value as an argument to the listener")
+ end
+
+ def test_add_remove_with_default_listener
+ assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
+ @observable.add_listener(:property)
+ end
+
+ heard = false
+ callback = proc { heard = true }
+ assert_equal(callback, @observable.add_listener(:property, &callback), "add_listener should return the listener that was added")
+
+ count = 0
+ @observable.instance_eval do
+ count = notify_listeners(:property)
+ end
+ assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
+ assert(heard, "Should have heard the property changed")
+
+ heard = false
+ assert_equal(callback, @observable.remove_listener(:property, callback), "remove_listener should return the callback")
+
+ count = 1
+ @observable.instance_eval do
+ count = notify_listeners(:property)
+ end
+ assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
+ assert(!heard, "Should not have heard the property change")
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/testunit/util/test_procwrapper.rb b/trunk/test/testunit/util/test_procwrapper.rb
new file mode 100644
index 0000000000..3e552c7711
--- /dev/null
+++ b/trunk/test/testunit/util/test_procwrapper.rb
@@ -0,0 +1,36 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/util/procwrapper'
+
+module Test
+ module Unit
+ module Util
+ class TC_ProcWrapper < TestCase
+ def munge_proc(&a_proc)
+ return a_proc
+ end
+ def setup
+ @original = proc {}
+ @munged = munge_proc(&@original)
+ @wrapped_original = ProcWrapper.new(@original)
+ @wrapped_munged = ProcWrapper.new(@munged)
+ end
+ def test_wrapping
+ assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped")
+ end
+ def test_hashing
+
+ assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped")
+ assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent")
+
+ a_hash = {@wrapped_original => @original}
+ assert(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash")
+ assert_equal(a_hash[@wrapped_original], @original, "Should be able to access the wrapper in the hash")
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/uri/test_common.rb b/trunk/test/uri/test_common.rb
new file mode 100644
index 0000000000..0fe031bdee
--- /dev/null
+++ b/trunk/test/uri/test_common.rb
@@ -0,0 +1,55 @@
+require 'test/unit'
+require 'uri'
+
+module URI
+
+
+class TestCommon < Test::Unit::TestCase
+ def setup
+ end
+
+ def teardown
+ end
+
+ def test_extract
+ assert_equal(['http://example.com'],
+ URI.extract('http://example.com'))
+ assert_equal(['http://example.com'],
+ URI.extract('(http://example.com)'))
+ assert_equal(['http://example.com/foo)'],
+ URI.extract('(http://example.com/foo)'))
+ assert_equal(['http://example.jphttp://example.jp'],
+ URI.extract('http://example.jphttp://example.jp'), "[ruby-list:36086]")
+ assert_equal(['http://example.jphttp://example.jp'],
+ URI.extract('http://example.jphttp://example.jp', ['http']), "[ruby-list:36086]")
+ assert_equal(['http://', 'mailto:'].sort,
+ URI.extract('ftp:// http:// mailto: https://', ['http', 'mailto']).sort)
+ # reported by Doug Kearns <djkea2@mugca.its.monash.edu.au>
+ assert_equal(['From:', 'mailto:xxx@xxx.xxx.xxx]'].sort,
+ URI.extract('From: XXX [mailto:xxx@xxx.xxx.xxx]').sort)
+ end
+
+ def test_regexp
+ assert_instance_of Regexp, URI.regexp
+ assert_instance_of Regexp, URI.regexp(['http'])
+ assert_equal URI.regexp, URI.regexp
+ assert_equal 'http://', 'x http:// x'.slice(URI.regexp)
+ assert_equal 'http://', 'x http:// x'.slice(URI.regexp(['http']))
+ assert_equal 'http://', 'x http:// x ftp://'.slice(URI.regexp(['http']))
+ assert_equal nil, 'http://'.slice(URI.regexp([]))
+ assert_equal nil, ''.slice(URI.regexp)
+ assert_equal nil, 'xxxx'.slice(URI.regexp)
+ assert_equal nil, ':'.slice(URI.regexp)
+ assert_equal 'From:', 'From:'.slice(URI.regexp)
+ end
+
+ def test_kernel_uri
+ expected = URI.parse("http://www.ruby-lang.org/")
+ assert_equal(expected, URI("http://www.ruby-lang.org/"))
+ assert_equal(expected, Kernel::URI("http://www.ruby-lang.org/"))
+ assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
+ end
+end
+
+
+end
diff --git a/trunk/test/uri/test_ftp.rb b/trunk/test/uri/test_ftp.rb
new file mode 100644
index 0000000000..c27cf6165b
--- /dev/null
+++ b/trunk/test/uri/test_ftp.rb
@@ -0,0 +1,62 @@
+require 'test/unit'
+require 'uri/ftp'
+
+module URI
+
+
+class TestFTP < Test::Unit::TestCase
+ def setup
+ end
+
+ def test_parse
+ url = URI.parse('ftp://user:pass@host.com/abc/def')
+ assert_kind_of(URI::FTP, url)
+
+ exp = [
+ 'ftp',
+ 'user:pass', 'host.com', URI::FTP.default_port,
+ 'abc/def', nil,
+ ]
+ ary = [
+ url.scheme, url.userinfo, url.host, url.port,
+ url.path, url.opaque
+ ]
+ assert_equal(exp, ary)
+
+ assert_equal('user', url.user)
+ assert_equal('pass', url.password)
+ end
+
+ def test_paths
+ # If you think what's below is wrong, please read RubyForge bug 2055,
+ # RFC 1738 section 3.2.2, and RFC 2396.
+ u = URI.parse('ftp://ftp.example.com/foo/bar/file.ext')
+ assert(u.path == 'foo/bar/file.ext')
+ u = URI.parse('ftp://ftp.example.com//foo/bar/file.ext')
+ assert(u.path == '/foo/bar/file.ext')
+ u = URI.parse('ftp://ftp.example.com/%2Ffoo/bar/file.ext')
+ assert(u.path == '/foo/bar/file.ext')
+ end
+
+ def test_assemble
+ # uri/ftp is conservative and uses the older RFC 1738 rules, rather than
+ # assuming everyone else has implemented RFC 2396.
+ uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
+ '/path/file.zip', 'i'])
+ assert(uri.to_s ==
+ 'ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=i')
+ end
+
+ def test_select
+ assert_equal(['ftp', 'a.b.c', 21], URI.parse('ftp://a.b.c/').select(:scheme, :host, :port))
+ u = URI.parse('ftp://a.b.c/')
+ ary = u.component.collect {|c| u.send(c)}
+ assert_equal(ary, u.select(*u.component))
+ assert_raises(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
+
+
+end
diff --git a/trunk/test/uri/test_generic.rb b/trunk/test/uri/test_generic.rb
new file mode 100644
index 0000000000..6661b4a5d2
--- /dev/null
+++ b/trunk/test/uri/test_generic.rb
@@ -0,0 +1,739 @@
+require 'test/unit'
+require 'uri'
+
+class URI::TestGeneric < Test::Unit::TestCase
+ def setup
+ @url = 'http://a/b/c/d;p?q'
+ @base_url = URI.parse(@url)
+ end
+
+ def teardown
+ end
+
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_parse
+ # 0
+ assert_kind_of(URI::HTTP, @base_url)
+
+ exp = [
+ 'http',
+ nil, 'a', URI::HTTP.default_port,
+ '/b/c/d;p',
+ 'q',
+ nil
+ ]
+ ary = uri_to_ary(@base_url)
+ assert_equal(exp, ary)
+
+ # 1
+ url = URI.parse('ftp://ftp.is.co.za/rfc/rfc1808.txt')
+ assert_kind_of(URI::FTP, url)
+
+ exp = [
+ 'ftp',
+ nil, 'ftp.is.co.za', URI::FTP.default_port,
+ 'rfc/rfc1808.txt', nil,
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 2
+ url = URI.parse('gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles')
+ assert_kind_of(URI::Generic, url)
+
+ exp = [
+ 'gopher',
+ nil, 'spinaltap.micro.umn.edu', nil, nil,
+ '/00/Weather/California/Los%20Angeles', nil,
+ nil,
+ nil
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 3
+ url = URI.parse('http://www.math.uio.no/faq/compression-faq/part1.html')
+ assert_kind_of(URI::HTTP, url)
+
+ exp = [
+ 'http',
+ nil, 'www.math.uio.no', URI::HTTP.default_port,
+ '/faq/compression-faq/part1.html',
+ nil,
+ nil
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 4
+ url = URI.parse('mailto:mduerst@ifi.unizh.ch')
+ assert_kind_of(URI::Generic, url)
+
+ exp = [
+ 'mailto',
+ 'mduerst@ifi.unizh.ch',
+ []
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 5
+ url = URI.parse('news:comp.infosystems.www.servers.unix')
+ assert_kind_of(URI::Generic, url)
+
+ exp = [
+ 'news',
+ nil, nil, nil, nil,
+ nil, 'comp.infosystems.www.servers.unix',
+ nil,
+ nil
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 6
+ url = URI.parse('telnet://melvyl.ucop.edu/')
+ assert_kind_of(URI::Generic, url)
+
+ exp = [
+ 'telnet',
+ nil, 'melvyl.ucop.edu', nil, nil,
+ '/', nil,
+ nil,
+ nil
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
+
+ # 7
+ # reported by Mr. Kubota <em6t-kbt@asahi-net.or.jp>
+ assert_raises(URI::InvalidURIError) { URI.parse('http://a_b:80/') }
+ assert_raises(URI::InvalidURIError) { URI.parse('http://a_b/') }
+
+ # 8
+ # reported by m_seki
+ uri = URI.parse('file:///foo/bar.txt')
+ assert_kind_of(URI::Generic, url)
+ uri = URI.parse('file:/foo/bar.txt')
+ assert_kind_of(URI::Generic, url)
+
+ # 9
+ url = URI.parse('ftp://:pass@localhost/')
+ assert_equal('', url.user, "[ruby-dev:25667]")
+ assert_equal('pass', url.password)
+ assert_equal(':pass', url.userinfo, "[ruby-dev:25667]")
+ url = URI.parse('ftp://user@localhost/')
+ assert_equal('user', url.user)
+ assert_equal(nil, url.password)
+ assert_equal('user', url.userinfo)
+ url = URI.parse('ftp://localhost/')
+ assert_equal(nil, url.user)
+ assert_equal(nil, url.password)
+ assert_equal(nil, url.userinfo)
+ end
+
+ def test_merge
+ u1 = URI.parse('http://foo')
+ u2 = URI.parse('http://foo/')
+ u3 = URI.parse('http://foo/bar')
+ u4 = URI.parse('http://foo/bar/')
+
+ assert_equal(URI.parse('http://foo/baz'), u1 + 'baz')
+ assert_equal(URI.parse('http://foo/baz'), u2 + 'baz')
+ assert_equal(URI.parse('http://foo/baz'), u3 + 'baz')
+ assert_equal(URI.parse('http://foo/bar/baz'), u4 + 'baz')
+
+ assert_equal(URI.parse('http://foo/baz'), u1 + '/baz')
+ assert_equal(URI.parse('http://foo/baz'), u2 + '/baz')
+ assert_equal(URI.parse('http://foo/baz'), u3 + '/baz')
+ assert_equal(URI.parse('http://foo/baz'), u4 + '/baz')
+
+ url = URI.parse('http://hoge/a.html') + 'b.html'
+ assert_equal('http://hoge/b.html', url.to_s, "[ruby-dev:11508]")
+
+ # reported by Mr. Kubota <em6t-kbt@asahi-net.or.jp>
+ url = URI.parse('http://a/b') + 'http://x/y'
+ assert_equal('http://x/y', url.to_s)
+ assert_equal(url, URI.parse('') + 'http://x/y')
+ assert_equal(url, URI.parse('').normalize + 'http://x/y')
+ assert_equal(url, URI.parse('http://a/b').normalize + 'http://x/y')
+
+ u = URI.parse('http://foo/bar/baz')
+ assert_equal(nil, u.merge!(""))
+ assert_equal(nil, u.merge!(u))
+ assert(nil != u.merge!("."))
+ assert_equal('http://foo/bar/', u.to_s)
+ assert(nil != u.merge!("../baz"))
+ assert_equal('http://foo/baz', u.to_s)
+
+ u0 = URI.parse('mailto:foo@example.com')
+ u1 = URI.parse('mailto:foo@example.com#bar')
+ assert_equal(uri_to_ary(u0 + '#bar'), uri_to_ary(u1), "[ruby-dev:23628]")
+
+ u0 = URI.parse('http://www.example.com/')
+ u1 = URI.parse('http://www.example.com/foo/..') + './'
+ assert_equal(u0, u1, "[ruby-list:39838]")
+ u0 = URI.parse('http://www.example.com/foo/')
+ u1 = URI.parse('http://www.example.com/foo/bar/..') + './'
+ assert_equal(u0, u1)
+ u0 = URI.parse('http://www.example.com/foo/bar/')
+ u1 = URI.parse('http://www.example.com/foo/bar/baz/..') + './'
+ assert_equal(u0, u1)
+ u0 = URI.parse('http://www.example.com/')
+ u1 = URI.parse('http://www.example.com/foo/bar/../..') + './'
+ assert_equal(u0, u1)
+ u0 = URI.parse('http://www.example.com/foo/')
+ u1 = URI.parse('http://www.example.com/foo/bar/baz/../..') + './'
+ assert_equal(u0, u1)
+
+ u = URI.parse('http://www.example.com/')
+ u0 = u + './foo/'
+ u1 = u + './foo/bar/..'
+ assert_equal(u0, u1, "[ruby-list:39844]")
+ u = URI.parse('http://www.example.com/')
+ u0 = u + './'
+ u1 = u + './foo/bar/../..'
+ assert_equal(u0, u1)
+ end
+
+ def test_route
+ url = URI.parse('http://hoge/a.html').route_to('http://hoge/b.html')
+ assert_equal('b.html', url.to_s)
+
+ url = URI.parse('http://hoge/a/').route_to('http://hoge/b/')
+ assert_equal('../b/', url.to_s)
+ url = URI.parse('http://hoge/a/b').route_to('http://hoge/b/')
+ assert_equal('../b/', url.to_s)
+
+ url = URI.parse('http://hoge/a/b/').route_to('http://hoge/b/')
+ assert_equal('../../b/', url.to_s)
+
+ url = URI.parse('http://hoge/a/b/').route_to('http://HOGE/b/')
+ assert_equal('../../b/', url.to_s)
+
+ url = URI.parse('http://hoge/a/b/').route_to('http://MOGE/b/')
+ assert_equal('//MOGE/b/', url.to_s)
+
+ url = URI.parse('file:///a/b/').route_to('file:///a/b/')
+ assert_equal('', url.to_s)
+
+ url = URI.parse('mailto:foo@example.com').route_to('mailto:foo@example.com#bar')
+ assert_equal('#bar', url.to_s)
+
+ url = URI.parse('mailto:foo@example.com#bar').route_to('mailto:foo@example.com')
+ assert_equal('', url.to_s)
+
+ url = URI.parse('mailto:foo@example.com').route_to('mailto:foo@example.com')
+ assert_equal('', url.to_s)
+ end
+
+ def test_rfc2396_examples
+# http://a/b/c/d;p?q
+# g:h = g:h
+ url = @base_url.merge('g:h')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g:h', url.to_s)
+ url = @base_url.route_to('g:h')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g:h', url.to_s)
+
+# http://a/b/c/d;p?q
+# g = http://a/b/c/g
+ url = @base_url.merge('g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g', url.to_s)
+
+# http://a/b/c/d;p?q
+# ./g = http://a/b/c/g
+ url = @base_url.merge('./g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g')
+ assert_kind_of(URI::Generic, url)
+ assert('./g' != url.to_s) # ok
+ assert_equal('g', url.to_s)
+
+# http://a/b/c/d;p?q
+# g/ = http://a/b/c/g/
+ url = @base_url.merge('g/')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g/', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g/')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g/', url.to_s)
+
+# http://a/b/c/d;p?q
+# /g = http://a/g
+ url = @base_url.merge('/g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/g')
+ assert_kind_of(URI::Generic, url)
+ assert('/g' != url.to_s) # ok
+ assert_equal('../../g', url.to_s)
+
+# http://a/b/c/d;p?q
+# //g = http://g
+ url = @base_url.merge('//g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://g', url.to_s)
+ url = @base_url.route_to('http://g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('//g', url.to_s)
+
+# http://a/b/c/d;p?q
+# ?y = http://a/b/c/d;p?y
+ url = @base_url.merge('?y')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/d;p?y', url.to_s)
+ url = @base_url.route_to('http://a/b/c/d;p?y')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('?y', url.to_s)
+
+# http://a/b/c/d;p?q
+# g?y = http://a/b/c/g?y
+ url = @base_url.merge('g?y')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g?y', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g?y')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g?y', url.to_s)
+
+# http://a/b/c/d;p?q
+# #s = (current document)#s
+ url = @base_url.merge('#s')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal(@base_url.to_s + '#s', url.to_s)
+ url = @base_url.route_to(@base_url.to_s + '#s')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('#s', url.to_s)
+
+# http://a/b/c/d;p?q
+# g#s = http://a/b/c/g#s
+ url = @base_url.merge('g#s')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g#s', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g#s')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g#s', url.to_s)
+
+# http://a/b/c/d;p?q
+# g?y#s = http://a/b/c/g?y#s
+ url = @base_url.merge('g?y#s')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g?y#s', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g?y#s')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g?y#s', url.to_s)
+
+# http://a/b/c/d;p?q
+# ;x = http://a/b/c/;x
+ url = @base_url.merge(';x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/;x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/;x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal(';x', url.to_s)
+
+# http://a/b/c/d;p?q
+# g;x = http://a/b/c/g;x
+ url = @base_url.merge('g;x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g;x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g;x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g;x', url.to_s)
+
+# http://a/b/c/d;p?q
+# g;x?y#s = http://a/b/c/g;x?y#s
+ url = @base_url.merge('g;x?y#s')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g;x?y#s', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g;x?y#s')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g;x?y#s', url.to_s)
+
+# http://a/b/c/d;p?q
+# . = http://a/b/c/
+ url = @base_url.merge('.')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/', url.to_s)
+ url = @base_url.route_to('http://a/b/c/')
+ assert_kind_of(URI::Generic, url)
+ assert('.' != url.to_s) # ok
+ assert_equal('./', url.to_s)
+
+# http://a/b/c/d;p?q
+# ./ = http://a/b/c/
+ url = @base_url.merge('./')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/', url.to_s)
+ url = @base_url.route_to('http://a/b/c/')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('./', url.to_s)
+
+# http://a/b/c/d;p?q
+# .. = http://a/b/
+ url = @base_url.merge('..')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/', url.to_s)
+ url = @base_url.route_to('http://a/b/')
+ assert_kind_of(URI::Generic, url)
+ assert('..' != url.to_s) # ok
+ assert_equal('../', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../ = http://a/b/
+ url = @base_url.merge('../')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/', url.to_s)
+ url = @base_url.route_to('http://a/b/')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('../', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../g = http://a/b/g
+ url = @base_url.merge('../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/g', url.to_s)
+ url = @base_url.route_to('http://a/b/g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('../g', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../.. = http://a/
+ url = @base_url.merge('../..')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/', url.to_s)
+ url = @base_url.route_to('http://a/')
+ assert_kind_of(URI::Generic, url)
+ assert('../..' != url.to_s) # ok
+ assert_equal('../../', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../../ = http://a/
+ url = @base_url.merge('../../')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/', url.to_s)
+ url = @base_url.route_to('http://a/')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('../../', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../../g = http://a/g
+ url = @base_url.merge('../../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('../../g', url.to_s)
+
+# http://a/b/c/d;p?q
+# <> = (current document)
+ url = @base_url.merge('')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/d;p?q', url.to_s)
+ url = @base_url.route_to('http://a/b/c/d;p?q')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('', url.to_s)
+
+# http://a/b/c/d;p?q
+# /./g = http://a/g
+ url = @base_url.merge('/./g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/./g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('/./g', url.to_s)
+
+# http://a/b/c/d;p?q
+# /../g = http://a/../g
+ url = @base_url.merge('/../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/../g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('/../g', url.to_s)
+
+# http://a/b/c/d;p?q
+# g. = http://a/b/c/g.
+ url = @base_url.merge('g.')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g.', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g.')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g.', url.to_s)
+
+# http://a/b/c/d;p?q
+# .g = http://a/b/c/.g
+ url = @base_url.merge('.g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/.g', url.to_s)
+ url = @base_url.route_to('http://a/b/c/.g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('.g', url.to_s)
+
+# http://a/b/c/d;p?q
+# g.. = http://a/b/c/g..
+ url = @base_url.merge('g..')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g..', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g..')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g..', url.to_s)
+
+# http://a/b/c/d;p?q
+# ..g = http://a/b/c/..g
+ url = @base_url.merge('..g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/..g', url.to_s)
+ url = @base_url.route_to('http://a/b/c/..g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('..g', url.to_s)
+
+# http://a/b/c/d;p?q
+# ../../../g = http://a/g
+ url = @base_url.merge('../../../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/../g')
+ assert_kind_of(URI::Generic, url)
+ assert('../../../g' != url.to_s) # ok? yes, it confuses you
+ assert_equal('/../g', url.to_s) # and it is clearly
+
+# http://a/b/c/d;p?q
+# ../../../../g = http://a/../../g
+ url = @base_url.merge('../../../../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/g', url.to_s)
+ url = @base_url.route_to('http://a/../../g')
+ assert_kind_of(URI::Generic, url)
+ assert('../../../../g' != url.to_s) # ok? yes, it confuses you
+ assert_equal('/../../g', url.to_s) # and it is clearly
+
+# http://a/b/c/d;p?q
+# ./../g = http://a/b/g
+ url = @base_url.merge('./../g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/g', url.to_s)
+ url = @base_url.route_to('http://a/b/g')
+ assert_kind_of(URI::Generic, url)
+ assert('./../g' != url.to_s) # ok
+ assert_equal('../g', url.to_s)
+
+# http://a/b/c/d;p?q
+# ./g/. = http://a/b/c/g/
+ url = @base_url.merge('./g/.')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g/', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g/')
+ assert_kind_of(URI::Generic, url)
+ assert('./g/.' != url.to_s) # ok
+ assert_equal('g/', url.to_s)
+
+# http://a/b/c/d;p?q
+# g/./h = http://a/b/c/g/h
+ url = @base_url.merge('g/./h')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g/h', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g/h')
+ assert_kind_of(URI::Generic, url)
+ assert('g/./h' != url.to_s) # ok
+ assert_equal('g/h', url.to_s)
+
+# http://a/b/c/d;p?q
+# g/../h = http://a/b/c/h
+ url = @base_url.merge('g/../h')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/h', url.to_s)
+ url = @base_url.route_to('http://a/b/c/h')
+ assert_kind_of(URI::Generic, url)
+ assert('g/../h' != url.to_s) # ok
+ assert_equal('h', url.to_s)
+
+# http://a/b/c/d;p?q
+# g;x=1/./y = http://a/b/c/g;x=1/y
+ url = @base_url.merge('g;x=1/./y')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g;x=1/y', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g;x=1/y')
+ assert_kind_of(URI::Generic, url)
+ assert('g;x=1/./y' != url.to_s) # ok
+ assert_equal('g;x=1/y', url.to_s)
+
+# http://a/b/c/d;p?q
+# g;x=1/../y = http://a/b/c/y
+ url = @base_url.merge('g;x=1/../y')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/y', url.to_s)
+ url = @base_url.route_to('http://a/b/c/y')
+ assert_kind_of(URI::Generic, url)
+ assert('g;x=1/../y' != url.to_s) # ok
+ assert_equal('y', url.to_s)
+
+# http://a/b/c/d;p?q
+# g?y/./x = http://a/b/c/g?y/./x
+ url = @base_url.merge('g?y/./x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g?y/./x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g?y/./x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g?y/./x', url.to_s)
+
+# http://a/b/c/d;p?q
+# g?y/../x = http://a/b/c/g?y/../x
+ url = @base_url.merge('g?y/../x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g?y/../x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g?y/../x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g?y/../x', url.to_s)
+
+# http://a/b/c/d;p?q
+# g#s/./x = http://a/b/c/g#s/./x
+ url = @base_url.merge('g#s/./x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g#s/./x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g#s/./x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g#s/./x', url.to_s)
+
+# http://a/b/c/d;p?q
+# g#s/../x = http://a/b/c/g#s/../x
+ url = @base_url.merge('g#s/../x')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http://a/b/c/g#s/../x', url.to_s)
+ url = @base_url.route_to('http://a/b/c/g#s/../x')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('g#s/../x', url.to_s)
+
+# http://a/b/c/d;p?q
+# http:g = http:g ; for validating parsers
+# | http://a/b/c/g ; for backwards compatibility
+ url = @base_url.merge('http:g')
+ assert_kind_of(URI::HTTP, url)
+ assert_equal('http:g', url.to_s)
+ url = @base_url.route_to('http:g')
+ assert_kind_of(URI::Generic, url)
+ assert_equal('http:g', url.to_s)
+ end
+
+ def test_join
+ assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo/bar'))
+ assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo', 'bar'))
+ assert_equal(URI.parse('http://foo/bar/'), URI.join('http://foo', 'bar/'))
+
+ assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', 'baz'))
+ assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', '/baz'))
+ assert_equal(URI.parse('http://foo/baz/'), URI.join('http://foo', 'bar', '/baz/'))
+ assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/', 'baz'))
+ assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar', 'baz', 'hoge'))
+
+ assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/baz'))
+ assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+ assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+ assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+ assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+ assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+ assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+ end
+
+ def test_set_component
+ uri = URI.parse('http://foo:bar@baz')
+ assert_equal('oof', uri.user = 'oof', "[ruby-dev:16728]")
+ assert_equal('http://oof:bar@baz', uri.to_s)
+ assert_equal('rab', uri.password = 'rab')
+ assert_equal('http://oof:rab@baz', uri.to_s)
+ assert_equal('foo', uri.userinfo = 'foo')
+ assert_equal('http://foo:rab@baz', uri.to_s)
+ assert_equal(['foo', 'bar'], uri.userinfo = ['foo', 'bar'])
+ assert_equal('http://foo:bar@baz', uri.to_s)
+ assert_equal(['foo'], uri.userinfo = ['foo'])
+ assert_equal('http://foo:bar@baz', uri.to_s)
+ assert_equal('zab', uri.host = 'zab')
+ assert_equal('http://foo:bar@zab', uri.to_s)
+ assert_equal(8080, uri.port = 8080)
+ assert_equal('http://foo:bar@zab:8080', uri.to_s)
+ assert_equal('/', uri.path = '/')
+ assert_equal('http://foo:bar@zab:8080/', uri.to_s)
+ assert_equal('a=1', uri.query = 'a=1')
+ assert_equal('http://foo:bar@zab:8080/?a=1', uri.to_s)
+ assert_equal('b123', uri.fragment = 'b123')
+ assert_equal('http://foo:bar@zab:8080/?a=1#b123', uri.to_s)
+
+ uri = URI.parse('http://example.com')
+ assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
+ uri.userinfo = 'foo:bar'
+ assert_equal('http://foo:bar@example.com', uri.to_s)
+ assert_raises(URI::InvalidURIError) { uri.registry = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.opaque = 'bar' }
+
+ uri = URI.parse('mailto:foo@example.com')
+ assert_raises(URI::InvalidURIError) { uri.user = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.userinfo = ['bar', 'baz'] }
+ assert_raises(URI::InvalidURIError) { uri.host = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.port = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.path = 'bar' }
+ assert_raises(URI::InvalidURIError) { uri.query = 'bar' }
+ end
+
+ def m(s)
+ @base_url.merge(s).to_s
+end
+
+ def test_rfc3986_examples
+ assert_equal("g:h", m("g:h"))
+ assert_equal("http://a/b/c/g", m("g"))
+ assert_equal("http://a/b/c/g", m("./g"))
+ assert_equal("http://a/b/c/g/", m("g/"))
+ assert_equal("http://a/g", m("/g"))
+ assert_equal("http://g", m("//g"))
+ assert_equal("http://a/b/c/d;p?y", m("?y"))
+ assert_equal("http://a/b/c/g?y", m("g?y"))
+ assert_equal("http://a/b/c/d;p?q#s", m("#s"))
+ assert_equal("http://a/b/c/g#s", m("g#s"))
+ assert_equal("http://a/b/c/g?y#s", m("g?y#s"))
+ assert_equal("http://a/b/c/;x", m(";x"))
+ assert_equal("http://a/b/c/g;x", m("g;x"))
+ assert_equal("http://a/b/c/g;x?y#s", m("g;x?y#s"))
+ assert_equal("http://a/b/c/d;p?q", m(""))
+ assert_equal("http://a/b/c/", m("."))
+ assert_equal("http://a/b/c/", m("./"))
+ assert_equal("http://a/b/", m(".."))
+ assert_equal("http://a/b/", m("../"))
+ assert_equal("http://a/b/g", m("../g"))
+ assert_equal("http://a/", m("../.."))
+ assert_equal("http://a/", m("../../"))
+ assert_equal("http://a/g", m("../../g"))
+ assert_equal("http://a/g", m("../../../g"))
+ assert_equal("http://a/g", m("../../../../g"))
+
+ assert_equal("http://a/g", m("/./g"))
+ assert_equal("http://a/g", m("/../g"))
+ assert_equal("http://a/b/c/g.", m("g."))
+ assert_equal("http://a/b/c/.g", m(".g"))
+ assert_equal("http://a/b/c/g..", m("g.."))
+ assert_equal("http://a/b/c/..g", m("..g"))
+
+ assert_equal("http://a/b/g", m("./../g"))
+ assert_equal("http://a/b/c/g/", m("./g/."))
+ assert_equal("http://a/b/c/g/h", m("g/./h"))
+ assert_equal("http://a/b/c/h", m("g/../h"))
+ assert_equal("http://a/b/c/g;x=1/y", m("g;x=1/./y"))
+ assert_equal("http://a/b/c/y", m("g;x=1/../y"))
+
+ assert_equal("http://a/b/c/g?y/./x", m("g?y/./x"))
+ assert_equal("http://a/b/c/g?y/../x", m("g?y/../x"))
+ assert_equal("http://a/b/c/g#s/./x", m("g#s/./x"))
+ assert_equal("http://a/b/c/g#s/../x", m("g#s/../x"))
+
+ assert_equal("http:g", m("http:g"))
+ end
+end
diff --git a/trunk/test/uri/test_http.rb b/trunk/test/uri/test_http.rb
new file mode 100644
index 0000000000..a6846141df
--- /dev/null
+++ b/trunk/test/uri/test_http.rb
@@ -0,0 +1,63 @@
+require 'test/unit'
+require 'uri/http'
+
+module URI
+
+
+class TestHTTP < Test::Unit::TestCase
+ def setup
+ end
+
+ def teardown
+ end
+
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_parse
+ u = URI.parse('http://a')
+ assert_kind_of(URI::HTTP, u)
+ assert_equal(['http',
+ nil, 'a', URI::HTTP.default_port,
+ '', nil, nil], uri_to_ary(u))
+ end
+
+ def test_normalize
+ host = 'aBcD'
+ u1 = URI.parse('http://' + host + '/eFg?HiJ')
+ u2 = URI.parse('http://' + host.downcase + '/eFg?HiJ')
+ assert(u1.normalize.host == 'abcd')
+ assert(u1.normalize.path == u1.path)
+ assert(u1.normalize == u2.normalize)
+ assert(!u1.normalize.host.equal?(u1.host))
+ assert( u2.normalize.host.equal?(u2.host))
+
+ assert_equal('http://abc/', URI.parse('http://abc').normalize.to_s)
+ end
+
+ def test_equal
+ assert(URI.parse('http://abc') == URI.parse('http://ABC'))
+ assert(URI.parse('http://abc/def') == URI.parse('http://ABC/def'))
+ assert(URI.parse('http://abc/def') != URI.parse('http://ABC/DEF'))
+ end
+
+ def test_request_uri
+ assert_equal('/', URI.parse('http://a.b.c/').request_uri)
+ assert_equal('/?abc=def', URI.parse('http://a.b.c/?abc=def').request_uri)
+ assert_equal('/', URI.parse('http://a.b.c').request_uri)
+ assert_equal('/?abc=def', URI.parse('http://a.b.c?abc=def').request_uri)
+ end
+
+ def test_select
+ assert_equal(['http', 'a.b.c', 80], URI.parse('http://a.b.c/').select(:scheme, :host, :port))
+ u = URI.parse('http://a.b.c/')
+ assert_equal(uri_to_ary(u), u.select(*u.component))
+ assert_raises(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
+
+
+end
diff --git a/trunk/test/uri/test_ldap.rb b/trunk/test/uri/test_ldap.rb
new file mode 100644
index 0000000000..866b7d8066
--- /dev/null
+++ b/trunk/test/uri/test_ldap.rb
@@ -0,0 +1,100 @@
+require 'test/unit'
+require 'uri/ldap'
+
+module URI
+
+
+class TestLDAP < Test::Unit::TestCase
+ def setup
+ end
+
+ def teardown
+ end
+
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_parse
+ url = 'ldap://ldap.jaist.ac.jp/o=JAIST,c=JP?sn?base?(sn=ttate*)'
+ u = URI.parse(url)
+ assert_kind_of(URI::LDAP, u)
+ assert_equal(url, u.to_s)
+ assert_equal('o=JAIST,c=JP', u.dn)
+ assert_equal('sn', u.attributes)
+ assert_equal('base', u.scope)
+ assert_equal('(sn=ttate*)', u.filter)
+ assert_equal(nil, u.extensions)
+
+ u.scope = URI::LDAP::SCOPE_SUB
+ u.attributes = 'sn,cn,mail'
+ assert_equal('ldap://ldap.jaist.ac.jp/o=JAIST,c=JP?sn,cn,mail?sub?(sn=ttate*)', u.to_s)
+ assert_equal('o=JAIST,c=JP', u.dn)
+ assert_equal('sn,cn,mail', u.attributes)
+ assert_equal('sub', u.scope)
+ assert_equal('(sn=ttate*)', u.filter)
+ assert_equal(nil, u.extensions)
+
+ # from RFC2255, section 6.
+ urls = {
+ 'ldap:///o=University%20of%20Michigan,c=US' =>
+ ['ldap', nil, URI::LDAP::DEFAULT_PORT,
+ 'o=University%20of%20Michigan,c=US',
+ nil, nil, nil, nil],
+
+ 'ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US' =>
+ ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT,
+ 'o=University%20of%20Michigan,c=US',
+ nil, nil, nil, nil],
+
+ 'ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress' =>
+ ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT,
+ 'o=University%20of%20Michigan,c=US',
+ 'postalAddress', nil, nil, nil],
+
+ 'ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)' =>
+ ['ldap', 'host.com', 6666,
+ 'o=University%20of%20Michigan,c=US',
+ nil, 'sub', '(cn=Babs%20Jensen)', nil],
+
+ 'ldap://ldap.itd.umich.edu/c=GB?objectClass?one' =>
+ ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT,
+ 'c=GB',
+ 'objectClass', 'one', nil, nil],
+
+ 'ldap://ldap.question.com/o=Question%3f,c=US?mail' =>
+ ['ldap', 'ldap.question.com', URI::LDAP::DEFAULT_PORT,
+ 'o=Question%3f,c=US',
+ 'mail', nil, nil, nil],
+
+ 'ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04)' =>
+ ['ldap', 'ldap.netscape.com', URI::LDAP::DEFAULT_PORT,
+ 'o=Babsco,c=US',
+ nil, '(int=%5c00%5c00%5c00%5c04)', nil, nil],
+
+ 'ldap:///??sub??bindname=cn=Manager%2co=Foo' =>
+ ['ldap', nil, URI::LDAP::DEFAULT_PORT,
+ '',
+ nil, 'sub', nil, 'bindname=cn=Manager%2co=Foo'],
+
+ 'ldap:///??sub??!bindname=cn=Manager%2co=Foo' =>
+ ['ldap', nil, URI::LDAP::DEFAULT_PORT,
+ '',
+ nil, 'sub', nil, '!bindname=cn=Manager%2co=Foo'],
+ }.each do |url, ary|
+ u = URI.parse(url)
+ assert_equal(ary, uri_to_ary(u))
+ end
+ end
+
+ def test_select
+ u = URI.parse('ldap:///??sub??!bindname=cn=Manager%2co=Foo')
+ assert_equal(uri_to_ary(u), u.select(*u.component))
+ assert_raises(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
+
+
+end
diff --git a/trunk/test/uri/test_mailto.rb b/trunk/test/uri/test_mailto.rb
new file mode 100644
index 0000000000..ba437904f8
--- /dev/null
+++ b/trunk/test/uri/test_mailto.rb
@@ -0,0 +1,122 @@
+require 'test/unit'
+require 'uri/mailto'
+
+module URI
+
+
+class TestMailTo < Test::Unit::TestCase
+ def setup
+ @u = URI::MailTo
+ end
+
+ def teardown
+ end
+
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_build
+ ok = []
+ bad = []
+
+ # RFC2368, 6. Examples
+ # mailto:chris@example.com
+ ok << ["mailto:chris@example.com"]
+ ok[-1] << ["chris@example.com", nil]
+ ok[-1] << {:to => "chris@example.com"}
+
+ # mailto:infobot@example.com?subject=current-issue
+ ok << ["mailto:infobot@example.com?subject=current-issue"]
+ ok[-1] << ["infobot@example.com", ["subject=current-issue"]]
+ ok[-1] << {:to => "infobot@example.com",
+ :headers => ["subject=current-issue"]}
+
+ # mailto:infobot@example.com?body=send%20current-issue
+ ok << ["mailto:infobot@example.com?body=send%20current-issue"]
+ ok[-1] << ["infobot@example.com", ["body=send%20current-issue"]]
+ ok[-1] << {:to => "infobot@example.com",
+ :headers => ["body=send%20current-issue"]}
+
+ # mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index
+ ok << ["mailto:infobot@example.com?body=send%20current-issue%0D%0Asend%20index"]
+ ok[-1] << ["infobot@example.com",
+ ["body=send%20current-issue%0D%0Asend%20index"]]
+ ok[-1] << {:to => "infobot@example.com",
+ :headers => ["body=send%20current-issue%0D%0Asend%20index"]}
+
+ # mailto:foobar@example.com?In-Reply-To=%3c3469A91.D10AF4C@example.com
+ ok << ["mailto:foobar@example.com?In-Reply-To=%3c3469A91.D10AF4C@example.com"]
+ ok[-1] << ["foobar@example.com",
+ ["In-Reply-To=%3c3469A91.D10AF4C@example.com"]]
+ ok[-1] << {:to => "foobar@example.com",
+ :headers => ["In-Reply-To=%3c3469A91.D10AF4C@example.com"]}
+
+ # mailto:majordomo@example.com?body=subscribe%20bamboo-l
+ ok << ["mailto:majordomo@example.com?body=subscribe%20bamboo-l"]
+ ok[-1] << ["majordomo@example.com", ["body=subscribe%20bamboo-l"]]
+ ok[-1] << {:to => "majordomo@example.com",
+ :headers => ["body=subscribe%20bamboo-l"]}
+
+ # mailto:joe@example.com?cc=bob@example.com&body=hello
+ ok << ["mailto:joe@example.com?cc=bob@example.com&body=hello"]
+ ok[-1] << ["joe@example.com", ["cc=bob@example.com", "body=hello"]]
+ ok[-1] << {:to => "joe@example.com",
+ :headers => ["cc=bob@example.com", "body=hello"]}
+
+ # mailto:?to=joe@example.com&cc=bob@example.com&body=hello
+ ok << ["mailto:?to=joe@example.com&cc=bob@example.com&body=hello"]
+ ok[-1] << [nil,
+ ["to=joe@example.com", "cc=bob@example.com", "body=hello"]]
+ ok[-1] << {:headers => ["to=joe@example.com",
+ "cc=bob@example.com", "body=hello"]}
+
+ # mailto:gorby%25kremvax@example.com
+ ok << ["mailto:gorby%25kremvax@example.com"]
+ ok[-1] << ["gorby%25kremvax@example.com", nil]
+ ok[-1] << {:to => "gorby%25kremvax@example.com"}
+
+ # mailto:unlikely%3Faddress@example.com?blat=foop
+ ok << ["mailto:unlikely%3Faddress@example.com?blat=foop"]
+ ok[-1] << ["unlikely%3Faddress@example.com", ["blat=foop"]]
+ ok[-1] << {:to => "unlikely%3Faddress@example.com",
+ :headers => ["blat=foop"]}
+
+ ok_all = ok.flatten.join("\0")
+
+ # mailto:joe@example.com?cc=bob@example.com?body=hello ; WRONG!
+ bad << ["joe@example.com", ["cc=bob@example.com?body=hello"]]
+
+ # mailto:javascript:alert()
+ bad << ["javascript:alert()", []]
+
+ # '=' which is in hname or hvalue is wrong.
+ bad << ["foo@example.jp?subject=1+1=2", []]
+
+ ok.each do |x|
+ assert_equal(x[0],
+ @u.build(x[1]).to_s)
+ assert_equal(x[0],
+ @u.build(x[2]).to_s)
+ end
+
+ bad.each do |x|
+ assert_raises(URI::InvalidComponentError) {
+ @u.build(x)
+ }
+ end
+
+ assert_equal(ok_all, ok.flatten.join("\0"))
+ end
+
+ def test_select
+ u = URI.parse('mailto:joe@example.com?cc=bob@example.com&body=hello')
+ assert_equal(uri_to_ary(u), u.select(*u.component))
+ assert_raises(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
+
+
+end
diff --git a/trunk/test/webrick/.htaccess b/trunk/test/webrick/.htaccess
new file mode 100644
index 0000000000..69d4659b9f
--- /dev/null
+++ b/trunk/test/webrick/.htaccess
@@ -0,0 +1 @@
+this file should not be published.
diff --git a/trunk/test/webrick/test_cgi.rb b/trunk/test/webrick/test_cgi.rb
new file mode 100644
index 0000000000..b50038d84c
--- /dev/null
+++ b/trunk/test/webrick/test_cgi.rb
@@ -0,0 +1,101 @@
+require "webrick"
+require File.join(File.dirname(__FILE__), "utils.rb")
+require "test/unit"
+
+class TestWEBrickCGI < Test::Unit::TestCase
+ CRLF = "\r\n"
+
+ def start_cgi_server(&block)
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :DirectoryIndex => ["webrick.cgi"],
+ :RequestHandler => Proc.new{|req, res|
+ def req.meta_vars
+ meta = super
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
+ return meta
+ end
+ },
+ }
+ if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/
+ config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
+ end
+ TestWEBrick.start_httpserver(config){|server, addr, port|
+ block.call(server, addr, port)
+ }
+ end
+
+ def test_cgi
+ start_cgi_server{|server, addr, port|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ http.request(req){|res| assert_equal("/webrick.cgi", res.body)}
+ req = Net::HTTP::Get.new("/webrick.cgi/path/info")
+ http.request(req){|res| assert_equal("/path/info", res.body)}
+ req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
+ http.request(req){|res| assert_equal("/???", res.body)}
+ req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
+ http.request(req){|res|
+ assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body)}
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body)}
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body)}
+
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1;a=2;b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body)}
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1&a=2&b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body)}
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ ary = res.body.lines.to_a
+ assert_match(%r{/$}, ary[0])
+ assert_match(%r{/webrick.cgi$}, ary[1])
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
+ http.request(req){|res|
+ assert_equal(
+ "CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
+ res.body)
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ cookie = %{$Version="1"; }
+ cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
+ cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
+ cookie << %{Shipping="FedEx"; $Path="/acme"}
+ req["Cookie"] = cookie
+ http.request(req){|res|
+ assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
+ res["Set-Cookie"])
+ assert_equal("Customer=WILE_E_COYOTE\n" +
+ "Part_Number=Rocket_Launcher_0001\n" +
+ "Shipping=FedEx\n", res.body)
+ }
+ }
+ end
+
+ def test_bad_request
+ start_cgi_server{|server, addr, port|
+ sock = TCPSocket.new(addr, port)
+ begin
+ sock << "POST /webrick.cgi HTTP/1.0" << CRLF
+ sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
+ sock << "Content-Length: 1024" << CRLF
+ sock << CRLF
+ sock << "a=1&a=2&b=x"
+ sock.close_write
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read)
+ ensure
+ sock.close
+ end
+ }
+ end
+end
diff --git a/trunk/test/webrick/test_cookie.rb b/trunk/test/webrick/test_cookie.rb
new file mode 100644
index 0000000000..c8ded4c2dd
--- /dev/null
+++ b/trunk/test/webrick/test_cookie.rb
@@ -0,0 +1,104 @@
+require "test/unit"
+require "webrick/cookie"
+
+class TestWEBrickCookie < Test::Unit::TestCase
+ def test_new
+ cookie = WEBrick::Cookie.new("foo","bar")
+ assert_equal("foo", cookie.name)
+ assert_equal("bar", cookie.value)
+ assert_equal("foo=bar", cookie.to_s)
+ end
+
+ def test_time
+ cookie = WEBrick::Cookie.new("foo","bar")
+ t = 1000000000
+ cookie.max_age = t
+ assert_match(t.to_s, cookie.to_s)
+
+ cookie = WEBrick::Cookie.new("foo","bar")
+ t = Time.at(1000000000)
+ cookie.expires = t
+ assert_equal(Time, cookie.expires.class)
+ assert_equal(t, cookie.expires)
+ ts = t.httpdate
+ cookie.expires = ts
+ assert_equal(Time, cookie.expires.class)
+ assert_equal(t, cookie.expires)
+ assert_match(ts, cookie.to_s)
+ end
+
+ def test_parse
+ data = ""
+ data << '$Version="1"; '
+ data << 'Customer="WILE_E_COYOTE"; $Path="/acme"; '
+ data << 'Part_Number="Rocket_Launcher_0001"; $Path="/acme"; '
+ data << 'Shipping="FedEx"; $Path="/acme"'
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(1, cookies[0].version)
+ assert_equal("Customer", cookies[0].name)
+ assert_equal("WILE_E_COYOTE", cookies[0].value)
+ assert_equal("/acme", cookies[0].path)
+ assert_equal(1, cookies[1].version)
+ assert_equal("Part_Number", cookies[1].name)
+ assert_equal("Rocket_Launcher_0001", cookies[1].value)
+ assert_equal(1, cookies[2].version)
+ assert_equal("Shipping", cookies[2].name)
+ assert_equal("FedEx", cookies[2].value)
+
+ data = "hoge=moge; __div__session=9865ecfd514be7f7"
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(0, cookies[0].version)
+ assert_equal("hoge", cookies[0].name)
+ assert_equal("moge", cookies[0].value)
+ assert_equal("__div__session", cookies[1].name)
+ assert_equal("9865ecfd514be7f7", cookies[1].value)
+ end
+
+ def test_parse_set_cookie
+ data = %(Customer="WILE_E_COYOTE"; Version="1"; Path="/acme")
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
+ assert_equal("Customer", cookie.name)
+ assert_equal("WILE_E_COYOTE", cookie.value)
+ assert_equal(1, cookie.version)
+ assert_equal("/acme", cookie.path)
+
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
+ assert_equal("Shipping", cookie.name)
+ assert_equal("FedEx", cookie.value)
+ assert_equal(1, cookie.version)
+ assert_equal("/acme", cookie.path)
+ assert_equal(true, cookie.secure)
+ end
+
+ def test_parse_set_cookies
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
+ data << %(, CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=/; Secure)
+ data << %(, name="Aaron"; Version="1"; path="/acme")
+ cookies = WEBrick::Cookie.parse_set_cookies(data)
+ assert_equal(3, cookies.length)
+
+ fed_ex = cookies.find { |c| c.name == 'Shipping' }
+ assert_not_nil(fed_ex)
+ assert_equal("Shipping", fed_ex.name)
+ assert_equal("FedEx", fed_ex.value)
+ assert_equal(1, fed_ex.version)
+ assert_equal("/acme", fed_ex.path)
+ assert_equal(true, fed_ex.secure)
+
+ name = cookies.find { |c| c.name == 'name' }
+ assert_not_nil(name)
+ assert_equal("name", name.name)
+ assert_equal("Aaron", name.value)
+ assert_equal(1, name.version)
+ assert_equal("/acme", name.path)
+
+ customer = cookies.find { |c| c.name == 'CUSTOMER' }
+ assert_not_nil(customer)
+ assert_equal("CUSTOMER", customer.name)
+ assert_equal("WILE_E_COYOTE", customer.value)
+ assert_equal(0, customer.version)
+ assert_equal("/", customer.path)
+ assert_equal(Time.utc(1999, 11, 9, 23, 12, 40), customer.expires)
+ end
+end
diff --git a/trunk/test/webrick/test_filehandler.rb b/trunk/test/webrick/test_filehandler.rb
new file mode 100644
index 0000000000..371527e413
--- /dev/null
+++ b/trunk/test/webrick/test_filehandler.rb
@@ -0,0 +1,204 @@
+require "test/unit"
+require "webrick"
+require "stringio"
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class WEBrick::TestFileHandler < Test::Unit::TestCase
+ def default_file_handler(filename)
+ klass = WEBrick::HTTPServlet::DefaultFileHandler
+ klass.new(WEBrick::Config::HTTP, filename)
+ end
+
+ def windows?
+ File.directory?("\\")
+ end
+
+ def get_res_body(res)
+ if defined? res.body.read
+ res.body.read
+ else
+ res.body
+ end
+ end
+
+ def make_range_request(range_spec)
+ msg = <<-_end_of_request_
+ GET / HTTP/1.0
+ Range: #{range_spec}
+
+ _end_of_request_
+ return StringIO.new(msg.gsub(/^ {6}/, ""))
+ end
+
+ def make_range_response(file, range_spec)
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(make_range_request(range_spec))
+ res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
+ size = File.size(file)
+ handler = default_file_handler(file)
+ handler.make_partial_content(req, res, file, size)
+ return res
+ end
+
+ def test_make_partial_content
+ filename = __FILE__
+ filesize = File.size(filename)
+
+ res = make_range_response(filename, "bytes=#{filesize-100}-")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 100)
+
+ res = make_range_response(filename, "bytes=-100")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 100)
+
+ res = make_range_response(filename, "bytes=0-99")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 100)
+
+ res = make_range_response(filename, "bytes=100-199")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 100)
+
+ res = make_range_response(filename, "bytes=0-0")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 1)
+
+ res = make_range_response(filename, "bytes=-1")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(get_res_body(res).size, 1)
+
+ res = make_range_response(filename, "bytes=0-0, -2")
+ assert_match(%r{^multipart/byteranges}, res["content-type"])
+ end
+
+ def test_filehandler
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code)
+ assert_equal("text/html", res.content_type)
+ assert_match(/HREF="#{this_file}"/, res.body)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("200", res.code)
+ assert_equal("text/plain", res.content_type)
+ assert_equal(File.read(__FILE__), res.body)
+ }
+ end
+ end
+
+ def test_non_disclosure_name
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+ doc_root_opts = server[:DocumentRootOptions]
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code)
+ assert_equal("text/html", res.content_type)
+ assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("404", res.code)
+ }
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
+ http.request(req){|res|
+ assert_equal("404", res.code)
+ }
+ end
+ end
+
+ def test_directory_traversal
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/../../")
+ http.request(req){|res| assert_equal("400", res.code) }
+ req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
+ http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code) }
+ req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
+ http.request(req){|res| assert_equal("404", res.code) }
+ end
+ end
+
+ def test_unwise_in_path
+ if windows?
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/..%5c..")
+ http.request(req){|res| assert_equal("301", res.code) }
+ end
+ end
+ end
+
+ def test_short_filename
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ }
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/webric~1.cgi/test")
+ http.request(req) do |res|
+ if windows?
+ assert_equal("200", res.code)
+ assert_equal("/test", res.body)
+ else
+ assert_equal("404", res.code)
+ end
+ end
+
+ req = Net::HTTP::Get.new("/.htaccess")
+ http.request(req) {|res| assert_equal("404", res.code) }
+ req = Net::HTTP::Get.new("/htacce~1")
+ http.request(req) {|res| assert_equal("404", res.code) }
+ req = Net::HTTP::Get.new("/HTACCE~1")
+ http.request(req) {|res| assert_equal("404", res.code) }
+ end
+ end
+
+ def test_script_disclosure
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ }
+ TestWEBrick.start_httpserver(config) do |server, addr, port|
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/webrick.cgi/test")
+ http.request(req) do |res|
+ assert_equal("200", res.code)
+ assert_equal("/test", res.body)
+ end
+
+ response_assertion = Proc.new do |res|
+ if windows?
+ assert_equal("200", res.code)
+ assert_equal("/test", res.body)
+ else
+ assert_equal("404", res.code)
+ end
+ end
+ req = Net::HTTP::Get.new("/webrick.cgi%20/test")
+ http.request(req, &response_assertion)
+ req = Net::HTTP::Get.new("/webrick.cgi./test")
+ http.request(req, &response_assertion)
+ req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
+ http.request(req, &response_assertion)
+ end
+ end
+end
diff --git a/trunk/test/webrick/test_httpauth.rb b/trunk/test/webrick/test_httpauth.rb
new file mode 100644
index 0000000000..75926b1624
--- /dev/null
+++ b/trunk/test/webrick/test_httpauth.rb
@@ -0,0 +1,82 @@
+require "test/unit"
+require "net/http"
+require "tempfile"
+require "webrick"
+require "webrick/httpauth/basicauth"
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestWEBrickHTTPAuth < Test::Unit::TestCase
+ def test_basic_auth
+ TestWEBrick.start_httpserver{|server, addr, port|
+ realm = "WEBrick's realm"
+ path = "/basic_auth"
+
+ server.mount_proc(path){|req, res|
+ WEBrick::HTTPAuth.basic_auth(req, res, realm){|user, pass|
+ user == "webrick" && pass == "supersecretpassword"
+ }
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("webrick", "supersecretpassword")
+ http.request(g){|res| assert_equal("hoge", res.body)}
+ g.basic_auth("webrick", "not super")
+ http.request(g){|res| assert_not_equal("hoge", res.body)}
+ }
+ end
+
+ def test_basic_auth2
+ TestWEBrick.start_httpserver{|server, addr, port|
+ realm = "WEBrick's realm"
+ path = "/basic_auth2"
+
+ tmpfile = Tempfile.new("test_webrick_auth")
+ tmpfile.close
+ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+ tmp_pass.flush
+
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ users = []
+ htpasswd.each{|user, pass| users << user }
+ assert_equal(2, users.size)
+ assert(users.member?("webrick"))
+ assert(users.member?("foo"))
+
+ server.mount_proc(path){|req, res|
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
+ :Realm => realm, :UserDB => htpasswd,
+ :Logger => server.logger
+ )
+ auth.authenticate(req, res)
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("webrick", "supersecretpassword")
+ http.request(g){|res| assert_equal("hoge", res.body)}
+ g.basic_auth("webrick", "not super")
+ http.request(g){|res| assert_not_equal("hoge", res.body)}
+ }
+ end
+
+ def test_basic_auth3
+ tmpfile = Tempfile.new("test_webrick_auth")
+ tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
+ tmpfile.flush
+ assert_raises(NotImplementedError){
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ }
+ tmpfile.close(true)
+
+ tmpfile = Tempfile.new("test_webrick_auth")
+ tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
+ tmpfile.flush
+ assert_raises(NotImplementedError){
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ }
+ tmpfile.close(true)
+ end
+end
diff --git a/trunk/test/webrick/test_httpproxy.rb b/trunk/test/webrick/test_httpproxy.rb
new file mode 100644
index 0000000000..67862543a8
--- /dev/null
+++ b/trunk/test/webrick/test_httpproxy.rb
@@ -0,0 +1,281 @@
+require "test/unit"
+require "net/http"
+require "webrick"
+require "webrick/httpproxy"
+begin
+ require "webrick/ssl"
+ require "net/https"
+ require File.expand_path("../openssl/utils.rb", File.dirname(__FILE__))
+rescue LoadError
+ # test_connect will be skipped
+end
+require File.expand_path("utils.rb", File.dirname(__FILE__))
+
+class TestWEBrickHTTPProxy < Test::Unit::TestCase
+ def test_fake_proxy
+ assert_nil(WEBrick::FakeProxyURI.scheme)
+ assert_nil(WEBrick::FakeProxyURI.host)
+ assert_nil(WEBrick::FakeProxyURI.port)
+ assert_nil(WEBrick::FakeProxyURI.path)
+ assert_nil(WEBrick::FakeProxyURI.userinfo)
+ assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
+ end
+
+ def test_proxy
+ # Testing GET or POST to the proxy server
+ # Note that the proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy ---+
+ # GET / POST GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
+ assert_equal("GET / ", res.body)
+ }
+ assert_equal(1, proxy_handler_called)
+ assert_equal(2, request_handler_called)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
+ assert_nil(res.body)
+ }
+ assert_equal(2, proxy_handler_called)
+ assert_equal(4, request_handler_called)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
+ assert_equal("POST / post-data", res.body)
+ }
+ assert_equal(3, proxy_handler_called)
+ assert_equal(6, request_handler_called)
+ }
+ end
+
+ def test_no_proxy
+ # Testing GET or POST to the proxy server without proxy request.
+ #
+ # client -------> proxy
+ # GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"])
+ assert_equal("GET / ", res.body)
+ }
+ assert_equal(0, proxy_handler_called)
+ assert_equal(1, request_handler_called)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"])
+ assert_nil(res.body)
+ }
+ assert_equal(0, proxy_handler_called)
+ assert_equal(2, request_handler_called)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_nil(res["via"])
+ assert_equal("POST / post-data", res.body)
+ }
+ assert_equal(0, proxy_handler_called)
+ assert_equal(3, request_handler_called)
+ }
+ end
+
+ def make_certificate(key, cn)
+ subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
+ exts = [
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
+ ]
+ cert = OpenSSL::TestUtils.issue_cert(
+ subject, key, 1, Time.now, Time.now + 3600, exts,
+ nil, nil, OpenSSL::Digest::SHA1.new
+ )
+ return cert
+ end
+
+ def test_connect
+ # Testing CONNECT to proxy server
+ #
+ # client -----------> proxy -----------> https
+ # 1. CONNECT establish TCP
+ # 2. ---- establish SSL session --->
+ # 3. ------- GET or POST ---------->
+ #
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :RequestHandler => Proc.new{|req, res|
+ assert_equal("CONNECT", req.request_method)
+ },
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
+ s_server.mount_proc("/"){|req, res|
+ res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port|
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("SSL GET / ", res.body)
+ }
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("SSL POST / post-data", res.body)
+ }
+ }
+ }
+ end if defined?(OpenSSL)
+
+ def test_upstream_proxy
+ # Testing GET or POST through the upstream proxy server
+ # Note that the upstream proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy -------> proxy ---+
+ # GET / POST GET / POST GET / POST
+ #
+ up_proxy_handler_called = up_request_handler_called = 0
+ proxy_handler_called = request_handler_called = 0
+ up_config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
+ :RequestHandler => Proc.new{|req, res| up_request_handler_called += 1}
+ }
+ TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port|
+ up_server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyURI => URI.parse("http://localhost:#{up_port}"),
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
+ :RequestHandler => Proc.new{|req, res| request_handler_called += 1},
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port|
+ http = Net::HTTP.new(up_addr, up_port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
+ assert(via.include?("1.1 localhost.localdomain:#{port}"))
+ assert_equal("GET / ", res.body)
+ }
+ assert_equal(1, up_proxy_handler_called)
+ assert_equal(2, up_request_handler_called)
+ assert_equal(1, proxy_handler_called)
+ assert_equal(1, request_handler_called)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
+ assert(via.include?("1.1 localhost.localdomain:#{port}"))
+ assert_nil(res.body)
+ }
+ assert_equal(2, up_proxy_handler_called)
+ assert_equal(4, up_request_handler_called)
+ assert_equal(2, proxy_handler_called)
+ assert_equal(2, request_handler_called)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
+ assert(via.include?("1.1 localhost.localdomain:#{port}"))
+ assert_equal("POST / post-data", res.body)
+ }
+ assert_equal(3, up_proxy_handler_called)
+ assert_equal(6, up_request_handler_called)
+ assert_equal(3, proxy_handler_called)
+ assert_equal(3, request_handler_called)
+
+ if defined?(OpenSSL)
+ # Testing CONNECT to the upstream proxy server
+ #
+ # client -------> proxy -------> proxy -------> https
+ # 1. CONNECT CONNECT establish TCP
+ # 2. -------- establish SSL session ------>
+ # 3. ---------- GET or POST -------------->
+ #
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
+ s_server.mount_proc("/"){|req, res|
+ res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("SSL GET / ", res.body)
+ }
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("SSL POST / post-data", res.body)
+ }
+ }
+ end
+ }
+ }
+ end
+end
diff --git a/trunk/test/webrick/test_httprequest.rb b/trunk/test/webrick/test_httprequest.rb
new file mode 100644
index 0000000000..f49bd59384
--- /dev/null
+++ b/trunk/test/webrick/test_httprequest.rb
@@ -0,0 +1,349 @@
+require "webrick"
+require "stringio"
+require "test/unit"
+
+class TestWEBrickHTTPRequest < Test::Unit::TestCase
+ def test_parse_09
+ msg = <<-_end_of_message_
+ GET /
+ foobar # HTTP/0.9 request don't have header nor entity body.
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("0.9"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_10
+ msg = <<-_end_of_message_
+ GET / HTTP/1.0
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("1.0"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_11
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/path", req.unparsed_uri)
+ assert_equal("", req.script_name)
+ assert_equal("/path", req.path_info)
+ assert_equal(WEBrick::HTTPVersion.new("1.1"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(true, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_request_uri_too_large
+ msg = <<-_end_of_message_
+ GET /#{"a"*1024} HTTP/1.1
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ assert_raises(WEBrick::HTTPStatus::RequestURITooLarge){
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ }
+ end
+
+ def test_parse_headers
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Connection: close
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+ Accept-Encoding: compress;q=0.5
+ Accept-Encoding: gzip;q=1.0, identity; q=0.4, *;q=0
+ Accept-Language: en;q=0.5, *; q=0
+ Accept-Language: ja
+ Content-Type: text/plain
+ Content-Length: 7
+ X-Empty-Header:
+
+ foobar
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(
+ URI.parse("http://test.ruby-lang.org:8080/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(8080, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(
+ %w(text/html;level=1 text/html */* text/html;level=2 text/*),
+ req.accept)
+ assert_equal(%w(gzip compress identity *), req.accept_encoding)
+ assert_equal(%w(ja en *), req.accept_language)
+ assert_equal(7, req.content_length)
+ assert_equal("text/plain", req.content_type)
+ assert_equal("foobar\n", req.body)
+ assert_equal("", req["x-empty-header"])
+ assert_equal(nil, req["x-no-header"])
+ assert(req.query.empty?)
+ end
+
+ def test_parse_header2()
+ msg = <<-_end_of_message_
+ POST /foo/bar/../baz?q=a HTTP/1.0
+ Content-Length: 9
+ User-Agent:
+ FOO BAR
+ BAZ
+
+ hogehoge
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("POST", req.request_method)
+ assert_equal("/foo/baz", req.path)
+ assert_equal("", req.script_name)
+ assert_equal("/foo/baz", req.path_info)
+ assert_equal("9", req['content-length'])
+ assert_equal("FOO BAR BAZ", req['user-agent'])
+ assert_equal("hogehoge\n", req.body)
+ end
+
+ def test_parse_headers3
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://test.ruby-lang.org/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1:8080/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(8080, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]:8080/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(8080, req.port)
+ end
+
+ def test_parse_get_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ GET /path?#{param} HTTP/1.1
+ Host: test.ruby-lang.org:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_parse_post_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: #{param.size}
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_chunked
+ crlf = "\x0d\x0a"
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: chunked
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ open(__FILE__){|io|
+ while chunk = io.read(100)
+ msg << chunk.size.to_s(16) << crlf
+ msg << chunk << crlf
+ end
+ }
+ msg << "0" << crlf
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal(File.read(__FILE__), req.body)
+ end
+
+ def test_forwarded
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(80, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com:8080
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(8080, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(443, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+ end
+
+ def test_bad_messages
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ assert_raises(WEBrick::HTTPStatus::LengthRequired){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: 100000
+
+ body is too short.
+ _end_of_message_
+ assert_raises(WEBrick::HTTPStatus::BadRequest){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: foobar
+
+ body is too short.
+ _end_of_message_
+ assert_raises(WEBrick::HTTPStatus::NotImplemented){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+ end
+end
diff --git a/trunk/test/webrick/test_httpserver.rb b/trunk/test/webrick/test_httpserver.rb
new file mode 100644
index 0000000000..eb685f916d
--- /dev/null
+++ b/trunk/test/webrick/test_httpserver.rb
@@ -0,0 +1,260 @@
+require "test/unit"
+require "net/http"
+require "webrick"
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestWEBrickHTTPServer < Test::Unit::TestCase
+ def test_mount
+ httpd = WEBrick::HTTPServer.new(
+ :Logger => WEBrick::Log.new(TestWEBrick::NullWriter),
+ :DoNotListen=>true
+ )
+ httpd.mount("/", :Root)
+ httpd.mount("/foo", :Foo)
+ httpd.mount("/foo/bar", :Bar, :bar1)
+ httpd.mount("/foo/bar/baz", :Baz, :baz1, :baz2)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "")
+ assert_equal(path_info, "/")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "")
+ assert_equal(path_info, "/sub")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "")
+ assert_equal(path_info, "/sub/")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "/foo")
+ assert_equal(path_info, "")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "/foo")
+ assert_equal(path_info, "/")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/sub")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal(script_name, "/foo")
+ assert_equal(path_info, "/sub")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar")
+ assert_equal(:Bar, serv)
+ assert_equal([:bar1], opts)
+ assert_equal(script_name, "/foo/bar")
+ assert_equal(path_info, "")
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar/baz")
+ assert_equal(:Baz, serv)
+ assert_equal([:baz1, :baz2], opts)
+ assert_equal(script_name, "/foo/bar/baz")
+ assert_equal(path_info, "")
+ end
+
+ class Req
+ attr_reader :port, :host
+ def initialize(addr, port, host)
+ @addr, @port, @host = addr, port, host
+ end
+ def addr
+ [0,0,0,@addr]
+ end
+ end
+
+ def httpd(addr, port, host, ali)
+ config ={
+ :Logger => WEBrick::Log.new(TestWEBrick::NullWriter),
+ :DoNotListen => true,
+ :BindAddress => addr,
+ :Port => port,
+ :ServerName => host,
+ :ServerAlias => ali,
+ }
+ return WEBrick::HTTPServer.new(config)
+ end
+
+ def assert_eql?(v1, v2)
+ assert_equal(v1.object_id, v2.object_id)
+ end
+
+ def test_lookup_server
+ addr1 = "192.168.100.1"
+ addr2 = "192.168.100.2"
+ addrz = "192.168.100.254"
+ local = "127.0.0.1"
+ port1 = 80
+ port2 = 8080
+ port3 = 10080
+ portz = 32767
+ name1 = "www.example.com"
+ name2 = "www2.example.com"
+ name3 = "www3.example.com"
+ namea = "www.example.co.jp"
+ nameb = "www.example.jp"
+ namec = "www2.example.co.jp"
+ named = "www2.example.jp"
+ namez = "foobar.example.com"
+ alias1 = [namea, nameb]
+ alias2 = [namec, named]
+
+ host1 = httpd(nil, port1, name1, nil)
+ hosts = [
+ host2 = httpd(addr1, port1, name1, nil),
+ host3 = httpd(addr1, port1, name2, alias1),
+ host4 = httpd(addr1, port2, name1, nil),
+ host5 = httpd(addr1, port2, name2, alias1),
+ host6 = httpd(addr1, port2, name3, alias2),
+ host7 = httpd(addr2, nil, name1, nil),
+ host8 = httpd(addr2, nil, name2, alias1),
+ host9 = httpd(addr2, nil, name3, alias2),
+ host10 = httpd(local, nil, nil, nil),
+ host11 = httpd(nil, port3, nil, nil),
+ ].sort_by{ rand }
+ hosts.each{|h| host1.virtual_host(h) }
+
+ # connect to addr1
+ assert_eql?(host2, host1.lookup_server(Req.new(addr1, port1, name1)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, name2)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, namea)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port1, namez)))
+ assert_eql?(host4, host1.lookup_server(Req.new(addr1, port2, name1)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, name2)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, namea)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namez)))
+
+ # connect to addr2
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port1, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port1, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port2, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port2, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port3, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr2, port3, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, portz, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, portz, namez)))
+
+ # connect to addrz
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namez)))
+
+ # connect to localhost
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namez)))
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ requested0 = requested1 = 0
+ config = {
+ :ServerName => "localhost",
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ :RequestCallback => Proc.new{|req, res| requested0 += 1 },
+ }
+ TestWEBrick.start_httpserver(config){|server, addr, port|
+ vhost_config = {
+ :ServerName => "myhostname",
+ :BindAddress => addr,
+ :Port => port,
+ :DoNotListen => true,
+ :Logger => WEBrick::Log.new(TestWEBrick::NullWriter),
+ :AccessLog => [],
+ :RequestCallback => Proc.new{|req, res| requested1 += 1 },
+ }
+ server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
+
+ true while server.status != :Running
+ assert_equal(started, 1)
+ assert_equal(stopped, 0)
+ assert_equal(accepted, 0)
+
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req["Host"] = "myhostname:#{port}"
+ http.request(req){|res| assert_equal("404", res.code)}
+ http.request(req){|res| assert_equal("404", res.code)}
+ http.request(req){|res| assert_equal("404", res.code)}
+ req["Host"] = "localhost:#{port}"
+ http.request(req){|res| assert_equal("404", res.code)}
+ http.request(req){|res| assert_equal("404", res.code)}
+ http.request(req){|res| assert_equal("404", res.code)}
+ assert_equal(6, accepted)
+ assert_equal(3, requested0)
+ assert_equal(3, requested1)
+ }
+ assert_equal(started, 1)
+ assert_equal(stopped, 1)
+ end
+end
diff --git a/trunk/test/webrick/test_httputils.rb b/trunk/test/webrick/test_httputils.rb
new file mode 100644
index 0000000000..9d39ff53ab
--- /dev/null
+++ b/trunk/test/webrick/test_httputils.rb
@@ -0,0 +1,96 @@
+require "test/unit"
+require "webrick/httputils"
+
+class TestWEBrickHTTPUtils < Test::Unit::TestCase
+ include WEBrick::HTTPUtils
+
+ def test_normilize_path
+ assert_equal("/foo", normalize_path("/foo"))
+ assert_equal("/foo/bar/", normalize_path("/foo/bar/"))
+
+ assert_equal("/", normalize_path("/foo/../"))
+ assert_equal("/", normalize_path("/foo/.."))
+ assert_equal("/", normalize_path("/foo/bar/../../"))
+ assert_equal("/", normalize_path("/foo/bar/../.."))
+ assert_equal("/", normalize_path("/foo/bar/../.."))
+ assert_equal("/baz", normalize_path("/foo/bar/../../baz"))
+ assert_equal("/baz", normalize_path("/foo/../bar/../baz"))
+ assert_equal("/baz/", normalize_path("/foo/../bar/../baz/"))
+ assert_equal("/...", normalize_path("/bar/../..."))
+ assert_equal("/.../", normalize_path("/bar/../.../"))
+
+ assert_equal("/foo/", normalize_path("/foo/./"))
+ assert_equal("/foo/", normalize_path("/foo/."))
+ assert_equal("/foo/", normalize_path("/foo/././"))
+ assert_equal("/foo/", normalize_path("/foo/./."))
+ assert_equal("/foo/bar", normalize_path("/foo/./bar"))
+ assert_equal("/foo/bar/", normalize_path("/foo/./bar/."))
+ assert_equal("/foo/bar/", normalize_path("/./././foo/./bar/."))
+
+ assert_equal("/foo/bar/", normalize_path("//foo///.//bar/.///.//"))
+ assert_equal("/", normalize_path("//foo///..///bar/.///..//.//"))
+
+ assert_raises(RuntimeError){ normalize_path("foo/bar") }
+ assert_raises(RuntimeError){ normalize_path("..") }
+ assert_raises(RuntimeError){ normalize_path("/..") }
+ assert_raises(RuntimeError){ normalize_path("/./..") }
+ assert_raises(RuntimeError){ normalize_path("/./../") }
+ assert_raises(RuntimeError){ normalize_path("/./../..") }
+ assert_raises(RuntimeError){ normalize_path("/./../../") }
+ assert_raises(RuntimeError){ normalize_path("/./../") }
+ assert_raises(RuntimeError){ normalize_path("/../..") }
+ assert_raises(RuntimeError){ normalize_path("/../../") }
+ assert_raises(RuntimeError){ normalize_path("/../../..") }
+ assert_raises(RuntimeError){ normalize_path("/../../../") }
+ assert_raises(RuntimeError){ normalize_path("/../foo/../") }
+ assert_raises(RuntimeError){ normalize_path("/../foo/../../") }
+ assert_raises(RuntimeError){ normalize_path("/foo/bar/../../../../") }
+ assert_raises(RuntimeError){ normalize_path("/foo/../bar/../../") }
+ assert_raises(RuntimeError){ normalize_path("/./../bar/") }
+ assert_raises(RuntimeError){ normalize_path("/./../") }
+ end
+
+ def test_split_header_value
+ assert_equal(['foo', 'bar'], split_header_value('foo, bar'))
+ assert_equal(['"foo"', 'bar'], split_header_value('"foo", bar'))
+ assert_equal(['foo', '"bar"'], split_header_value('foo, "bar"'))
+ assert_equal(['*'], split_header_value('*'))
+ assert_equal(['W/"xyzzy"', 'W/"r2d2xxxx"', 'W/"c3piozzzz"'],
+ split_header_value('W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"'))
+ end
+
+ def test_escape
+ assert_equal("/foo/bar", escape("/foo/bar"))
+ assert_equal("/~foo/bar", escape("/~foo/bar"))
+ assert_equal("/~foo%20bar", escape("/~foo bar"))
+ assert_equal("/~foo%20bar", escape("/~foo bar"))
+ assert_equal("/~foo%09bar", escape("/~foo\tbar"))
+ assert_equal("/~foo+bar", escape("/~foo+bar"))
+ end
+
+ def test_escape_form
+ assert_equal("%2Ffoo%2Fbar", escape_form("/foo/bar"))
+ assert_equal("%2F~foo%2Fbar", escape_form("/~foo/bar"))
+ assert_equal("%2F~foo+bar", escape_form("/~foo bar"))
+ assert_equal("%2F~foo+%2B+bar", escape_form("/~foo + bar"))
+ end
+
+ def test_unescape
+ assert_equal("/foo/bar", unescape("%2ffoo%2fbar"))
+ assert_equal("/~foo/bar", unescape("/%7efoo/bar"))
+ assert_equal("/~foo/bar", unescape("%2f%7efoo%2fbar"))
+ assert_equal("/~foo+bar", unescape("/%7efoo+bar"))
+ end
+
+ def test_unescape_form
+ assert_equal("//foo/bar", unescape_form("/%2Ffoo/bar"))
+ assert_equal("//foo/bar baz", unescape_form("/%2Ffoo/bar+baz"))
+ assert_equal("/~foo/bar baz", unescape_form("/%7Efoo/bar+baz"))
+ end
+
+ def test_escape_path
+ assert_equal("/foo/bar", escape_path("/foo/bar"))
+ assert_equal("/foo/bar/", escape_path("/foo/bar/"))
+ assert_equal("/%25foo/bar/", escape_path("/%foo/bar/"))
+ end
+end
diff --git a/trunk/test/webrick/test_httpversion.rb b/trunk/test/webrick/test_httpversion.rb
new file mode 100644
index 0000000000..81a871a226
--- /dev/null
+++ b/trunk/test/webrick/test_httpversion.rb
@@ -0,0 +1,40 @@
+require "test/unit"
+require "webrick/httpversion"
+
+class TestWEBrickHTTPVersion < Test::Unit::TestCase
+ def setup
+ @v09 = WEBrick::HTTPVersion.new("0.9")
+ @v10 = WEBrick::HTTPVersion.new("1.0")
+ @v11 = WEBrick::HTTPVersion.new("1.001")
+ end
+
+ def test_to_s()
+ assert_equal("0.9", @v09.to_s)
+ assert_equal("1.0", @v10.to_s)
+ assert_equal("1.1", @v11.to_s)
+ end
+
+ def test_major()
+ assert_equal(0, @v09.major)
+ assert_equal(1, @v10.major)
+ assert_equal(1, @v11.major)
+ end
+
+ def test_minor()
+ assert_equal(9, @v09.minor)
+ assert_equal(0, @v10.minor)
+ assert_equal(1, @v11.minor)
+ end
+
+ def test_compar()
+ assert_equal(0, @v09 <=> "0.9")
+ assert_equal(0, @v09 <=> "0.09")
+
+ assert_equal(-1, @v09 <=> @v10)
+ assert_equal(-1, @v09 <=> "1.00")
+
+ assert_equal(1, @v11 <=> @v09)
+ assert_equal(1, @v11 <=> "1.0")
+ assert_equal(1, @v11 <=> "0.9")
+ end
+end
diff --git a/trunk/test/webrick/test_server.rb b/trunk/test/webrick/test_server.rb
new file mode 100644
index 0000000000..ce5ee85c6c
--- /dev/null
+++ b/trunk/test/webrick/test_server.rb
@@ -0,0 +1,64 @@
+require "test/unit"
+require "tempfile"
+require "webrick"
+require File.join(File.dirname(__FILE__), "utils.rb")
+
+class TestWEBrickServer < Test::Unit::TestCase
+ class Echo < WEBrick::GenericServer
+ def run(sock)
+ while line = sock.gets
+ sock << line
+ end
+ end
+ end
+
+ def test_server
+ TestWEBrick.start_server(Echo){|server, addr, port|
+ TCPSocket.open(addr, port){|sock|
+ sock.puts("foo"); assert_equal("foo\n", sock.gets)
+ sock.puts("bar"); assert_equal("bar\n", sock.gets)
+ sock.puts("baz"); assert_equal("baz\n", sock.gets)
+ sock.puts("qux"); assert_equal("qux\n", sock.gets)
+ }
+ }
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ config = {
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ }
+ TestWEBrick.start_server(Echo, config){|server, addr, port|
+ true while server.status != :Running
+ assert_equal(started, 1)
+ assert_equal(stopped, 0)
+ assert_equal(accepted, 0)
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ assert_equal(accepted, 3)
+ }
+ assert_equal(started, 1)
+ assert_equal(stopped, 1)
+ end
+
+ def test_daemon
+ begin
+ r, w = IO.pipe
+ Process.fork{
+ r.close
+ WEBrick::Daemon.start
+ w.puts(Process.pid)
+ sleep
+ }
+ assert(Process.kill(:KILL, r.gets.to_i))
+ rescue NotImplementedError
+ # snip this test
+ ensure
+ r.close
+ w.close
+ end
+ end
+end
diff --git a/trunk/test/webrick/test_utils.rb b/trunk/test/webrick/test_utils.rb
new file mode 100644
index 0000000000..ace4632547
--- /dev/null
+++ b/trunk/test/webrick/test_utils.rb
@@ -0,0 +1,64 @@
+require "test/unit"
+require "webrick/utils"
+
+class TestWEBrickUtils < Test::Unit::TestCase
+ def assert_expired(flag, m)
+ if m == WEBrick::Utils
+ handler = WEBrick::Utils::TimeoutHandler.instance
+ assert_equal(flag, handler.instance_eval{ @timeout_info.empty? })
+ end
+ end
+
+ def do_test_timeout(m)
+ ex = Class.new(StandardError)
+
+ assert_equal(:foo, m.timeout(10){ :foo })
+ assert_expired(true, m)
+
+ i = 0
+ assert_raises(Timeout::Error){
+ m.timeout(2){
+ assert_raises(Timeout::Error){ m.timeout(1){ i += 1; sleep } }
+ assert_expired(false, m)
+ i += 1
+ sleep
+ }
+ }
+ assert_equal(2, i)
+ assert_expired(true, m)
+
+ assert_raises(Timeout::Error){ m.timeout(0.1){ sleep } }
+ assert_expired(true, m)
+
+ assert_raises(ex){ m.timeout(0.1, ex){ sleep } }
+ assert_expired(true, m)
+
+ i = 0
+ assert_raises(ex){
+ m.timeout(10){
+ m.timeout(1, ex){ i += 1; sleep }
+ }
+ sleep
+ }
+ assert_equal(1, i)
+ assert_expired(true, m)
+
+ i = 0
+ assert_raises(Timeout::Error){
+ m.timeout(1){
+ m.timeout(10, ex){ i += 1; sleep }
+ }
+ sleep
+ }
+ assert_equal(1, i)
+ assert_expired(true, m)
+ end
+
+ def test_webrick_timeout
+ do_test_timeout(WEBrick::Utils)
+ end
+
+ #def test_timeout
+ # do_test_timeout(Timeout)
+ #end
+end
diff --git a/trunk/test/webrick/utils.rb b/trunk/test/webrick/utils.rb
new file mode 100644
index 0000000000..39cadcff54
--- /dev/null
+++ b/trunk/test/webrick/utils.rb
@@ -0,0 +1,56 @@
+begin
+ loadpath = $:.dup
+ $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
+ require 'envutil'
+ensure
+ $:.replace(loadpath)
+end
+require "webrick"
+begin
+ require "webrick/https"
+rescue LoadError
+end
+require "webrick/httpproxy"
+
+module TestWEBrick
+ NullWriter = Object.new
+ def NullWriter.<<(msg)
+ puts msg if $DEBUG
+ return self
+ end
+
+ RubyBin = "\"#{EnvUtil.rubybin}\""
+ RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\""
+ RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\""
+ RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\""
+
+ module_function
+
+ def start_server(klass, config={}, &block)
+ server = klass.new({
+ :BindAddress => "127.0.0.1", :Port => 0,
+ :ShutdownSocketWithoutClose =>true,
+ :ServerType => Thread,
+ :Logger => WEBrick::Log.new(NullWriter),
+ :AccessLog => [[NullWriter, ""]]
+ }.update(config))
+ begin
+ server.start
+ addr = server.listeners[0].addr
+ block.yield([server, addr[3], addr[1]])
+ ensure
+ server.shutdown
+ until server.status == :Stop
+ sleep 0.1
+ end
+ end
+ end
+
+ def start_httpserver(config={}, &block)
+ start_server(WEBrick::HTTPServer, config, &block)
+ end
+
+ def start_httpproxy(config={}, &block)
+ start_server(WEBrick::HTTPProxyServer, config, &block)
+ end
+end
diff --git a/trunk/test/webrick/webrick.cgi b/trunk/test/webrick/webrick.cgi
new file mode 100644
index 0000000000..73ba729407
--- /dev/null
+++ b/trunk/test/webrick/webrick.cgi
@@ -0,0 +1,36 @@
+#!ruby -d
+require "webrick/cgi"
+
+class TestApp < WEBrick::CGI
+ def do_GET(req, res)
+ res["content-type"] = "text/plain"
+ if (p = req.path_info) && p.length > 0
+ res.body = p
+ elsif (q = req.query).size > 0
+ res.body = q.keys.sort.collect{|key|
+ q[key].list.sort.collect{|v|
+ "#{key}=#{v}"
+ }.join(", ")
+ }.join(", ")
+ elsif %r{/$} =~ req.request_uri.to_s
+ res.body = ""
+ res.body << req.request_uri.to_s << "\n"
+ res.body << req.script_name
+ elsif !req.cookies.empty?
+ res.body = req.cookies.inject(""){|result, cookie|
+ result << "%s=%s\n" % [cookie.name, cookie.value]
+ }
+ res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE")
+ res.cookies << WEBrick::Cookie.new("Shipping", "FedEx")
+ else
+ res.body = req.script_name
+ end
+ end
+
+ def do_POST(req, res)
+ do_GET(req, res)
+ end
+end
+
+cgi = TestApp.new
+cgi.start
diff --git a/trunk/test/webrick/webrick_long_filename.cgi b/trunk/test/webrick/webrick_long_filename.cgi
new file mode 100644
index 0000000000..73ba729407
--- /dev/null
+++ b/trunk/test/webrick/webrick_long_filename.cgi
@@ -0,0 +1,36 @@
+#!ruby -d
+require "webrick/cgi"
+
+class TestApp < WEBrick::CGI
+ def do_GET(req, res)
+ res["content-type"] = "text/plain"
+ if (p = req.path_info) && p.length > 0
+ res.body = p
+ elsif (q = req.query).size > 0
+ res.body = q.keys.sort.collect{|key|
+ q[key].list.sort.collect{|v|
+ "#{key}=#{v}"
+ }.join(", ")
+ }.join(", ")
+ elsif %r{/$} =~ req.request_uri.to_s
+ res.body = ""
+ res.body << req.request_uri.to_s << "\n"
+ res.body << req.script_name
+ elsif !req.cookies.empty?
+ res.body = req.cookies.inject(""){|result, cookie|
+ result << "%s=%s\n" % [cookie.name, cookie.value]
+ }
+ res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE")
+ res.cookies << WEBrick::Cookie.new("Shipping", "FedEx")
+ else
+ res.body = req.script_name
+ end
+ end
+
+ def do_POST(req, res)
+ do_GET(req, res)
+ end
+end
+
+cgi = TestApp.new
+cgi.start
diff --git a/trunk/test/win32ole/err_in_callback.rb b/trunk/test/win32ole/err_in_callback.rb
new file mode 100644
index 0000000000..d09870c95d
--- /dev/null
+++ b/trunk/test/win32ole/err_in_callback.rb
@@ -0,0 +1,11 @@
+require 'win32ole'
+ie = WIN32OLE.new('InternetExplorer.Application')
+ie.visible = true
+WIN32OLE_EVENT.message_loop
+sleep 0.2
+ev = WIN32OLE_EVENT.new(ie)
+
+ev.on_event('BeforeNavigate2') {|*args|
+ foo
+}
+ie.navigate(ARGV.shift)
diff --git a/trunk/test/win32ole/test_err_in_callback.rb b/trunk/test/win32ole/test_err_in_callback.rb
new file mode 100644
index 0000000000..11ea6273fd
--- /dev/null
+++ b/trunk/test/win32ole/test_err_in_callback.rb
@@ -0,0 +1,82 @@
+#
+# test Win32OLE avoids cfp consistency error when the exception raised
+# in WIN32OLE_EVENT handler block. [ruby-dev:35450]
+#
+
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'rbconfig'
+if defined?(WIN32OLE)
+ require 'mkmf'
+ require 'test/unit'
+ class TestErrInCallBack < Test::Unit::TestCase
+ def setup
+ @ruby = nil
+ if File.exist?("./" + CONFIG["RUBY_INSTALL_NAME"] + CONFIG["EXEEXT"])
+ sep = File::ALT_SEPARATOR || "/"
+ @ruby = "." + sep + CONFIG["RUBY_INSTALL_NAME"]
+ @iopt = $:.map {|e|
+ " -I " + e
+ }.join("")
+ @script = File.dirname(__FILE__) + "/err_in_callback.rb"
+ @param = create_temp_html
+ @param = "file:///" + @param.gsub(/\\/, '/')
+ end
+ end
+
+ def create_temp_html
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ dummy_file = fso.GetTempName + ".html"
+ cfolder = fso.getFolder(".")
+ @str = "This is test HTML file for Win32OLE (#{Time.now})"
+ f = cfolder.CreateTextFile(dummy_file)
+ f.writeLine("<html><body><div id='str'>#{@str}</div></body></html>")
+ f.close
+ @f = dummy_file
+ dummy_path = cfolder.path + "\\" + dummy_file
+ dummy_path
+ end
+
+ def test_err_in_callback
+ if @ruby
+ cmd = "#{@ruby} -v #{@iopt} #{@script} #{@param} > test_err_in_callback.log 2>&1"
+ system(cmd)
+ str = ""
+ open("test_err_in_callback.log") {|ifs|
+ str = ifs.read
+ }
+ assert_match(/NameError/, str)
+ end
+ end
+
+ def ie_quit
+ sh = WIN32OLE.new('Shell.Application')
+ sh.windows.each do |w|
+ if w.ole_type.name == 'IWebBrowser2'
+ 20.times do |i|
+ if w.locationURL != "" && w.document
+ break
+ end
+ WIN32OLE_EVENT.message_loop
+ sleep 1
+ end
+ e = w.document.getElementById("str")
+ if e && e.innerHTML == @str
+ w.quit
+ WIN32OLE_EVENT.message_loop
+ sleep 0.2
+ end
+ end
+ end
+ end
+
+ def teardown
+ WIN32OLE_EVENT.message_loop
+ ie_quit
+ File.unlink(@f)
+ File.unlink("test_err_in_callback.log")
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_folderitem2_invokeverb.rb b/trunk/test/win32ole/test_folderitem2_invokeverb.rb
new file mode 100644
index 0000000000..07cb9802d6
--- /dev/null
+++ b/trunk/test/win32ole/test_folderitem2_invokeverb.rb
@@ -0,0 +1,89 @@
+#
+# This script check that Win32OLE can execute InvokeVerb method of FolderItem2.
+#
+
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(WIN32OLE)
+ class TestInvokeVerb < Test::Unit::TestCase
+ def setup
+ #
+ # make dummy.txt file for InvokeVerb test.
+ #
+
+ @fso = WIN32OLE.new('Scripting.FileSystemObject')
+ @dummy_file = @fso.GetTempName
+ @cfolder = @fso.getFolder(".")
+ f = @cfolder.CreateTextFile(@dummy_file)
+ f.close
+ @dummy_path = @cfolder.path + "\\" + @dummy_file
+
+ @shell=WIN32OLE.new('Shell.Application')
+ @nsp = @shell.NameSpace(@cfolder.path)
+ @fi2 = @nsp.parseName(@dummy_file)
+
+ @shortcut = nil
+
+ #
+ # Search the 'Create Shortcut (&S)' string in Japanese.
+ # Yes, I know the string in the Windows 2000 Japanese Edition.
+ # But I do not know about the string in any other Windows.
+ #
+ verbs = @fi2.verbs
+ verbs.extend(Enumerable)
+ @cp = WIN32OLE.codepage
+ begin
+ WIN32OLE.codepage = 932
+ rescue
+ end
+ @shortcut = verbs.collect{|verb|
+ verb.name
+ }.find {|name|
+ name.unpack("C*") == [131, 86, 131, 135, 129, 91, 131, 103, 131, 74, 131, 98, 131, 103, 130, 204, 141, 236, 144, 172, 40, 38, 83, 41]
+ # /.*\(\&S\)$/ =~ name
+ }
+ end
+
+ def find_link(path)
+ arlink = []
+ @cfolder.files.each do |f|
+ if /\.lnk$/ =~ f.path
+ linkinfo = @nsp.parseName(f.name).getLink
+ arlink.push f if linkinfo.path == path
+ end
+ end
+ arlink
+ end
+
+ def test_invokeverb
+ links = find_link(@dummy_path)
+ assert(0, links.size)
+
+ assert(@shortcut)
+
+ # Now create shortcut to @dummy_path
+ arg = WIN32OLE_VARIANT.new(@shortcut)
+ @fi2.InvokeVerb(arg)
+
+ # Now search shortcut to @dummy_path
+ links = find_link(@dummy_path)
+ assert(1, links.size)
+ @lpath = links[0].path
+ end
+
+ def teardown
+ if @lpath
+ @fso.deleteFile(@lpath)
+ end
+ if @dummy_path
+ @fso.deleteFile(@dummy_path)
+ end
+ WIN32OLE.codepage = @cp
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_nil2vtempty.rb b/trunk/test/win32ole/test_nil2vtempty.rb
new file mode 100644
index 0000000000..4be3902b6d
--- /dev/null
+++ b/trunk/test/win32ole/test_nil2vtempty.rb
@@ -0,0 +1,36 @@
+# This is test script to check that WIN32OLE should convert nil to VT_EMPTY in second try.
+# [ruby-talk:137054]
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(WIN32OLE)
+ class TestNIL2VT_EMPTY < Test::Unit::TestCase
+ def setup
+ fs = WIN32OLE.new('Scripting.FileSystemObject')
+ @path = fs.GetFolder(".").path
+ end
+ def test_openSchema
+ con = nil
+ begin
+ con = WIN32OLE.new('ADODB.Connection')
+ con.connectionString = "Provider=MSDASQL;Extended Properties="
+ con.connectionString +="\"DRIVER={Microsoft Text Driver (*.txt; *.csv)};DBQ=#{@path}\""
+ con.open
+ rescue
+ con = nil
+ end
+ if con
+ rs = con.openSchema(4, [nil,nil,"DUMMY", "TABLE"])
+ assert(rs)
+ assert_equal("_Recordset", rs.ole_type.name)
+
+ rs = con.openSchema(4, [WIN32OLE_VARIANT::Empty, WIN32OLE_VARIANT::Empty, "DUMMY", "TABLE"])
+ assert(rs)
+ assert_equal("_Recordset", rs.ole_type.name)
+ end
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_ole_methods.rb b/trunk/test/win32ole/test_ole_methods.rb
new file mode 100644
index 0000000000..ca1c03b010
--- /dev/null
+++ b/trunk/test/win32ole/test_ole_methods.rb
@@ -0,0 +1,36 @@
+#
+# This is test for [ruby-talk:196897]
+#
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE)
+ class TestWIN32OLE_FOR_PROPERTYPUTREF < Test::Unit::TestCase
+
+ def setup
+ @obj = WIN32OLE.new('Scripting.Dictionary')
+ end
+
+ def test_ole_methods
+ x = @obj.ole_methods.select {|m|
+ m.invoke_kind == 'PROPERTYPUTREF'
+ }
+ assert(x.size > 0)
+ assert_equal(1, x.size)
+ assert_equal('Item', x[0].name)
+ end
+
+ def test_ole_put_methods
+ x = @obj.ole_put_methods.select {|m|
+ m.invoke_kind == 'PROPERTYPUTREF'
+ }
+ assert(x.size > 0)
+ assert_equal(1, x.size)
+ assert_equal('Item', x[0].name)
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_propertyputref.rb b/trunk/test/win32ole/test_propertyputref.rb
new file mode 100644
index 0000000000..24459afe9b
--- /dev/null
+++ b/trunk/test/win32ole/test_propertyputref.rb
@@ -0,0 +1,30 @@
+require 'test/unit'
+begin
+ require 'win32ole'
+rescue LoadError
+end
+
+if defined?(WIN32OLE)
+ class TestWIN32OLE_PROPERTYPUTREF < Test::Unit::TestCase
+ def setup
+ begin
+ @sapi = WIN32OLE.new('SAPI.SpVoice')
+ @sv = @sapi.voice
+ rescue WIN32OLERuntimeError
+ @sapi = nil
+ end
+ end
+ def test_sapi
+ if @sapi
+ new_id = @sapi.getvoices.item(0).Id
+ @sapi.voice = @sapi.getvoices.item(0)
+ assert_equal(new_id, @sapi.voice.Id)
+ end
+ end
+ def teardown
+ if @sapi
+ @sapi.voice = @sv
+ end
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole.rb b/trunk/test/win32ole/test_win32ole.rb
new file mode 100644
index 0000000000..d9e595347c
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole.rb
@@ -0,0 +1,445 @@
+#
+
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(WIN32OLE)
+ module CONST1
+ end
+ module CONST2
+ end
+
+ module TestCaseForDict
+ def test_convert_bignum
+ @dict1.add("a", 9999999999)
+ @dict1.add("b", 999999999)
+ @dict1.add("c", @dict1.item("b") * 10 + 9)
+ assert_equal(9999999999, @dict1.item("a"))
+ assert_equal(9999999999, @dict1.item("c"))
+ end
+ def test_add
+ @dict1.add("a", 1000)
+ assert_equal(1000, @dict1.item("a"))
+ end
+ def test_setproperty_equal_ended
+ @dict1.compareMode = 1
+ @dict1.add("one", 1)
+ assert_equal(1, @dict1.item("ONE"))
+ @dict2.add("one", 1)
+ assert_nil(@dict2.item("ONE"))
+ assert_equal(1, @dict2.item("one"))
+ end
+ def test_non_exist_property
+ assert_raise(WIN32OLERuntimeError) {
+ @dict1.unknown_property = 1
+ }
+ end
+
+ def test_raise_message
+ exc = assert_raise(WIN32OLERuntimeError) {
+ @dict1.add
+ }
+ assert_match(/^\(in OLE method `add': \)/, exc.message) #`
+
+ exc = assert_raise(WIN32OLERuntimeError) {
+ @dict1._invoke(1, [], [])
+ }
+ assert_match(/^\(in OLE method `<dispatch id:1>': \)/, exc.message) #`
+
+ exc = assert_raise(WIN32OLERuntimeError) {
+ @dict1.compareMode = -1
+ }
+ assert_match(/^\(in setting property `compareMode': \)/, exc.message) #`
+ end
+
+ def test_ole_methods
+ methods = @dict1.ole_methods
+ mnames = methods.collect {|m|
+ m.name
+ }
+ assert(mnames.include?("Add"))
+ end
+
+ def test_ole_func_methods
+ methods = @dict1.ole_func_methods
+ mnames = methods.collect {|m|
+ m.name
+ }
+ assert(mnames.include?("Add"))
+ end
+
+ def test_ole_put_methods
+ methods = @dict1.ole_put_methods
+ mnames = methods.collect {|m|
+ m.name
+ }
+ assert(mnames.include?("CompareMode"))
+ end
+
+ def test_ole_get_methods
+ methods = @dict1.ole_get_methods
+ mnames = methods.collect {|m|
+ m.name
+ }
+ assert(mnames.include?("Count"))
+ end
+
+ def test_ole_mehtod_help
+ minfo = @dict1.ole_method_help("Add")
+ assert_equal(2, minfo.size_params)
+ end
+
+ def test_ole_typelib
+ tlib = @dict1.ole_typelib
+ assert_equal("Microsoft Scripting Runtime", tlib.name);
+ end
+
+ def test_each
+ @dict1.add("one", 1)
+ @dict1.add("two", 2)
+ i = 0
+ @dict1.keys.each do |item|
+ i += 1
+ end
+ assert_equal(2, i)
+ end
+
+ def test_bracket
+ @dict1.add("foo", "FOO")
+ assert_equal("FOO", @dict1.item("foo"))
+ assert_equal("FOO", @dict1["foo"])
+ end
+
+ def test_bracket_equal
+ @dict1.add("foo", "FOO")
+ @dict1["foo"] = "BAR"
+ assert_equal("BAR", @dict1["foo"])
+ end
+
+ def test_invoke_with_array
+ @dict1.add("ary1", [1,2,3])
+ assert_equal([1,2,3], @dict1["ary1"])
+
+ @dict1.add("ary2", [[1,2,"a"], [3,4,"b"]])
+ assert_equal([[1,2,"a"], [3,4,"b"]], @dict1["ary2"])
+
+ @dict1.add("ary3", [[[1]]])
+ assert_equal([[[1]]], @dict1["ary3"])
+
+ @dict1.add("ary4", [[[1], [2], [3]], [[4], [5], [6]]])
+ assert_equal([[[1],[2], [3]], [[4], [5], [6]]], @dict1["ary4"])
+ end
+ end
+
+ class TestWin32OLE < Test::Unit::TestCase
+ include TestCaseForDict
+ def setup
+ @dict1 = WIN32OLE.new('Scripting.Dictionary')
+ @dict2 = WIN32OLE.new('Scripting.Dictionary')
+ end
+ def test_s_new
+ assert_instance_of(WIN32OLE, @dict1)
+ assert_instance_of(WIN32OLE, @dict2)
+ end
+
+ def test_s_new_DCOM
+ rshell = WIN32OLE.new("Shell.Application")
+ assert_instance_of(WIN32OLE, rshell)
+ end
+
+ def test_s_new_from_clsid
+ shell = WIN32OLE.new("{13709620-C279-11CE-A49E-444553540000}")
+ assert_instance_of(WIN32OLE, shell)
+ exc = assert_raise(WIN32OLERuntimeError) {
+ WIN32OLE.new("{000}")
+ }
+ assert_match(/unknown OLE server: `\{000\}'/, exc.message) #`
+ end
+
+ def test_s_connect
+ obj = WIN32OLE.connect("winmgmts:")
+ assert_instance_of(WIN32OLE, obj)
+ end
+
+ def test_invoke_accept_symbol_hash_key
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ afolder = fso.getFolder(".")
+ bfolder = fso.getFolder({"FolderPath" => "."})
+ cfolder = fso.getFolder({:FolderPath => "."})
+ assert_equal(afolder.path, bfolder.path)
+ assert_equal(afolder.path, cfolder.path)
+ fso = nil
+ end
+
+ def test_setproperty
+ installer = WIN32OLE.new("WindowsInstaller.Installer")
+ record = installer.CreateRecord(2)
+ # this is the way to set property with argument in Win32OLE.
+ record.setproperty( "StringData", 1, 'dddd')
+ assert_equal('dddd', record.StringData(1))
+ end
+
+ def test_ole_type
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ tobj = fso.ole_type
+ assert_match(/^IFileSystem/, tobj.name)
+ end
+
+ def test_ole_obj_help
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ tobj = fso.ole_obj_help
+ assert_match(/^IFileSystem/, tobj.name)
+ end
+
+
+ def test_invoke_hash_key_non_str_sym
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ begin
+ bfolder = fso.getFolder({1 => "."})
+ assert(false)
+ rescue TypeError
+ assert(true)
+ end
+ fso = nil
+ end
+
+ def test_get_win32ole_object
+ shell = WIN32OLE.new('Shell.Application')
+ folder = shell.nameSpace(0)
+ assert_instance_of(WIN32OLE, folder)
+ end
+
+ def test_invoke_accept_multi_hash_key
+ shell = WIN32OLE.new('Shell.Application')
+ folder = shell.nameSpace(0)
+ item = folder.items.item(0)
+ name = folder.getDetailsOf(item, 0)
+ assert_equal(item.name, name)
+ name = folder.getDetailsOf({:vItem => item, :iColumn => 0})
+ assert_equal(item.name, name)
+ name = folder.getDetailsOf({"vItem" => item, :iColumn => 0})
+ assert_equal(item.name, name)
+ end
+
+ def test_ole_invoke_with_named_arg_last
+ shell = WIN32OLE.new('Shell.Application')
+ folder = shell.nameSpace(0)
+ item = folder.items.item(0)
+ name = folder.getDetailsOf(item, {:iColumn => 0})
+ assert_equal(item.name, name)
+ end
+
+ def test__invoke
+ shell=WIN32OLE.new('Shell.Application')
+ assert_equal(shell.NameSpace(0).title, shell._invoke(0x60020002, [0], [WIN32OLE::VARIANT::VT_VARIANT]).title)
+ end
+
+ def test_ole_query_interface
+ shell=WIN32OLE.new('Shell.Application')
+ assert_raise(ArgumentError) {
+ shell2 = shell.ole_query_interface
+ }
+ shell2 = shell.ole_query_interface('{A4C6892C-3BA9-11D2-9DEA-00C04FB16162}')
+ assert_instance_of(WIN32OLE, shell2)
+ end
+
+ def test_ole_respond_to
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ assert(fso.ole_respond_to?('getFolder'))
+ assert(fso.ole_respond_to?('GETFOLDER'))
+ assert(fso.ole_respond_to?(:getFolder))
+ assert(!fso.ole_respond_to?('XXXXX'))
+ assert_raise(TypeError) {
+ assert_raise(fso.ole_respond_to?(1))
+ }
+ end
+
+ def test_invoke
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ assert(fso.invoke(:getFolder, "."))
+ assert(fso.invoke('getFolder', "."))
+ end
+
+ def test_s_const_load
+ assert(!defined?(CONST1::SsfWINDOWS))
+ shell=WIN32OLE.new('Shell.Application')
+ WIN32OLE.const_load(shell, CONST1)
+ assert_equal(36, CONST1::SsfWINDOWS)
+
+ assert(!defined?(CONST2::SsfWINDOWS))
+ WIN32OLE.const_load("Microsoft Shell Controls And Automation", CONST2)
+ assert_equal(36, CONST2::SsfWINDOWS)
+ end
+
+ def test_s_create_guid
+ guid = WIN32OLE.create_guid
+ assert_match(/^\{[A-Z0-9]{8}\-[A-Z0-9]{4}\-[A-Z0-9]{4}\-[A-Z0-9]{4}\-[A-Z0-9]{12}/,
+ guid)
+ end
+
+ #
+ # WIN32OLE.codepage is initialized according to Encoding.default_external.
+ #
+ # def test_s_codepage
+ # assert_equal(WIN32OLE::CP_ACP, WIN32OLE.codepage)
+ # end
+
+ def test_s_codepage_set
+ cp = WIN32OLE.codepage
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
+ assert_equal(WIN32OLE::CP_UTF8, WIN32OLE.codepage)
+ WIN32OLE.codepage = cp
+ end
+
+ def test_s_codepage_changed
+ cp = WIN32OLE.codepage
+ fso = WIN32OLE.new("Scripting.FileSystemObject")
+ fname = fso.getTempName
+ begin
+ obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8"))
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
+ assert_equal("\xE3\x81\x82".force_encoding("CP65001"), obj.value)
+
+ begin
+ WIN32OLE.codepage = 932 # Windows-31J
+ rescue WIN32OLERuntimeError
+ end
+ if (WIN32OLE.codepage == 932)
+ assert_equal("\x82\xA0".force_encoding("CP932"), obj.value)
+ end
+
+ begin
+ WIN32OLE.codepage = 20932 # MS EUC-JP
+ rescue WIN32OLERuntimeError
+ end
+ if (WIN32OLE.codepage == 20932)
+ assert_equal("\xA4\xA2".force_encoding("CP20932"), obj.value)
+ end
+
+ WIN32OLE.codepage = cp
+ file = fso.opentextfile(fname, 2, true)
+ file.write [0x3042].pack("U*").force_encoding("UTF-8")
+ file.close
+ str = ""
+ open(fname, "r:ascii-8bit") {|ifs|
+ str = ifs.read
+ }
+ assert_equal("\202\240", str)
+
+ # This test fail if codepage 20932 (euc) is not installed.
+ begin
+ WIN32OLE.codepage = 20932
+ rescue WIN32OLERuntimeError
+ end
+ if (WIN32OLE.codepage == 20932)
+ WIN32OLE.codepage = cp
+ file = fso.opentextfile(fname, 2, true)
+ file.write [164, 162].pack("c*").force_encoding("EUC-JP")
+ file.close
+ open(fname, "r:ascii-8bit") {|ifs|
+ str = ifs.read
+ }
+ assert_equal("\202\240", str)
+ end
+
+ ensure
+ WIN32OLE.codepage = cp
+ if (File.exist?(fname))
+ File.unlink(fname)
+ end
+ end
+ end
+
+ def test_s_locale
+ assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale)
+ end
+
+ def test_s_locale_set
+ begin
+ WIN32OLE.locale = 1041
+ assert_equal(1041, WIN32OLE.locale)
+ WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ assert_raise(WIN32OLERuntimeError) {
+ WIN32OLE.locale = 111
+ }
+ assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale)
+ ensure
+ WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ end
+ end
+
+ def test_s_locale_change
+ begin
+ WIN32OLE.locale = 0x0411
+ obj = WIN32OLE_VARIANT.new("\\100,000", WIN32OLE::VARIANT::VT_CY)
+ assert_equal("100000", obj.value)
+ assert_raise(WIN32OLERuntimeError) {
+ obj = WIN32OLE_VARIANT.new("$100.000", WIN32OLE::VARIANT::VT_CY)
+ }
+
+ WIN32OLE.locale = 1033
+ obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
+ assert_equal("100000", obj.value)
+ ensure
+ WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ end
+ end
+
+ def test_const_CP_ACP
+ assert_equal(0, WIN32OLE::CP_ACP)
+ end
+
+ def test_const_CP_OEMCP
+ assert_equal(1, WIN32OLE::CP_OEMCP)
+ end
+
+ def test_const_CP_MACCP
+ assert_equal(2, WIN32OLE::CP_MACCP)
+ end
+
+ def test_const_CP_THREAD_ACP
+ assert_equal(3, WIN32OLE::CP_THREAD_ACP)
+ end
+
+ def test_const_CP_SYMBOL
+ assert_equal(42, WIN32OLE::CP_SYMBOL)
+ end
+
+ def test_const_CP_UTF7
+ assert_equal(65000, WIN32OLE::CP_UTF7)
+ end
+
+ def test_const_CP_UTF8
+ assert_equal(65001, WIN32OLE::CP_UTF8)
+ end
+
+ def test_const_LOCALE_SYSTEM_DEFAULT
+ assert_equal(0x0800, WIN32OLE::LOCALE_SYSTEM_DEFAULT);
+ end
+
+ def test_const_LOCALE_USER_DEFAULT
+ assert_equal(0x0400, WIN32OLE::LOCALE_USER_DEFAULT);
+ end
+ end
+
+ # test of subclass of WIN32OLE
+ class MyDict < WIN32OLE
+ def MyDict.new
+ super('Scripting.Dictionary')
+ end
+ end
+ class TestMyDict < Test::Unit::TestCase
+ include TestCaseForDict
+ def setup
+ @dict1 = MyDict.new
+ @dict2 = MyDict.new
+ end
+ def test_s_new
+ assert_instance_of(MyDict, @dict1)
+ assert_instance_of(MyDict, @dict2)
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_event.rb b/trunk/test/win32ole/test_win32ole_event.rb
new file mode 100644
index 0000000000..5b2a1af420
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_event.rb
@@ -0,0 +1,333 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(WIN32OLE_EVENT)
+ class TestWIN32OLE_EVENT < Test::Unit::TestCase
+ module IE
+ end
+ def create_temp_html
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ dummy_file = fso.GetTempName + ".html"
+ cfolder = fso.getFolder(".")
+ f = cfolder.CreateTextFile(dummy_file)
+ f.writeLine("<html><body>This is test HTML file for Win32OLE.</body></html>")
+ f.close
+ dummy_path = cfolder.path + "\\" + dummy_file
+ dummy_path
+ end
+
+ def message_loop
+ WIN32OLE_EVENT.message_loop
+ sleep 0.1
+ end
+
+ def wait_ie
+ while @ie.readyState != IE::READYSTATE_COMPLETE
+ message_loop
+ end
+ end
+
+ def setup
+ WIN32OLE_EVENT.message_loop
+ @ie = WIN32OLE.new("InternetExplorer.Application")
+ if !defined?(IE::READYSTATE_COMPLETE)
+ WIN32OLE.const_load(@ie, IE)
+ end
+ @ie.visible = true
+ message_loop
+ @event = ""
+ @event2 = ""
+ @event3 = ""
+ @f = create_temp_html
+ end
+
+ def default_handler(event, *args)
+ @event += event
+ end
+
+ def test_s_new
+ assert_raise(TypeError) {
+ ev = WIN32OLE_EVENT.new("A")
+ }
+ end
+
+ def test_s_new_without_itf
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event {|*args| default_handler(*args)}
+ @ie.navigate("file:///#{@f}")
+ while @ie.busy
+ WIN32OLE_EVENT.new(@ie)
+ GC.start
+ message_loop
+ end
+ assert_match(/BeforeNavigate/, @event)
+ assert_match(/NavigateComplete/, @event)
+ end
+
+ def test_on_event
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event {|*args| default_handler(*args)}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_match(/BeforeNavigate/, @event)
+ assert_match(/NavigateComplete/, @event)
+ end
+
+ def test_on_event_symbol
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event(:BeforeNavigate2) {|*args|
+ handler1
+ }
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("handler1", @event2)
+ end
+
+ def test_on_event2
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event('BeforeNavigate') {|*args| handler1}
+ ev.on_event('BeforeNavigate') {|*args| handler2}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("handler2", @event2)
+ end
+
+ def test_on_event3
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event {|*args| handler1}
+ ev.on_event {|*args| handler2}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("handler2", @event2)
+ end
+
+ def test_on_event4
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event{|*args| handler1}
+ ev.on_event{|*args| handler2}
+ ev.on_event('NavigateComplete'){|*args| handler3(*args)}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert(@event3!="")
+ assert("handler2", @event2)
+ end
+
+ def test_on_event5
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event {|*args| default_handler(*args)}
+ ev.on_event('NavigateComplete'){|*args| handler3(*args)}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_match(/BeforeNavigate/, @event)
+ assert(/NavigateComplete/ !~ @event)
+ assert(@event!="")
+ end
+
+ def test_unadvise
+ ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ ev.on_event {|*args| default_handler(*args)}
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_match(/BeforeNavigate/, @event)
+ ev.unadvise
+ @event = ""
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("", @event);
+ assert_raise(WIN32OLERuntimeError) {
+ ev.on_event {|*args| default_handler(*args)}
+ }
+ end
+
+ def test_non_exist_event
+ assert_raise(RuntimeError) {
+ ev = WIN32OLE_EVENT.new(@ie, 'XXXX')
+ }
+ dict = WIN32OLE.new('Scripting.Dictionary')
+ assert_raise(RuntimeError) {
+ ev = WIN32OLE_EVENT.new(dict)
+ }
+ end
+
+ def test_on_event_with_outargs
+ ev = WIN32OLE_EVENT.new(@ie)
+ # ev.on_event_with_outargs('BeforeNavigate'){|*args|
+ # args.last[5] = true # Cancel = true
+ # }
+ ev.on_event_with_outargs('BeforeNavigate2'){|*args|
+ args.last[6] = true # Cancel = true
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_on_event_hash_return
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){|*args|
+ {:return => 1, :Cancel => true}
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_on_event_hash_return2
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){|*args|
+ {:Cancel => true}
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_on_event_hash_return3
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){|*args|
+ {'Cancel' => true}
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_on_event_hash_return4
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){|*args|
+ {'return' => 2, 'Cancel' => true}
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_on_event_hash_return5
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){|*args|
+ {6 => true}
+ }
+ bl = @ie.locationURL
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal(bl, @ie.locationURL)
+ end
+
+ def test_off_event
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event{handler1}
+ ev.off_event
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("", @event2)
+ end
+
+ def test_off_event_arg
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){handler1}
+ ev.off_event('BeforeNavigate2')
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("", @event2)
+ end
+
+ def test_off_event_sym_arg
+ ev = WIN32OLE_EVENT.new(@ie)
+ ev.on_event('BeforeNavigate2'){handler1}
+ ev.off_event(:BeforeNavigate2)
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert_equal("", @event2)
+ end
+
+ def handler1
+ @event2 = "handler1"
+ end
+
+ def handler2
+ @event2 = "handler2"
+ end
+
+ def handler3(url)
+ @event3 += url
+ end
+
+ def teardown
+ @ie.quit
+ message_loop
+ @ie = nil
+ i = 0
+ begin
+ i += 1
+ File.unlink(@f) if i < 10
+ rescue Errno::EACCES
+ message_loop
+ retry
+ end
+ message_loop
+ GC.start
+ message_loop
+ end
+
+ class Handler1
+ attr_reader :val1, :val2, :val3, :val4
+ def initialize
+ @val1 = nil
+ @val2 = nil
+ @val3 = nil
+ @val4 = nil
+ end
+ def onStatusTextChange(t)
+ @val1 = t
+ end
+ def onProgressChange(p, pmax)
+ @val2 = p
+ @val3 = pmax
+ end
+ def onPropertyChange(p)
+ @val4 = p
+ end
+ end
+
+ class Handler2
+ attr_reader :ev
+ def initialize
+ @ev = ""
+ end
+ def method_missing(ev, *arg)
+ @ev += ev
+ end
+ end
+
+ def test_handler1
+ ev = WIN32OLE_EVENT.new(@ie)
+ h1 = Handler1.new
+ ev.handler = h1
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert(h1.val1)
+ assert_equal(h1.val1, ev.handler.val1)
+ assert(h1.val2)
+ assert(h1.val3)
+ assert(h1.val4)
+ end
+
+ def test_handler2
+ ev = WIN32OLE_EVENT.new(@ie)
+ h2 = Handler2.new
+ ev.handler = h2
+ @ie.navigate("file:///#{@f}")
+ wait_ie
+ assert(h2.ev != "")
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_method.rb b/trunk/test/win32ole/test_win32ole_method.rb
new file mode 100644
index 0000000000..161b10233f
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_method.rb
@@ -0,0 +1,138 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE_METHOD)
+ class TestWIN32OLE_METHOD < Test::Unit::TestCase
+
+ def setup
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_open = WIN32OLE_METHOD.new(ole_type, "open")
+ @m_namespace = WIN32OLE_METHOD.new(ole_type, "namespace")
+ @m_parent = WIN32OLE_METHOD.new(ole_type, "parent")
+ @m_invoke = WIN32OLE_METHOD.new(ole_type, "invoke")
+ @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Internet Controls", "WebBrowser")
+ @m_navigate_complete = WIN32OLE_METHOD.new(ole_type, "NavigateComplete")
+ end
+
+ def test_initialize
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ assert_raise(ArgumentError) {
+ method = WIN32OLE_METHOD.new("foo")
+ }
+ assert_raise(ArgumentError) {
+ method = WIN32OLE_METHOD.new(ole_type)
+ }
+ assert_raise(WIN32OLERuntimeError) {
+ method = WIN32OLE_METHOD.new(ole_type, "NonExistMethod")
+ }
+ assert_raise(TypeError) {
+ method = WIN32OLE_METHOD.new(ole_type, 1)
+ }
+ method = WIN32OLE_METHOD.new(ole_type, "Open")
+ assert_instance_of(WIN32OLE_METHOD, method)
+ method = WIN32OLE_METHOD.new(ole_type, "open")
+ assert_instance_of(WIN32OLE_METHOD, method)
+ end
+
+ def test_name
+ assert_equal("Open", @m_open.name)
+ end
+
+ def test_return_type
+ assert_equal("VOID", @m_open.return_type)
+ assert_equal("Folder", @m_namespace.return_type)
+ end
+
+ def test_return_vtype
+ assert_equal(24, @m_open.return_vtype)
+ assert_equal(26, @m_namespace.return_vtype)
+ end
+
+ def test_return_type_detail
+ assert_equal(['VOID'], @m_open.return_type_detail)
+ assert_equal(['PTR', 'USERDEFINED', 'Folder'], @m_namespace.return_type_detail)
+ end
+
+ def test_invoke_kind
+ assert_equal('FUNC', @m_open.invoke_kind)
+ assert_equal('FUNC', @m_namespace.invoke_kind)
+ assert_equal('PROPERTYGET', @m_parent.invoke_kind)
+ end
+
+ def test_invkind
+ assert_equal(1, @m_namespace.invkind)
+ assert_equal(2, @m_parent.invkind)
+ end
+
+ def test_visible?
+ assert(@m_namespace.visible?)
+ assert(!@m_invoke.visible?)
+ end
+
+ def test_event?
+ assert(@m_navigate_complete.event?)
+ assert(!@m_namespace.event?)
+ end
+
+ def test_event_interface
+ assert_equal("DWebBrowserEvents", @m_navigate_complete.event_interface)
+ assert_equal(nil, @m_namespace.event_interface)
+ end
+
+ def test_helpstring
+ assert_equal("Get special folder from ShellSpecialFolderConstants", @m_namespace.helpstring)
+ end
+
+ def test_helpfile
+ assert_equal("", @m_namespace.helpfile)
+ assert_match(/VBENLR.*\.CHM$/i, @m_file_name.helpfile)
+ end
+
+ def test_helpcontext
+ assert_equal(0, @m_namespace.helpcontext)
+ assert_equal(2181996, @m_file_name.helpcontext)
+ end
+
+ def test_dispid
+ assert_equal(1610743810, @m_namespace.dispid)
+ end
+
+ def test_offset_vtbl
+ assert_equal(24, @m_invoke.offset_vtbl)
+ end
+
+ def test_size_params
+ assert_equal(1, @m_open.size_params)
+ assert_equal(4, @m_browse_for_folder.size_params)
+ end
+
+ def test_size_opt_params
+ assert_equal(0, @m_open.size_opt_params)
+ assert_equal(1, @m_browse_for_folder.size_opt_params)
+ end
+
+ def test_params
+ params = @m_browse_for_folder.params
+ assert_instance_of(Array, params)
+ assert_equal(4, params.size)
+ assert_instance_of(WIN32OLE_PARAM, params[0])
+ end
+
+ def test_to_s
+ assert_equal(@m_namespace.name, @m_namespace.to_s)
+ end
+
+ def test_inspect
+ assert_equal("#<WIN32OLE_METHOD:NameSpace>", @m_namespace.inspect)
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_param.rb b/trunk/test/win32ole/test_win32ole_param.rb
new file mode 100644
index 0000000000..1c866ca53e
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_param.rb
@@ -0,0 +1,91 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE_PARAM)
+ class TestWIN32OLE_PARAM < Test::Unit::TestCase
+
+ def setup
+ ole_type = WIN32OLE_TYPE.new("Microsoft Internet Controls", "WebBrowser")
+ m_navigate = WIN32OLE_METHOD.new(ole_type, "Navigate")
+ m_before_navigate = WIN32OLE_METHOD.new(ole_type, "BeforeNavigate")
+ params = m_navigate.params
+ @param_url = params[0]
+ @param_flags = params[1]
+ @param_cancel = m_before_navigate.params[5]
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellLinkObject")
+ m_geticonlocation = WIN32OLE_METHOD.new(ole_type, "GetIconLocation")
+ @param_pbs = m_geticonlocation.params[0]
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft HTML Object Library", "FontNames")
+ m_count = WIN32OLE_METHOD.new(ole_type, "Count")
+ @param_p = m_count.params[0]
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ @param_overwritefiles = m_copyfile.params[2]
+ end
+
+ def test_s_new
+ assert_raise(ArgumentError) {
+ WIN32OLE_PARAM.new("hoge")
+ }
+ end
+
+
+ def test_name
+ assert_equal('URL', @param_url.name)
+ assert_equal('Flags', @param_flags.name)
+ assert_equal('Cancel', @param_cancel.name)
+ end
+
+ def test_ole_type
+ assert_equal('BSTR', @param_url.ole_type)
+ assert_equal('VARIANT', @param_flags.ole_type)
+ end
+
+ def test_ole_type_detail
+ assert_equal(['BSTR'], @param_url.ole_type_detail)
+ assert_equal(['PTR', 'VARIANT'], @param_flags.ole_type_detail)
+ end
+
+ def test_input?
+ assert(@param_url.input?)
+ assert(@param_cancel.input?)
+ assert(!@param_pbs.input?)
+ end
+
+ def test_output?
+ assert(!@param_url.output?)
+ assert(@param_cancel.output?)
+ assert(@param_pbs.output?)
+ end
+
+ def test_optional?
+ assert(!@param_url.optional?)
+ assert(@param_flags.optional?)
+ end
+
+ def test_retval?
+ assert(!@param_url.retval?)
+ assert(@param_p.retval?)
+ end
+
+ def test_default
+ assert_equal(nil, @param_url.default)
+ assert_equal(true, @param_overwritefiles.default)
+ end
+
+ def test_to_s
+ assert_equal(@param_url.name, @param_url.to_s)
+ end
+
+ def test_inspect
+ assert_equal("#<WIN32OLE_PARAM:URL>", @param_url.inspect)
+ assert_equal("#<WIN32OLE_PARAM:OverWriteFiles=true>", @param_overwritefiles.inspect)
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_type.rb b/trunk/test/win32ole/test_win32ole_type.rb
new file mode 100644
index 0000000000..f8ea525ea9
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_type.rb
@@ -0,0 +1,249 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE_TYPE)
+ class TestWIN32OLE_TYPE < Test::Unit::TestCase
+
+ def test_s_progids
+ progids = WIN32OLE_TYPE.progids
+ assert_instance_of(Array, progids)
+ assert(progids.size > 0)
+ assert_instance_of(String, progids[0])
+ assert(progids.include?("Shell.Application.1"))
+ end
+
+ def test_initialize
+ assert_raise(ArgumentError) {
+ WIN32OLE_TYPE.new
+ }
+ assert_raise(ArgumentError) {
+ WIN32OLE_TYPE.new("foo")
+ }
+ assert_raise(TypeError) {
+ WIN32OLE_TYPE.new(1, 2)
+ }
+ assert_raise(TypeError) {
+ WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", 1)
+ }
+ assert_raise(WIN32OLERuntimeError) {
+ WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "foo")
+ }
+ assert_raise(WIN32OLERuntimeError) {
+ WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Application")
+ }
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ assert_instance_of(WIN32OLE_TYPE, ole_type)
+ assert_equal("Shell", ole_type.name)
+ assert_equal("Class", ole_type.ole_type)
+ assert_equal("{13709620-C279-11CE-A49E-444553540000}", ole_type.guid)
+ assert_equal("Shell.Application.1", ole_type.progid)
+ assert_equal(true, ole_type.visible?)
+ assert_equal("Shell", ole_type.to_s)
+ assert_equal(0, ole_type.major_version)
+ assert_equal(0, ole_type.minor_version)
+ assert_equal(5, ole_type.typekind)
+ assert_equal("Shell Object Type Information", ole_type.helpstring)
+ assert_equal(nil, ole_type.src_type)
+ assert_equal("", ole_type.helpfile)
+ assert_equal(0, ole_type.helpcontext)
+ assert_equal([], ole_type.variables)
+ assert(ole_type.ole_methods.select{|m|/NameSpace/i =~ m.name}.size > 0)
+
+ ole_type2 = WIN32OLE_TYPE.new("{13709620-C279-11CE-A49E-444553540000}", "Shell")
+ assert_instance_of(WIN32OLE_TYPE, ole_type)
+ assert_equal(ole_type.name, ole_type2.name)
+ assert_equal(ole_type.ole_type, ole_type2.ole_type)
+ assert_equal(ole_type.guid, ole_type2.guid)
+ assert_equal(ole_type.progid, ole_type2.progid)
+ assert_equal(ole_type.visible?, ole_type2.visible?)
+ assert_equal(ole_type.to_s, ole_type2.to_s)
+ assert_equal(ole_type.major_version, ole_type2.major_version)
+ assert_equal(ole_type.minor_version, ole_type2.minor_version)
+ assert_equal(ole_type.typekind, ole_type2.typekind)
+ assert_equal(ole_type.helpstring, ole_type2.helpstring)
+ assert_equal(ole_type.src_type, ole_type2.src_type)
+ assert_equal(ole_type.helpfile, ole_type2.helpfile)
+ assert_equal(ole_type.helpcontext, ole_type2.helpcontext)
+ assert_equal(ole_type.variables.size, ole_type2.variables.size)
+ assert_equal(ole_type.ole_methods[0].name, ole_type2.ole_methods[0].name)
+ assert_equal(ole_type.ole_typelib.name, ole_type2.ole_typelib.name)
+ assert_equal(ole_type.implemented_ole_types.size, ole_type2.implemented_ole_types.size)
+ assert_equal(ole_type.inspect, ole_type2.inspect)
+ end
+
+ def setup
+ @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ end
+
+ def test_name
+ assert_equal("Shell", @ole_type.name)
+ end
+
+ def test_ole_type
+ assert_equal("Class", @ole_type.ole_type)
+ end
+
+ def test_guid
+ assert_equal("{13709620-C279-11CE-A49E-444553540000}", @ole_type.guid)
+ end
+
+ def test_progid
+ assert_equal("Shell.Application.1", @ole_type.progid)
+ end
+
+ def test_visible?
+ assert(@ole_type.visible?)
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "IShellDispatch")
+ assert(!ole_type.visible?)
+ end
+
+ def test_to_s
+ assert_equal(@ole_type.to_s, @ole_type.name)
+ end
+
+ def test_major_version
+ assert_equal(0, @ole_type.major_version)
+ # ole_type = WIN32OLE_TYPE.new("Microsoft Word 11.0 Object Library", "Documents")
+ # assert_equal(8, ole_type.major_version)
+ end
+
+ def test_minor_version
+ assert_equal(0, @ole_type.minor_version)
+ # ole_type = WIN32OLE_TYPE.new("Microsoft Word 11.0 Object Library", "Documents")
+ # assert_equal(3, ole_type.minor_version)
+ end
+
+ def test_typekind
+ assert_equal(5, @ole_type.typekind)
+ end
+
+ def test_helpstring
+ assert_equal("Shell Object Type Information", @ole_type.helpstring)
+ end
+
+ def test_src_type
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "DriveTypeConst")
+ assert_match(/__MIDL___MIDL_itf_scrrun_/, ole_type.src_type)
+ assert_equal(nil, @ole_type.src_type)
+ end
+
+ def test_helpfile
+ assert_equal("", @ole_type.helpfile)
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Folders")
+ assert_match(/VBENLR98\.CHM$/i, ole_type.helpfile)
+ end
+
+ def test_helpcontext
+ assert_equal(0, @ole_type.helpcontext)
+ ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Folders")
+ assert_equal(2181929, ole_type.helpcontext)
+ end
+
+ def test_variables
+ variables = @ole_type.variables
+ assert_instance_of(Array, variables)
+ assert(variables.size == 0)
+
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ variables = ole_type.variables
+ assert_instance_of(Array, variables)
+ assert(variables.size > 0)
+
+ assert_instance_of(WIN32OLE_VARIABLE, variables[0])
+ end
+
+ def test_ole_methods
+ methods = @ole_type.ole_methods
+ assert_instance_of(Array, methods)
+ assert(methods.size > 0)
+ assert_instance_of(WIN32OLE_METHOD, methods[0]);
+ assert(methods.collect{|m| m.name}.include?("Application"))
+ end
+
+ def test_ole_typelib
+ tlib = @ole_type.ole_typelib
+ assert_instance_of(WIN32OLE_TYPELIB, tlib)
+ assert_equal("Microsoft Shell Controls And Automation", tlib.name)
+ end
+
+ def test_implemented_ole_types
+ ole_types = @ole_type.implemented_ole_types
+ assert_instance_of(Array, ole_types)
+ assert_equal(1, ole_types.size)
+ assert_match(/^IShellDispatch5{0,1}$/, ole_types[0].name)
+
+ ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+ ole_types = ie_otype.implemented_ole_types
+ assert_equal(4, ole_types.size)
+ otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}
+ assert_equal(1, otype.size)
+ end
+
+ def test_default_ole_types
+ ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+ ole_types = ie_otype.default_ole_types
+ otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+ assert_equal(0, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}
+ assert_equal(0, otype.size)
+ end
+
+ def test_source_ole_types
+ ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+ ole_types = ie_otype.source_ole_types
+ otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+ assert_equal(0, otype.size)
+ otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+ assert_equal(0, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}
+ assert_equal(1, otype.size)
+ end
+
+ def test_default_event_sources
+ ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+ ole_types = ie_otype.default_event_sources
+ otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+ assert_equal(0, otype.size)
+ otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+ assert_equal(0, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+ assert_equal(1, otype.size)
+ otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}
+ assert_equal(0, otype.size)
+ end
+
+ def test_inspect
+ assert_equal("#<WIN32OLE_TYPE:Shell>", @ole_type.inspect)
+ end
+ # WIN32OLE_TYPE.typelibs will be obsoleted.
+ def test_s_typelibs
+ tlibs = WIN32OLE_TYPE.typelibs.sort
+ tlibs2 = WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}.sort
+ assert_equal(tlibs2, tlibs)
+ end
+
+ # WIN32OLE_TYPE.ole_classes will be obsoleted.
+ def test_s_ole_classes
+ ots1 = WIN32OLE_TYPE.ole_classes("Microsoft Shell Controls And Automation")
+ ots2 = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation").ole_types
+ otns1 = ots1.collect{|t| t.name}.sort
+ otns2 = ots2.collect{|t| t.name}.sort
+ assert_equal(otns2, otns1)
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_typelib.rb b/trunk/test/win32ole/test_win32ole_typelib.rb
new file mode 100644
index 0000000000..a1c3891396
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_typelib.rb
@@ -0,0 +1,110 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE_TYPELIB)
+ class TestWIN32OLE_TYPELIB < Test::Unit::TestCase
+ def test_s_typelibs
+ tlibs = WIN32OLE_TYPELIB.typelibs
+ assert_instance_of(Array, tlibs)
+ assert(tlibs.size > 0)
+ tlib = tlibs.find {|tlib| tlib.name == "Microsoft Shell Controls And Automation"}
+ assert(tlib)
+ end
+
+ def test_initialize
+ assert_raise(ArgumentError) {
+ WIN32OLE_TYPELIB.new(1,2,3,4)
+ }
+
+ assert_raise(TypeError) {
+ WIN32OLE_TYPELIB.new(100)
+ }
+
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_instance_of(WIN32OLE_TYPELIB, tlib)
+
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation", 1.0)
+ assert_instance_of(WIN32OLE_TYPELIB, tlib)
+
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation", 1, 0)
+ assert_instance_of(WIN32OLE_TYPELIB, tlib)
+ guid = tlib.guid
+
+ tlib_by_guid = WIN32OLE_TYPELIB.new(guid, 1, 0)
+ assert_instance_of(WIN32OLE_TYPELIB, tlib_by_guid)
+ assert_equal("Microsoft Shell Controls And Automation" , tlib_by_guid.name)
+
+ path = tlib.path
+ tlib_by_path = WIN32OLE_TYPELIB.new(path)
+ assert_equal("Microsoft Shell Controls And Automation" , tlib_by_path.name)
+
+ assert_raise(WIN32OLERuntimeError) {
+ WIN32OLE_TYPELIB.new("Non Exist Type Library")
+ }
+ end
+
+ def test_guid
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", tlib.guid)
+ end
+
+ def test_name
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal("Microsoft Shell Controls And Automation", tlib.name)
+ tlib = WIN32OLE_TYPELIB.new("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}")
+ assert_equal("Microsoft Shell Controls And Automation", tlib.name)
+ end
+
+ def test_version
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal(1.0, tlib.version)
+ end
+
+ def test_major_version
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal(1, tlib.major_version)
+ end
+
+ def test_minor_version
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal(0, tlib.minor_version)
+ end
+
+ def test_path
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_match(/shell32\.dll$/i, tlib.path)
+ end
+
+ def test_visible?
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert(tlib.visible?)
+ end
+
+ def test_library_name
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal("Shell32", tlib.library_name)
+ end
+
+ def test_to_s
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal("Microsoft Shell Controls And Automation", tlib.to_s)
+ end
+
+ def test_ole_types
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ ole_types = tlib.ole_types
+ assert_instance_of(Array, ole_types)
+ assert(ole_types.size > 0)
+ assert_instance_of(WIN32OLE_TYPE, ole_types[0])
+ end
+
+ def test_inspect
+ tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ assert_equal("#<WIN32OLE_TYPELIB:Microsoft Shell Controls And Automation>", tlib.inspect)
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_variable.rb b/trunk/test/win32ole/test_win32ole_variable.rb
new file mode 100644
index 0000000000..43529d3bad
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_variable.rb
@@ -0,0 +1,61 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE_VARIABLE)
+ class TestWIN32OLE_VARIABLE < Test::Unit::TestCase
+
+ def setup
+ ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @var1 = ole_type.variables.find {|v| v.name == 'ssfDESKTOP'}
+
+ variables = WIN32OLE_TYPE.new("Microsoft Windows Installer Object Library", "Installer").variables
+ @var2 = variables.find {|v| v.name == 'UILevel'}
+ end
+
+ def test_name
+ assert_equal('ssfDESKTOP', @var1.name)
+ end
+
+ def test_ole_type
+ assert_equal('INT', @var1.ole_type)
+ assert_equal('MsiUILevel', @var2.ole_type)
+ end
+
+ def test_ole_type_detail
+ assert_equal(['INT'], @var1.ole_type_detail)
+ assert_equal(['USERDEFINED', 'MsiUILevel'], @var2.ole_type_detail)
+ end
+
+ def test_ole_type_value
+ assert_equal(0, @var1.value)
+ assert_equal(nil, @var2.value)
+ end
+
+ def test_ole_type_visible?
+ assert(@var1.visible?)
+ end
+
+ def test_ole_type_variable_kind
+ assert_equal("CONSTANT", @var1.variable_kind)
+ assert_equal("DISPATCH", @var2.variable_kind)
+ end
+
+ def test_ole_type_varkind
+ assert_equal(2, @var1.varkind)
+ assert_equal(3, @var2.varkind)
+ end
+
+ def test_to_s
+ assert_equal(@var1.name, @var1.to_s)
+ end
+
+ def test_inspect
+ assert_equal("#<WIN32OLE_VARIABLE:ssfDESKTOP=0>", @var1.inspect)
+ assert_equal("#<WIN32OLE_VARIABLE:UILevel=nil>", @var2.inspect)
+ end
+
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_variant.rb b/trunk/test/win32ole/test_win32ole_variant.rb
new file mode 100644
index 0000000000..1226e0de50
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_variant.rb
@@ -0,0 +1,638 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+$MSGS = []
+def add_skip_message(msg)
+ $MSGS.push msg
+end
+
+if defined?(WIN32OLE_VARIANT)
+
+ class TestWIN32OLE_VARIANT < Test::Unit::TestCase
+
+ def test_s_new
+ obj = WIN32OLE_VARIANT.new('foo')
+ assert_instance_of(WIN32OLE_VARIANT, obj)
+ end
+
+ def test_s_new_no_argument
+ ex = nil
+ begin
+ obj = WIN32OLE_VARIANT.new
+ rescue ArgumentError
+ ex = $!
+ end
+ assert_instance_of(ArgumentError, ex)
+ assert_equal("wrong number of arguments (0 for 1..3)", ex.message);
+ end
+
+ def test_s_new_one_argument
+ ex = nil
+ begin
+ obj = WIN32OLE_VARIANT.new('foo')
+ rescue
+ ex = $!
+ end
+ assert_equal(nil, ex);
+ end
+
+ def test_s_new_with_nil
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I2)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I2, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I4)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_R4)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R4, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_R8)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R8, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_CY)
+ assert_equal("0", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_CY, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1899/12/30 00:00:00", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_DATE, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_BSTR)
+ assert_equal("", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DISPATCH)
+ assert_nil(obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_DISPATCH, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_BOOL)
+ assert_equal(false, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BOOL, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT)
+ assert_nil(obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_VARIANT, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I1)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I1, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI1)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI1, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI2)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI2, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI4)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI4, obj.vartype)
+
+
+ if defined?(WIN32OLE::VARIANT::VT_I8)
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I8)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I8, obj.vartype)
+ end
+
+ if defined?(WIN32OLE::VARIANT::VT_UI8)
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI8)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI8, obj.vartype)
+ end
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_INT)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_INT, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UINT)
+ assert_equal(0, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UINT, obj.vartype)
+ end
+
+ def test_s_new_with_non_nil
+ obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I2)
+ assert_equal(2, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I2, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_I4)
+ assert_equal(3, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(4.5, WIN32OLE::VARIANT::VT_R4)
+ assert_equal(4.5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R4, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5.5, WIN32OLE::VARIANT::VT_R8)
+ assert_equal(5.5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R8, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(600, WIN32OLE::VARIANT::VT_CY)
+ assert_equal("600", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_CY, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2001/06/15 12:17:34", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_DATE, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new("foo", WIN32OLE::VARIANT::VT_BSTR)
+ assert_equal("foo", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(true, WIN32OLE::VARIANT::VT_BOOL)
+ assert_equal(true, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BOOL, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I1)
+ assert_equal(2, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I1, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_UI1)
+ assert_equal(3, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI1, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_UI2)
+ assert_equal(4, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI2, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UI4)
+ assert_equal(5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI4, obj.vartype)
+
+ if defined?(WIN32OLE::VARIANT::VT_I8)
+ obj = WIN32OLE_VARIANT.new(-123456789012345, WIN32OLE::VARIANT::VT_I8)
+ assert_equal(-123456789012345, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I8, obj.vartype)
+ end
+
+ if defined?(WIN32OLE::VARIANT::VT_UI8)
+ obj = WIN32OLE_VARIANT.new(123456789012345, WIN32OLE::VARIANT::VT_UI8)
+ assert_equal(123456789012345, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI8, obj.vartype)
+ end
+
+ obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_INT)
+ assert_equal(4, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_INT, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UINT)
+ assert_equal(5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UINT, obj.vartype)
+ end
+
+ def test_s_new_with_non_nil_byref
+ obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(2, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(3, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(4.5, WIN32OLE::VARIANT::VT_R4|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(4.5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5.5, WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(5.5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(600, WIN32OLE::VARIANT::VT_CY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal("600", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_CY|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal("2001/06/15 12:17:34", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new("foo", WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal("foo", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(true, WIN32OLE::VARIANT::VT_BOOL|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(true, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_BOOL|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I1|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(2, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I1|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(3, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_UI2|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(4, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI2|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UI4|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_INT|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(4, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_INT|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UINT|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(5, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UINT|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+ end
+
+ # This test is failed in cygwin.
+ # The tagVARIANT definition has no union member pllVal in cygwin.
+ def test_s_new_with_i8_byref
+ if defined?(WIN32OLE::VARIANT::VT_I8) && /mswin/ =~ RUBY_PLATFORM
+ obj = WIN32OLE_VARIANT.new(-123456789012345, WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(-123456789012345, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+ else
+ STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_new_with_i8_byref is skipped")
+ end
+ end
+
+ # This test is failed in cygwin.
+ # The tagVARIANT definition has no union member pullVal in cygwin.
+ def test_s_new_with_ui8_byref
+ if defined?(WIN32OLE::VARIANT::VT_UI8) && /mswin/ =~ RUBY_PLATFORM
+ obj = WIN32OLE_VARIANT.new(123456789012345, WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(123456789012345, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+ else
+ STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_new_with_ui8_byref is skipped.")
+ end
+ end
+
+ def test_value
+ obj = WIN32OLE_VARIANT.new('foo')
+ assert_equal('foo', obj.value)
+ end
+
+ def test_s_new_2_argument
+ obj = WIN32OLE_VARIANT.new('foo', WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal('foo', obj.value);
+ end
+
+ def test_s_new_2_argument2
+ obj = WIN32OLE_VARIANT.new('foo', WIN32OLE::VARIANT::VT_BSTR)
+ assert_equal('foo', obj.value);
+ end
+
+ def test_s_new_dispatch_array
+ vt = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH
+ obj = WIN32OLE_VARIANT.new(nil, vt)
+ assert_equal(vt, obj.vartype)
+ assert_nil(obj.value)
+
+ vt = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH|WIN32OLE::VARIANT::VT_BYREF
+ obj = WIN32OLE_VARIANT.new(nil, vt)
+ assert_equal(vt, obj.vartype)
+ assert_nil(obj.value)
+ end
+
+ def test_s_new_array
+ # should not occur stack over flow
+ ar = (1..500000).to_a.map{|i| [i]}
+ ar2 = WIN32OLE_VARIANT.new(ar)
+ assert_equal(ar, ar2.value)
+ end
+
+ def test_s_array
+ obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4)
+ assert_instance_of(WIN32OLE_VARIANT, obj)
+ assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype)
+ assert_equal([[0, 0, 0],[0, 0, 0]], obj.value)
+
+ obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype)
+ assert_equal([[0, 0, 0],[0, 0, 0]], obj.value)
+
+ obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY)
+ assert_instance_of(WIN32OLE_VARIANT, obj)
+ assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype)
+ assert_equal([[0, 0, 0],[0, 0, 0]], obj.value)
+
+ assert_equal(0, obj[0,0])
+ obj[0,0] = 10
+ assert_equal([[10, 0, 0],[0, 0, 0]], obj.value)
+ obj[0,1] = "13.2"
+ assert_equal([[10, 13, 0],[0, 0, 0]], obj.value)
+
+ obj = WIN32OLE_VARIANT.array([3, 2], WIN32OLE::VARIANT::VT_VARIANT)
+ obj[0,0] = 10
+ obj[0,1] = "string"
+ obj[1,0] = 12.735
+ assert_equal([[10, "string"],[12.735, nil],[nil,nil]], obj.value)
+
+ obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_DISPATCH)
+ assert_equal([[nil, nil, nil],[nil,nil,nil]], obj.value)
+
+ end
+
+ def test_s_array_exc
+ assert_raise(TypeError) {
+ obj = WIN32OLE_VARIANT.array(2, WIN32OLE::VARIANT::VT_I4)
+ }
+ end
+
+ def test_conversion_num2str
+ obj = WIN32OLE_VARIANT.new(124, WIN32OLE::VARIANT::VT_BSTR)
+ assert_equal("124", obj.value);
+ end
+
+ def test_conversion_float2int
+ obj = WIN32OLE_VARIANT.new(12.345, WIN32OLE::VARIANT::VT_I4)
+ assert_equal(12, obj.value)
+ obj = WIN32OLE_VARIANT.new(12.345, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(12, obj.value)
+ end
+
+ def test_conversion_str2num
+ obj = WIN32OLE_VARIANT.new("12.345", WIN32OLE::VARIANT::VT_R8)
+ assert_equal(12.345, obj.value)
+ end
+
+ def test_conversion_ole_variant2ole_variant
+ obj = WIN32OLE_VARIANT.new("12.345", WIN32OLE::VARIANT::VT_R4)
+ obj = WIN32OLE_VARIANT.new(obj, WIN32OLE::VARIANT::VT_I4)
+ assert_equal(12, obj.value)
+ end
+
+ def test_conversion_str2date
+ obj = WIN32OLE_VARIANT.new("2004-12-24 12:24:45", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2004/12/24 12:24:45", obj.value)
+ end
+
+ def test_conversion_time2date
+ dt = Time.mktime(2004, 12, 24, 12, 24, 45)
+ obj = WIN32OLE_VARIANT.new(dt, WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2004/12/24 12:24:45", obj.value)
+ end
+
+ def test_conversion_str2cy
+ begin
+ WIN32OLE.locale = 0x0411 # set locale Japanese
+ obj = WIN32OLE_VARIANT.new("\\10,000", WIN32OLE::VARIANT::VT_CY)
+ assert_equal("10000", obj.value)
+ ensure
+ WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
+ end
+ end
+
+ def test_create_vt_array
+ obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8)
+ assert_equal([1.2, 2.3], obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([1.2, 2.3], obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+ end
+
+ def test_create_vt_array2
+ obj = WIN32OLE_VARIANT.new([1.2, "a"], WIN32OLE::VARIANT::VT_ARRAY)
+ assert_equal([1.2, "a"], obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_VARIANT, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new([1.2, "a"])
+ assert_equal([1.2, "a"], obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_VARIANT, obj.vartype)
+ end
+
+
+ def test_create_vt_nested_array
+ obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]], WIN32OLE::VARIANT::VT_ARRAY)
+ assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]])
+ assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]])
+ assert_equal([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]])
+ assert_equal([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]], obj.value)
+ end
+
+ def test_create_vt_array3
+ obj = WIN32OLE_VARIANT.new([])
+ assert_equal([], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[]])
+ assert_equal([[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[],[]])
+ assert_equal([[],[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[],[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([[],[]], obj.value)
+ end
+
+ def test_create_vt_array_nil
+ vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH|WIN32OLE::VARIANT::VT_BYREF
+ obj = WIN32OLE_VARIANT.new(nil, vartype)
+ assert_nil(obj.value)
+ assert_equal(vartype, obj.vartype)
+
+ vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH
+ obj = WIN32OLE_VARIANT.new(nil, vartype)
+ assert_nil(obj.value)
+ assert_equal(vartype, obj.vartype)
+ end
+
+ def test_create_vt_array_str
+ vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BSTR
+ obj = WIN32OLE_VARIANT.new(["abc", "123"], vartype)
+ assert_equal(vartype, obj.vartype)
+ assert_equal(["abc", "123"], obj.value)
+
+ vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_BSTR
+ obj = WIN32OLE_VARIANT.new(["abc", "123"], vartype)
+ assert_equal(vartype, obj.vartype)
+ assert_equal(["abc", "123"], obj.value)
+ end
+
+ def test_create_vt_array_exc
+ exc = assert_raise(TypeError) {
+ obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_ARRAY);
+ }
+ assert_match(/wrong argument type Fixnum \(expected Array\)/, exc.message)
+ end
+
+ def test_create_vt_array_str2ui1array
+ obj = WIN32OLE_VARIANT.new("ABC", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ assert_equal("ABC", obj.value)
+
+ obj.value = "DEF"
+ assert_equal("DEF", obj.value)
+ obj[0] = 71
+ assert_equal("GEF", obj.value)
+
+ obj = WIN32OLE_VARIANT.new([65, 0].pack("C*"), WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ assert_equal([65, 0].pack("C*"), obj.value)
+
+ obj = WIN32OLE_VARIANT.new("abc", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal("abc", obj.value)
+ obj.value = "DEF"
+ assert_equal("DEF", obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
+ obj[1] = 71
+ assert_equal("DGF", obj.value)
+
+ end
+
+ def test_create_vt_array_int
+ obj = WIN32OLE_VARIANT.new([65, 0], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ assert_equal([65, 0].pack("C*"), obj.value)
+
+ obj = WIN32OLE_VARIANT.new([65, 0])
+ assert_equal([65, 0], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([65, 0], WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_ARRAY)
+ assert_equal([65, 0], obj.value)
+
+ end
+
+ def test_vt_array_bracket
+ obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
+ assert_equal(1, obj[0,0])
+ assert_equal(2, obj[0,1])
+ assert_equal(3, obj[0,2])
+ assert_equal(4, obj[1,0])
+ assert_equal(5, obj[1,1])
+ assert_equal(6, obj[1,2])
+
+ assert_raise(WIN32OLERuntimeError) {
+ obj[0,4]
+ }
+ assert_raise(WIN32OLERuntimeError) {
+ obj[0,-1]
+ }
+ assert_raise(ArgumentError) {
+ obj[0]
+ }
+
+ obj[0,0] = 7
+ obj[1,2] = 8
+ assert_equal([[7,2,3], [4,5,8]], obj.value)
+
+ assert_raise(WIN32OLERuntimeError) {
+ obj[0,4] = 9
+ }
+ assert_raise(WIN32OLERuntimeError) {
+ obj[0,-1] = 10
+ }
+ assert_raise(ArgumentError) {
+ obj[0] = 11
+ }
+ end
+
+ def test_conversion_vt_date
+ obj = WIN32OLE_VARIANT.new(-657434, WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("0100/01/01 00:00:00", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1500/12/29 23:59:59", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1500/12/30 00:00:00", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1500/12/30 00:00:01", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1899/12/29 23:59:59", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1899/12/30 00:00:00", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1899/12/30 00:00:01", obj.value)
+
+ obj = WIN32OLE_VARIANT.new(0, WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("1899/12/30 00:00:00", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2008/12/29 23:59:59", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2008/12/30 00:00:00", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("2008/12/30 00:00:01", obj.value)
+
+ obj = WIN32OLE_VARIANT.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ assert_equal("9999/12/31 23:59:59", obj.value)
+ end
+
+ def test_create_nil_dispatch
+ var = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DISPATCH)
+ assert_nil(var.value)
+ end
+
+ def test_create_variant_byref
+ obj = WIN32OLE_VARIANT.new("Str", WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF);
+ assert_equal("Str", obj.value);
+ end
+
+ def test_vartype
+ obj = WIN32OLE_VARIANT.new("Str")
+ assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype)
+ end
+
+ def test_set_value
+ obj = WIN32OLE_VARIANT.new(10)
+ obj.value = 12
+ assert_equal(12, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
+ obj.value = "14"
+ assert_equal(14, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
+ obj.value = 11.2
+ assert_equal(11, obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new([1,2])
+ assert_raise(WIN32OLERuntimeError) {
+ obj.value = [3,4]
+ }
+
+ obj = WIN32OLE_VARIANT.new("2007/01/01", WIN32OLE::VARIANT::VT_DATE)
+ assert_raise(WIN32OLERuntimeError) {
+ obj.value = "hogehoge"
+ }
+ assert_equal("2007/01/01 00:00:00", obj.value)
+
+ obj2 = WIN32OLE_VARIANT.new("2006/01/01", WIN32OLE::VARIANT::VT_DATE)
+ obj.value = obj2
+ assert_equal("2006/01/01 00:00:00", obj.value)
+ end
+
+ def test_c_nothing
+ assert_nil(WIN32OLE_VARIANT::Nothing.value)
+ end
+
+ def test_c_empty
+ assert_nil(WIN32OLE_VARIANT::Empty.value)
+ end
+
+ def test_c_null
+ assert_nil(WIN32OLE_VARIANT::Null.value)
+ end
+
+ end
+end
+
diff --git a/trunk/test/win32ole/test_win32ole_variant_m.rb b/trunk/test/win32ole/test_win32ole_variant_m.rb
new file mode 100644
index 0000000000..b3e48c20f0
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_variant_m.rb
@@ -0,0 +1,35 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+if defined?(WIN32OLE::VARIANT)
+ class TestWin32OLE_VARIANT_MODULE < Test::Unit::TestCase
+ include WIN32OLE::VARIANT
+ def test_variant
+ assert_equal(0, VT_EMPTY)
+ assert_equal(1, VT_NULL)
+ assert_equal(2, VT_I2)
+ assert_equal(3, VT_I4)
+ assert_equal(4, VT_R4)
+ assert_equal(5, VT_R8)
+ assert_equal(6, VT_CY)
+ assert_equal(7, VT_DATE)
+ assert_equal(8, VT_BSTR)
+ assert_equal(9, VT_DISPATCH)
+ assert_equal(10, VT_ERROR)
+ assert_equal(11, VT_BOOL)
+ assert_equal(12, VT_VARIANT)
+ assert_equal(13, VT_UNKNOWN)
+ assert_equal(16, VT_I1)
+ assert_equal(17, VT_UI1)
+ assert_equal(18, VT_UI2)
+ assert_equal(19, VT_UI4)
+ assert_equal(22, VT_INT)
+ assert_equal(23, VT_UINT)
+ assert_equal(0x2000, VT_ARRAY)
+ assert_equal(0x4000, VT_BYREF)
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_win32ole_variant_with_ie.rb b/trunk/test/win32ole/test_win32ole_variant_with_ie.rb
new file mode 100644
index 0000000000..680f17ff54
--- /dev/null
+++ b/trunk/test/win32ole/test_win32ole_variant_with_ie.rb
@@ -0,0 +1,53 @@
+# This is test script to check WIN32OLE_VARIANT using Internet Explorer
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+
+if defined?(WIN32OLE)
+ class TestWIN32OLE_VARIANT_WITH_IE < Test::Unit::TestCase
+ def create_temp_html
+ fso = WIN32OLE.new('Scripting.FileSystemObject')
+ dummy_file = fso.GetTempName + ".html"
+ cfolder = fso.getFolder(".")
+ f = cfolder.CreateTextFile(dummy_file)
+ f.writeLine("<html><body>This is test HTML file for Win32OLE.</body></html>")
+ f.close
+ dummy_path = cfolder.path + "\\" + dummy_file
+ dummy_path
+ end
+ def setup
+ @f = create_temp_html
+ @ie = WIN32OLE.new('InternetExplorer.Application')
+ @ie.visible = true
+ @ie.navigate("file:///#{@f}")
+ while @ie.busy
+ sleep 0.5
+ end
+ end
+ def test_variant_ref_and_argv
+ @ie.execWB(19, 0, nil, -1)
+ size = WIN32OLE::ARGV[3]
+ assert(size >= 0)
+
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ @ie.execWb(19, 0, nil, obj)
+ assert_equal(size, obj.value)
+ assert_equal(size, WIN32OLE::ARGV[3])
+
+ obj = WIN32OLE_VARIANT.new(-1, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ @ie.execWb(19, 0, nil, obj)
+ assert_equal(size, obj.value)
+ assert_equal(size, WIN32OLE::ARGV[3])
+ end
+
+ def teardown
+ File.unlink(@f)
+ if @ie
+ @ie.quit
+ @ie = nil
+ end
+ end
+ end
+end
diff --git a/trunk/test/win32ole/test_word.rb b/trunk/test/win32ole/test_word.rb
new file mode 100644
index 0000000000..d5b2d91812
--- /dev/null
+++ b/trunk/test/win32ole/test_word.rb
@@ -0,0 +1,72 @@
+#
+# This is test for [ruby-Bugs#3237]
+#
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require "test/unit"
+
+def word_installed?
+ installed = false
+ w = nil
+ if defined?(WIN32OLE)
+ begin
+ w = WIN32OLE.new('Word.Application')
+ installed = true
+ rescue
+ ensure
+ if w
+ w.quit
+ w = nil
+ end
+ end
+ end
+ return installed
+end
+
+if defined?(WIN32OLE)
+ w = nil
+ dotest = word_installed?
+ if !dotest
+ STDERR.puts("\n#{__FILE__} skipped(Microsoft Word not found.)")
+ end
+ if dotest
+ class TestWIN32OLE_WITH_WORD < Test::Unit::TestCase
+ def setup
+ begin
+ @obj = WIN32OLE.new('Word.Application')
+ rescue WIN32OLERuntimeError
+ @obj = nil
+ if !$skipped
+ $skipped = true
+ end
+ end
+ end
+
+ def test_ole_methods
+ if @obj
+ @obj.visible = true
+ @obj.wordbasic.disableAutoMacros(true)
+ assert(true)
+ else
+ end
+ end
+
+ def test_s_connect
+ if @obj
+ obj2 = WIN32OLE.connect("Word.Application")
+ assert_instance_of(WIN32OLE, obj2)
+ obj2.visible = true
+ end
+ end
+
+ def teardown
+ if @obj
+ @obj.quit
+ @obj = nil
+ end
+ end
+ end
+ end
+end
diff --git a/trunk/test/xmlrpc/data/bug_bool.expected b/trunk/test/xmlrpc/data/bug_bool.expected
new file mode 100644
index 0000000000..121e3a84ba
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_bool.expected
@@ -0,0 +1,3 @@
+---
+- true
+- false \ No newline at end of file
diff --git a/trunk/test/xmlrpc/data/bug_bool.xml b/trunk/test/xmlrpc/data/bug_bool.xml
new file mode 100644
index 0000000000..04ed00709e
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_bool.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<methodResponse>
+ <params>
+ <param>
+ <value><boolean>0</boolean></value>
+ </param>
+ </params>
+</methodResponse>
diff --git a/trunk/test/xmlrpc/data/bug_cdata.expected b/trunk/test/xmlrpc/data/bug_cdata.expected
new file mode 100644
index 0000000000..17d7861318
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_cdata.expected
@@ -0,0 +1,3 @@
+---
+- true
+- test \ No newline at end of file
diff --git a/trunk/test/xmlrpc/data/bug_cdata.xml b/trunk/test/xmlrpc/data/bug_cdata.xml
new file mode 100644
index 0000000000..ba990e04f1
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_cdata.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<methodResponse>
+ <params>
+ <param>
+ <value><string><![CDATA[test]]></string></value>
+ </param>
+ </params>
+</methodResponse>
diff --git a/trunk/test/xmlrpc/data/bug_covert.expected b/trunk/test/xmlrpc/data/bug_covert.expected
new file mode 100644
index 0000000000..a9ac103c64
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_covert.expected
@@ -0,0 +1,10 @@
+---
+- true
+- >
+ Site,SANs,Array
+
+ Configured Capacity,Array Reserved Capacity,Array Ava
+
+ ilable Capacity,Array % Reserved,Host Allocated,Host Used,Host Free,Host %
+
+ Used
diff --git a/trunk/test/xmlrpc/data/bug_covert.xml b/trunk/test/xmlrpc/data/bug_covert.xml
new file mode 100644
index 0000000000..1d9abd2a06
--- /dev/null
+++ b/trunk/test/xmlrpc/data/bug_covert.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"
+encoding="ISO-8859-1"?><methodResponse><params><param><value>Site,SANs,Array
+Configured Capacity,Array Reserved Capacity,Array Ava
+ilable Capacity,Array % Reserved,Host Allocated,Host Used,Host Free,Host %
+Used
+</value></param></params></methodResponse>
diff --git a/trunk/test/xmlrpc/data/datetime_iso8601.xml b/trunk/test/xmlrpc/data/datetime_iso8601.xml
new file mode 100644
index 0000000000..43d8da6c13
--- /dev/null
+++ b/trunk/test/xmlrpc/data/datetime_iso8601.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<methodResponse>
+ <params>
+ <param>
+ <value><dateTime.iso8601>20041105T01:15:23Z</dateTime.iso8601></value>
+ </param>
+ </params>
+</methodResponse>
diff --git a/trunk/test/xmlrpc/data/fault.xml b/trunk/test/xmlrpc/data/fault.xml
new file mode 100644
index 0000000000..041c464eb3
--- /dev/null
+++ b/trunk/test/xmlrpc/data/fault.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<methodResponse>
+ <fault>
+ <value><struct>
+ <member>
+ <name>faultCode</name>
+ <value><int>4</int></value>
+ </member>
+ <member>
+ <name>faultString</name>
+ <value>an error message</value>
+ </member>
+ </struct></value>
+ </fault>
+</methodResponse>
+
diff --git a/trunk/test/xmlrpc/data/value.expected b/trunk/test/xmlrpc/data/value.expected
new file mode 100644
index 0000000000..9463d02b13
--- /dev/null
+++ b/trunk/test/xmlrpc/data/value.expected
@@ -0,0 +1,7 @@
+---
+- Test
+-
+ - Hallo Leute
+ - " Hallo "
+ - ''
+ - " " \ No newline at end of file
diff --git a/trunk/test/xmlrpc/data/value.xml b/trunk/test/xmlrpc/data/value.xml
new file mode 100644
index 0000000000..1978616099
--- /dev/null
+++ b/trunk/test/xmlrpc/data/value.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<methodCall>
+ <methodName>Test</methodName>
+ <params>
+ <param>
+ <value>Hallo Leute</value>
+ </param>
+ <param>
+ <value> Hallo </value>
+ </param>
+ <param>
+ <value></value>
+ </param>
+ <param>
+ <value> </value>
+ </param>
+ </params>
+</methodCall>
+
+
+
+
diff --git a/trunk/test/xmlrpc/data/xml1.expected b/trunk/test/xmlrpc/data/xml1.expected
new file mode 100644
index 0000000000..ff96de8df3
--- /dev/null
+++ b/trunk/test/xmlrpc/data/xml1.expected
@@ -0,0 +1,243 @@
+---
+- true
+-
+ -
+ subscriber: MegaCorp
+ lastName: Baker
+ telephone1: 1-508-791-1267
+ telephone2: 1-800-445-2588
+ password: p1111
+ OID: "1"
+ email: hbaker@yahoo.com
+ adminId: hbaker
+ objectName: AdministratorDO
+ -
+ subscriber: CornerStore
+ lastName: Dragon
+ telephone1: 1-781-789-9089
+ telephone2: 1-800-445-2588
+ password: p3333
+ OID: "3"
+ email: adragon@yahoo.com
+ adminId: adragon
+ objectName: AdministratorDO
+ -
+ subscriber: Cyberdyne
+ lastName: Rodman
+ telephone1: 1-617-789-1890
+ telephone2: 1-800-445-2588
+ password: p4444
+ OID: "4"
+ email: mrodman@yahoo.com
+ adminId: mrodman
+ objectName: AdministratorDO
+ -
+ subscriber: StarSports
+ lastName: Jordan
+ telephone1: 1-617-890-7897
+ telephone2: 1-800-445-2588
+ password: p5555
+ OID: "5"
+ email: mjordan@yahoo.com
+ adminId: mjordan
+ objectName: AdministratorDO
+ -
+ subscriber: GreatBooks
+ lastName: Pippen
+ telephone1: 1-781-789-9876
+ telephone2: 1-800-445-2588
+ password: p6666
+ OID: "6"
+ email: gpippen@yahoo.com
+ adminId: gpippen
+ objectName: AdministratorDO
+ -
+ subscriber: AxisChemicals
+ lastName: Andhrew
+ telephone1: 1-781-678-8970
+ telephone2: 1-800-445-2588
+ password: p7777
+ OID: "7"
+ email: aandrew@yahoo.com
+ adminId: aandrew
+ objectName: AdministratorDO
+ -
+ subscriber: MediaShop
+ lastName: Vincent
+ telephone1: 1-786-897-8908
+ telephone2: 1-800-445-2588
+ password: p8888
+ OID: "8"
+ email: tvincent@yahoo.com
+ adminId: tvincent
+ objectName: AdministratorDO
+ -
+ subscriber: SmartShop
+ lastName: Richard
+ telephone1: 1-508-789-6789
+ telephone2: 1-800-445-2588
+ password: p9999
+ OID: "9"
+ email: krichard@yahoo.com
+ adminId: krichard
+ objectName: AdministratorDO
+ -
+ subscriber: HomeNeeds
+ lastName: Cornell
+ telephone1: 1-617-789-8979
+ telephone2: 1-800-445-2588
+ password: paaaa
+ OID: "10"
+ email: gconell@yahoo.com
+ adminId: gcornell
+ objectName: AdministratorDO
+ -
+ subscriber: MegaCorp
+ lastName: HorstMann
+ telephone1: 1-508-791-1267
+ telephone2: 1-800-445-2588
+ password: p1111
+ OID: "11"
+ email: shorstmann@yahoo.com
+ adminId: shorstmann
+ objectName: AdministratorDO
+ -
+ subscriber: CornerStore
+ lastName: Bob
+ telephone1: 1-781-789-9089
+ telephone2: 1-800-445-2588
+ password: p3333
+ OID: "13"
+ email: rbob@yahoo.com
+ adminId: rbob
+ objectName: AdministratorDO
+ -
+ subscriber: Cyberdyne
+ lastName: Peter
+ telephone1: 1-617-789-1890
+ telephone2: 1-800-445-2588
+ password: p4444
+ OID: "14"
+ email: speter@yahoo.com
+ adminId: speter
+ objectName: AdministratorDO
+ -
+ subscriber: StarSports
+ lastName: Novak
+ telephone1: 1-617-890-7897
+ telephone2: 1-800-445-2588
+ password: p5555
+ OID: "15"
+ email: pnovak@yahoo.com
+ adminId: pnovak
+ objectName: AdministratorDO
+ -
+ subscriber: GreatBooks
+ lastName: Nancy
+ telephone1: 1-781-789-9876
+ telephone2: 1-800-445-2588
+ password: p6666
+ OID: "16"
+ email: pnancy@yahoo.com
+ adminId: pnancy
+ objectName: AdministratorDO
+ -
+ subscriber: AxisChemicals
+ lastName: Michel
+ telephone1: 1-781-678-8970
+ telephone2: 1-800-445-2588
+ password: p7777
+ OID: "17"
+ email: hmichel@yahoo.com
+ adminId: hmichel
+ objectName: AdministratorDO
+ -
+ subscriber: MediaShop
+ lastName: David
+ telephone1: 1-786-897-8908
+ telephone2: 1-800-445-2588
+ password: p8888
+ OID: "18"
+ email: kdavid@yahoo.com
+ adminId: kdavid
+ objectName: AdministratorDO
+ -
+ subscriber: SmartShop
+ lastName: Valnoor
+ telephone1: 1-508-789-6789
+ telephone2: 1-800-445-2588
+ password: p9999
+ OID: "19"
+ email: pvalnoor@yahoo.com
+ adminId: pvalnoor
+ objectName: AdministratorDO
+ -
+ subscriber: HomeNeeds
+ lastName: Smith
+ telephone1: 1-617-789-8979
+ telephone2: 1-800-445-2588
+ password: paaaa
+ OID: "20"
+ email: wsmith@yahoo.com
+ adminId: wsmith
+ objectName: AdministratorDO
+ -
+ subscriber: MegaCorp
+ lastName: Caral
+ telephone1: 1-781-789-9876
+ telephone2: 1-800-445-2588
+ password: p6666
+ OID: "21"
+ email: gcaral@yahoo.com
+ adminId: gcaral
+ objectName: AdministratorDO
+ -
+ subscriber: CornerStore
+ lastName: Hillary
+ telephone1: 1-786-897-8908
+ telephone2: 1-800-445-2588
+ password: p8888
+ OID: "23"
+ email: phillary@yahoo.com
+ adminId: phillary
+ objectName: AdministratorDO
+ -
+ subscriber: Cyberdyne
+ lastName: Philip
+ telephone1: 1-508-789-6789
+ telephone2: 1-800-445-2588
+ password: p9999
+ OID: "24"
+ email: bphilip@yahoo.com
+ adminId: bphilip
+ objectName: AdministratorDO
+ -
+ subscriber: StarSports
+ lastName: Andrea
+ telephone1: 1-617-789-8979
+ telephone2: 1-800-445-2588
+ password: paaaa
+ OID: "25"
+ email: sandrea@yahoo.com
+ adminId: sandrea
+ objectName: AdministratorDO
+ -
+ subscriber: s4
+ lastName: "null"
+ telephone1: "null"
+ telephone2: "null"
+ password: s4
+ OID: "26"
+ email: "null"
+ adminId: s4
+ objectName: AdministratorDO
+ -
+ subscriber: BigBank
+ lastName: administrator
+ telephone1: ''
+ telephone2: ''
+ password: admin
+ OID: "82"
+ email: ''
+ adminId: admin
+ objectName: AdministratorDO \ No newline at end of file
diff --git a/trunk/test/xmlrpc/data/xml1.xml b/trunk/test/xmlrpc/data/xml1.xml
new file mode 100644
index 0000000000..10aa55483b
--- /dev/null
+++ b/trunk/test/xmlrpc/data/xml1.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="ISO-8859-1"?><methodResponse><params><param><value><array><data><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>hbaker</value></member><member><name>email</name><value>hbaker@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-508-791-1267</value></member><member><name>OID</name><value>1</value></member><member><name>password</name><value>p1111</value></member><member><name>lastName</name><value>Baker</value></member><member><name>subscriber</name><value>MegaCorp</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>adragon</value></member><member><name>email</name><value>adragon@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-789-9089</value></member><member><name>OID</name><value>3</value></member><member><name>password</name><value>p3333</value></member><member><name>lastName</name><value>Dragon</value></member><member><name>subscriber</name><value>CornerStore</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>mrodman</value></member><member><name>email</name><value>mrodman@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-789-1890</value></member><member><name>OID</name><value>4</value></member><member><name>password</name><value>p4444</value></member><member><name>lastName</name><value>Rodman</value></member><member><name>subscriber</name><value>Cyberdyne</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>mjordan</value></member><member><name>email</name><value>mjordan@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-890-7897</value></member><member><name>OID</name><value>5</value></member><member><name>password</name><value>p5555</value></member><member><name>lastName</name><value>Jordan</value></member><member><name>subscriber</name><value>StarSports</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>gpippen</value></member><member><name>email</name><value>gpippen@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-789-9876</value></member><member><name>OID</name><value>6</value></member><member><name>password</name><value>p6666</value></member><member><name>lastName</name><value>Pippen</value></member><member><name>subscriber</name><value>GreatBooks</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>aandrew</value></member><member><name>email</name><value>aandrew@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-678-8970</value></member><member><name>OID</name><value>7</value></member><member><name>password</name><value>p7777</value></member><member><name>lastName</name><value>Andhrew</value></member><member><name>subscriber</name><value>AxisChemicals</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>tvincent</value></member><member><name>email</name><value>tvincent@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-786-897-8908</value></member><member><name>OID</name><value>8</value></member><member><name>password</name><value>p8888</value></member><member><name>lastName</name><value>Vincent</value></member><member><name>subscriber</name><value>MediaShop</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>krichard</value></member><member><name>email</name><value>krichard@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-508-789-6789</value></member><member><name>OID</name><value>9</value></member><member><name>password</name><value>p9999</value></member><member><name>lastName</name><value>Richard</value></member><member><name>subscriber</name><value>SmartShop</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>gcornell</value></member><member><name>email</name><value>gconell@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-789-8979</value></member><member><name>OID</name><value>10</value></member><member><name>password</name><value>paaaa</value></member><member><name>lastName</name><value>Cornell</value></member><member><name>subscriber</name><value>HomeNeeds</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>shorstmann</value></member><member><name>email</name><value>shorstmann@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-508-791-1267</value></member><member><name>OID</name><value>11</value></member><member><name>password</name><value>p1111</value></member><member><name>lastName</name><value>HorstMann</value></member><member><name>subscriber</name><value>MegaCorp</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>rbob</value></member><member><name>email</name><value>rbob@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-789-9089</value></member><member><name>OID</name><value>13</value></member><member><name>password</name><value>p3333</value></member><member><name>lastName</name><value>Bob</value></member><member><name>subscriber</name><value>CornerStore</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>speter</value></member><member><name>email</name><value>speter@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-789-1890</value></member><member><name>OID</name><value>14</value></member><member><name>password</name><value>p4444</value></member><member><name>lastName</name><value>Peter</value></member><member><name>subscriber</name><value>Cyberdyne</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>pnovak</value></member><member><name>email</name><value>pnovak@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-890-7897</value></member><member><name>OID</name><value>15</value></member><member><name>password</name><value>p5555</value></member><member><name>lastName</name><value>Novak</value></member><member><name>subscriber</name><value>StarSports</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>pnancy</value></member><member><name>email</name><value>pnancy@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-789-9876</value></member><member><name>OID</name><value>16</value></member><member><name>password</name><value>p6666</value></member><member><name>lastName</name><value>Nancy</value></member><member><name>subscriber</name><value>GreatBooks</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>hmichel</value></member><member><name>email</name><value>hmichel@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-678-8970</value></member><member><name>OID</name><value>17</value></member><member><name>password</name><value>p7777</value></member><member><name>lastName</name><value>Michel</value></member><member><name>subscriber</name><value>AxisChemicals</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>kdavid</value></member><member><name>email</name><value>kdavid@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-786-897-8908</value></member><member><name>OID</name><value>18</value></member><member><name>password</name><value>p8888</value></member><member><name>lastName</name><value>David</value></member><member><name>subscriber</name><value>MediaShop</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>pvalnoor</value></member><member><name>email</name><value>pvalnoor@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-508-789-6789</value></member><member><name>OID</name><value>19</value></member><member><name>password</name><value>p9999</value></member><member><name>lastName</name><value>Valnoor</value></member><member><name>subscriber</name><value>SmartShop</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>wsmith</value></member><member><name>email</name><value>wsmith@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-789-8979</value></member><member><name>OID</name><value>20</value></member><member><name>password</name><value>paaaa</value></member><member><name>lastName</name><value>Smith</value></member><member><name>subscriber</name><value>HomeNeeds</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>gcaral</value></member><member><name>email</name><value>gcaral@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-781-789-9876</value></member><member><name>OID</name><value>21</value></member><member><name>password</name><value>p6666</value></member><member><name>lastName</name><value>Caral</value></member><member><name>subscriber</name><value>MegaCorp</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>phillary</value></member><member><name>email</name><value>phillary@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-786-897-8908</value></member><member><name>OID</name><value>23</value></member><member><name>password</name><value>p8888</value></member><member><name>lastName</name><value>Hillary</value></member><member><name>subscriber</name><value>CornerStore</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>bphilip</value></member><member><name>email</name><value>bphilip@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-508-789-6789</value></member><member><name>OID</name><value>24</value></member><member><name>password</name><value>p9999</value></member><member><name>lastName</name><value>Philip</value></member><member><name>subscriber</name><value>Cyberdyne</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>sandrea</value></member><member><name>email</name><value>sandrea@yahoo.com</value></member><member><name>telephone2</name><value>1-800-445-2588</value></member><member><name>telephone1</name><value>1-617-789-8979</value></member><member><name>OID</name><value>25</value></member><member><name>password</name><value>paaaa</value></member><member><name>lastName</name><value>Andrea</value></member><member><name>subscriber</name><value>StarSports</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>s4</value></member><member><name>email</name><value>null</value></member><member><name>telephone2</name><value>null</value></member><member><name>telephone1</name><value>null</value></member><member><name>OID</name><value>26</value></member><member><name>password</name><value>s4</value></member><member><name>lastName</name><value>null</value></member><member><name>subscriber</name><value>s4</value></member></struct></value><value><struct><member><name>objectName</name><value>AdministratorDO</value></member><member><name>adminId</name><value>admin</value></member><member><name>email</name><value></value></member><member><name>telephone2</name><value></value></member><member><name>telephone1</name><value></value></member><member><name>OID</name><value>82</value></member><member><name>password</name><value>admin</value></member><member><name>lastName</name><value>administrator</value></member><member><name>subscriber</name><value>BigBank</value></member></struct></value></data></array></value></param></params></methodResponse>
diff --git a/trunk/test/xmlrpc/test_cookie.rb b/trunk/test/xmlrpc/test_cookie.rb
new file mode 100644
index 0000000000..c1be5c5577
--- /dev/null
+++ b/trunk/test/xmlrpc/test_cookie.rb
@@ -0,0 +1,96 @@
+require 'test/unit'
+require 'time'
+require 'webrick'
+require File.join(File.dirname(__FILE__), 'webrick_testing')
+require "xmlrpc/server"
+require 'xmlrpc/client'
+
+class TestCookie < Test::Unit::TestCase
+ include WEBrick_Testing
+
+ def create_servlet
+ s = XMLRPC::WEBrickServlet.new
+
+ def s.logged_in_users
+ @logged_in_users ||= {}
+ end
+ def s.request
+ @request
+ end
+ def s.response
+ @response
+ end
+ def s.service(request, response)
+ @request = request
+ @response = response
+ super
+ ensure
+ @request = nil
+ @response = nil
+ end
+
+ key = Time.now.to_i.to_s
+ valid_user = "valid-user"
+ s.add_handler("test.login") do |user, password|
+ ok = (user == valid_user and password == "secret")
+ if ok
+ s.logged_in_users[key] = user
+ expires = (Time.now + 60 * 60).httpdate
+ cookies = s.response.cookies
+ cookies << "key=\"#{key}\"; path=\"/RPC2\"; expires=#{expires}"
+ cookies << "user=\"#{user}\"; path=\"/RPC2\""
+ end
+ ok
+ end
+
+ s.add_handler("test.require_authenticate_echo") do |string|
+ cookies = {}
+ s.request.cookies.each do |cookie|
+ cookies[cookie.name] = cookie.value
+ end
+ if cookies == {"key" => key, "user" => valid_user}
+ string
+ else
+ raise XMLRPC::FaultException.new(29, "Authentication required")
+ end
+ end
+
+ s.set_default_handler do |name, *args|
+ raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
+ " or wrong number of parameters!")
+ end
+
+ s.add_introspection
+
+ s
+ end
+
+ def setup_http_server(port)
+ option = {:Port => port}
+
+ start_server(option) {|w| w.mount('/RPC2', create_servlet) }
+
+ @s = XMLRPC::Client.new3(:port => port)
+ end
+
+ PORT = 8070
+ def test_cookie
+ begin
+ setup_http_server(PORT)
+ do_test
+ ensure
+ stop_server
+ end
+ end
+
+ def do_test
+ assert(!@s.call("test.login", "invalid-user", "invalid-password"))
+ exception = assert_raise(XMLRPC::FaultException) do
+ @s.call("test.require_authenticate_echo", "Hello")
+ end
+ assert_equal(29, exception.faultCode)
+
+ assert(@s.call("test.login", "valid-user", "secret"))
+ assert_equal("Hello", @s.call("test.require_authenticate_echo", "Hello"))
+ end
+end
diff --git a/trunk/test/xmlrpc/test_datetime.rb b/trunk/test/xmlrpc/test_datetime.rb
new file mode 100644
index 0000000000..e38cea6f74
--- /dev/null
+++ b/trunk/test/xmlrpc/test_datetime.rb
@@ -0,0 +1,159 @@
+require 'test/unit'
+require "xmlrpc/datetime"
+
+class Test_DateTime < Test::Unit::TestCase
+
+ def test_new
+ dt = createDateTime()
+
+ assert_instance_of(XMLRPC::DateTime, dt)
+ end
+
+ def test_new_exception
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(4.5, 13, 32, 25, 60, 60) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 32, 25, 60, 60) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 25, 60, 60) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 60, 60) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 59, 60) }
+ assert_nothing_raised(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 59, 59) }
+
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 0, 0, -1, -1, -1) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 0, -1, -1, -1) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, -1, -1, -1) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, -1, -1) }
+ assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, 0, -1) }
+ assert_nothing_raised(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, 0, 0) }
+ end
+
+
+ def test_get_values
+ y, m, d, h, mi, s = 1970, 3, 24, 12, 0, 5
+ dt = XMLRPC::DateTime.new(y, m, d, h, mi, s)
+
+ assert_equal(y, dt.year)
+ assert_equal(m, dt.month)
+ assert_equal(m, dt.mon)
+ assert_equal(d, dt.day)
+
+ assert_equal(h, dt.hour)
+ assert_equal(mi,dt.min)
+ assert_equal(s, dt.sec)
+ end
+
+ def test_set_values
+ dt = createDateTime()
+ y, m, d, h, mi, s = 1950, 12, 9, 8, 52, 30
+
+ dt.year = y
+ dt.month = m
+ dt.day = d
+ dt.hour = h
+ dt.min = mi
+ dt.sec = s
+
+ assert_equal(y, dt.year)
+ assert_equal(m, dt.month)
+ assert_equal(m, dt.mon)
+ assert_equal(d, dt.day)
+
+ assert_equal(h, dt.hour)
+ assert_equal(mi,dt.min)
+ assert_equal(s, dt.sec)
+
+ dt.mon = 5
+ assert_equal(5, dt.month)
+ assert_equal(5, dt.mon)
+ end
+
+ def test_set_exception
+ dt = createDateTime()
+
+ assert_raises(ArgumentError) { dt.year = 4.5 }
+ assert_nothing_raised(ArgumentError) { dt.year = -2000 }
+
+ assert_raises(ArgumentError) { dt.month = 0 }
+ assert_raises(ArgumentError) { dt.month = 13 }
+ assert_nothing_raised(ArgumentError) { dt.month = 7 }
+
+ assert_raises(ArgumentError) { dt.mon = 0 }
+ assert_raises(ArgumentError) { dt.mon = 13 }
+ assert_nothing_raised(ArgumentError) { dt.mon = 7 }
+
+ assert_raises(ArgumentError) { dt.day = 0 }
+ assert_raises(ArgumentError) { dt.day = 32 }
+ assert_nothing_raised(ArgumentError) { dt.day = 16 }
+
+ assert_raises(ArgumentError) { dt.hour = -1 }
+ assert_raises(ArgumentError) { dt.hour = 25 }
+ assert_nothing_raised(ArgumentError) { dt.hour = 12 }
+
+ assert_raises(ArgumentError) { dt.min = -1 }
+ assert_raises(ArgumentError) { dt.min = 60 }
+ assert_nothing_raised(ArgumentError) { dt.min = 30 }
+
+ assert_raises(ArgumentError) { dt.sec = -1 }
+ assert_raises(ArgumentError) { dt.sec = 60 }
+ assert_nothing_raised(ArgumentError) { dt.sec = 30 }
+ end
+
+ def test_to_a
+ y, m, d, h, mi, s = 1970, 3, 24, 12, 0, 5
+ dt = XMLRPC::DateTime.new(y, m, d, h, mi, s)
+ a = dt.to_a
+
+ assert_instance_of(Array, a)
+ assert_equal(6, a.size, "Returned array has wrong size")
+
+ assert_equal(y, a[0])
+ assert_equal(m, a[1])
+ assert_equal(d, a[2])
+ assert_equal(h, a[3])
+ assert_equal(mi, a[4])
+ assert_equal(s, a[5])
+ end
+
+ def test_to_time1
+ y, m, d, h, mi, s = 1970, 3, 24, 12, 0, 5
+ dt = XMLRPC::DateTime.new(y, m, d, h, mi, s)
+ time = dt.to_time
+
+ assert_not_nil(time)
+
+ assert_equal(y, time.year)
+ assert_equal(m, time.month)
+ assert_equal(d, time.day)
+ assert_equal(h, time.hour)
+ assert_equal(mi, time.min)
+ assert_equal(s, time.sec)
+ end
+
+ def test_to_time2
+ dt = createDateTime()
+ dt.year = 1969
+
+ assert_nil(dt.to_time)
+ end
+
+ def test_to_date1
+ y, m, d, h, mi, s = 1970, 3, 24, 12, 0, 5
+ dt = XMLRPC::DateTime.new(y, m, d, h, mi, s)
+ date = dt.to_date
+
+ assert_equal(y, date.year)
+ assert_equal(m, date.month)
+ assert_equal(d, date.day)
+ end
+
+ def test_to_date2
+ dt = createDateTime()
+ dt.year = 666
+
+ assert_equal(666, dt.to_date.year)
+ end
+
+
+ def createDateTime
+ XMLRPC::DateTime.new(1970, 3, 24, 12, 0, 5)
+ end
+
+end
diff --git a/trunk/test/xmlrpc/test_features.rb b/trunk/test/xmlrpc/test_features.rb
new file mode 100644
index 0000000000..96a6313202
--- /dev/null
+++ b/trunk/test/xmlrpc/test_features.rb
@@ -0,0 +1,48 @@
+require 'test/unit'
+require "xmlrpc/create"
+require "xmlrpc/parser"
+require "xmlrpc/config"
+
+class Test_Features < Test::Unit::TestCase
+
+ def setup
+ @params = [nil, {"test" => nil}, [nil, 1, nil]]
+ end
+
+ def test_nil_create
+ XMLRPC::XMLWriter.each_installed_writer do |writer|
+ c = XMLRPC::Create.new(writer)
+
+ XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_CREATE)}
+ XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, false)
+ assert_raises(RuntimeError) { str = c.methodCall("test", *@params) }
+
+ XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_CREATE)}
+ XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
+ assert_nothing_raised { str = c.methodCall("test", *@params) }
+ end
+ end
+
+ def test_nil_parse
+ XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_CREATE)}
+ XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
+
+ XMLRPC::XMLWriter.each_installed_writer do |writer|
+ c = XMLRPC::Create.new(writer)
+ str = c.methodCall("test", *@params)
+ XMLRPC::XMLParser.each_installed_parser do |parser|
+ para = nil
+
+ XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_PARSER)}
+ XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, false)
+ assert_raises(RuntimeError) { para = parser.parseMethodCall(str) }
+
+ XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_PARSER)}
+ XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)
+ assert_nothing_raised { para = parser.parseMethodCall(str) }
+ assert_equal(para[1], @params)
+ end
+ end
+ end
+
+end
diff --git a/trunk/test/xmlrpc/test_marshal.rb b/trunk/test/xmlrpc/test_marshal.rb
new file mode 100644
index 0000000000..38bc8c646f
--- /dev/null
+++ b/trunk/test/xmlrpc/test_marshal.rb
@@ -0,0 +1,93 @@
+require 'test/unit'
+require "xmlrpc/marshal"
+
+class Test_Marshal < Test::Unit::TestCase
+ # for test_parser_values
+ class Person
+ include XMLRPC::Marshallable
+ attr_reader :name
+ def initialize(name)
+ @name = name
+ end
+ end
+
+
+ def test1_dump_response
+ assert_nothing_raised(NameError) {
+ XMLRPC::Marshal.dump_response('arg')
+ }
+ end
+
+ def test1_dump_call
+ assert_nothing_raised(NameError) {
+ XMLRPC::Marshal.dump_call('methodName', 'arg')
+ }
+ end
+
+ def test2_dump_load_response
+ value = [1, 2, 3, {"test" => true}, 3.4]
+ res = XMLRPC::Marshal.dump_response(value)
+
+ assert_equal(value, XMLRPC::Marshal.load_response(res))
+ end
+
+ def test2_dump_load_call
+ methodName = "testMethod"
+ value = [1, 2, 3, {"test" => true}, 3.4]
+ exp = [methodName, [value, value]]
+
+ res = XMLRPC::Marshal.dump_call(methodName, value, value)
+
+ assert_equal(exp, XMLRPC::Marshal.load_call(res))
+ end
+
+ def test_parser_values
+ v1 = [
+ 1, -7778, # integers
+ 1.0, 0.0, -333.0, 2343434343.0, # floats
+ false, true, true, false, # booleans
+ "Hallo", "with < and >", "" # strings
+ ]
+
+ v2 = [
+ [v1, v1, v1],
+ {"a" => v1}
+ ]
+
+ v3 = [
+ XMLRPC::Base64.new("\001"*1000), # base64
+ :aSymbol, :anotherSym # symbols (-> string)
+ ]
+ v3_exp = [
+ "\001"*1000,
+ "aSymbol", "anotherSym"
+ ]
+ person = Person.new("Michael")
+
+ XMLRPC::XMLParser.each_installed_parser do |parser|
+ m = XMLRPC::Marshal.new(parser)
+
+ assert_equal( v1, m.load_response(m.dump_response(v1)) )
+ assert_equal( v2, m.load_response(m.dump_response(v2)) )
+ assert_equal( v3_exp, m.load_response(m.dump_response(v3)) )
+
+ pers = m.load_response(m.dump_response(person))
+
+ assert( pers.is_a?(Person) )
+ assert( person.name == pers.name )
+ end
+
+ # missing, Date, Time, DateTime
+ # Struct
+ end
+
+ def test_no_params_tag
+ # bug found by Idan Sofer
+
+ expect = %{<?xml version="1.0" ?><methodCall><methodName>myMethod</methodName><params/></methodCall>\n}
+
+ str = XMLRPC::Marshal.dump_call("myMethod")
+ assert_equal(expect, str)
+ end
+
+end
diff --git a/trunk/test/xmlrpc/test_parser.rb b/trunk/test/xmlrpc/test_parser.rb
new file mode 100644
index 0000000000..44ca1f88b7
--- /dev/null
+++ b/trunk/test/xmlrpc/test_parser.rb
@@ -0,0 +1,85 @@
+require 'test/unit'
+require 'xmlrpc/datetime'
+require "xmlrpc/parser"
+require 'yaml'
+
+module GenericParserTest
+ def datafile(base)
+ File.join(File.dirname(__FILE__), "data", base)
+ end
+
+ def load_data(name)
+ [File.read(datafile(name) + ".xml"), YAML.load(File.read(datafile(name) + ".expected"))]
+ end
+
+ def setup
+ @xml1, @expected1 = load_data('xml1')
+ @xml2, @expected2 = load_data('bug_covert')
+ @xml3, @expected3 = load_data('bug_bool')
+ @xml4, @expected4 = load_data('value')
+
+ @cdata_xml, @cdata_expected = load_data('bug_cdata')
+
+ @datetime_xml = File.read(datafile('datetime_iso8601.xml'))
+ @datetime_expected = XMLRPC::DateTime.new(2004, 11, 5, 1, 15, 23)
+
+ @fault_doc = File.read(datafile('fault.xml'))
+ end
+
+ # test parseMethodResponse --------------------------------------------------
+
+ def test_parseMethodResponse1
+ assert_equal(@expected1, @p.parseMethodResponse(@xml1))
+ end
+
+ def test_parseMethodResponse2
+ assert_equal(@expected2, @p.parseMethodResponse(@xml2))
+ end
+
+ def test_parseMethodResponse3
+ assert_equal(@expected3, @p.parseMethodResponse(@xml3))
+ end
+
+ def test_cdata
+ assert_equal(@cdata_expected, @p.parseMethodResponse(@cdata_xml))
+ end
+
+ def test_dateTime
+ assert_equal(@datetime_expected, @p.parseMethodResponse(@datetime_xml)[1])
+ end
+
+ # test parseMethodCall ------------------------------------------------------
+
+ def test_parseMethodCall
+ assert_equal(@expected4, @p.parseMethodCall(@xml4))
+ end
+
+ # test fault ----------------------------------------------------------------
+
+ def test_fault
+ flag, fault = @p.parseMethodResponse(@fault_doc)
+ assert_equal(flag, false)
+ unless fault.is_a? XMLRPC::FaultException
+ assert(false, "must be an instance of class XMLRPC::FaultException")
+ end
+ assert_equal(fault.faultCode, 4)
+ assert_equal(fault.faultString, "an error message")
+ end
+end
+
+# create test class for each installed parser
+XMLRPC::XMLParser.each_installed_parser do |parser|
+ klass = parser.class
+ name = klass.to_s.split("::").last
+
+ eval %{
+ class Test_#{name} < Test::Unit::TestCase
+ include GenericParserTest
+
+ def setup
+ super
+ @p = #{klass}.new
+ end
+ end
+ }
+end
diff --git a/trunk/test/xmlrpc/test_webrick_server.rb b/trunk/test/xmlrpc/test_webrick_server.rb
new file mode 100644
index 0000000000..4cd63cfa74
--- /dev/null
+++ b/trunk/test/xmlrpc/test_webrick_server.rb
@@ -0,0 +1,98 @@
+require 'test/unit'
+require 'webrick'
+require File.join(File.dirname(__FILE__), 'webrick_testing')
+require "xmlrpc/server"
+require 'xmlrpc/client'
+
+class Test_Webrick < Test::Unit::TestCase
+ include WEBrick_Testing
+
+ def create_servlet
+ s = XMLRPC::WEBrickServlet.new
+
+ s.add_handler("test.add") do |a,b|
+ a + b
+ end
+
+ s.add_handler("test.div") do |a,b|
+ if b == 0
+ raise XMLRPC::FaultException.new(1, "division by zero")
+ else
+ a / b
+ end
+ end
+
+ s.set_default_handler do |name, *args|
+ raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
+ " or wrong number of parameters!")
+ end
+
+ s.add_introspection
+
+ return s
+ end
+
+ def setup_http_server(port, use_ssl)
+ option = {
+ :Port => port,
+ :SSLEnable => use_ssl,
+ }
+ if use_ssl
+ require 'webrick/https'
+ option.update(
+ :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
+ :SSLCertName => []
+ )
+ end
+
+ start_server(option) {|w| w.mount('/RPC2', create_servlet) }
+
+ @s = XMLRPC::Client.new3(:port => port, :use_ssl => use_ssl)
+ end
+
+ PORT = 8070
+ def test_client_server
+ # NOTE: I don't enable SSL testing as this hangs
+ [false].each do |use_ssl|
+ begin
+ setup_http_server(PORT, use_ssl)
+ do_test
+ ensure
+ stop_server
+ end
+ end
+ end
+
+ def do_test
+ # simple call
+ assert_equal 9, @s.call('test.add', 4, 5)
+
+ # fault exception
+ assert_raises(XMLRPC::FaultException) { @s.call('test.div', 1, 0) }
+
+ # fault exception via call2
+ ok, param = @s.call2('test.div', 1, 0)
+ assert_equal false, ok
+ assert_instance_of XMLRPC::FaultException, param
+ assert_equal 1, param.faultCode
+ assert_equal 'division by zero', param.faultString
+
+ # call2 without fault exception
+ ok, param = @s.call2('test.div', 10, 5)
+ assert_equal true, ok
+ assert_equal param, 2
+
+ # introspection
+ assert_equal ["test.add", "test.div", "system.listMethods", "system.methodSignature", "system.methodHelp"], @s.call("system.listMethods")
+
+ # default handler (missing handler)
+ ok, param = @s.call2('test.nonexisting')
+ assert_equal false, ok
+ assert_equal -99, param.faultCode
+
+ # default handler (wrong number of arguments)
+ ok, param = @s.call2('test.add', 1, 2, 3)
+ assert_equal false, ok
+ assert_equal -99, param.faultCode
+ end
+end
diff --git a/trunk/test/xmlrpc/webrick_testing.rb b/trunk/test/xmlrpc/webrick_testing.rb
new file mode 100644
index 0000000000..2ca52bad22
--- /dev/null
+++ b/trunk/test/xmlrpc/webrick_testing.rb
@@ -0,0 +1,38 @@
+require 'timeout'
+
+module WEBrick_Testing
+ class DummyLog < WEBrick::BasicLog
+ def initialize() super(self) end
+ def <<(*args) end
+ end
+
+ def start_server(config={})
+ raise "already started" if @__server
+ @__started = false
+
+ @__server_thread = Thread.new {
+ @__server = WEBrick::HTTPServer.new(
+ {
+ :Logger => DummyLog.new,
+ :AccessLog => [],
+ :StartCallback => proc { @__started = true }
+ }.update(config))
+ yield @__server
+ @__server.start
+ @__started = false
+ }
+
+ Timeout.timeout(5) {
+ Thread.pass until @__started # wait until the server is ready
+ }
+ end
+
+ def stop_server
+ Timeout.timeout(5) {
+ @__server.shutdown
+ Thread.pass while @__started # wait until the server is down
+ }
+ @__server_thread.join
+ @__server = nil
+ end
+end
diff --git a/trunk/test/yaml/test_yaml.rb b/trunk/test/yaml/test_yaml.rb
new file mode 100644
index 0000000000..74a2fa851e
--- /dev/null
+++ b/trunk/test/yaml/test_yaml.rb
@@ -0,0 +1,1298 @@
+# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*-
+# vim:sw=4:ts=4
+# $Id$
+#
+require 'test/unit'
+require 'yaml'
+
+# [ruby-core:01946]
+module YAML_Tests
+ StructTest = Struct::new( :c )
+end
+
+class YAML_Unit_Tests < Test::Unit::TestCase
+ #
+ # Convert between YAML and the object to verify correct parsing and
+ # emitting
+ #
+ def assert_to_yaml( obj, yaml )
+ assert_equal( obj, YAML::load( yaml ) )
+ assert_equal( obj, YAML::parse( yaml ).transform )
+ assert_equal( obj, YAML::load( obj.to_yaml ) )
+ assert_equal( obj, YAML::parse( obj.to_yaml ).transform )
+ assert_equal( obj, YAML::load(
+ obj.to_yaml( :UseVersion => true, :UseHeader => true, :SortKeys => true )
+ ) )
+ end
+
+ #
+ # Test parser only
+ #
+ def assert_parse_only( obj, yaml )
+ assert_equal( obj, YAML::load( yaml ) )
+ assert_equal( obj, YAML::parse( yaml ).transform )
+ end
+
+ def assert_cycle( obj )
+ assert_equal( obj, YAML::load( obj.to_yaml ) )
+ end
+
+ def assert_path_segments( path, segments )
+ YAML::YPath.each_path( path ) { |choice|
+ assert_equal( choice.segments, segments.shift )
+ }
+ assert_equal( segments.length, 0, "Some segments leftover: #{ segments.inspect }" )
+ end
+
+ #
+ # Make a time with the time zone
+ #
+ def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" )
+ usec = usec.to_s.to_f * 1000000
+ val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec )
+ if zone != "Z"
+ hour = zone[0,3].to_i * 3600
+ min = zone[3,2].to_i * 60
+ ofs = (hour + min)
+ val = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 )
+ end
+ return val
+ end
+
+ #
+ # Tests modified from 00basic.t in YAML.pm
+ #
+ def test_basic_map
+ # Simple map
+ assert_parse_only(
+ { 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, <<EOY
+one: foo
+two: bar
+three: baz
+EOY
+ )
+ end
+
+ def test_basic_strings
+ # Common string types
+ assert_cycle("x")
+ assert_cycle(":x")
+ assert_cycle(":")
+ assert_parse_only(
+ { 1 => 'simple string', 2 => 42, 3 => '1 Single Quoted String',
+ 4 => 'YAML\'s Double "Quoted" String', 5 => "A block\n with several\n lines.\n",
+ 6 => "A \"chomped\" block", 7 => "A folded\n string\n", 8 => ": started string" },
+ <<EOY
+1: simple string
+2: 42
+3: '1 Single Quoted String'
+4: "YAML's Double \\\"Quoted\\\" String"
+5: |
+ A block
+ with several
+ lines.
+6: |-
+ A "chomped" block
+7: >
+ A
+ folded
+ string
+8: ": started string"
+EOY
+ )
+ end
+
+ #
+ # Test the specification examples
+ # - Many examples have been changes because of whitespace problems that
+ # caused the two to be inequivalent, or keys to be sorted wrong
+ #
+
+ def test_spec_simple_implicit_sequence
+ # Simple implicit sequence
+ assert_to_yaml(
+ [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ], <<EOY
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+EOY
+ )
+ end
+
+ def test_spec_simple_implicit_map
+ # Simple implicit map
+ assert_to_yaml(
+ { 'hr' => 65, 'avg' => 0.278, 'rbi' => 147 }, <<EOY
+avg: 0.278
+hr: 65
+rbi: 147
+EOY
+ )
+ end
+
+ def test_spec_simple_map_with_nested_sequences
+ # Simple mapping with nested sequences
+ assert_to_yaml(
+ { 'american' =>
+ [ 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ],
+ 'national' =>
+ [ 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ] }, <<EOY
+american:
+ - Boston Red Sox
+ - Detroit Tigers
+ - New York Yankees
+national:
+ - New York Mets
+ - Chicago Cubs
+ - Atlanta Braves
+EOY
+ )
+ end
+
+ def test_spec_simple_sequence_with_nested_map
+ # Simple sequence with nested map
+ assert_to_yaml(
+ [
+ {'name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278},
+ {'name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288}
+ ], <<EOY
+-
+ avg: 0.278
+ hr: 65
+ name: Mark McGwire
+-
+ avg: 0.288
+ hr: 63
+ name: Sammy Sosa
+EOY
+ )
+ end
+
+ def test_spec_sequence_of_sequences
+ # Simple sequence with inline sequences
+ assert_parse_only(
+ [
+ [ 'name', 'hr', 'avg' ],
+ [ 'Mark McGwire', 65, 0.278 ],
+ [ 'Sammy Sosa', 63, 0.288 ]
+ ], <<EOY
+- [ name , hr , avg ]
+- [ Mark McGwire , 65 , 0.278 ]
+- [ Sammy Sosa , 63 , 0.288 ]
+EOY
+ )
+ end
+
+ def test_spec_mapping_of_mappings
+ # Simple map with inline maps
+ assert_parse_only(
+ { 'Mark McGwire' =>
+ { 'hr' => 65, 'avg' => 0.278 },
+ 'Sammy Sosa' =>
+ { 'hr' => 63, 'avg' => 0.288 }
+ }, <<EOY
+Mark McGwire: {hr: 65, avg: 0.278}
+Sammy Sosa: {hr: 63,
+ avg: 0.288}
+EOY
+ )
+ end
+
+ def test_ambiguous_comments
+ # [ruby-talk:88012]
+ assert_to_yaml( "Call the method #dave", <<EOY )
+--- "Call the method #dave"
+EOY
+ end
+
+ def test_spec_nested_comments
+ # Map and sequences with comments
+ assert_parse_only(
+ { 'hr' => [ 'Mark McGwire', 'Sammy Sosa' ],
+ 'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
+hr: # 1998 hr ranking
+ - Mark McGwire
+ - Sammy Sosa
+rbi:
+ # 1998 rbi ranking
+ - Sammy Sosa
+ - Ken Griffey
+EOY
+ )
+ end
+
+ def test_spec_anchors_and_aliases
+ # Anchors and aliases
+ assert_parse_only(
+ { 'hr' =>
+ [ 'Mark McGwire', 'Sammy Sosa' ],
+ 'rbi' =>
+ [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
+hr:
+ - Mark McGwire
+ # Name "Sammy Sosa" scalar SS
+ - &SS Sammy Sosa
+rbi:
+ # So it can be referenced later.
+ - *SS
+ - Ken Griffey
+EOY
+ )
+
+ assert_to_yaml(
+ [{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}], <<EOY
+ -
+ &F fareref: DOGMA
+ &C currency: GBP
+ &D departure: LAX
+ &A arrival: EDI
+ - { *F: MADF, *C: AUD, *D: SYD, *A: MEL }
+ - { *F: DFSF, *C: USD, *D: JFK, *A: MCO }
+EOY
+ )
+
+ assert_to_yaml(
+ {"ALIASES"=>["fareref", "currency", "departure", "arrival"], "FARES"=>[{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}]}, <<EOY
+---
+ALIASES: [&f fareref, &c currency, &d departure, &a arrival]
+FARES:
+- *f: DOGMA
+ *c: GBP
+ *d: LAX
+ *a: EDI
+
+- *f: MADF
+ *c: AUD
+ *d: SYD
+ *a: MEL
+
+- *f: DFSF
+ *c: USD
+ *d: JFK
+ *a: MCO
+
+EOY
+ )
+
+ end
+
+ def test_spec_mapping_between_sequences
+ # Complex key #1
+ dj = Date.new( 2001, 7, 23 )
+ assert_parse_only(
+ { [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
+ [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] }, <<EOY
+? # PLAY SCHEDULE
+ - Detroit Tigers
+ - Chicago Cubs
+:
+ - 2001-07-23
+
+? [ New York Yankees,
+ Atlanta Braves ]
+: [ 2001-07-02, 2001-08-12,
+ 2001-08-14 ]
+EOY
+ )
+
+ # Complex key #2
+ assert_parse_only(
+ { [ 'New York Yankees', 'Atlanta Braves' ] =>
+ [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ),
+ Date.new( 2001, 8, 14 ) ],
+ [ 'Detroit Tigers', 'Chicago Cubs' ] =>
+ [ Date.new( 2001, 7, 23 ) ]
+ }, <<EOY
+?
+ - New York Yankees
+ - Atlanta Braves
+:
+ - 2001-07-02
+ - 2001-08-12
+ - 2001-08-14
+?
+ - Detroit Tigers
+ - Chicago Cubs
+:
+ - 2001-07-23
+EOY
+ )
+ end
+
+ def test_spec_sequence_key_shortcut
+ # Shortcut sequence map
+ assert_parse_only(
+ { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
+ 'bill-to' => 'Chris Dumars', 'product' =>
+ [ { 'item' => 'Super Hoop', 'quantity' => 1 },
+ { 'item' => 'Basketball', 'quantity' => 4 },
+ { 'item' => 'Big Shoes', 'quantity' => 1 } ] }, <<EOY
+invoice: 34843
+date : 2001-01-23
+bill-to: Chris Dumars
+product:
+ - item : Super Hoop
+ quantity: 1
+ - item : Basketball
+ quantity: 4
+ - item : Big Shoes
+ quantity: 1
+EOY
+ )
+ end
+
+ def test_spec_sequence_in_sequence_shortcut
+ # Seq-in-seq
+ assert_parse_only( [ [ [ 'one', 'two', 'three' ] ] ], <<EOY )
+- - - one
+ - two
+ - three
+EOY
+ end
+
+ def test_spec_sequence_shortcuts
+ # Sequence shortcuts combined
+ assert_parse_only(
+[
+ [
+ [ [ 'one' ] ],
+ [ 'two', 'three' ],
+ { 'four' => nil },
+ [ { 'five' => [ 'six' ] } ],
+ [ 'seven' ]
+ ],
+ [ 'eight', 'nine' ]
+], <<EOY )
+- - - - one
+ - - two
+ - three
+ - four:
+ - - five:
+ - six
+ - - seven
+- - eight
+ - nine
+EOY
+ end
+
+ def test_spec_single_literal
+ # Literal scalar block
+ assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
+- |
+ \\/|\\/|
+ / | |_
+EOY
+ end
+
+ def test_spec_single_folded
+ # Folded scalar block
+ assert_parse_only(
+ [ "Mark McGwire's year was crippled by a knee injury.\n" ], <<EOY
+- >
+ Mark McGwire\'s
+ year was crippled
+ by a knee injury.
+EOY
+ )
+ end
+
+ def test_spec_preserve_indent
+ # Preserve indented spaces
+ assert_parse_only(
+ "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n", <<EOY
+--- >
+ Sammy Sosa completed another
+ fine season with great stats.
+
+ 63 Home Runs
+ 0.288 Batting Average
+
+ What a year!
+EOY
+ )
+ end
+
+ def test_spec_indentation_determines_scope
+ assert_parse_only(
+ { 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n",
+ 'stats' => "65 Home Runs\n0.278 Batting Average\n" }, <<EOY
+name: Mark McGwire
+accomplishment: >
+ Mark set a major league
+ home run record in 1998.
+stats: |
+ 65 Home Runs
+ 0.278 Batting Average
+EOY
+ )
+ end
+
+ def test_spec_multiline_scalars
+ # Multiline flow scalars
+ assert_parse_only(
+ { 'plain' => 'This unquoted scalar spans many lines.',
+ 'quoted' => "So does this quoted scalar.\n" }, <<EOY
+plain: This unquoted
+ scalar spans
+ many lines.
+quoted: "\\
+ So does this quoted
+ scalar.\\n"
+EOY
+ )
+ end
+
+ def test_spec_type_int
+ assert_parse_only(
+ { 'canonical' => 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, <<EOY
+canonical: 12345
+decimal: +12,345
+octal: 014
+hexadecimal: 0xC
+EOY
+ )
+ assert_parse_only(
+ { 'canonical' => 685230, 'decimal' => 685230, 'octal' => 02472256, 'hexadecimal' => 0x0A74AE, 'sexagesimal' => 685230 }, <<EOY)
+canonical: 685230
+decimal: +685,230
+octal: 02472256
+hexadecimal: 0x0A,74,AE
+sexagesimal: 190:20:30
+EOY
+ end
+
+ def test_spec_type_float
+ assert_parse_only(
+ { 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15,
+ 'negative infinity' => -1.0/0.0 }, <<EOY)
+canonical: 1.23015e+3
+exponential: 12.3015e+02
+fixed: 1,230.15
+negative infinity: -.inf
+EOY
+ nan = YAML::load( <<EOY )
+not a number: .NaN
+EOY
+ assert( nan['not a number'].nan? )
+ end
+
+ def test_spec_type_misc
+ assert_parse_only(
+ { nil => nil, true => true, false => false, 'string' => '12345' }, <<EOY
+null: ~
+true: yes
+false: no
+string: '12345'
+EOY
+ )
+ end
+
+ def test_spec_complex_invoice
+ # Complex invoice type
+ id001 = { 'given' => 'Chris', 'family' => 'Dumars', 'address' =>
+ { 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak',
+ 'state' => 'MI', 'postal' => 48046 } }
+ assert_parse_only(
+ { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
+ 'bill-to' => id001, 'ship-to' => id001, 'product' =>
+ [ { 'sku' => 'BL394D', 'quantity' => 4,
+ 'description' => 'Basketball', 'price' => 450.00 },
+ { 'sku' => 'BL4438H', 'quantity' => 1,
+ 'description' => 'Super Hoop', 'price' => 2392.00 } ],
+ 'tax' => 251.42, 'total' => 4443.52,
+ 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" }, <<EOY
+invoice: 34843
+date : 2001-01-23
+bill-to: &id001
+ given : Chris
+ family : !str Dumars
+ address:
+ lines: |
+ 458 Walkman Dr.
+ Suite #292
+ city : Royal Oak
+ state : MI
+ postal : 48046
+ship-to: *id001
+product:
+ - !map
+ sku : BL394D
+ quantity : 4
+ description : Basketball
+ price : 450.00
+ - sku : BL4438H
+ quantity : 1
+ description : Super Hoop
+ price : 2392.00
+tax : 251.42
+total: 4443.52
+comments: >
+ Late afternoon is best.
+ Backup contact is Nancy
+ Billsmer @ 338-4338.
+EOY
+ )
+ end
+
+ def test_spec_log_file
+ doc_ct = 0
+ YAML::load_documents( <<EOY
+---
+Time: 2001-11-23 15:01:42 -05:00
+User: ed
+Warning: >
+ This is an error message
+ for the log file
+---
+Time: 2001-11-23 15:02:31 -05:00
+User: ed
+Warning: >
+ A slightly different error
+ message.
+---
+Date: 2001-11-23 15:03:17 -05:00
+User: ed
+Fatal: >
+ Unknown variable "bar"
+Stack:
+ - file: TopClass.py
+ line: 23
+ code: |
+ x = MoreObject("345\\n")
+ - file: MoreClass.py
+ line: 58
+ code: |-
+ foo = bar
+EOY
+ ) { |doc|
+ case doc_ct
+ when 0
+ assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
+ 'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
+ when 1
+ assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
+ 'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
+ when 2
+ assert_equal( doc, { 'Date' => mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
+ 'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
+ 'Stack' => [
+ { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
+ { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
+ end
+ doc_ct += 1
+ }
+ assert_equal( doc_ct, 3 )
+ end
+
+ def test_spec_root_fold
+ y = YAML::load( <<EOY
+--- >
+This YAML stream contains a single text value.
+The next stream is a log file - a sequence of
+log entries. Adding an entry to the log is a
+simple matter of appending it at the end.
+EOY
+ )
+ assert_equal( y, "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n" )
+ end
+
+ def test_spec_root_mapping
+ y = YAML::load( <<EOY
+# This stream is an example of a top-level mapping.
+invoice : 34843
+date : 2001-01-23
+total : 4443.52
+EOY
+ )
+ assert_equal( y, { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } )
+ end
+
+ def test_spec_oneline_docs
+ doc_ct = 0
+ YAML::load_documents( <<EOY
+# The following is a sequence of three documents.
+# The first contains an empty mapping, the second
+# an empty sequence, and the last an empty string.
+--- {}
+--- [ ]
+--- ''
+EOY
+ ) { |doc|
+ case doc_ct
+ when 0
+ assert_equal( doc, {} )
+ when 1
+ assert_equal( doc, [] )
+ when 2
+ assert_equal( doc, '' )
+ end
+ doc_ct += 1
+ }
+ assert_equal( doc_ct, 3 )
+ end
+
+ def test_spec_domain_prefix
+ customer_proc = proc { |type, val|
+ if Hash === val
+ scheme, domain, type = type.split( ':', 3 )
+ val['type'] = "domain #{type}"
+ val
+ else
+ raise ArgumentError, "Not a Hash in domain.tld,2002/invoice: " + val.inspect
+ end
+ }
+ YAML.add_domain_type( "domain.tld,2002", 'invoice', &customer_proc )
+ YAML.add_domain_type( "domain.tld,2002", 'customer', &customer_proc )
+ assert_parse_only( { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <<EOY
+# 'http://domain.tld,2002/invoice' is some type family.
+invoice: !domain.tld,2002/^invoice
+ # 'seq' is shorthand for 'http://yaml.org/seq'.
+ # This does not effect '^customer' below
+ # because it is does not specify a prefix.
+ customers: !seq
+ # '^customer' is shorthand for the full
+ # notation 'http://domain.tld,2002/customer'.
+ - !^customer
+ given : Chris
+ family : Dumars
+EOY
+ )
+ end
+
+ def test_spec_throwaway
+ assert_parse_only(
+ {"this"=>"contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"}, <<EOY
+### These are four throwaway comment ###
+
+### lines (the second line is empty). ###
+this: | # Comments may trail lines.
+ contains three lines of text.
+ The third one starts with a
+ # character. This isn't a comment.
+
+# These are three throwaway comment
+# lines (the first line is empty).
+EOY
+ )
+ end
+
+ def test_spec_force_implicit
+ # Force implicit
+ assert_parse_only(
+ { 'integer' => 12, 'also int' => 12, 'string' => '12' }, <<EOY
+integer: 12
+also int: ! "12"
+string: !str 12
+EOY
+ )
+ end
+
+ def test_spec_private_types
+ doc_ct = 0
+ YAML::parse_documents( <<EOY
+# Private types are per-document.
+---
+pool: !!ball
+ number: 8
+ color: black
+---
+bearing: !!ball
+ material: steel
+EOY
+ ) { |doc|
+ case doc_ct
+ when 0
+ assert_equal( doc['pool'].type_id, 'x-private:ball' )
+ assert_equal( doc['pool'].transform.value, { 'number' => 8, 'color' => 'black' } )
+ when 1
+ assert_equal( doc['bearing'].type_id, 'x-private:ball' )
+ assert_equal( doc['bearing'].transform.value, { 'material' => 'steel' } )
+ end
+ doc_ct += 1
+ }
+ assert_equal( doc_ct, 2 )
+ end
+
+ def test_spec_url_escaping
+ YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
+ "ONE: #{val}"
+ }
+ YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
+ "TWO: #{val}"
+ }
+ assert_parse_only(
+ { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, <<EOY
+same:
+ - !domain.tld,2002/type\\x30 value
+ - !domain.tld,2002/type0 value
+different: # As far as the YAML parser is concerned
+ - !domain.tld,2002/type%30 value
+EOY
+ )
+ end
+
+ def test_spec_override_anchor
+ # Override anchor
+ a001 = "The alias node below is a repeated use of this value.\n"
+ assert_parse_only(
+ { 'anchor' => 'This scalar has an anchor.', 'override' => a001, 'alias' => a001 }, <<EOY
+anchor : &A001 This scalar has an anchor.
+override : &A001 >
+ The alias node below is a
+ repeated use of this value.
+alias : *A001
+EOY
+ )
+ end
+
+ def test_spec_explicit_families
+ YAML.add_domain_type( "somewhere.com,2002", 'type' ) { |type, val|
+ "SOMEWHERE: #{val}"
+ }
+ assert_parse_only(
+ { 'not-date' => '2002-04-28', 'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;", 'hmm' => "SOMEWHERE: family above is short for\nhttp://somewhere.com/type\n" }, <<EOY
+not-date: !str 2002-04-28
+picture: !binary |
+ R0lGODlhDAAMAIQAAP//9/X
+ 17unp5WZmZgAAAOfn515eXv
+ Pz7Y6OjuDg4J+fn5OTk6enp
+ 56enmleECcgggoBADs=
+
+hmm: !somewhere.com,2002/type |
+ family above is short for
+ http://somewhere.com/type
+EOY
+ )
+ end
+
+ def test_spec_application_family
+ # Testing the clarkevans.com graphs
+ YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
+ if Array === val
+ val << "Shape Container"
+ val
+ else
+ raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
+ end
+ }
+ one_shape_proc = Proc.new { |type, val|
+ if Hash === val
+ type = type.split( /:/ )
+ val['TYPE'] = "Shape: #{type[2]}"
+ val
+ else
+ raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
+ end
+ }
+ YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
+ YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
+ YAML.add_domain_type( "clarkevans.com,2002", 'graph/text', &one_shape_proc )
+ assert_parse_only(
+ [[{"radius"=>7, "center"=>{"x"=>73, "y"=>129}, "TYPE"=>"Shape: graph/circle"}, {"finish"=>{"x"=>89, "y"=>102}, "TYPE"=>"Shape: graph/line", "start"=>{"x"=>73, "y"=>129}}, {"TYPE"=>"Shape: graph/text", "value"=>"Pretty vector drawing.", "start"=>{"x"=>73, "y"=>129}, "color"=>16772795}, "Shape Container"]], <<EOY
+- !clarkevans.com,2002/graph/^shape
+ - !^circle
+ center: &ORIGIN {x: 73, y: 129}
+ radius: 7
+ - !^line # !clarkevans.com,2002/graph/line
+ start: *ORIGIN
+ finish: { x: 89, y: 102 }
+ - !^text
+ start: *ORIGIN
+ color: 0xFFEEBB
+ value: Pretty vector drawing.
+EOY
+ )
+ end
+
+ def test_spec_float_explicit
+ assert_parse_only(
+ [ 10.0, 10.0, 10.0, 10.0 ], <<EOY
+# All entries in the sequence
+# have the same type and value.
+- 10.0
+- !float 10
+- !yaml.org,2002/^float '10'
+- !yaml.org,2002/float "\\
+ 1\\
+ 0"
+EOY
+ )
+ end
+
+ def test_spec_builtin_seq
+ # Assortment of sequences
+ assert_parse_only(
+ { 'empty' => [], 'in-line' => [ 'one', 'two', 'three', 'four', 'five' ],
+ 'nested' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
+ "A multi-line sequence entry\n", 'Sixth item in top sequence' ] }, <<EOY
+empty: []
+in-line: [ one, two, three # May span lines,
+ , four, # indentation is
+ five ] # mostly ignored.
+nested:
+ - First item in top sequence
+ -
+ - Subordinate sequence entry
+ - >
+ A multi-line
+ sequence entry
+ - Sixth item in top sequence
+EOY
+ )
+ end
+
+ def test_spec_builtin_map
+ # Assortment of mappings
+ assert_parse_only(
+ { 'empty' => {}, 'in-line' => { 'one' => 1, 'two' => 2 },
+ 'spanning' => { 'one' => 1, 'two' => 2 },
+ 'nested' => { 'first' => 'First entry', 'second' =>
+ { 'key' => 'Subordinate mapping' }, 'third' =>
+ [ 'Subordinate sequence', {}, 'Previous mapping is empty.',
+ { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
+ 'The previous entry is equal to the following one.',
+ { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
+ 12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
+ "\a" => 'This key had to be escaped.',
+ "This is a multi-line folded key\n" => "Whose value is also multi-line.\n",
+ [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }, <<EOY
+
+empty: {}
+in-line: { one: 1, two: 2 }
+spanning: { one: 1,
+ two: 2 }
+nested:
+ first : First entry
+ second:
+ key: Subordinate mapping
+ third:
+ - Subordinate sequence
+ - { }
+ - Previous mapping is empty.
+ - A key: value pair in a sequence.
+ A second: key:value pair.
+ - The previous entry is equal to the following one.
+ -
+ A key: value pair in a sequence.
+ A second: key:value pair.
+ !float 12 : This key is a float.
+ ? >
+ ?
+ : This key had to be protected.
+ "\\a" : This key had to be escaped.
+ ? >
+ This is a
+ multi-line
+ folded key
+ : >
+ Whose value is
+ also multi-line.
+ ?
+ - This key
+ - is a sequence
+ :
+ - With a sequence value.
+# The following parses correctly,
+# but Ruby 1.6.* fails the comparison!
+# ?
+# This: key
+# is a: mapping
+# :
+# with a: mapping value.
+EOY
+ )
+ end
+
+ def test_spec_builtin_literal_blocks
+ # Assortment of literal scalar blocks
+ assert_parse_only(
+ {"both are equal to"=>" This has no newline.", "is equal to"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n", "also written as"=>" This has no newline.", "indented and chomped"=>" This has no newline.", "empty"=>"", "literal"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n"}, <<EOY
+empty: |
+
+literal: |
+ The \\ ' " characters may be
+ freely used. Leading white
+ space is significant.
+
+ Line breaks are significant.
+ Thus this value contains one
+ empty line and ends with a
+ single line break, but does
+ not start with one.
+
+is equal to: "The \\ ' \\" characters may \\
+ be\\nfreely used. Leading white\\n space \\
+ is significant.\\n\\nLine breaks are \\
+ significant.\\nThus this value contains \\
+ one\\nempty line and ends with a\\nsingle \\
+ line break, but does\\nnot start with one.\\n"
+
+# Comments may follow a nested
+# scalar value. They must be
+# less indented.
+
+# Modifiers may be combined in any order.
+indented and chomped: |2-
+ This has no newline.
+
+also written as: |-2
+ This has no newline.
+
+both are equal to: " This has no newline."
+EOY
+ )
+
+ str1 = "This has one newline.\n"
+ str2 = "This has no newline."
+ str3 = "This has two newlines.\n\n"
+ assert_parse_only(
+ { 'clipped' => str1, 'same as "clipped" above' => str1,
+ 'stripped' => str2, 'same as "stripped" above' => str2,
+ 'kept' => str3, 'same as "kept" above' => str3 }, <<EOY
+clipped: |
+ This has one newline.
+
+same as "clipped" above: "This has one newline.\\n"
+
+stripped: |-
+ This has no newline.
+
+same as "stripped" above: "This has no newline."
+
+kept: |+
+ This has two newlines.
+
+same as "kept" above: "This has two newlines.\\n\\n"
+
+EOY
+ )
+ end
+
+ def test_spec_span_single_quote
+ assert_parse_only( {"third"=>"a single quote ' must be escaped.", "second"=>"! : \\ etc. can be used freely.", "is same as"=>"this contains six spaces\nand one line break", "empty"=>"", "span"=>"this contains six spaces\nand one line break"}, <<EOY
+empty: ''
+second: '! : \\ etc. can be used freely.'
+third: 'a single quote '' must be escaped.'
+span: 'this contains
+ six spaces
+
+ and one
+ line break'
+is same as: "this contains six spaces\\nand one line break"
+EOY
+ )
+ end
+
+ def test_spec_span_double_quote
+ assert_parse_only( {"is equal to"=>"this contains four spaces", "third"=>"a \" or a \\ must be escaped.", "second"=>"! : etc. can be used freely.", "empty"=>"", "fourth"=>"this value ends with an LF.\n", "span"=>"this contains four spaces"}, <<EOY
+empty: ""
+second: "! : etc. can be used freely."
+third: "a \\\" or a \\\\ must be escaped."
+fourth: "this value ends with an LF.\\n"
+span: "this contains
+ four \\
+ spaces"
+is equal to: "this contains four spaces"
+EOY
+ )
+ end
+
+ def test_spec_builtin_time
+ # Time
+ assert_parse_only(
+ { "space separated" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ),
+ "canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ),
+ "date (noon UTC)" => Date.new( 2002, 12, 14),
+ "valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, <<EOY
+canonical: 2001-12-15T02:59:43.1Z
+valid iso8601: 2001-12-14t21:59:43.10-05:00
+space separated: 2001-12-14 21:59:43.10 -05:00
+date (noon UTC): 2002-12-14
+EOY
+ )
+ end
+
+ def test_spec_builtin_binary
+ arrow_gif = "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005, \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;"
+ assert_parse_only(
+ { 'canonical' => arrow_gif, 'base64' => arrow_gif,
+ 'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" }, <<EOY
+canonical: !binary "\\
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf\\
+ n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW\\
+ NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++\\
+ f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg\\
+ d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN\\
+ AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww\\
+ EeECcgggoBADs="
+base64: !binary |
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf
+ n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW
+ NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++
+ f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg
+ d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN
+ AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww
+ EeECcgggoBADs=
+description: >
+ The binary value above is a tiny arrow
+ encoded as a gif image.
+EOY
+ )
+ end
+ def test_ruby_regexp
+ # Test Ruby regular expressions
+ assert_to_yaml(
+ { 'simple' => /a.b/, 'complex' => %r'\A"((?:[^"]|\")+)"',
+ 'case-insensitive' => /George McFly/i }, <<EOY
+case-insensitive: !ruby/regexp "/George McFly/i"
+complex: !ruby/regexp "/\\\\A\\"((?:[^\\"]|\\\\\\")+)\\"/"
+simple: !ruby/regexp "/a.b/"
+EOY
+ )
+ end
+
+ #
+ # Test of Ranges
+ #
+ def test_ranges
+
+ # Simple numeric
+ assert_to_yaml( 1..3, <<EOY )
+--- !ruby/range 1..3
+EOY
+
+ # Simple alphabetic
+ assert_to_yaml( 'a'..'z', <<EOY )
+--- !ruby/range a..z
+EOY
+
+ # Float
+ assert_to_yaml( 10.5...30.3, <<EOY )
+--- !ruby/range 10.5...30.3
+EOY
+
+ end
+
+ def test_ruby_struct
+ # Ruby structures
+ book_struct = Struct::new( "BookStruct", :author, :title, :year, :isbn )
+ assert_to_yaml(
+ [ book_struct.new( "Yukihiro Matsumoto", "Ruby in a Nutshell", 2002, "0-596-00214-9" ),
+ book_struct.new( [ 'Dave Thomas', 'Andy Hunt' ], "The Pickaxe", 2002,
+ book_struct.new( "This should be the ISBN", "but I have another struct here", 2002, "None" )
+ ) ], <<EOY
+- !ruby/struct:BookStruct
+ :author: Yukihiro Matsumoto
+ :title: Ruby in a Nutshell
+ :year: 2002
+ :isbn: 0-596-00214-9
+- !ruby/struct:BookStruct
+ :author:
+ - Dave Thomas
+ - Andy Hunt
+ :title: The Pickaxe
+ :year: 2002
+ :isbn: !ruby/struct:BookStruct
+ :author: This should be the ISBN
+ :title: but I have another struct here
+ :year: 2002
+ :isbn: None
+EOY
+ )
+
+ assert_to_yaml( YAML_Tests::StructTest.new( 123 ), <<EOY )
+--- !ruby/struct:YAML_Tests::StructTest
+:c: 123
+EOY
+
+ end
+
+ def test_emitting_indicators
+ assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
+--- "Hi, from Object 1. You passed: please, pretty please"
+EOY
+ )
+ end
+
+ #
+ # Test the YAML::Stream class -- INACTIVE at the moment
+ #
+ def test_document
+ y = YAML::Stream.new( :Indent => 2, :UseVersion => 0 )
+ y.add(
+ { 'hi' => 'hello', 'map' =>
+ { 'good' => 'two' },
+ 'time' => Time.now,
+ 'try' => /^po(.*)$/,
+ 'bye' => 'goodbye'
+ }
+ )
+ y.add( { 'po' => 'nil', 'oper' => 90 } )
+ y.add( { 'hi' => 'wow!', 'bye' => 'wow!' } )
+ y.add( { [ 'Red Socks', 'Boston' ] => [ 'One', 'Two', 'Three' ] } )
+ y.add( [ true, false, false ] )
+ end
+
+ #
+ # Test YPath choices parsing
+ #
+ def test_ypath_parsing
+ assert_path_segments( "/*/((one|three)/name|place)|//place",
+ [ ["*", "one", "name"],
+ ["*", "three", "name"],
+ ["*", "place"],
+ ["/", "place"] ]
+ )
+ end
+
+ #
+ # Tests from Tanaka Akira on [ruby-core]
+ #
+ def test_akira
+
+ # Commas in plain scalars [ruby-core:1066]
+ assert_to_yaml(
+ {"A"=>"A,","B"=>"B"}, <<EOY
+A: "A,"
+B: B
+EOY
+ )
+
+ # Double-quoted keys [ruby-core:1069]
+ assert_to_yaml(
+ {"1"=>2, "2"=>3}, <<EOY
+'1': 2
+"2": 3
+EOY
+ )
+
+ # Anchored mapping [ruby-core:1071]
+ assert_to_yaml(
+ [{"a"=>"b"}] * 2, <<EOY
+- &id001
+ a: b
+- *id001
+EOY
+ )
+
+ # Stress test [ruby-core:1071]
+ # a = []; 1000.times { a << {"a"=>"b", "c"=>"d"} }
+ # YAML::load( a.to_yaml )
+
+ end
+
+ #
+ # Test Time.now cycle
+ #
+ def test_time_now_cycle
+ #
+ # From Minero Aoki [ruby-core:2305]
+ #
+ require 'yaml'
+ t = Time.now
+ t = Time.at(t.tv_sec, t.tv_usec)
+ 5.times do
+ assert_cycle(t)
+ end
+ end
+
+ #
+ # Test Range cycle
+ #
+ def test_range_cycle
+ #
+ # From Minero Aoki [ruby-core:02306]
+ #
+ assert_cycle("a".."z")
+
+ #
+ # From Nobu Nakada [ruby-core:02311]
+ #
+ assert_cycle(0..1)
+ assert_cycle(1.0e20 .. 2.0e20)
+ assert_cycle("0".."1")
+ assert_cycle(".."..."...")
+ assert_cycle(".rb"..".pl")
+ assert_cycle(".rb"...".pl")
+ assert_cycle('"'...".")
+ assert_cycle("'"...".")
+ end
+
+ #
+ # Circular references
+ #
+ def test_circular_references
+ a = []; a[0] = a; a[1] = a
+ inspect_str = "[[...], [...]]"
+ assert_equal( inspect_str, YAML::load( a.to_yaml ).inspect )
+ end
+
+ #
+ # Test Symbol cycle
+ #
+ def test_symbol_cycle
+ #
+ # From Aaron Schrab [ruby-Bugs:2535]
+ #
+ assert_cycle(:"^foo")
+ end
+
+ #
+ # Test Numeric cycle
+ #
+ class NumericTest < Numeric
+ def initialize(value)
+ @value = value
+ end
+ def ==(other)
+ @value == other.instance_eval{ @value }
+ end
+ end
+ def test_numeric_cycle
+ assert_cycle(1) # Fixnum
+ assert_cycle(111111111111111111111111111111111) # Bignum
+ assert_cycle(NumericTest.new(3)) # Subclass of Numeric
+ end
+
+ #
+ # Test empty map/seq in map cycle
+ #
+ def test_empty_map_key
+ #
+ # empty seq as key
+ #
+ o = YAML.load({[]=>""}.to_yaml)
+ assert_equal(Hash, o.class)
+ assert_equal([[]], o.keys)
+
+ #
+ # empty map as key
+ #
+ o = YAML.load({{}=>""}.to_yaml)
+ assert_equal(Hash, o.class)
+ assert_equal([{}], o.keys)
+ end
+
+ #
+ # contributed by riley lynch [ruby-Bugs-8548]
+ #
+ def test_object_id_collision
+ omap = YAML::Omap.new
+ 1000.times { |i| omap["key_#{i}"] = { "value" => i } }
+ raise "id collision in ordered map" if omap.to_yaml =~ /id\d+/
+ end
+
+ def test_normal_exit
+ YAML.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
+ # '[ruby-core:13735]'
+ end
+end
+
+if $0 == __FILE__
+ suite = Test::Unit::TestSuite.new('YAML')
+ ObjectSpace.each_object(Class) do |klass|
+ suite << klass.suite if (Test::Unit::TestCase > klass)
+ end
+ require 'test/unit/ui/console/testrunner'
+ Test::Unit::UI::Console::TestRunner.run(suite).passed?
+end
diff --git a/trunk/test/yaml/test_yamlstore.rb b/trunk/test/yaml/test_yamlstore.rb
new file mode 100644
index 0000000000..7a3d90469e
--- /dev/null
+++ b/trunk/test/yaml/test_yamlstore.rb
@@ -0,0 +1,74 @@
+require 'test/unit'
+require 'yaml/store'
+
+class YAMLStoreTest < Test::Unit::TestCase
+ def setup
+ @yamlstore_file = "yamlstore.tmp.#{Process.pid}"
+ @yamlstore = YAML::Store.new(@yamlstore_file)
+ end
+
+ def teardown
+ File.unlink(@yamlstore_file) rescue nil
+ end
+
+ def test_opening_new_file_in_readonly_mode_should_result_in_empty_values
+ @yamlstore.transaction(true) do
+ assert_nil @yamlstore[:foo]
+ assert_nil @yamlstore[:bar]
+ end
+ end
+
+ def test_opening_new_file_in_readwrite_mode_should_result_in_empty_values
+ @yamlstore.transaction do
+ assert_nil @yamlstore[:foo]
+ assert_nil @yamlstore[:bar]
+ end
+ end
+
+ def test_data_should_be_loaded_correctly_when_in_readonly_mode
+ @yamlstore.transaction do
+ @yamlstore[:foo] = "bar"
+ end
+ @yamlstore.transaction(true) do
+ assert_equal "bar", @yamlstore[:foo]
+ end
+ end
+
+ def test_data_should_be_loaded_correctly_when_in_readwrite_mode
+ @yamlstore.transaction do
+ @yamlstore[:foo] = "bar"
+ end
+ @yamlstore.transaction do
+ assert_equal "bar", @yamlstore[:foo]
+ end
+ end
+
+ def test_changes_after_commit_are_discarded
+ @yamlstore.transaction do
+ @yamlstore[:foo] = "bar"
+ @yamlstore.commit
+ @yamlstore[:foo] = "baz"
+ end
+ @yamlstore.transaction(true) do
+ assert_equal "bar", @yamlstore[:foo]
+ end
+ end
+
+ def test_changes_are_not_written_on_abort
+ @yamlstore.transaction do
+ @yamlstore[:foo] = "bar"
+ @yamlstore.abort
+ end
+ @yamlstore.transaction(true) do
+ assert_nil @yamlstore[:foo]
+ end
+ end
+
+ def test_writing_inside_readonly_transaction_raises_error
+ assert_raise(PStore::Error) do
+ @yamlstore.transaction(true) do
+ @yamlstore[:foo] = "bar"
+ end
+ end
+ end
+end
diff --git a/trunk/test/zlib/test_zlib.rb b/trunk/test/zlib/test_zlib.rb
new file mode 100644
index 0000000000..fe8cee5622
--- /dev/null
+++ b/trunk/test/zlib/test_zlib.rb
@@ -0,0 +1,638 @@
+require 'test/unit'
+require 'stringio'
+require 'tempfile'
+
+begin
+ require 'zlib'
+rescue LoadError
+end
+
+if defined? Zlib
+ class TestZlibDeflate < Test::Unit::TestCase
+ def test_initialize
+ z = Zlib::Deflate.new
+ s = z.deflate("foo", Zlib::FINISH)
+ assert_equal("foo", Zlib::Inflate.inflate(s))
+
+ z = Zlib::Deflate.new
+ s = z.deflate("foo")
+ s << z.deflate(nil, Zlib::FINISH)
+ assert_equal("foo", Zlib::Inflate.inflate(s))
+
+ assert_raise(Zlib::StreamError) { Zlib::Deflate.new(10000) }
+ end
+
+ def test_dup
+ z1 = Zlib::Deflate.new
+ s = z1.deflate("foo")
+ z2 = z1.dup
+ s1 = s + z1.deflate("bar", Zlib::FINISH)
+ s2 = s + z2.deflate("baz", Zlib::FINISH)
+ assert_equal("foobar", Zlib::Inflate.inflate(s1))
+ assert_equal("foobaz", Zlib::Inflate.inflate(s2))
+ end
+
+ def test_deflate
+ s = Zlib::Deflate.deflate("foo")
+ assert_equal("foo", Zlib::Inflate.inflate(s))
+
+ assert_raise(Zlib::StreamError) { Zlib::Deflate.deflate("foo", 10000) }
+ end
+
+ def test_addstr
+ z = Zlib::Deflate.new
+ z << "foo"
+ s = z.deflate(nil, Zlib::FINISH)
+ assert_equal("foo", Zlib::Inflate.inflate(s))
+ end
+
+ def test_flush
+ z = Zlib::Deflate.new
+ z << "foo"
+ s = z.flush
+ z << "bar"
+ s << z.flush_next_in
+ z << "baz"
+ s << z.flush_next_out
+ s << z.deflate("qux", Zlib::FINISH)
+ assert_equal("foobarbazqux", Zlib::Inflate.inflate(s))
+ end
+
+ def test_avail
+ z = Zlib::Deflate.new
+ assert_equal(0, z.avail_in)
+ assert_equal(0, z.avail_out)
+ z << "foo"
+ z.avail_out += 100
+ z << "bar"
+ s = z.finish
+ assert_equal("foobar", Zlib::Inflate.inflate(s))
+ end
+
+ def test_total
+ z = Zlib::Deflate.new
+ 1000.times { z << "foo" }
+ s = z.finish
+ assert_equal(3000, z.total_in)
+ assert_operator(3000, :>, z.total_out)
+ assert_equal("foo" * 1000, Zlib::Inflate.inflate(s))
+ end
+
+ def test_data_type
+ z = Zlib::Deflate.new
+ assert([Zlib::ASCII, Zlib::BINARY, Zlib::UNKNOWN].include?(z.data_type))
+ end
+
+ def test_adler
+ z = Zlib::Deflate.new
+ z << "foo"
+ s = z.finish
+ assert_equal(0x02820145, z.adler)
+ end
+
+ def test_finished_p
+ z = Zlib::Deflate.new
+ assert_equal(false, z.finished?)
+ z << "foo"
+ assert_equal(false, z.finished?)
+ s = z.finish
+ assert_equal(true, z.finished?)
+ z.close
+ assert_raise(Zlib::Error) { z.finished? }
+ end
+
+ def test_closed_p
+ z = Zlib::Deflate.new
+ assert_equal(false, z.closed?)
+ z << "foo"
+ assert_equal(false, z.closed?)
+ s = z.finish
+ assert_equal(false, z.closed?)
+ z.close
+ assert_equal(true, z.closed?)
+ end
+
+ def test_params
+ z = Zlib::Deflate.new
+ z << "foo"
+ z.params(Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
+ z << "bar"
+ s = z.finish
+ assert_equal("foobar", Zlib::Inflate.inflate(s))
+
+ data = ('a'..'z').to_a.join
+ z = Zlib::Deflate.new(Zlib::NO_COMPRESSION, Zlib::MAX_WBITS,
+ Zlib::DEF_MEM_LEVEL, Zlib::DEFAULT_STRATEGY)
+ z << data[0, 10]
+ z.params(Zlib::BEST_COMPRESSION, Zlib::DEFAULT_STRATEGY)
+ z << data[10 .. -1]
+ assert_equal(data, Zlib::Inflate.inflate(z.finish))
+
+ z = Zlib::Deflate.new
+ s = z.deflate("foo", Zlib::FULL_FLUSH)
+ z.avail_out = 0
+ z.params(Zlib::NO_COMPRESSION, Zlib::FILTERED)
+ s << z.deflate("bar", Zlib::FULL_FLUSH)
+ z.avail_out = 0
+ z.params(Zlib::BEST_COMPRESSION, Zlib::HUFFMAN_ONLY)
+ s << z.deflate("baz", Zlib::FINISH)
+ assert_equal("foobarbaz", Zlib::Inflate.inflate(s))
+
+ z = Zlib::Deflate.new
+ assert_raise(Zlib::StreamError) { z.params(10000, 10000) }
+ z.close # without this, outputs `zlib(finalizer): the stream was freed prematurely.'
+ end
+
+ def test_set_dictionary
+ z = Zlib::Deflate.new
+ z.set_dictionary("foo")
+ s = z.deflate("foo" * 100, Zlib::FINISH)
+ z = Zlib::Inflate.new
+ assert_raise(Zlib::NeedDict) { z.inflate(s) }
+ z.set_dictionary("foo")
+ assert_equal("foo" * 100, z.inflate(s)) # ???
+
+ z = Zlib::Deflate.new
+ z << "foo"
+ assert_raise(Zlib::StreamError) { z.set_dictionary("foo") }
+ z.close # without this, outputs `zlib(finalizer): the stream was freed prematurely.'
+ end
+
+ def test_reset
+ z = Zlib::Deflate.new
+ z << "foo"
+ z.reset
+ z << "bar"
+ s = z.finish
+ assert_equal("bar", Zlib::Inflate.inflate(s))
+ end
+
+ def test_close
+ z = Zlib::Deflate.new
+ z.close
+ assert_raise(Zlib::Error) { z << "foo" }
+ assert_raise(Zlib::Error) { z.reset }
+ end
+ end
+
+ class TestZlibInflate < Test::Unit::TestCase
+ def test_initialize
+ assert_raise(Zlib::StreamError) { Zlib::Inflate.new(-1) }
+
+ s = Zlib::Deflate.deflate("foo")
+ z = Zlib::Inflate.new
+ z << s << nil
+ assert_equal("foo", z.finish)
+ end
+
+ def test_inflate
+ s = Zlib::Deflate.deflate("foo")
+ z = Zlib::Inflate.new
+ s = z.inflate(s)
+ s << z.inflate(nil)
+ assert_equal("foo", s)
+ z.inflate("foo") # ???
+ z << "foo" # ???
+ end
+
+ def test_sync
+ z = Zlib::Deflate.new
+ s = z.deflate("foo" * 1000, Zlib::FULL_FLUSH)
+ z.avail_out = 0
+ z.params(Zlib::NO_COMPRESSION, Zlib::FILTERED)
+ s << z.deflate("bar" * 1000, Zlib::FULL_FLUSH)
+ z.avail_out = 0
+ z.params(Zlib::BEST_COMPRESSION, Zlib::HUFFMAN_ONLY)
+ s << z.deflate("baz" * 1000, Zlib::FINISH)
+
+ z = Zlib::Inflate.new
+ assert_raise(Zlib::DataError) { z << "\0" * 100 }
+ assert_equal(false, z.sync(""))
+ assert_equal(false, z.sync_point?)
+
+ z = Zlib::Inflate.new
+ assert_raise(Zlib::DataError) { z << "\0" * 100 + s }
+ assert_equal(true, z.sync(""))
+ #assert_equal(true, z.sync_point?)
+
+ z = Zlib::Inflate.new
+ assert_equal(false, z.sync("\0" * 100))
+ assert_equal(false, z.sync_point?)
+
+ z = Zlib::Inflate.new
+ assert_equal(true, z.sync("\0" * 100 + s))
+ #assert_equal(true, z.sync_point?)
+ end
+
+ def test_set_dictionary
+ z = Zlib::Inflate.new
+ assert_raise(Zlib::StreamError) { z.set_dictionary("foo") }
+ z.close
+ end
+ end
+
+ class TestZlibGzipFile < Test::Unit::TestCase
+ def test_to_io
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_kind_of(IO, f.to_io)
+ end
+
+ def test_crc
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ f.read
+ assert_equal(0x8c736521, f.crc)
+ end
+
+ def test_mtime
+ tim = Time.now
+
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) do |gz|
+ gz.mtime = -1
+ gz.mtime = tim
+ gz.print("foo")
+ gz.flush
+ assert_raise(Zlib::GzipFile::Error) { gz.mtime = Time.now }
+ end
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal(tim.to_i, f.mtime.to_i)
+ end
+
+ def test_level
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal(Zlib::DEFAULT_COMPRESSION, f.level)
+ end
+
+ def test_os_code
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal(Zlib::OS_CODE, f.os_code)
+ end
+
+ def test_orig_name
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) do |gz|
+ gz.orig_name = "foobarbazqux\0quux"
+ gz.print("foo")
+ gz.flush
+ assert_raise(Zlib::GzipFile::Error) { gz.orig_name = "quux" }
+ end
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foobarbazqux", f.orig_name)
+ end
+
+ def test_comment
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) do |gz|
+ gz.comment = "foobarbazqux\0quux"
+ gz.print("foo")
+ gz.flush
+ assert_raise(Zlib::GzipFile::Error) { gz.comment = "quux" }
+ end
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foobarbazqux", f.comment)
+ end
+
+ def test_lineno
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo\nbar\nbaz\nqux\n") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal([0, "foo\n"], [f.lineno, f.gets])
+ assert_equal([1, "bar\n"], [f.lineno, f.gets])
+ f.lineno = 1000
+ assert_equal([1000, "baz\n"], [f.lineno, f.gets])
+ assert_equal([1001, "qux\n"], [f.lineno, f.gets])
+ end
+
+ def test_closed_p
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal(false, f.closed?)
+ f.read
+ assert_equal(false, f.closed?)
+ f.close
+ assert_equal(true, f.closed?)
+ end
+
+ def test_sync
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ f.sync = true
+ assert_equal(true, f.sync)
+ f.read
+ f.sync = false
+ assert_equal(false, f.sync)
+ f.close
+ end
+
+ def test_pos
+ t = Tempfile.new("test_zlib_gzip_file")
+ t.close
+ Zlib::GzipWriter.open(t.path) do |gz|
+ gz.print("foo")
+ gz.flush
+ assert_equal(3, gz.tell)
+ end
+ end
+ end
+
+ class TestZlibGzipReader < Test::Unit::TestCase
+ D0 = "\037\213\010\000S`\017A\000\003\003\000\000\000\000\000\000\000\000\000"
+ def test_read0
+ assert_equal("", Zlib::GzipReader.new(StringIO.new(D0)).read(0))
+ end
+
+ def test_ungetc
+ s = ""
+ w = Zlib::GzipWriter.new(StringIO.new(s))
+ w << (1...1000).to_a.inspect
+ w.close
+ r = Zlib::GzipReader.new(StringIO.new(s))
+ r.read(100)
+ r.ungetc ?a
+ assert_nothing_raised("[ruby-dev:24060]") {
+ r.read(100)
+ r.read
+ r.close
+ }
+ end
+
+ def test_ungetc_paragraph
+ s = ""
+ w = Zlib::GzipWriter.new(StringIO.new(s))
+ w << "abc"
+ w.close
+ r = Zlib::GzipReader.new(StringIO.new(s))
+ r.ungetc ?\n
+ assert_equal("abc", r.gets(""))
+ assert_nothing_raised("[ruby-dev:24065]") {
+ r.read
+ r.close
+ }
+ end
+
+ def test_open
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ assert_raise(ArgumentError) { Zlib::GzipReader.open }
+
+ assert_equal("foo", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo", f.read)
+ f.close
+ end
+
+ def test_rewind
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo", f.read)
+ f.rewind
+ assert_equal("foo", f.read)
+ f.close
+ end
+
+ def test_unused
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo", f.read(3))
+ f.unused
+ assert_equal("bar", f.read)
+ f.unused
+ f.close
+ end
+
+ def test_read
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_raise(ArgumentError) { f.read(-1) }
+ end
+
+ def test_readpartial
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert("foo".start_with?(f.readpartial(3)))
+
+ f = Zlib::GzipReader.open(t.path)
+ s = ""
+ f.readpartial(3, s)
+ assert("foo".start_with?(s))
+
+ assert_raise(ArgumentError) { f.readpartial(-1) }
+ end
+
+ def test_getc
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ "foobar".each_byte {|c| assert_equal(c, f.getc) }
+ assert_nil(f.getc)
+ end
+
+ def test_readchar
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ "foobar".each_byte {|c| assert_equal(c, f.readchar) }
+ assert_raise(EOFError) { f.readchar }
+ end
+
+ def test_each_byte
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ a = []
+ f.each_byte {|c| a << c }
+ assert_equal("foobar".each_byte.to_a, a)
+ end
+
+ def test_gets
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo\nbar\nbaz\n") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo\n", f.gets)
+ assert_equal("bar\n", f.gets)
+ assert_equal("baz\n", f.gets)
+ assert_nil(f.gets)
+ f.close
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo\nbar\nbaz\n", f.gets(nil))
+ f.close
+ end
+
+ def test_gets
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo\nbar\nbaz\n") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal("foo\n", f.readline)
+ assert_equal("bar\n", f.readline)
+ assert_equal("baz\n", f.readline)
+ assert_raise(EOFError) { f.readline }
+ f.close
+ end
+
+ def test_each
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo\nbar\nbaz\n") }
+
+ f = Zlib::GzipReader.open(t.path)
+ a = ["foo\n", "bar\n", "baz\n"]
+ f.each {|l| assert_equal(a.shift, l) }
+ f.close
+ end
+
+ def test_readlines
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo\nbar\nbaz\n") }
+
+ f = Zlib::GzipReader.open(t.path)
+ assert_equal(["foo\n", "bar\n", "baz\n"], f.readlines)
+ f.close
+ end
+
+ def test_reader_wrap
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+ f = open(t.path)
+ assert_equal("foo", Zlib::GzipReader.wrap(f) {|gz| gz.read })
+ assert_raise(IOError) { f.close }
+ end
+ end
+
+ class TestZlibGzipWriter < Test::Unit::TestCase
+ def test_invalid_new
+ assert_raise(NoMethodError, "[ruby-dev:23228]") { Zlib::GzipWriter.new(nil).close }
+ assert_raise(NoMethodError, "[ruby-dev:23344]") { Zlib::GzipWriter.new(true).close }
+ assert_raise(NoMethodError, "[ruby-dev:23344]") { Zlib::GzipWriter.new(0).close }
+ assert_raise(NoMethodError, "[ruby-dev:23344]") { Zlib::GzipWriter.new(:hoge).close }
+ end
+
+ def test_open
+ assert_raise(ArgumentError) { Zlib::GzipWriter.open }
+
+ t = Tempfile.new("test_zlib_gzip_writer")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+ assert_equal("foo", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+
+ f = Zlib::GzipWriter.open(t.path)
+ f.print("bar")
+ f.close
+ assert_equal("bar", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+
+ assert_raise(Zlib::StreamError) { Zlib::GzipWriter.open(t.path, 10000) }
+ end
+
+ def test_write
+ t = Tempfile.new("test_zlib_gzip_writer")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foo") }
+ assert_equal("foo", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+
+ o = Object.new
+ def o.to_s; "bar"; end
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print(o) }
+ assert_equal("bar", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+ end
+
+ def test_putc
+ t = Tempfile.new("test_zlib_gzip_writer")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.putc(?x) }
+ assert_equal("x", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+
+ # todo: multibyte char
+ end
+
+ def test_writer_wrap
+ t = Tempfile.new("test_zlib_gzip_writer")
+ Zlib::GzipWriter.wrap(t) {|gz| gz.print("foo") }
+ t.close
+ assert_equal("foo", Zlib::GzipReader.open(t.path) {|gz| gz.read })
+ end
+ end
+
+ class TestZlib < Test::Unit::TestCase
+ def test_version
+ assert_instance_of(String, Zlib.zlib_version)
+ assert(Zlib.zlib_version.tainted?)
+ end
+
+ def test_adler32
+ assert_equal(0x00000001, Zlib.adler32)
+ assert_equal(0x02820145, Zlib.adler32("foo"))
+ assert_equal(0x02820145, Zlib.adler32("o", Zlib.adler32("fo")))
+ assert_equal(0x8a62c964, Zlib.adler32("abc\x01\x02\x03" * 10000))
+ end
+
+ def test_crc32
+ assert_equal(0x00000000, Zlib.crc32)
+ assert_equal(0x8c736521, Zlib.crc32("foo"))
+ assert_equal(0x8c736521, Zlib.crc32("o", Zlib.crc32("fo")))
+ assert_equal(0x07f0d68f, Zlib.crc32("abc\x01\x02\x03" * 10000))
+ end
+
+ def test_crc_table
+ t = Zlib.crc_table
+ assert_instance_of(Array, t)
+ t.each {|x| assert_kind_of(Integer, x) }
+ end
+ end
+end